Interface ResponseMarshaler
The MarshaledResponse value returned from these methods is what is ultimately sent back to
clients as bytes over the wire.
A standard threadsafe implementation builder can be acquired via withDefaults() or withCharset(Charset) builder factory methods.
This builder allows you to specify, for example, how to turn a Resource Method response object into a wire format (e.g. JSON) and is generally what you want.
A standard threadsafe implementation can be acquired via the defaultInstance() factory method.
This is generally not needed unless your implementation requires dynamic "fall back to default" behavior that is not otherwise accessible.
Example implementation using withDefaults():
// Let's use Gson to write response body data
// See https://github.com/google/gson
final Gson GSON = new Gson();
// The request was matched to a Resource Method and executed non-exceptionally
ResourceMethodHandler resourceMethodHandler = (
@Nonnull Request request,
@Nonnull Response response,
@Nonnull ResourceMethod resourceMethod
) -> {
// Turn response body into JSON bytes with Gson
Object bodyObject = response.getBody().orElse(null);
byte[] body = bodyObject == null
? null
: GSON.toJson(bodyObject).getBytes(StandardCharsets.UTF_8);
// To be a good citizen, set the Content-Type header
Map<String, Set<String>> headers = new HashMap<>(response.getHeaders());
headers.put("Content-Type", Set.of("application/json;charset=UTF-8"));
// Tell Soklet: "OK - here is the final response data to send"
return MarshaledResponse.withResponse(response)
.headers(headers)
.body(body)
.build();
};
// Function to create responses for exceptions that bubble out
ThrowableHandler throwableHandler = (
@Nonnull Request request,
@Nonnull Throwable throwable,
@Nullable ResourceMethod resourceMethod
) -> {
// Keep track of what to write to the response
String message;
int statusCode;
// Examine the exception that bubbled out and determine what
// the HTTP status and a user-facing message should be.
// Note: real systems should localize these messages
switch (throwable) {
// Soklet throws this exception, a specific subclass of BadRequestException
case IllegalQueryParameterException e -> {
message = String.format("Illegal value '%s' for parameter '%s'",
e.getQueryParameterValue().orElse("[not provided]"),
e.getQueryParameterName());
statusCode = 400;
}
// Generically handle other BadRequestExceptions
case BadRequestException ignored -> {
message = "Your request was improperly formatted.";
statusCode = 400;
}
// Something else? Fall back to a 500
default -> {
message = "An unexpected error occurred.";
statusCode = 500;
}
}
// Turn response body into JSON bytes with Gson.
// Note: real systems should expose richer error constructs
// than an object with a single message field
byte[] body = GSON.toJson(Map.of("message", message))
.getBytes(StandardCharsets.UTF_8);
// Specify our headers
Map<String, Set<String>> headers = new HashMap<>();
headers.put("Content-Type", Set.of("application/json;charset=UTF-8"));
return MarshaledResponse.withStatusCode(statusCode)
.headers(headers)
.body(body)
.build();
};
// Supply our custom handlers to the standard response marshaler
SokletConfig config = SokletConfig.withServer(
Server.withPort(8080).build()
).responseMarshaler(ResponseMarshaler.withDefaults()
.resourceMethodHandler(resourceMethodHandler)
.throwableHandler(throwableHandler)
.build()
).build();
Full documentation is available at https://www.soklet.com/docs/response-writing.
- Author:
- Mark Allen
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic final classBuilder used to construct a standard implementation ofResponseMarshaler. -
Method Summary
Modifier and TypeMethodDescriptionstatic ResponseMarshalerAcquires a threadsafeResponseMarshalerwith a reasonable "out of the box" configuration that uses UTF-8 to write character data.forContentTooLarge(Request request, ResourceMethod resourceMethod) Prepares a response for a request that triggers an HTTP 413 Content Too Large.forCorsAllowed(Request request, Cors cors, CorsResponse corsResponse, MarshaledResponse marshaledResponse) Applies "CORS is permitted for this request" data to a response.forCorsPreflightAllowed(Request request, CorsPreflight corsPreflight, CorsPreflightResponse corsPreflightResponse) Prepares a response for "CORS preflight allowed" scenario when yourCorsAuthorizerapproves a preflight request.forCorsPreflightRejected(Request request, CorsPreflight corsPreflight) Prepares a response for "CORS preflight rejected" scenario when yourCorsAuthorizerdenies a preflight request.forHead(Request request, MarshaledResponse getMethodMarshaledResponse) Prepares a response for an HTTPHEADrequest.forMethodNotAllowed(Request request, Set<HttpMethod> allowedHttpMethods) Prepares a response for a request that triggers an HTTP 405 Method Not Allowed.forNotFound(Request request) Prepares a response for a request that does not have a matching Resource Method, which triggers an HTTP 404 Not Found.forOptions(Request request, Set<HttpMethod> allowedHttpMethods) Prepares a response for an HTTPOPTIONSrequest.forOptionsSplat(Request request) Prepares a response for an HTTPOPTIONS *(colloquially, "OPTIONSSplat") request.forResourceMethod(Request request, Response response, ResourceMethod resourceMethod) Prepares a response for a request that was matched to a Resource Method and returned normally (i.e., without throwing an exception).forThrowable(Request request, Throwable throwable, ResourceMethod resourceMethod) Prepares a response for scenarios in which an uncaught exception is encountered.static ResponseMarshaler.BuilderwithCharset(Charset charset) Acquires a builder for a defaultResponseMarshalerimplementation.static ResponseMarshaler.BuilderAcquires a builder for a defaultResponseMarshalerimplementation that usesStandardCharsets.UTF_8encoding.
-
Method Details
-
forResourceMethod
@Nonnull MarshaledResponse forResourceMethod(@Nonnull Request request, @Nonnull Response response, @Nonnull ResourceMethod resourceMethod) Prepares a response for a request that was matched to a Resource Method and returned normally (i.e., without throwing an exception).Note that the returned
Responsemay represent any HTTP status (e.g., 200, 403, 404), and is not restricted to "successful" outcomes.Detailed documentation is available at https://www.soklet.com/docs/response-writing#resource-method.
- Parameters:
request- the HTTP requestresponse- the response provided by the Resource Method that handled the requestresourceMethod- the Resource Method that handled the request- Returns:
- the response to be sent over the wire
-
forNotFound
Prepares a response for a request that does not have a matching Resource Method, which triggers an HTTP 404 Not Found.Detailed documentation is available at https://www.soklet.com/docs/response-writing#404-not-found.
- Parameters:
request- the HTTP request- Returns:
- the response to be sent over the wire
-
forMethodNotAllowed
@Nonnull MarshaledResponse forMethodNotAllowed(@Nonnull Request request, @Nonnull Set<HttpMethod> allowedHttpMethods) Prepares a response for a request that triggers an HTTP 405 Method Not Allowed.Detailed documentation is available at https://www.soklet.com/docs/response-writing#405-method-not-allowed.
- Parameters:
request- the HTTP requestallowedHttpMethods- appropriate HTTP methods to write to theAllowresponse header- Returns:
- the response to be sent over the wire
-
forContentTooLarge
@Nonnull MarshaledResponse forContentTooLarge(@Nonnull Request request, @Nullable ResourceMethod resourceMethod) Prepares a response for a request that triggers an HTTP 413 Content Too Large.Detailed documentation is available at https://www.soklet.com/docs/response-writing#413-content-too-large.
- Parameters:
request- the HTTP requestresourceMethod- the Resource Method that would have handled the request, if available- Returns:
- the response to be sent over the wire
-
forOptions
@Nonnull MarshaledResponse forOptions(@Nonnull Request request, @Nonnull Set<HttpMethod> allowedHttpMethods) Prepares a response for an HTTPOPTIONSrequest.Note that CORS preflight responses are handled specially by
forCorsPreflightAllowed(Request, CorsPreflight, CorsPreflightResponse)andforCorsPreflightRejected(Request, CorsPreflight)- not this method.Detailed documentation is available at https://www.soklet.com/docs/response-writing#http-options.
- Parameters:
request- the HTTP requestallowedHttpMethods- appropriate HTTP methods to write to theAllowresponse header- Returns:
- the response to be sent over the wire
-
forOptionsSplat
Prepares a response for an HTTPOPTIONS *(colloquially, "OPTIONSSplat") request.This is a special HTTP/1.1 request defined in RFC 7231 ยง4.3.7 which permits querying of server-wide capabilities, not the capabilities of a particular resource - e.g. a load balancer asking "is the system up?" without an explicit health-check URL.
Detailed documentation is available at https://www.soklet.com/docs/response-writing#http-options.
- Parameters:
request- the HTTP request- Returns:
- the response to be sent over the wire
-
forThrowable
@Nonnull MarshaledResponse forThrowable(@Nonnull Request request, @Nonnull Throwable throwable, @Nullable ResourceMethod resourceMethod) Prepares a response for scenarios in which an uncaught exception is encountered.Detailed documentation is available at https://www.soklet.com/docs/response-writing#uncaught-exceptions.
- Parameters:
request- the HTTP requestthrowable- the exception that was thrownresourceMethod- the Resource Method that would have handled the request, if available- Returns:
- the response to be sent over the wire
-
forHead
@Nonnull MarshaledResponse forHead(@Nonnull Request request, @Nonnull MarshaledResponse getMethodMarshaledResponse) Prepares a response for an HTTPHEADrequest.Detailed documentation is available at https://www.soklet.com/docs/response-writing#http-head.
- Parameters:
request- the HTTP requestgetMethodMarshaledResponse- the binary data that would have been sent over the wire for an equivalentGETrequest (necessary in order to write theContent-Lengthheader for aHEADresponse)- Returns:
- the response to be sent over the wire
-
forCorsPreflightAllowed
@Nonnull MarshaledResponse forCorsPreflightAllowed(@Nonnull Request request, @Nonnull CorsPreflight corsPreflight, @Nonnull CorsPreflightResponse corsPreflightResponse) Prepares a response for "CORS preflight allowed" scenario when yourCorsAuthorizerapproves a preflight request.Detailed documentation is available at https://www.soklet.com/docs/cors#writing-cors-responses.
- Parameters:
request- the HTTP requestcorsPreflight- the CORS preflight request datacorsPreflightResponse- the data that should be included in this CORS preflight response- Returns:
- the response to be sent over the wire
-
forCorsPreflightRejected
@Nonnull MarshaledResponse forCorsPreflightRejected(@Nonnull Request request, @Nonnull CorsPreflight corsPreflight) Prepares a response for "CORS preflight rejected" scenario when yourCorsAuthorizerdenies a preflight request.Detailed documentation is available at https://www.soklet.com/docs/cors#writing-cors-responses.
- Parameters:
request- the HTTP requestcorsPreflight- the CORS preflight request data- Returns:
- the response to be sent over the wire
-
forCorsAllowed
@Nonnull MarshaledResponse forCorsAllowed(@Nonnull Request request, @Nonnull Cors cors, @Nonnull CorsResponse corsResponse, @Nonnull MarshaledResponse marshaledResponse) Applies "CORS is permitted for this request" data to a response.Invoked for any non-preflight CORS request that your
CorsAuthorizerapproves.This method will normally return a copy of the
marshaledResponsewith these headers applied based on the values ofcorsResponse:Access-Control-Allow-Origin(required)Access-Control-Allow-Credentials(optional)Access-Control-Expose-Headers(optional)
- Parameters:
request- the HTTP requestcors- the CORS request datacorsResponse- CORS response data to write as specified byCorsAuthorizermarshaledResponse- the existing response to which we should apply relevant CORS headers- Returns:
- the response to be sent over the wire
-
defaultInstance
Acquires a threadsafeResponseMarshalerwith a reasonable "out of the box" configuration that uses UTF-8 to write character data.The returned instance is guaranteed to be a JVM-wide singleton.
- Returns:
- a UTF-8
ResponseMarshalerwith default settings
-
withDefaults
Acquires a builder for a defaultResponseMarshalerimplementation that usesStandardCharsets.UTF_8encoding.- Returns:
- a
ResponseMarshalerbuilder
-
withCharset
Acquires a builder for a defaultResponseMarshalerimplementation.- Parameters:
charset- the default charset to use when writing response data- Returns:
- a
ResponseMarshalerbuilder
-