/** Execute a GET or POST request by injecting and running the appropriate {@link Action}. */
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
// The poorly named method getRequestURI gives the path.
RegisteredAction registeredAction = DELEGATOR.getRegisteredAction(request.getRequestURI());
Action action = registeredAction.getAction();
String origin = request.getHeader(ORIGIN);
String method = request.getMethod();
if (!(("GET".equals(request.getMethod()) && action instanceof GetAction)
|| ("POST".equals(request.getMethod()) && action instanceof PostAction)
|| ("OPTIONS".equals(method) && origin != null))) {
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "Unsupported method.");
return;
}
// Turn off reflected-XSS filtering in modern browsers. Without this, you couldn't execute a
// script from a page served via /echo. This protection is useless to us because /stash allows
// for a far more powerful stored-XSS (albeit short lived), and in any case we allow scripts.
response.addHeader(X_XSS_PROTECTION, "0");
// Enable Cross-Origin Resource Sharing. See http://www.w3.org/TR/cors/ for details.
if (origin != null) {
response.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
if ("OPTIONS".equals(method)) { // Only allow OPTIONS to support CORS preflight.
return;
}
}
ObjectGraph requestGraph = GLOBAL_GRAPH
.plus(new RequestModule(request, response, registeredAction.getPath()))
.plus(REQUEST_MODULES);
Metrics metrics = requestGraph.get(Metrics.class);
try {
requestGraph.inject(action).run();
} catch (HttpErrorException e) {
metrics.setResponseCode(e.getResponseCode());
metrics.addActivity("error"); // Mark this as user error.
response.sendError(e.getResponseCode(), e.getMessage());
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Bad request");
return; // Return without exporting metrics.
}
if (registeredAction.isExportingMetrics()) {
metrics.export();
}
}