Jetty custom status message ?? - rest

I am writing a service in clojure (using ring and compojure) which should change the status message. It is running on embedded Jetty 8. For example I have
200 OK
and I would like to have something like
200 <custome message>
In the EJB world there was possibility to set up header "X-Http-Status-Message" which does some magic behind the scene and changed message in response.
Is there any header in Jetty which allow me to do the same thing??
or Is there any other way in clojure to do it??

Not with a magic header like that.
The status reason has to be set along with the status code in the same call in Jetty.
You can use either javax.servlet.http.HttpServletResponse.setStatus(int, String) or org.eclipse.jetty.server.Response.setStatus(int, String).
Example:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setStatus(HttpServletResponse.SC_OK, "Alrighty");
}
Note that some error conditions this status reason cannot be overridden. But generally, use of HttpServletResponse.sendError(int, String) will behave as you expect.

According to Ring documentation, you can only set the status code, not message:
https://github.com/mmcgrana/ring/wiki/Concepts
Also, the ring.util.servlet/set-status function invokes javax.servlet.http.HttpServletResponse .setStatus(int):
(defn set-status
"Update a HttpServletResponse with a status code."
[^HttpServletResponse response, status]
(.setStatus response status))
Whole implementation is here: https://github.com/ring-clojure/ring/blob/master/ring-servlet/src/ring/util/servlet.clj#L64
It should be fairly trivial to change Ring to add optional support for status message.
I suppose that the change could be introduced to the ring.util.servlet/update-servlet-response function:
(defn update-servlet-response
"Update the HttpServletResponse using a response map."
[^HttpServletResponse response, {:keys [status headers body]}]
(when-not response
(throw (Exception. "Null response given.")))
(when status
(set-status response status))
(doto response
(set-headers headers)
(set-body body)))
For example by adding status-message key to the response map.
https://github.com/ring-clojure/ring/blob/master/ring-servlet/src/ring/util/servlet.clj#L105

Related

How to return error message and HTTP status code together?

I'm using JAX-RS and I want to display the HTTP status and an error message.
Example: HTTP 204 No Content
Here is my code:
public Response getMessageById(#Context HttpServletRequest request,
#PathParam("idMessage") BigInteger idMessage){
if (idMessage== null){
return Response.status(HttpURLConnection.HTTP_NO_CONTENT)
.entity("No Content").build();
}
}
It displays No Content without the HTTP status.
HTTP defines a response header and a response body. The latter one is set by calling entity(), the former by status(). So what you actually send is this:
204 No Content
No Content
You just don't see the header if the tool you use does not display it by default. Use for example curl -v http://your-rest-service/api/resource so see it.
Furthermore:
Don't return 204 if an id is missing. This would rather be a 400 or 404 depending on the sematics. 204 is for operations that don't need to return anything (like PUT, POST, DELETE).
I doubt that this parameter can be null. JaxRS will not select the method if the request does not match the #Path.
Although using the constants in HttpURLConnection is possible, it would be more consistent to use javax.ws.rs.core.Response.Status
HttpServletRequest is for rare edge cases only. Don't use it if you don't need it.

What response code should we use on a REST reply when the response data is an error message

We have a REST service where the response to a request may be an error message. A simple example is the request is a formula to calculate and the formula might have a divide by zero. In that case the response is an error code and error message.
So the communication with the REST service is all good. The service itself is responding to the request. But the response is an error message instead of the expected result.
In this case what is the best response code to use? 200 to say the entire communication process is good and we look in the returned JSON to determine if it’s an error? 500 to say it’s an error, but then look to see if we have the expected JSON to determine it was an error in the calculation? Some other code which says we are getting a response from the server but the response is an error message?
A simple example is the request is a formula to calculate and the formula might have a divide by zero. [...] In this case what is the best response code to use?
I would use 422 Unprocessable Entity
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
Don't rely only on HTTP code anyway, always add a description of the error in the body. I believe it's common practice to have all your endpoints reply with a JSON with success (true or false) and something like error (with the error message) if success if false, or data (with the result) if success is true.
For error messages we can use 4XX Bad Request
Look at this post, for various status codes.
http://www.restapitutorial.com/httpstatuscodes.html

Which status to return for request to invalid URL for different http methods?

When a REST application receives a request for a non-existent resource, should it always return a 404 Not Found?
Should it return a different status for any of the HTTP methods GET, HEAD, POST, PUT, DELETE, OPTIONS or TRACE?
Spring returns a 404 for GET and HEAD, a 200 OK for OPTIONS, and a 405 Method Not Supported for the others. Is that wrong?
e.g. This Spring Boot application shows the different responses for requests to a mis-typed URL (greetings instead of greeting).
#RestController
#SpringBootApplication
public class Application {
private static Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
RestTemplate restTemplate = new RestTemplate();
String badUrl = "http://localhost:8080/greetings";
for (HttpMethod httpMethod : HttpMethod.values()) {
try {
restTemplate.execute(badUrl, httpMethod, null, null);
} catch (Exception e) {
log.error("Failed to " + httpMethod + " -- " + e.getMessage());
}
}
}
#RequestMapping("/greeting")
public String greeting() {
return "hello";
}
}
The logged output is:
Failed to GET -- 404 Not Found
Failed to HEAD -- 404 Not Found
Failed to POST -- 405 Method Not Allowed
Failed to PUT -- 405 Method Not Allowed
Failed to PATCH -- I/O error on PATCH request for "http://localhost:8080/greetings": Invalid HTTP method: PATCH; nested exception is java.net.ProtocolException: Invalid HTTP method: PATCH
Failed to DELETE -- 405 Method Not Allowed
OPTIONS request for "http://localhost:8080/greetings" resulted in 200 (OK)
Failed to TRACE -- 405 Method Not Allowed
Short answer: It does not have to always return 404. Longer answer: The specification seems to provide some options regarding which status codes to use. The specification at https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5 says:
10.4.5 404 Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
10.4.6 405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.
There is some room for interpretation when to use those two codes. My interpretation would be: If some resource does not exist, yet some operation conceivably could still be applied to the URI, then a 405 would be more appropriate.
For example:
GET /reservation/1
405 Method not allowed
Allow: PUT
Could mean, that although GET is not allowed on that particular resource (because it does not actually exist), you could still make PUT work, thereby creating said resource in the process.
Arguably, a 404, although allowed by the specification, would be less usable.
Regarding OPTIONS. Specification is here: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2 . According to specification is does not imply an interaction with the resource itself. It is more of a query to the server specifically, to determine what methods would be "theoretically" supported on the given URI. It supports for example a wildcard ("*") query, which also probably does not exist at all.

CSRF Filtering using GWT RequestFactoryServlet

I am implementing a token based system to prevent CSRF attacks in my Request Factory based GWT App.
To implement my filter on the server side I have overridden the doPost method on RequestFactoryServlet, thus:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String sessionToken = CsrfTokenManager.getToken(request.getSession());
String requestToken = request.getHeader(CsrfTokenManager.CSRF_TOKEN_NAME);
if (sessionToken.equals(requestToken)) {
super.doPost(request, response);
} else {
logger.error(String.format("Received unsafe http request [%s]", getFullRequest(request)));
response.sendError(401,"Unsafe HTTP Request");
}
}
This works in that it does not allow requests without a valid token to be processed, and my logs contain a suitable message, but the error I get back is a 500-Internal Server Error rather than a 401.
Can anyone shed light on why this is and what I should be doing differently?
There is very little information provided by you on the reason for 500 internal server error. Please share the exception stack trace ( 500 internal server error would have thrown one).
Also avoid implementing a custom one if it is not based on GWT recommendation. Read this stackoverflow query on CSRF with RequestFactory.

Using a default method for unmatched REST methods in Jersey

I know this is not quite "restful" but, I want to learn if and how I can handle all requests which do not match any of the methods in my REST resource (I want to proxy these requests to another server). For example, it could be a method like:
#GET
#Path("*")
public Response defaultMethod(#Context HttpServletRequest request, #Context HttpServletResponse response)
{
// do proxying here
}
how can I achieve this?
BR,
SerkanC
#Path("/{default: .*}")
This works for:
http://example.com/someUnexpectedPath
http://example.com/someUnexpectedPath/withAdditionalSubPaths
http://example.com/someUnexpectedPath/withAdditionalSubPaths?andParams=whatever
One possible option would be to define a custom 404 mapping. Since 404s handles all unmatched requests it should catch all undefined urls.
I added the following this to my web.xml file
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
Where location is the path you want to direct the request to. Then just define that the call as normal.