Javadocs for Response and Context. (#9388)
Signed-off-by: Simone Bordet <simone.bordet@gmail.com> Co-authored-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
d21f38798e
commit
a8737cd170
|
@ -18,21 +18,22 @@ import java.util.List;
|
|||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.Decorator;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
* A Context for handling a request.
|
||||
* Every request will always have a non-null context, which may initially be the Server context, or
|
||||
* a context provided by a ContextHandler.
|
||||
* <p>
|
||||
* A Context is also an {@link Executor}, which allows tasks to be run by a thread pool, but scoped
|
||||
* to the classloader and any other aspects of the context. Method {@link #run(Runnable)}
|
||||
* is also provided to allow the current Thread to be scoped to the context.
|
||||
* <p>
|
||||
* A Context is also a {@link Decorator}, allowing objects to be decorated in a context scope.
|
||||
*
|
||||
* <p>The context for handling an HTTP request.</p>
|
||||
* <p>Every request has a non-{@code null} context, which may initially
|
||||
* be the {@link Server#getContext() server context}, or
|
||||
* a context provided by a {@link ContextHandler}.</p>
|
||||
* <p>A context is also an {@link Executor}, which allows tasks to be run by a
|
||||
* thread pool, but scoped to the ClassLoader and any other context property.</p>
|
||||
* <p>Method {@link #run(Runnable)} is also provided to allow the current thread
|
||||
* to be scoped to the context for the execution of the task.</p>
|
||||
* <p>A Context is also a {@link Decorator}, allowing objects to be decorated
|
||||
* in a context scope.</p>
|
||||
*/
|
||||
public interface Context extends Attributes, Decorator, Executor
|
||||
{
|
||||
|
@ -41,39 +42,70 @@ public interface Context extends Attributes, Decorator, Executor
|
|||
*/
|
||||
String getContextPath();
|
||||
|
||||
/**
|
||||
* @return the {@link ClassLoader} associated with this Context
|
||||
*/
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
/**
|
||||
* @return the base resource used to lookup other resources
|
||||
* specified by the request URI path
|
||||
*/
|
||||
Resource getBaseResource();
|
||||
|
||||
/**
|
||||
* @return the error {@link Request.Handler} associated with this Context
|
||||
*/
|
||||
Request.Handler getErrorHandler();
|
||||
|
||||
/**
|
||||
* @return a list of virtual host names associated with this Context
|
||||
*/
|
||||
List<String> getVirtualHosts();
|
||||
|
||||
/**
|
||||
* @return the mime types associated with this Context
|
||||
*/
|
||||
MimeTypes getMimeTypes();
|
||||
|
||||
/** execute runnable in container thread scoped to context */
|
||||
/**
|
||||
* <p>Executes the given task in a thread scoped to this Context.</p>
|
||||
*
|
||||
* @param task the task to run
|
||||
* @see #run(Runnable)
|
||||
*/
|
||||
@Override
|
||||
void execute(Runnable runnable);
|
||||
void execute(Runnable task);
|
||||
|
||||
/** scope the calling thread to the context and run the runnable. */
|
||||
void run(Runnable runnable);
|
||||
/**
|
||||
* <p>Runs the given task in the current thread scoped to this Context.</p>
|
||||
*
|
||||
* @param task the task to run
|
||||
* @see #run(Runnable, Request)
|
||||
*/
|
||||
void run(Runnable task);
|
||||
|
||||
/** scope the calling thread to the context and request and run the runnable. */
|
||||
void run(Runnable runnable, Request request);
|
||||
/**
|
||||
* <p>Runs the given task in the current thread scoped to this Context and the given Request.</p>
|
||||
*
|
||||
* @param task the task to run
|
||||
* @param request the HTTP request to use in the scope
|
||||
*/
|
||||
void run(Runnable task, Request request);
|
||||
|
||||
/**
|
||||
* <p>Returns a URI path scoped to this Context.</p>
|
||||
* <p>For example, if the context path is {@code /ctx} then a
|
||||
* full path of {@code /ctx/foo/bar} will return {@code /foo/bar}.</p>
|
||||
*
|
||||
* @param fullPath A full URI path
|
||||
* @return The URI path scoped to this Context, or {@code null} if the full path does not match this Context.
|
||||
* The empty string is returned if the full path is exactly the context path.
|
||||
* @param fullPath a full URI path
|
||||
* @return the URI path scoped to this Context, or {@code null} if the full path does not match this Context.
|
||||
* The empty string is returned if the full path is exactly the context path.
|
||||
*/
|
||||
String getPathInContext(String fullPath);
|
||||
|
||||
/**
|
||||
* @return A temporary directory, configured either for the context, the server or the JVM. Never null.
|
||||
* @return a non-{@code null} temporary directory, configured either for the context, the server or the JVM
|
||||
*/
|
||||
File getTempDirectory();
|
||||
}
|
||||
|
|
|
@ -504,7 +504,7 @@ public interface Request extends Attributes, Content.Source
|
|||
* completing the passed callback. The handling may be asynchronous, i.e. this method may return true and
|
||||
* complete the given callback later, possibly from a different thread. If this method returns false,
|
||||
* then the callback must not be invoked and any mutation on the response reversed.</p>
|
||||
* <p>Exceptions thrown by this method may be subsequently handled by an {@link ErrorHandler},
|
||||
* <p>Exceptions thrown by this method may be subsequently handled by an error {@link Request.Handler},
|
||||
* if present, otherwise a default HTTP 500 error is generated and the
|
||||
* callback completed while writing the error response.</p>
|
||||
* <p>The simplest implementation is:</p>
|
||||
|
|
|
@ -38,44 +38,98 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An asynchronous HTTP response.
|
||||
* TODO Javadoc
|
||||
* <p>The representation of an HTTP response, for any protocol version (HTTP/1.1, HTTP/2, HTTP/3).</p>
|
||||
*/
|
||||
public interface Response extends Content.Sink
|
||||
{
|
||||
// This is needed so that response methods can access the wrapped Request#getContext method
|
||||
/**
|
||||
* @return the {@link Request} associated with this {@code Response}
|
||||
*/
|
||||
Request getRequest();
|
||||
|
||||
/**
|
||||
* @return the response HTTP status code
|
||||
*/
|
||||
int getStatus();
|
||||
|
||||
/**
|
||||
* @param code the response HTTP status code
|
||||
*/
|
||||
void setStatus(int code);
|
||||
|
||||
/**
|
||||
* @return the response HTTP headers
|
||||
*/
|
||||
HttpFields.Mutable getHeaders();
|
||||
|
||||
/**
|
||||
* @return a supplier for the HTTP trailers
|
||||
*/
|
||||
Supplier<HttpFields> getTrailersSupplier();
|
||||
|
||||
/**
|
||||
* @param trailers a supplier for the HTTP trailers
|
||||
*/
|
||||
void setTrailersSupplier(Supplier<HttpFields> trailers);
|
||||
|
||||
/**
|
||||
* <p>Returns whether this response has already been committed.</p>
|
||||
* <p>Committing a response means that the HTTP status code and HTTP headers
|
||||
* cannot be modified anymore, typically because they have already been
|
||||
* serialized and sent over the network.</p>
|
||||
*
|
||||
* @return whether this response has already been committed
|
||||
*/
|
||||
boolean isCommitted();
|
||||
|
||||
/**
|
||||
* <p>Returns whether the response completed successfully.</p>
|
||||
* <p>The response HTTP status code, HTTP headers and content
|
||||
* have been successfully serialized and sent over the network
|
||||
* without errors.</p>
|
||||
*
|
||||
* @return whether the response completed successfully
|
||||
*/
|
||||
boolean isCompletedSuccessfully();
|
||||
|
||||
/**
|
||||
* <p>Resets this response, clearing the HTTP status code, HTTP headers
|
||||
* and HTTP trailers.</p>
|
||||
*
|
||||
* @throws IllegalStateException if the response is already
|
||||
* {@link #isCommitted() committed}
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* <p>Writes an {@link HttpStatus#isInterim(int) HTTP interim response},
|
||||
* with the given HTTP status code and HTTP headers.</p>
|
||||
* <p>It is possible to write more than one interim response, for example
|
||||
* in case of {@link HttpStatus#EARLY_HINT_103}.</p>
|
||||
* <p>The returned {@link CompletableFuture} is notified of the result
|
||||
* of this write, whether it succeeded or failed.</p>
|
||||
*
|
||||
* @param status the interim HTTP status code
|
||||
* @param headers the HTTP headers
|
||||
* @return a {@link CompletableFuture} with the result of the write
|
||||
*/
|
||||
CompletableFuture<Void> writeInterim(int status, HttpFields headers);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>Invocations of the passed {@code Callback} are serialized and a callback for a completed {@code write} call is
|
||||
* not invoked until any previous {@code write} callback has returned.
|
||||
* Thus the {@code Callback} should not block waiting for a callback of a future write call.</p>
|
||||
* <p>The invocation of the passed {@code Callback} is serialized
|
||||
* with previous calls of this method, so that it is not invoked until
|
||||
* any invocation of the callback of a previous call to this method
|
||||
* has returned.</p>
|
||||
* <p>Thus a {@code Callback} should not block waiting for a callback
|
||||
* of a future call to this method.</p>
|
||||
* <p>Furthermore, the invocation of the passed callback is serialized
|
||||
* with invocations of the {@link Runnable} demand callback passed to
|
||||
* {@link Request#demand(Runnable)}.</p>
|
||||
*
|
||||
* @param last whether the ByteBuffer is the last to write
|
||||
* @param byteBuffer the ByteBuffer to write
|
||||
* @param callback the callback to notify when the write operation is complete
|
||||
* In addition to the invocation guarantees of {@link Content.Sink#write(boolean, ByteBuffer, Callback)},
|
||||
* this implementation serializes the invocation of the {@code Callback} with
|
||||
* invocations of any {@link Request#demand(Runnable)} {@code Runnable} invocations.
|
||||
* @see Content.Sink#write(boolean, ByteBuffer, Callback)
|
||||
*/
|
||||
@Override
|
||||
void write(boolean last, ByteBuffer byteBuffer, Callback callback);
|
||||
|
@ -125,6 +179,16 @@ public interface Response extends Content.Sink
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Unwraps the given response, recursively, until the wrapped instance
|
||||
* is an instance of the given type, otherwise returns {@code null}.</p>
|
||||
*
|
||||
* @param response the response to unwrap
|
||||
* @param type the response type to find
|
||||
* @return the response as the given type, or {@code null}
|
||||
* @param <T> the response type
|
||||
* @see Wrapper
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends Response.Wrapper> T as(Response response, Class<T> type)
|
||||
{
|
||||
|
@ -137,11 +201,34 @@ public interface Response extends Content.Sink
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sends a {@code 302} HTTP redirect status code to the given location,
|
||||
* without consuming the available request content.</p>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param callback the callback to complete
|
||||
* @param location the redirect location
|
||||
* @see #sendRedirect(Request, Response, Callback, int, String, boolean)
|
||||
*/
|
||||
static void sendRedirect(Request request, Response response, Callback callback, String location)
|
||||
{
|
||||
sendRedirect(request, response, callback, HttpStatus.MOVED_TEMPORARILY_302, location, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sends a {@code 302} HTTP redirect status code to the given location.</p>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param callback the callback to complete
|
||||
* @param code the redirect HTTP status code
|
||||
* @param location the redirect location
|
||||
* @param consumeAvailable whether to consumer the available request content
|
||||
* @see Request#toRedirectURI(Request, String)
|
||||
* @throws IllegalArgumentException if the status code is not a redirect, or the location is {@code null}
|
||||
* @throws IllegalStateException if the response is already {@link #isCommitted() committed}
|
||||
*/
|
||||
static void sendRedirect(Request request, Response response, Callback callback, int code, String location, boolean consumeAvailable)
|
||||
{
|
||||
if (!HttpStatus.isRedirection(code))
|
||||
|
@ -174,6 +261,12 @@ public interface Response extends Content.Sink
|
|||
response.write(true, null, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Adds an HTTP cookie to the response.</p>
|
||||
*
|
||||
* @param response the HTTP response
|
||||
* @param cookie the HTTP cookie to add
|
||||
*/
|
||||
static void addCookie(Response response, HttpCookie cookie)
|
||||
{
|
||||
if (StringUtil.isBlank(cookie.getName()))
|
||||
|
@ -187,6 +280,12 @@ public interface Response extends Content.Sink
|
|||
response.getHeaders().put(HttpFields.EXPIRES_01JAN1970);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Replaces (if already exists, otherwise adds) an HTTP cookie to the response.</p>
|
||||
*
|
||||
* @param response the HTTP response
|
||||
* @param cookie the HTTP cookie to replace or add
|
||||
*/
|
||||
static void replaceCookie(Response response, HttpCookie cookie)
|
||||
{
|
||||
if (StringUtil.isBlank(cookie.getName()))
|
||||
|
@ -222,6 +321,16 @@ public interface Response extends Content.Sink
|
|||
addCookie(response, cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes an error response with HTTP status code {@code 500}.</p>
|
||||
* <p>The error {@link Request.Handler} returned by {@link Context#getErrorHandler()},
|
||||
* if any, is invoked.</p>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param callback the callback to complete
|
||||
* @param cause the cause of the error
|
||||
*/
|
||||
static void writeError(Request request, Response response, Callback callback, Throwable cause)
|
||||
{
|
||||
if (cause == null)
|
||||
|
@ -236,16 +345,51 @@ public interface Response extends Content.Sink
|
|||
writeError(request, response, callback, status, message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes an error response with the given HTTP status code.</p>
|
||||
* <p>The error {@link Request.Handler} returned by {@link Context#getErrorHandler()},
|
||||
* if any, is invoked.</p>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param callback the callback to complete
|
||||
* @param status the error HTTP status code
|
||||
*/
|
||||
static void writeError(Request request, Response response, Callback callback, int status)
|
||||
{
|
||||
writeError(request, response, callback, status, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes an error response with the given HTTP status code,
|
||||
* and the given message in the response content.</p>
|
||||
* <p>The error {@link Request.Handler} returned by {@link Context#getErrorHandler()},
|
||||
* if any, is invoked.</p>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param callback the callback to complete
|
||||
* @param status the error HTTP status code
|
||||
* @param message the error message to write in the response content
|
||||
*/
|
||||
static void writeError(Request request, Response response, Callback callback, int status, String message)
|
||||
{
|
||||
writeError(request, response, callback, status, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes an error response with the given HTTP status code,
|
||||
* and the given message in the response content.</p>
|
||||
* <p>The error {@link Request.Handler} returned by {@link Context#getErrorHandler()},
|
||||
* if any, is invoked.</p>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param callback the callback to complete
|
||||
* @param status the error HTTP status code
|
||||
* @param message the error message to write in the response content
|
||||
* @param cause the cause of the error
|
||||
*/
|
||||
static void writeError(Request request, Response response, Callback callback, int status, String message, Throwable cause)
|
||||
{
|
||||
// Retrieve the Logger instance here, rather than having a
|
||||
|
@ -298,6 +442,13 @@ public interface Response extends Content.Sink
|
|||
response.write(true, null, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Unwraps the given response until the innermost wrapped response instance.</p>
|
||||
*
|
||||
* @param response the response to unwrap
|
||||
* @return the innermost wrapped response instance
|
||||
* @see Wrapper
|
||||
*/
|
||||
static Response getOriginalResponse(Response response)
|
||||
{
|
||||
while (response instanceof Response.Wrapper wrapped)
|
||||
|
@ -307,6 +458,11 @@ public interface Response extends Content.Sink
|
|||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param response the HTTP response
|
||||
* @return the number of response content bytes written so far,
|
||||
* or {@code -1} if the number is unknown
|
||||
*/
|
||||
static long getContentBytesWritten(Response response)
|
||||
{
|
||||
Response originalResponse = getOriginalResponse(response);
|
||||
|
@ -326,17 +482,17 @@ public interface Response extends Content.Sink
|
|||
_wrapped = wrapped;
|
||||
}
|
||||
|
||||
public Response getWrapped()
|
||||
{
|
||||
return _wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest()
|
||||
{
|
||||
return _request;
|
||||
}
|
||||
|
||||
public Response getWrapped()
|
||||
{
|
||||
return _wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus()
|
||||
{
|
||||
|
@ -367,12 +523,6 @@ public interface Response extends Content.Sink
|
|||
getWrapped().setTrailersSupplier(trailers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(boolean last, ByteBuffer byteBuffer, Callback callback)
|
||||
{
|
||||
getWrapped().write(last, byteBuffer, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommitted()
|
||||
{
|
||||
|
@ -396,5 +546,11 @@ public interface Response extends Content.Sink
|
|||
{
|
||||
return getWrapped().writeInterim(status, headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(boolean last, ByteBuffer byteBuffer, Callback callback)
|
||||
{
|
||||
getWrapped().write(last, byteBuffer, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue