I have a REST API published with Jersey and documented with Swagger, I also have a Swagger UI installation consuming that API.
Almost all my operations produce application/json and work as expected, except for one GET operation that produces: 'text/plain;charset=utf-8'
When I try to call the service from the Swagger UI, the server logs a javax.ws.rs.NotAcceptableException and returns a 406 response. If I call the same service from a REST client it works as expected.
@GET
@Path("/text")
@Produces(MediaType.TEXT_PLAIN + ";charset=utf-8")
@ApiOperation(value= "Return text")
public Response getText(@QueryParam("user") String user) {
return Response.ok(textService.getTextForUser(user)).build();
}
If I change to @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") then it works fine, but I don't want to set a wrong content type.
The problem seems to be that Swagger UI is wrongly setting the Accept headers to application/json as can be seen by observing the request:
GET /supertext/text?user=1
...
Accept: application/json
When using the rest client the Accept header are:
GET /supertext/text?user=1
...
Accept: */*
Why is Swagger UI not setting the Accept headers properly?
Can this be configured?
It seems that swagger ui sets the accept header to application/json when it finds that the @Produces annotation contains a single value, otherwise it renders a drop-down list in the ui to choose from the available content types.
In swagger-ui.js:
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
When the drop-down list doesn't exist, the property becomes undefined.
Later in the code, the response content type is set to application/json if the property is null or undefined:
In swagger.js:
if (this.type === "POST" || this.type === "GET" || this.type === "PATCH") {
if (this.opts.responseContentType) {
responseContentType = this.opts.responseContentType;
} else {
responseContentType = "application/json";
}
}
So my solution was to modify the code in swagger-ui.js to make sure that the correct content-type was set, by exploring the produces array and choosing the first element as the response content type:
In swagger-ui.js replace the line:
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
With:
if($("div select[name=responseContentType]", $(this.el)).val() === undefined) {
opts.responseContentType = opts.parent.model.produces[0];
}
else {
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
}