API 요약
이 장은 API 표면 전체를 나열하며, 각 항목은 그것을 설명하는 장을 가리킨다.
공개된 모든 패키지는 JSpecify로 `@NullMarked`되어 있으므로, 시그니처에 `@Nullable`이 명시되지 않은 한 파라미터나 반환값은 null을 배제한다. NullAway나 IntelliJ IDEA처럼 JSpecify를 읽는 도구는 non-null 파라미터에 도달하는 null을 보고한다.
`App`이 제공하는 것
-
라우트:
get,post,put,patch,delete,head,options, 각각(path, description, handler)형태로도 제공되며, `path(prefix, group → …)`가 있다; 패턴과 매칭 순서는 라우팅에서 다룬다 -
인트로스펙션:
routes()`는 등록된 모든 라우트를 `Route(method, path, description)`로 등록 순서대로 보고한다. `guards()`는 그 곁에서 동작하는 필터와 에러 핸들러를 `Guard.BeforeRequest(path),Guard.BeforeRoute(path),Guard.AfterRoute(path),Guard.Error(status),Guard.ResponseFilter()`로 보고한다. `spider-silk-openapi는 라우트 목록을 OpenAPI 3.1 문서로 바꾼다 -
필터: 라우팅 전의
beforeRequest(filter)/beforeRequest(path, filter),beforeRoute(filter)/beforeRoute(path, filter), 같은 형태의afterRoute, 그리고 after 필터가 보지 못하는 응답까지 포함해 모든 응답에 적용되는responseFilter(filter) -
로깅:
requestLogger((request, completion) → …), `RequestCompletion`에는 서블릿 상태, 경과 시간, 응답 정의, 전송 실패, 그리고 요청에 응답하게 된 예외가 담긴다; 요청 로깅을 참고한다 -
에러:
exception(Type, handler), 등록된 타입 중 가장 구체적인 것이 이기고HttpException`은 자신의 타입이나 하위 타입의 핸들러에만 도달한다, `error(HttpStatus, handler) -
응답 전반에 걸친 관심사:
cors(Cors),gzip()/gzip(Gzip),securityHeaders()/securityHeaders(SecurityHeaders). 각각은 명시하기 전까지 꺼져 있고, 정적 파일과 에러를 포함한 모든 응답에 적용되므로 필터가 아니다; CORS, 압축, 보안을 참고한다 -
렌더링과 자산:
templates(renderer),staticFiles(classpathRoot),staticFiles(StaticFiles…).classpath:/jte위의 jte와 루트의classpath:/public`이 기본값이므로 둘 다 호출하지 않아도 된다. `StaticFiles.directory(path)`는 클래스패스 대신 디스크의 디렉터리를 제공하고, 한 번에 주어진 여러 루트는 순서대로 읽히며, `precompressed()`는 빌드가 남겨둔 `.br`이나 `.gz형제 파일이 있는 곳에서 그것으로 응답한다.FreeMarkerTemplates,HandlebarsTemplates,ThymeleafTemplates`는 각자의 모듈에 있는 `TemplateRenderer구현체다 -
서버:
start()/start(port),stop(),join(),port(),server(factory). 어떤 방식으로 시작했든AppServlet`이 애플리케이션을 서비스하는 동안 등록은 닫힌다: 그때 추가되는 라우트, 필터, 설정은 `IllegalStateException`을 던지고, `stop()`이 등록을 다시 연다. `Cors,Gzip,SecurityHeaders, `StaticFiles`는 등록될 때 복사된다
`WebRequest`가 제공하는 것
-
요청 정보:
method(),path(),header(name), 반복된 헤더를 위한headers(name), 전체를 위한headers(),contentType(),queryString(),isSecure(),scheme(),host(),remoteAddress(), 그리고 서블릿 요청 자체를 위한raw().host()`는 포트가 스킴의 기본값이 아닐 때 포트를 함께 담으므로, `scheme(),host(), `path()`로 절대 URL을 다시 만들 수 있다 -
매칭된 라우트:
route(), 응답한 `Route`로 그 패턴과 설명을 담는다; 라우팅 전과 매칭된 라우트가 없는 곳에서는 null이며, 라우트 인트로스펙션을 참고한다 -
경로 변수:
pathParam,pathParamLong,pathParamEnum, 그리고 그 밖의 타입을 위한pathParam(name, parser). 패턴이 선언한 적 없는 이름은 400이 아니라IllegalStateException`을 던진다. `\{name*}꼬리는 경로의 나머지를 슬래시까지 포함해 바인딩하고, 아무것도 매칭하지 않았을 때는 `""`가 된다 -
파라미터:
param(없으면 400),paramOrNull(없으면 null),paramLong,paramBoolean(true또는false`만), `paramEnum, 각각 선택 파라미터를 위한(…, default)형태가 있다; 반복된 값을 위한params(name) -
그 밖의 타입:
param(name, parser)`와 `param(name, parser, default), 파서는UUID::fromString`이나 `LocalDate::parse같은 `Function<String, T>`다. `IllegalArgumentException`이나 `DateTimeException`을 던지는 파서는 파라미터 이름을 밝히며 400으로 응답한다 -
한 출처만: `queryParam(name)`과 `formParam(name)`은 값을 요구하며 없으면 400으로 응답한다. `queryParamOrNull(name)`과 `formParamOrNull(name)`은 없으면 null을 반환한다. 파서 오버로드는 `(…, parser, default)`가 기본값을 제공하지 않는 한 값을 요구한다
-
쿼리 대 폼:
queryParam,queryParams,formParam,formParams -
콘텐츠 협상:
accepts(types…)`는 제시된 타입 중 호출자가 선호하는 타입으로 응답하고, 어느 것도 받지 않으면 406이다; 파싱된 `Accept헤더를 위한acceptedTypes() -
클라이언트가 보낸 쿠키:
cookie(name),cookies() -
본문:
body(),bodyJson(),bodyJson(reader)(리더가 거부하는 본문에는 400). 텍스트는 한 번 읽어 보관하므로 모든 호출이 본문 전체로 응답한다 -
멀티파트 업로드:
file(name)(없으면 400),fileOrNull(name)(없으면 null), 여러 파일을 담은 필드를 위한files(name).UploadedFile`은 `fileName(),contentType(),size(),bytes(),asText(),inputStream(), `writeTo(path)`로 응답한다 -
읽지 않은 본문: `bodyStream()`과 `bodyReader()`는 다른 라이브러리의 파서를 위해 본문을 넘겨주며, 둘 다 보관된 텍스트와 섞이지 않는다: 나중에 호출된 쪽이 `IllegalStateException`을 던진다. `bodyNdjson(reader)`는 줄 단위로 구분된 JSON을 지연 읽기하고, 줄 번호를 밝히며 400으로 응답한다; 대용량 JSON과 NDJSON과 외부 JSON 바인딩을 참고한다
-
세션: `sessionAttr(key, Class<T>)`는 지정한 타입으로 읽고 실패하면 그 줄에서 키와 두 타입을 밝히며, `sessionAttr(key)`는 캐스트를 호출 지점에 맡기고, `setSessionAttr(key, value)`는 쓰고, `removeSessionAttr(key)`는 하나를 제거하고, `invalidateSession()`은 세션을 끝낸다
-
플래시:
flash(key, value), 리다이렉트 뒤의 요청에서 `flashed(key)`로 정확히 한 번 읽히며, null 값은 세션 속성에서와 마찬가지로 키를 제거한다 -
에러:
error(status, handler)핸들러 안의errorMessage()
`WebResponse`가 제공하는 것
-
본문:
html,text,json(raw),json(JsonValue),json(value, writer),bytes(contentType, data),template(name),template(name, model),stream(contentType, out → …),file(path),sse(stream → …),raw((req, res) → …) -
`file(path)`는 콘텐츠 타입을 이름에서, 길이를 파일에서 읽는다. 읽을 수 있는 일반 파일이 아닌 경로는 `UncheckedIOException`을 던지므로, 없는 파일에 대한 404는 핸들러가 직접 써야 하는 줄이다
-
값을 하나씩 쓰는 본문: 담아 두기에 너무 큰 배열을 위한
jsonArray(sink → …), 한 줄에 값 하나를 쓰는ndjson(sink → …). 둘 다 내부적으로는stream본문이며, 라이터는 핸들러 예외 처리 밖에서 실행된다 -
상태:
empty(),empty(HttpStatus),noContent(),redirect(location),redirect(location, HttpStatus) -
덧붙이기:
status,header,withoutHeader(name),contentType,vary(field),attachment,body,cookie(name, value),cookie(name, value, maxAge),cookie(Cookie),removeCookie -
되읽기:
status(),header(name),headers(),cookies(),body(). 헤더 이름은 대소문자를 구분하지 않고 비교되며, 어떤 표기로 몇 번을 설정하든 한 필드는 하나의 값을 가진다. 두 번 보내야 하는 헤더는 `raw`를 통해 쓴다; 헤더를 참고한다
`body()`의 형태와 람다 계열에 대해서는 응답을 참고한다.