Swagger UI导致对生成除JSON之外的内容类型的操作的HTTP 406不可接受的响应 [英] Swagger UI causing HTTP 406 Not Acceptable response for operations producing content types other than json
问题描述
我有一个发布于Jersey并由Swagger记录的REST API,也有一个使用该API的Swagger UI安装.
I have a REST API published with Jersey and documented with Swagger, I also have a Swagger UI installation consuming that API.
几乎我所有的操作都会产生application/json并按预期工作,除了一个GET操作会产生:'text/plain; charset = utf-8'
Almost all my operations produce application/json and work as expected, except for one GET operation that produces: 'text/plain;charset=utf-8'
当我尝试从Swagger UI调用服务时,服务器记录一个javax.ws.rs.NotAcceptableException并返回406响应.如果我从REST客户端调用相同的服务,它将按预期工作.
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();
}
如果我更改为@Produces(MediaType.APPLICATION_JSON +; charset = utf-8"),则可以正常使用,但我不想设置错误的内容类型.
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.
问题似乎是Swagger UI错误地将Accept标头设置为application/json,这可以通过观察请求来看到:
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
使用其余客户端时,Accept标头为:
When using the rest client the Accept header are:
GET /supertext/text?user=1
...
Accept: */*
为什么Swagger UI无法正确设置Accept标头?
Why is Swagger UI not setting the Accept headers properly?
可以配置吗?
推荐答案
当发现@Produces批注包含单个值时,swagger ui似乎将接受标头设置为application/json,否则将显示一个下拉列表在用户界面中列出,以从可用的内容类型中进行选择.
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.
在swagger-ui.js中:
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.
稍后在代码中,如果属性为null或未定义,则将响应内容类型设置为application/json:
Later in the code, the response content type is set to application/json if the property is null or undefined:
在swagger.js中:
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";
}
}
因此,我的解决方案是修改swagger-ui.js中的代码,以确保设置了正确的内容类型,方法是探索Produces数组并选择第一个元素作为响应内容类型:
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:
在swagger-ui.js中替换以下行:
In swagger-ui.js replace the line:
opts.responseContentType = $("div select[name=responseContentType]", $(this.el)).val();
使用:
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();
}
这篇关于Swagger UI导致对生成除JSON之外的内容类型的操作的HTTP 406不可接受的响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!