在带有spring-boot rest和Swagger的标头中使用utf-8字符时,响应未加载

hud*_*udi 5 java rest swagger spring-boot

我有一个招摇的春天启动应用程序.当我测试我的休息服务时,标题中没有utf-8字符,一切正常.Swagger生成命令,我可以使用它来测试它:

curl -X GET --header 'Accept: application/json' --header 'user: me' --header 'reason: zst' --header 'Authorization: Basic dG9tYXM6dG9tYXMxMjM=' 'http://localhost:8080/my-app/uuid/756531B55A3D029A0894D7C9C4ACDF3EC0'
Run Code Online (Sandbox Code Playgroud)

但当我在招摇时使用utf-8字符时,我没有得到任何回应.Swagger正在加载一些东西.当我查看firefox的控制台时,我看到一些get请求:

http://localhost:8080/my-app/webjars/springfox-swagger-ui/images/throbber.gif 
Run Code Online (Sandbox Code Playgroud)

没有回应.

当我尝试编辑curl上面的命令时:

curl -X GET --header 'Accept: application/json' --header 'user: me' --header 'reason: žš?' --header 'Authorization: Basic dG9tYXM6dG9tYXMxMjM=' 'http://localhost:8080/my-app/uuid/756531B55A3D029A0894D7C9C4ACDF3EC0'
Run Code Online (Sandbox Code Playgroud)

一切正常,所以我猜我的后端没问题.有什么办法可以解决/调试这个问题吗?

Nic*_*tto 3

根据RFC 2616 第 4 节消息头定义如下:

\n\n
message-header = field-name ":" [ field-value ]\nfield-name     = token\nfield-value    = *( field-content | LWS )\nfield-content  = <the OCTETs making up the field-value\n                 and consisting of either *TEXT or combinations\n                 of token, separators, and quoted-string>\n
Run Code Online (Sandbox Code Playgroud)\n\n

根据第 2 节可知:

\n\n
token          = 1*<any CHAR except CTLs or separators>\nseparators     = "(" | ")" | "<" | ">" | "@"\n                  | "," | ";" | ":" | "\\" | <">\n                  | "/" | "[" | "]" | "?" | "="\n                  | "{" | "}" | SP | HT\nCHAR           = <any US-ASCII character (octets 0 - 127)>\nquoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )\nqdtext         = <any TEXT except <">>\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

TEXT 规则仅用于不打算由消息解析器解释的描述性字段内容和值。*TEXT 的单词\n 可能包含字符集中的字符,除非ISO-8859-1仅根据RFC 2047的规则进行编码。

\n
\n\n
TEXT          = <any OCTET except CTLs,\n                but including LWS>    \n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

换句话说,标头的值只能进行ISO-8859-1编码,如果您想对未包含在此字符集中的字符进行编码(这里似乎是这种情况),您应该根据 RFC 2047(也称为MIME)对其进行编码(多用途 Internet 邮件扩展)第三部分:非 ASCII 文本的消息头扩展

\n\n

所以而不是

\n\n
reason: \xc5\xbe\xc5\xa1\xc5\xa5\n
Run Code Online (Sandbox Code Playgroud)\n\n

它应该是

\n\n
reason: =?utf-8?q?=C5=BE=C5=A1=C5=A5?=\n
Run Code Online (Sandbox Code Playgroud)\n\n

实际上,当您不只有US-ASCII字符时,甚至建议对值进行编码。

\n\n

您要检查的最后一件事是您的 JAX-RS 实现是否支持开箱即用的RFC 2047,如果不支持,您将需要手动解码它,例如使用实用程序方法MimeUtility.decodeText(String etext)

\n\n

这是一个具体的例子:

\n\n
@GET\npublic Response showHeader(@HeaderParam("reason") String reason) \n    throws UnsupportedEncodingException {\n    // Decode it\n    reason = MimeUtility.decodeText(reason);\n    // Return the value of the decoded String\n    return Response.status(Response.Status.OK)\n        .entity(String.format("Value of reason = \'%s\'", reason))\n        .build();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用curl调用此资源方法会按预期给出:--header \'reason: =?utf-8?q?=C5=BE=C5=A1=C5=A5?=\'

\n\n
Value of reason = \'\xc5\xbe\xc5\xa1\xc5\xa5\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意:要从 js 前端对 header 的值进行编码,您可以使用库q-encoding,这是一个现场演示

\n