Accept header. */
String ACCEPT = "Accept";
/** Constant for GMT. */
ZoneId GMT = ZoneId.of("GMT");
/** RFC1123 date pattern. */
String RFC1123_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z";
/** RFC1123 date formatter. */
DateTimeFormatter RFC1123 = DateTimeFormatter
.ofPattern(RFC1123_PATTERN, Locale.US)
.withZone(GMT);
/*
* **********************************************************************************************
* **** Native methods *************************************************************************
* **********************************************************************************************
*/
/**
* Context attributes (a.k.a request attributes).
*
* @return Context attributes.
*/
@Nonnull Mapnull.
*/
@Nullable null.
*/
@Nullable Session sessionOrNull();
/**
* Get a cookie matching the given name.
*
* @param name Cookie's name.
* @return Cookie value.
*/
@Nonnull Value cookie(@Nonnull String name);
/**
* Request cookies.
*
* @return Request cookies.
*/
@Nonnull Mapnull reference.
*/
@Nonnull Value path(@Nonnull String name);
/**
* Convert the {@link #pathMap()} to the given type.
*
* @param type Target type.
* @param {@code
* {
* get("/:id", ctx -> ctx.pathMap());
* }
* }
*
* A call to:
* GET /678* Produces a path map like:
id: 678
*
* @return Path map from path pattern.
*/
@Nonnull Map{@code
* {
* get("/search", ctx -> {
* String q = ctx.query("q").value();
* ...
* });
*
* }
* }
*
* @param name Parameter name.
* @return A query value.
*/
@Nonnull ValueNode query(@Nonnull String name);
/**
* Query string with the leading ? or empty string. This is the raw query string,
* without decoding it.
*
* @return Query string with the leading ? or empty string. This is the raw query
* string, without decoding it.
*/
@Nonnull String queryString();
/**
* Convert the queryString to the given type.
*
* @param type Target type.
* @param {@code/search?q=jooby&sort=name}
*
* Produces
*
* {q: jooby, sort: name}
*
* @return Query string as map.
*/
@Nonnull Map{@code/search?q=jooby&sort=name&sort=id}
*
* Produces
*
* {q: [jooby], sort: [name, id]}
*
* @return Query string as map.
*/
@Nonnull Mapnull reference.
*/
@Nonnull Value header(@Nonnull String name);
/**
* Header as single-value map.
*
* @return Header as single-value map.
*/
@Nonnull Maptrue
* if there is no accept header.
*
* @param contentType Content type to match.
* @return True for matching type or if content header is absent.
*/
boolean accept(@Nonnull MediaType contentType);
/**
* Check if the accept type list matches the given produces list and return the most
* specific media type from produces list.
*
* @param produceTypes Produced types.
* @return The most specific produces type.
*/
@Nullable MediaType accept(@Nonnull ListContent-Type header or null when missing.
*
* @return Request Content-Type header or null when missing.
*/
@Nullable MediaType getRequestType();
/**
* Request Content-Type header or null when missing.
*
* @param defaults Default content type to use when the header is missing.
* @return Request Content-Type header or null when missing.
*/
@Nonnull MediaType getRequestType(MediaType defaults);
/**
* Request Content-Length header or -1 when missing.
*
* @return Request Content-Length header or -1 when missing.
*/
long getRequestLength();
/**
* Returns a list of locales that best matches the current request.
*
* The first filter argument is the value of Accept-Language as a list of
* {@link Locale.LanguageRange} instances while the second argument is a list of supported
* locales specified by {@link Jooby#setLocales(List)} or by the
* application.lang configuration property.
*
* The next example returns a list of matching {@code Locale} instances using the filtering
* mechanism defined in RFC 4647:
*
* {@code
* ctx.locales(Locale::filter)
* }
*
* @param filter A locale filter.
* @return A list of matching locales.
*/
@Nonnull default ListAccept-Language as a list of
* {@link Locale.LanguageRange} instances while the second argument is a list of supported
* locales specified by {@link Jooby#setLocales(List)} or by the
* application.lang configuration property.
*
* The next example returns a {@code Locale} instance for the best-matching language
* tag using the lookup mechanism defined in RFC 4647.
*
* {@code
* ctx.locale(Locale::lookup)
* }
*
* @param filter A locale filter.
* @return A matching locale.
*/
@Nonnull default Locale locale(BiFunctionapplication.lang
* configuration property.
*
* @return A matching locale.
*/
@Nonnull default Locale locale() {
return locale((priorityList, locales) -> Optional.ofNullable(Locale.lookup(priorityList, locales))
.orElse(locales.get(0)));
}
/**
* Current user or null if none was set.
*
* @param null if none was set.
*/
@Nullable Host header.
*
* If you run behind a reverse proxy that has been configured to send the X-Forwarded-* header,
* please consider to set {@link Router#setTrustProxy(boolean)} option.
*
* @return Full/entire request url using the Host header.
*/
@Nonnull String getRequestURL();
/**
* Recreates full/entire request url using the Host header with a custom path/suffix.
*
* If you run behind a reverse proxy that has been configured to send the X-Forwarded-* header,
* please consider to set {@link Router#setTrustProxy(boolean)} option.
*
* @param path Path or suffix to use, can also include query string parameters.
* @return Full/entire request url using the Host header.
*/
@Nonnull String getRequestURL(@Nonnull String path);
/**
* The IP address of the client or last proxy that sent the request.
*
* If you run behind a reverse proxy that has been configured to send the X-Forwarded-* header,
* please consider to set {@link Router#setTrustProxy(boolean)} option.
*
* @return The IP address of the client or last proxy that sent the request or
* empty string for interrupted requests.
*/
@Nonnull String getRemoteAddress();
/**
* Set IP address of client or last proxy that sent the request.
*
* @param remoteAddress Remote Address.
* @return This context.
*/
@Nonnull Context setRemoteAddress(@Nonnull String remoteAddress);
/**
* Return the host that this request was sent to, in general this will be the
* value of the Host header, minus the port specifier. Unless, it is set manually using the
* {@link #setHost(String)} method.
*
* If you run behind a reverse proxy that has been configured to send the X-Forwarded-* header,
* please consider to set {@link Router#setTrustProxy(boolean)} option.
*
* @return Return the host that this request was sent to, in general this will be the
* value of the Host header, minus the port specifier.
*/
@Nonnull String getHost();
/**
* Set the host (without the port value).
*
* Please keep in mind this method doesn't alter/modify the host header.
*
* @param host Host value.
* @return This context.
*/
@Nonnull Context setHost(@Nonnull String host);
/**
* Return the host and port that this request was sent to, in general this will be the
* value of the Host.
*
* If you run behind a reverse proxy that has been configured to send the X-Forwarded-* header,
* please consider to set {@link Router#setTrustProxy(boolean)} option.
*
* @return Return the host that this request was sent to, in general this will be the
* value of the Host header.
*/
@Nonnull String getHostAndPort();
/**
* Return the port that this request was sent to. In general this will be the value of the Host
* header, minus the host name.
*
* If no host header is present, this method returns the value of {@link #getServerPort()}.
*
* @return Return the port that this request was sent to. In general this will be the value of
* the Host header, minus the host name.
*/
int getPort();
/**
* Set port this request was sent to.
*
* @param port Port.
* @return This context.
*/
@Nonnull Context setPort(int port);
/**
* The name of the protocol the request. Always in lower-case.
*
* @return The name of the protocol the request. Always in lower-case.
*/
@Nonnull String getProtocol();
/**
* The certificates presented by the client for mutual TLS. Empty if ssl is not enabled, or client authentication is not required.
*
* @return The certificates presented by the client for mutual TLS. Empty if ssl is not enabled, or client authentication is not required.
*/
@Nonnull Listapplication/form-url-encoded
* request.
*
* @return Formdata as {@link ValueNode}. This method is for application/form-url-encoded
* request.
*/
@Nonnull Formdata form();
/**
* Formdata as multi-value map. Only for application/form-url-encoded request.
*
* @return Formdata as multi-value map. Only for application/form-url-encoded
* request.
*/
@Nonnull Mapapplication/form-url-encoded request.
*
* @return Formdata as single-value map. Only for application/form-url-encoded
* request.
*/
@Nonnull Mapapplication/form-url-encoded
* request.
*
* @param name Field name.
* @return Form value.
*/
@Nonnull ValueNode form(@Nonnull String name);
/**
* Convert formdata to the given type. Only for application/form-url-encoded
* request.
*
* @param type Target type.
* @param multipart/form-data request..
*
* @return Multipart value.
*/
@Nonnull Multipart multipart();
/**
* Get a multipart field that matches the given name.
*
* File upload retrieval is available using {@link Context#file(String)}.
*
* Only for multipart/form-data request.
*
* @param name Field name.
* @return Multipart value.
*/
@Nonnull ValueNode multipart(@Nonnull String name);
/**
* Convert multipart data to the given type.
*
* Only for multipart/form-data request.
*
* @param type Target type.
* @param multipart/form-data request.
*
* @return Multi-value map.
*/
@Nonnull Mapmultipart/form-data request.
*
* @return Single-value map.
*/
@Nonnull Mapmultipart/form-data request.
*
* @return All file uploads.
*/
@Nonnull Listmultipart/form-data request.
*
* @param name Field name. Please note this is the form field name, not the actual file name.
* @return All file uploads.
*/
@Nonnull Listmultipart/form-data request.
*
* @param name Field name. Please note this is the form field name, not the actual file name.
* @return A file upload.
*/
@Nonnull FileUpload file(@Nonnull String name);
/* **********************************************************************************************
* Parameter Lookup
* **********************************************************************************************
*/
/**
* Searches for a parameter in the specified sources, in the specified
* order, returning the first non-missing {@link Value}, or a 'missing'
* {@link Value} if none found.
* * At least one {@link ParamSource} must be specified. * * @param name The name of the parameter. * @param sources Sources to search in. * @return The first non-missing {@link Value} or a {@link Value} representing * a missing value if none found. * @throws IllegalArgumentException If no {@link ParamSource}s are specified. */ default Value lookup(String name, ParamSource... sources) { if (sources.length == 0) { throw new IllegalArgumentException("No parameter sources were specified."); } return Arrays.stream(sources) .map(source -> source.provider.apply(this, name)) .filter(value -> !value.isMissing()) .findFirst() .orElseGet(() -> Value.missing(name)); } /** * Returns a {@link ParamLookup} instance which is a fluent interface covering * the functionality of the {@link #lookup(String, ParamSource...)} method. * *
{@code
* Value foo = ctx.lookup()
* .inQuery()
* .inPath()
* .get("foo");
* }
*
* @return A {@link ParamLookup} instance.
* @see ParamLookup
* @see #lookup(String, ParamSource...)
*/
default ParamLookup lookup() {
return new ParamLookupImpl(this);
}
/* **********************************************************************************************
* Request Body
* **********************************************************************************************
*/
/**
* HTTP body which provides access to body content.
*
* @return HTTP body which provides access to body content.
*/
@Nonnull Body body();
/**
* Convert the HTTP body to the given type.
*
* @param type Reified type.
* @param {@code
*
* get("/", ctx -> {
* return ctx.dispatch(() -> {
*
* // run blocking code
*
* }):
* });
*
* }
*
* @param action Application code.
* @return This context.
*/
@Nonnull Context dispatch(@Nonnull Runnable action);
/**
* Dispatch context to the given executor.
*
* Example:
*
* {@code
*
* Executor executor = ...;
* get("/", ctx -> {
* return ctx.dispatch(executor, () -> {
*
* // run blocking code
*
* }):
* });
*
* }
*
* @param executor Executor to use.
* @param action Application code.
* @return This context.
*/
@Nonnull Context dispatch(@Nonnull Executor executor, @Nonnull Runnable action);
/**
* Tells context that response will be generated form a different thread. This operation is
* similar to {@link #dispatch(Runnable)} except there is no thread dispatching here.
*
* This operation integrates easily with third-party libraries like rxJava or others.
*
* @param next Application code.
* @return This context.
* @throws Exception When detach operation fails.
*/
@Nonnull Context detach(@Nonnull Route.Handler next) throws Exception;
/**
* Perform a websocket handsahke and upgrade a HTTP GET into a websocket protocol.
*
* NOTE: This method is part of Public API, but shouldn't be used by client code.
*
* @param handler Web socket initializer.
* @return This context.
*/
@Nonnull Context upgrade(@Nonnull WebSocket.Initializer handler);
/**
* Perform a server-sent event handshake and upgrade HTTP GET into a Server-Sent protocol.
*
* NOTE: This method is part of Public API, but shouldn't be used by client code.
*
* @param handler Server-Sent event handler.
* @return This context.
*/
@Nonnull Context upgrade(@Nonnull ServerSentEmitter.Handler handler);
/*
* **********************************************************************************************
* **** Response methods *************************************************************************
* **********************************************************************************************
*/
/**
* Set response header.
*
* @param name Header name.
* @param value Header value.
* @return This context.
*/
@Nonnull Context setResponseHeader(@Nonnull String name, @Nonnull Date value);
/**
* Set response header.
*
* @param name Header name.
* @param value Header value.
* @return This context.
*/
@Nonnull Context setResponseHeader(@Nonnull String name, @Nonnull Instant value);
/**
* Set response header.
*
* @param name Header name.
* @param value Header value.
* @return This context.
*/
@Nonnull Context setResponseHeader(@Nonnull String name, @Nonnull Object value);
/**
* Set response header.
*
* @param name Header name.
* @param value Header value.
* @return This context.
*/
@Nonnull Context setResponseHeader(@Nonnull String name, @Nonnull String value);
/**
* Remove a response header.
*
* @param name Header's name.
* @return This context.
*/
@Nonnull Context removeResponseHeader(@Nonnull String name);
/**
* Clear/reset all the headers, including cookies.
*
* @return This context.
*/
@Nonnull Context removeResponseHeaders();
/**
* Set response content length header.
*
* @param length Response length.
* @return This context.
*/
@Nonnull Context setResponseLength(long length);
/**
* Get response header.
*
* @param name Header's name.
* @return Header's value (if set previously) or null.
*/
@Nullable String getResponseHeader(@Nonnull String name);
/**
* Get response content length or -1 when none was set.
*
* @return Response content length or -1 when none was set.
*/
long getResponseLength();
/**
* Set/add a cookie to response.
*
* @param cookie Cookie to add.
* @return This context.
*/
@Nonnull Context setResponseCookie(@Nonnull Cookie cookie);
/**
* Set response content type header.
*
* @param contentType Content type.
* @return This context.
*/
@Nonnull Context setResponseType(@Nonnull String contentType);
/**
* Set response content type header.
*
* @param contentType Content type.
* @return This context.
*/
@Nonnull Context setResponseType(@Nonnull MediaType contentType);
/**
* Set response content type header.
*
* @param contentType Content type.
* @param charset Charset.
* @return This context.
*/
@Nonnull Context setResponseType(@Nonnull MediaType contentType, @Nullable Charset charset);
/**
* Set the default response content type header. It is used if the response content type header
* was not set yet.
*
* @param contentType Content type.
* @return This context.
*/
@Nonnull Context setDefaultResponseType(@Nonnull MediaType contentType);
/**
* Get response content type.
*
* @return Response content type.
*/
@Nonnull MediaType getResponseType();
/**
* Set response status code.
*
* @param statusCode Status code.
* @return This context.
*/
@Nonnull Context setResponseCode(@Nonnull StatusCode statusCode);
/**
* Set response status code.
*
* @param statusCode Status code.
* @return This context.
*/
@Nonnull Context setResponseCode(int statusCode);
/**
* Get response status code.
*
* @return Response status code.
*/
@Nonnull StatusCode getResponseCode();
/**
* Render a value and send the response to client.
*
* @param value Object value.
* @return This context.
*/
@Nonnull Context render(@Nonnull Object value);
/**
* HTTP response channel as output stream. Usually for chunked responses.
*
* @return HTTP channel as output stream. Usually for chunked responses.
*/
@Nonnull OutputStream responseStream();
/**
* HTTP response channel as output stream. Usually for chunked responses.
*
* @param contentType Media type.
* @return HTTP channel as output stream. Usually for chunked responses.
*/
@Nonnull OutputStream responseStream(@Nonnull MediaType contentType);
/**
* HTTP response channel as output stream. Usually for chunked responses.
*
* @param contentType Content type.
* @param consumer Output stream consumer.
* @return HTTP channel as output stream. Usually for chunked responses.
* @throws Exception Is something goes wrong.
*/
@Nonnull Context responseStream(@Nonnull MediaType contentType,
@Nonnull SneakyThrows.Consumer302 response.
*
* @param location Location.
* @return This context.
*/
@Nonnull Context sendRedirect(@Nonnull String location);
/**
* Send a redirect response.
*
* @param redirect Redirect status code.
* @param location Location.
* @return This context.
*/
@Nonnull Context sendRedirect(@Nonnull StatusCode redirect, @Nonnull String location);
/**
* Send response data.
*
* @param data Response. Use UTF-8 charset.
* @return This context.
*/
@Nonnull Context send(@Nonnull String data);
/**
* Send response data.
*
* @param data Response.
* @param charset Charset.
* @return This context.
*/
@Nonnull Context send(@Nonnull String data, @Nonnull Charset charset);
/**
* Send response data.
*
* @param data Response.
* @return This context.
*/
@Nonnull Context send(@Nonnull byte[] data);
/**
* Send response data.
*
* @param data Response.
* @return This context.
*/
@Nonnull Context send(@Nonnull ByteBuffer data);
/**
* Send response data.
*
* @param data Response.
* @return This context.
*/
@Nonnull Context send(@Nonnull byte[]... data);
/**
* Send response data.
*
* @param data Response.
* @return This context.
*/
@Nonnull Context send(@Nonnull ByteBuffer[] data);
/**
* Send response data.
*
* @param channel Response input.
* @return This context.
*/
@Nonnull Context send(@Nonnull ReadableByteChannel channel);
/**
* Send response data.
*
* @param input Response.
* @return This context.
*/
@Nonnull Context send(@Nonnull InputStream input);
/**
* Send a file download response.
*
* @param file File download.
* @return This context.
*/
@Nonnull Context send(@Nonnull FileDownload file);
/**
* Send a file response.
*
* @param file File response.
* @return This context.
*/
@Nonnull Context send(@Nonnull Path file);
/**
* Send a file response.
*
* @param file File response.
* @return This context.
*/
@Nonnull Context send(@Nonnull FileChannel file);
/**
* Send an empty response with the given status code.
*
* @param statusCode Status code.
* @return This context.
*/
@Nonnull Context send(@Nonnull StatusCode statusCode);
/**
* Send an error response. Status code is computed via {@link Router#errorCode(Throwable)}.
*
* @param cause Error. If this is a fatal error it is going to be rethrow it.
* @return This context.
*/
@Nonnull Context sendError(@Nonnull Throwable cause);
/**
* Send an error response.
*
* @param cause Error. If this is a fatal error it is going to be rethrow it.
* @param statusCode Status code.
* @return This context.
*/
@Nonnull Context sendError(@Nonnull Throwable cause, @Nonnull StatusCode statusCode);
/**
* True if response already started.
*
* @return True if response already started.
*/
boolean isResponseStarted();
/**
* True if response headers are cleared on application error. If none set it uses the
* default/global value specified by {@link RouterOption#RESET_HEADERS_ON_ERROR}.
*
* @return True if response headers are cleared on application error. If none set it uses the
* default/global value specified by {@link RouterOption#RESET_HEADERS_ON_ERROR}.
*/
boolean getResetHeadersOnError();
/**
* Set whenever reset/clear headers on application error.
*
* @param value True for reset/clear headers.
* @return This context.
*/
@Nonnull Context setResetHeadersOnError(boolean value);
/**
* Add a complete listener.
*
* @param task Task to execute.
* @return This context.
*/
@Nonnull Context onComplete(@Nonnull Route.Complete task);
/* **********************************************************************************************
* Factory methods
* **********************************************************************************************
*/
/**
* Wrap a HTTP context and make read only. Attempt to modify the HTTP response resulted in
* exception.
*
* @param ctx Originating context.
* @return Read only context.
*/
static @Nonnull Context readOnly(@Nonnull Context ctx) {
return new ReadOnlyContext(ctx);
}
/**
* Wrap a HTTP context and make it WebSocket friendly. Attempt to modify the HTTP response
* is completely ignored, except for {@link #send(byte[])} and {@link #send(String)} which
* are delegated to the given web socket.
*
* This context is necessary for creating a bridge between {@link MessageEncoder}
* and {@link WebSocket}.
*
* This method is part of Public API, but direct usage is discourage.
*
* @param ctx Originating context.
* @param ws WebSocket.
* @return Read only context.
*/
static @Nonnull Context websocket(@Nonnull Context ctx, @Nonnull WebSocket ws) {
return new WebSocketSender(ctx, ws);
}
}