Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Response not loading when using utf-8 chars in header with spring-boot rest and Swagger

I have spring boot-application with swagger. When I am testing my rest services with no utf-8 chars in header everything works OK. Swagger generate command which I can use to test it:

curl -X GET --header 'Accept: application/json' --header 'user: me' --header 'reason: zst' --header 'Authorization: Basic dG9tYXM6dG9tYXMxMjM=' 'http://localhost:8080/my-app/uuid/756531B55A3D029A0894D7C9C4ACDF3EC0'

but when I am using utf-8 chars in swagger I got no response. Swagger is just loading something. When I look into console of firefox I see just some get request:

http://localhost:8080/my-app/webjars/springfox-swagger-ui/images/throbber.gif 

without response.

When I try to edit curl command above:

curl -X GET --header 'Accept: application/json' --header 'user: me' --header 'reason: žšť' --header 'Authorization: Basic dG9tYXM6dG9tYXMxMjM=' 'http://localhost:8080/my-app/uuid/756531B55A3D029A0894D7C9C4ACDF3EC0'

everything works OK so I guess there is no problem with my backend. Is there some way how I can fix/debug this problem ?

like image 479
hudi Avatar asked Oct 18 '22 21:10

hudi


1 Answers

According to the RFC 2616 section 4, Message Headers are defined as follows:

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

Knowing that according to the section 2:

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

The TEXT rule is only used for descriptive field contents and values that are not intended to be interpreted by the message parser. Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 only when encoded according to the rules of RFC 2047.

TEXT          = <any OCTET except CTLs,
                but including LWS>    

In other words, the value of an header can only be ISO-8859-1 encoded, if you want to encode characters that are not included into this charset which seems to be the case here, you are supposed to encode it according to the RFC 2047 also known as MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text.

So instead of

reason: žšť

It should be

reason: =?utf-8?q?=C5=BE=C5=A1=C5=A5?=

In practice, it is even recommended to encode the value when you don't have only US-ASCII characters.

The last thing to check on your side, is if your JAX-RS implementation supports out of the box the RFC 2047, if not you will need to decode it manually for example using the utility method MimeUtility.decodeText(String etext).

Here is a concrete example:

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

Calling this resource method using curl with --header 'reason: =?utf-8?q?=C5=BE=C5=A1=C5=A5?=' gives as expected:

Value of reason = 'žšť'

NB: To encode your header's value from your js front-end, you could use the library q-encoding, here is a live demo.

like image 91
Nicolas Filotto Avatar answered Nov 15 '22 05:11

Nicolas Filotto