I wrote a Web API in Java (JAX-RS by Jersey) which returns "403 Forbidden" with JSON.
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=UTF-8
...
{"resultCode":"..."}
It works on the local GAE dev server as expected. However, on the real GAE, the content type is changed from JSON to HTML.
HTTP/1.1. 403 Forbidden
Content-Type: text/html; charset=utf-8
...
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
</body></html>
How can I prevent GAE from changing the content type and the entity body?
Additional Information
My endpoint does not throw any exception. It returns a Response instance. The code snippet below is a test endpoint. On the local GAE dev server, this endpoint returns JSON. On the real GAE, it returns HTML. Too much of a good thing.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@Path("/test")
public class TestEndpoint
{
@GET
public Response get()
{
return Response
.status(Status.BAD_REQUEST)
.type(MediaType.APPLICATION_JSON_TYPE)
.entity("{\"id\":1}")
.build();
}
}
Additional Information 2
I wrote a simpler example code like below. This code returns JSON even on the real GAE! What's the difference?
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setStatus(400);
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.write("{\"hello\":\"world\"}");
}
}
You'll have to define your own exception mapper and payload extensions in your service context file:
my-custom-exception-mapper implements ExceptionMapper, ResponseExceptionMapper. Something like this is a good start: http://www.luckyryan.com/2013/06/15/apache-cxf-exception-handler-for-jaxrs-rest/
Mentioned solution without web.xml may look like:
I read Jersey's source code and intuited this answer.
Setting "jersey.config.server.response.setStatusOverSendError" (one of Jersey's server configuration properties) to true solved the issue.
The following is an excerpt from my new web.xml.