In my Spring MVC Test (UTF-8 encoded) we find:
this.mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity())
.apply(documentationConfiguration(restDocumentation)
.snippets().withEncoding("UTF-8")) // default
.build();
...
myRequestDTO.setValue("Größe");
ResultActions action = this.mockMvc
.perform(post("/my-service")
.content(jacksonObjectMapper.writeValueAsString(myRequestDTO))
...
action.andDo(document("docs"));
The asciidoctor file contains
HTTP Request
include::{snippets}/docs/http-request.adoc[]
After I have rendered it and open the generated HTML file (which is UTF-8 encoded, too) in my firefox browser I find
HTTP Request
POST /my-service HTTP/1.1
...
Größe
How can the special chars be displayed correctly?
The underlying problem here was with the conversion of a request's content as a byte[] into a String. Spring REST Docs uses the charset attribute of the Content-Type header to determine the Charset that should be used when creating the String. If there's no Content-Type header or its value doesn't have a charset attribute, the JVM's default Charset is used (as a result of calling new String(bytes)).
There are two ways to avoid corruption of special characters:
Specify a charset attribute in the request's Content-Type header. Use text/plain;charset=UTF-8 rather than text/plain, for example.
Configure the JVM's default Charset by setting the file.encoding system property. -Dfile.encoding=UTF8, for example.
After I have called prettyPrint() it works:
action.andDo(document("docs",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint())));
Related
In my Java application, I set the default system locale (Locale.getDefault()) as Accept-Language header for the HTTP request to my tomcat web application.
In my case, this is de_DE.
On server side, I try to get the locale by using request.getLocale(). But I only get an empty string.
If I set the Accept-Language to de, everything works fine.
Why does de_DE not work as Accept-Language header?
EDIT:
This is my client side code:
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("Accept-Language", Locale.getDefault().toString());
And this my server side code:
request.getLocale().toString(); //empty string
request.getHeader("Accept-Language"); //"de_DE"
The correct format for language tags is de-DE. With a dash, not an underscore.
I guess it wouldn't be surprising if other webservers were more lenient and would accept de_DE to be equivalent, but Tomcat does not. For reference, Tomcat delegates this parsing to Locale.forLanguageTag(), which makes it clear that it expects format de-DE.
As kumesana pointed out, Tomcat will use Locale.forLanguageTag() to convert the Accept-Language header value into a Locale. There is an opposite method to convert a Locale instance into the expected header String: toLanguageTag()
I would suggest using this rather than manually replacing underscore with hyphen, so your code would be like the following:
connection.setRequestProperty("Accept-Language", Locale.getDefault().toLanguageTag());
I'm trying to modify some server code which uses an httpExchangeobject to handle the server's response to the client.
My issue is that for responses containing characters not supported by iso-8859-1, such as Chinese characters, I get something like '????' in place of the characters. I'd like to set the encoding of the response to utf-8, but have thus far been unsuccessful in doing so.
I tried adding this line:
httpExchange.getResponseHeaders().put("charset", Arrays.asList("UTF-8"));
This successfully puts a "charset" header in the response, but I still can't send the characters I want in the response.
How do I set the encoding of the response to allow for these characters?
Use Content-Type header to specify encoding.
String encoding = "UTF-8";
httpExchange.getResponseHeaders().set("Content-Type", "text/html; charset=" + encoding);
Writer out = new OutputStreamWriter(httpExchange.getResponseBody(), encoding));
out.write(something);
ServletRequest.setCharacterEncoding() only affects Parameters submitted in the body of the request. It does not affect URL-Parameters.
JBoss is encoding URL-Parameters with ISO-8859-1 as default and this can only be changed server-wide.
ServletRequest.getParameterMap() is returning a Map filled with both - form-data from the request-body and URL-Parameters. So if I recive form-data endoded with UTF-8 and URL-Parameters I will find different endodings in the parameter-map.
What I'm doing now is parsing HttpServletRequest.getQueryString() with URLEncodedUtils and overwriting every parameter in the requestParameterMap which comes from the queryString.
Is there a better way to solve this problem?
I am talking to a file upload service that accepts post data, not form data. By default, java's HttpURLConnection sets the Content-Type header to application/x-www-form-urlencoded. this is obviously wrong if i'm posting pure data.
I (the client) don't know the content type. I don't want the Content-Type header set at all. the service has a feature where it will guess at the content type (based on the file name, reading some data from the file, etc).
How do I unset a header? There's no remove header, and setting it to null doesn't change the value and setting it to the empty string results in the header being set with no value.
I haven't tested this approach but you can try this:
Extend HttpURLConnection and try by overriding its getContentHandler() and setContentHandler(...) methods. Most probably this should work as, you will take a look at code of getContentHandler().
Use Apache HttpClient instead of URLConnection
Use fluent Request to generate your request
use removeHeader()
What do you mean "i don't want the Content-Type header to set at all"?
The browser (or other http client) sends your post request to the server, so it has to inform the server which way it encoded the parameters.
If the Content-Type header is not set, on the server side you (= your server) won't be able to understand how to parse the received data.
If you didn't set Content-Type, the default value will be used.
You browser (or other http client) MUST do two things:
Send key/value pairs.
Inform the server how the key/value pairs were encoded.
So, it is impossible to completely get rid of this header.
I just accomplished this by setting the header to null.
connection.setRequestProperty(MY_HEADER, null);
i want to send arabic data from servlet using HTTPServletResponse to client
i am trying this
response.setCharacterEncoding("UTF-8");
response.setHeader("Info", arabicWord);
and i receive the word like this
String arabicWord = response.getHeader("Info");
in client(receiving) also tried this
byte[]d = response.getHeader("Info").getBytes("UTF-8");
arabicWord = new String(d);
but seems like there is no unicode because i receive strange english words,so please how can i send and receive arabic utf8 words?
HTTP headers doesn't support UTF-8. They officially support ISO-8859-1 only. See also RFC 2616 section 2:
Words of *TEXT MAY contain characters from character sets other than ISO- 8859-1 [22] only when encoded according to the rules of RFC 2047 [14].
Your best bet is to URL-encode and decode them.
response.setHeader("Info", URLEncoder.encode(arabicWord, "UTF-8"));
and
String arabicWord = URLDecoder.decode(response.getHeader("Info"), "UTF-8");
URL-encoding will transform them into %nn format which is perfectly valid ISO-8859-1. Note that the data sent in the headers may have size limitations. Rather send it in the response body instead, in plain text, JSON, CSV or XML format. Using custom HTTP headers this way is namely a design smell.
I don't know where word variable is comming from, but try this:
arabicWord = new String(d, "UTF-8");
UPDATE: Looks like the problem is with UTF-8 encoded data in HTTP headers, see: HTTP headers encoding/decoding in Java for detailed discussion.