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?
The HyperText Transfer Protocol (HTTP) 406 Not Acceptable client error response code indicates that the server cannot produce a response matching the list of acceptable values defined in the request's proactive content negotiation headers, and that the server is unwilling to supply a default representation.
The Swagger specification of the REST API consists of a file of JSON data called swagger. json. This schema file includes endpoint URLs, descriptions, request parameters and response structures for the entire API.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With