com.yahoo.jdisc.Response Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc;
import com.yahoo.jdisc.handler.ContentChannel;
import com.yahoo.jdisc.handler.RequestHandler;
import com.yahoo.jdisc.handler.ResponseDispatch;
import com.yahoo.jdisc.handler.ResponseHandler;
import java.util.HashMap;
import java.util.Map;
/**
* This class represents the single response (which may have any content model that a {@link RequestHandler} chooses
* to implement) of some single request. Contrary to the {@link Request} class, this has no active reference to the
* parent {@link Container} (this is tracked internally by counting the number of requests vs the number of responses
* seen). The {@link ResponseHandler} of a Response is implicit in the invocation of {@link
* RequestHandler#handleRequest(Request, ResponseHandler)}.
*
* The usage pattern of the Response is similar to that of the Request in that the {@link ResponseHandler} returns a
* {@link ContentChannel} into which to write the Response content.
*
* @author Simon Thoresen Hult
* @see Request
* @see ResponseHandler
*/
public class Response {
/**
* This interface acts as a namespace for the built-in status codes of the jDISC core. These are identical to the
* common HTTP status codes (see RFC2616).
*/
public interface Status {
/**
* 1xx: Informational - Request received, continuing process.
*/
int CONTINUE = 100;
int SWITCHING_PROTOCOLS = 101;
int PROCESSING = 102;
/**
* 2xx: Success - The action was successfully received, understood, and accepted.
*/
int OK = 200;
int CREATED = 201;
int ACCEPTED = 202;
int NON_AUTHORITATIVE_INFORMATION = 203;
int NO_CONTENT = 204;
int RESET_CONTENT = 205;
int PARTIAL_CONTENT = 206;
int MULTI_STATUS = 207;
/**
* 3xx: Redirection - Further action must be taken in order to complete the request.
*/
int MULTIPLE_CHOICES = 300;
int MOVED_PERMANENTLY = 301;
int FOUND = 302;
int SEE_OTHER = 303;
int NOT_MODIFIED = 304;
int USE_PROXY = 305;
int TEMPORARY_REDIRECT = 307;
/**
* 4xx: Client Error - The request contains bad syntax or cannot be fulfilled.
*/
int BAD_REQUEST = 400;
int UNAUTHORIZED = 401;
int PAYMENT_REQUIRED = 402;
int FORBIDDEN = 403;
int NOT_FOUND = 404;
int METHOD_NOT_ALLOWED = 405;
int NOT_ACCEPTABLE = 406;
int PROXY_AUTHENTICATION_REQUIRED = 407;
int REQUEST_TIMEOUT = 408;
int CONFLICT = 409;
int GONE = 410;
int LENGTH_REQUIRED = 411;
int PRECONDITION_FAILED = 412;
int REQUEST_TOO_LONG = 413;
int REQUEST_URI_TOO_LONG = 414;
int UNSUPPORTED_MEDIA_TYPE = 415;
int REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int EXPECTATION_FAILED = 417;
int INSUFFICIENT_SPACE_ON_RESOURCE = 419;
int METHOD_FAILURE = 420;
int UNPROCESSABLE_ENTITY = 422;
int LOCKED = 423;
int FAILED_DEPENDENCY = 424;
int TOO_MANY_REQUESTS = 429;
/** 5xx: Server Error - The server failed to fulfill an apparently valid request. */
int INTERNAL_SERVER_ERROR = 500;
int NOT_IMPLEMENTED = 501;
int BAD_GATEWAY = 502;
int SERVICE_UNAVAILABLE = 503;
int GATEWAY_TIMEOUT = 504;
int VERSION_NOT_SUPPORTED = 505;
int INSUFFICIENT_STORAGE = 507;
}
private final Map context = new HashMap<>();
private final HeaderFields headers = new HeaderFields();
private Throwable error;
private int status;
private Request.RequestType requestType;
/**
* Creates a new instance of this class.
*
* @param status The status code to assign to this.
*/
public Response(int status) {
this(status, null);
}
/**
* Creates a new instance of this class.
*
* @param status The status code to assign to this.
* @param error The error to assign to this.
*/
public Response(int status, Throwable error) {
this.status = status;
this.error = error;
}
/**
* Returns the named application context objects. This data is not intended for network transport, rather they
* are intended for passing shared data between components of an Application.
*
* Modifying the context map is a thread-unsafe operation -- any changes made after calling {@link
* ResponseHandler#handleResponse(Response)} might never become visible to other threads, and might throw
* ConcurrentModificationExceptions in other threads.
*
* @return The context map.
*/
public Map context() {
return context;
}
/**
* Returns the set of header fields of this Request. These are the meta-data of the Request, and are not applied
* to any internal {@link Container} logic. Modifying headers is a thread-unsafe operation -- any changes made after
* calling {@link ResponseHandler#handleResponse(Response)} might never become visible to other threads, and might
* throw ConcurrentModificationExceptions in other threads.
*
* @return The header fields.
*/
public HeaderFields headers() {
return headers;
}
/**
* Returns the status code of this response. This is an integer result code of the attempt to understand and
* satisfy the corresponding {@link Request}. It is encouraged, although not enforced, to use the built-in {@link
* Status} codes whenever possible.
*
* @return The status code.
* @see #setStatus(int)
*/
public int getStatus() {
return status;
}
/**
* Sets the status code of this response. This is an integer result code of the attempt to understand and
* satisfy the corresponding {@link Request}. It is encouraged, although not enforced, to use the built-in {@link
* Status} codes whenever possible.
*
* Because access to this field is not guarded by any lock, any changes made after calling {@link
* ResponseHandler#handleResponse(Response)} might never become visible to other threads.
*
* @param status The status code to set.
* @return This, to allow chaining.
* @see #getStatus()
*/
public Response setStatus(int status) {
this.status = status;
return this;
}
/**
* Returns the error of this response, or null if none has been set. This is typically non-null if the status
* indicates an unsuccessful response.
*
* @return The error.
* @see #getError()
*/
public Throwable getError() {
return error;
}
/**
* Sets the error of this response. It is encouraged, although not enforced, to use this field to attach
* additional information to an unsuccessful response.
*
* Because access to this field is not guarded by any lock, any changes made after calling {@link
* ResponseHandler#handleResponse(Response)} might never become visible to other threads.
*
* @param error The error to set.
* @return This, to allow chaining.
* @see #getError()
*/
public Response setError(Throwable error) {
this.error = error;
return this;
}
/** Sets the type classification of this request for metric collection purposes */
public void setRequestType(Request.RequestType requestType) {
this.requestType = requestType;
}
/** Returns the type classification of this request for metric collection purposes, or null if not set */
public Request.RequestType getRequestType() { return requestType; }
/**
* This is a convenience method for creating a Response with status {@link Status#GATEWAY_TIMEOUT} and passing
* that to the given {@link ResponseHandler#handleResponse(Response)}. For trivial implementations of {@link
* RequestHandler#handleTimeout(Request, ResponseHandler)}, simply call this method.
*
* @param handler The handler to pass the timeout {@link Response} to.
*/
public static void dispatchTimeout(ResponseHandler handler) {
ResponseDispatch.newInstance(Status.GATEWAY_TIMEOUT).dispatch(handler);
}
}