UTF-8 encoded characters from REST-query not rendered properly - rest

I'm consuming an external REST service that provides all content as UTF-8 encoded.
For some reason my application cannot properly handle the response. If I dump the response I will se things like LuleÃ¥ (should be Luleå).
EDIT:
The same behavior happens if i forward (without altering) the string to the UI, ex.:
flash.message = "Test" + integrationService.testEncoding()
What I did was to create a _Events.groovy file in the /script folder and specifying there that
eventConfigureTomcat = { tomcat ->
tomcat.connector.URIEncoding = "UTF-8"
tomcat.connector.useBodyEncodingForURI = true
}
I also have the following in my Config.groovy:
grails.views.gsp.encoding = "UTF-8"
grails.converters.encoding = "UTF-8"
But that changed nothing. The response is still wrongly shown. I'm not sure if this is a configuration issue with Grails, with the embedded tomcat or with something else. I'm currently running my test setup on windows 7, but the same issue happens on my server running on Centos. Please advice.
EDIT2:
If i consume the REST service using curl, everything is rendered correctly in the output.
EDIT3:
I'm using org.springframework.web.client.RestTemplate and HttpComponents to consume the service:
private static final HttpHeaders requestHeaders
static{
requestHeaders = new HttpHeaders()
requestHeaders.set(HttpHeaders.CONTENT_TYPE, "application/json")
requestHeaders.set(HttpHeaders.ACCEPT, "application/json")
requestHeaders.set("Accept-Encoding", "gzip")
}
private final static RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(
HttpClientBuilder.create().build()))
...
...
public def testEncoding(){
ResponseEntity<String> response = restTemplate.exchange(
"https://www.url.com", HttpMethod.GET, new HttpEntity<Object>(requestHeaders),
String.class)
def gamesJson = JSON.parse(response.getBody())
//...
//parse value from gamesJson
//...
return testValue
}

Per my previous answer:
You just need to add the StringHttpMessageConverter to the template's message converters:
RestTemplate template = new RestTemplate();
template.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
ResponseEntity<Object> response = template.exchange(endpoint, method, entity,
Object.class);

The encoding type can be enforced in the environment itself.
JAVA_TOOL_OPTIONS -Dfile.encoding=UTF8 -Dclient.encoding.override=UTF-8
Just try setting the above encoding settings in windows/linux. I hope this should resolve the issue.
In this case, JVM will pickup the default encoding type from environment variable.

Our team experienced a similar issue before, we have a 3rd party service and they said their output is encoded in UTF-8. But the strings returned are still garbled. After a bit of testing, it turns out that they were returning ISO-8859-1 encoded strings. What we did was to decode/encode their input into UTF-8 encoded characters so we can use those properly.
For your case, I think this is a similar issue:
UTF-8: Luleå
ISO-8859-1: Luleå
In Java, we did something like this:
Charset initialEncoding = Charsets.ISO_8859_1;
Charset outputEncoding = Charsets.UTF_8;
byte[] byteArray = input.getBytes(initialEncoding);
String output = new String(new String(byteArray, outputEncoding));
In Groovy, I think you could do something like
import groovy.json.JsonSlurper;
def main = {
def response = '{"name":"Luleå"}'
def slurper = new JsonSlurper()
def result = slurper.parse(response.getBytes(), 'UTF-8')
println result.name // prints Luleå
}

The answer to my problem is already found on Stack Exchange.
You just need to add the StringHttpMessageConverter to the template's message converters:
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));

In my case that i had the same problem with contents received from my REST web service from the server and not my local enviroment.
I had search a lot and finally i found a solution that resolved my issue.
In Windows I added a new environment variable with key: JAVA_TOOL_OPTIONS and set its value to: -Dfile.encoding=UTF8.
The (Java) System property will be set automatically every time a JVM is started. You will know that the parameter has been picked up because the following message will be posted to System.err:
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8

Related

Spring RestTemplate POST file with UTF-8 filename

I'm using Spring RestTemplate to perform POST request sending a PDF file. The filename contains some UTF-8 characters (e.g. é, è, à, ê, ë).
The problem is that after sending the request, on the other side where the request is received, the filename doesn't have the expected UTF-8 characters, and I have something like ?popi?.pdf instead.
I've tried to explicitly set UTF-8 charset in RestTemplate, but it still doesn't work.
Here is my code,
public SomeThing storeFile(InputStream content, String fileName) {
Charset utf8 = Charset.forName("UTF-8");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headersFile = new HttpHeaders();
headersFile.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headersFile.setContentDispositionFormData("file", fileName);
List<Charset> listCharSet = new ArrayList<Charset>();
listCharSet.add(utf8);
headersFile.setAcceptCharset(listCharSet);
InputStreamResource inputStreamResource = new InputStreamResource(content);
HttpEntity<InputStreamResource> requestEntityFile = new HttpEntity<>(inputStreamResource, headersFile);
MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();
multipartRequest.add("file", requestEntityFile);
RestTemplate newRestTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
HttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
newRestTemplate.getMessageConverters().add(0, stringHttpMessageConverter);
newRestTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
FormHttpMessageConverter convForm = new FormHttpMessageConverter();
convForm.setCharset(utf8);
newRestTemplate.getMessageConverters().add(convForm);
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(multipartRequest, header);
ResponseEntity<String> result = newRestTemplate.postForEntity(env.getProperty("core.endpoint") + "/documents", requestEntity, String.class);
}
according to rfc7578 when you POST a file with multipart/form-data you should use "percent-encoding" instead of filename*
NOTE: The encoding method described in [RFC5987], which would add a
"filename*" parameter to the Content-Disposition header field, MUST NOT be used.
it could be easyly realesed:
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(0, new FormHttpMessageConverter() {
#Override
protected String getFilename(Object part) {
if (part instanceof Resource) {
Resource resource = (Resource) part;
try {
return URLEncoder.encode(resource.getFilename(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
} else {
return null;
}
}
});
Most likely the file encoding's system property of the used JVM hasn't been explicitly set, meanwhile the operating system where JVM runs is not using UTF-8 as the default charset. For instance, if JVM runs on Windows, and we don't specify the charset, the default value will be Windows-1252 instead.
Could you double check the JVM arguments of both applications that send and receive the file? Please ensure that it has -Dfile.encoding=UTF-8 argument before specifying the main class name.
Please also ensure that the application/service which receives the file has been configured to accept UTF-8 charset.
Feel free to also check the other possible related answers, if adding the file.encoding argument on JVMs doesn't help solving the problem,
How to get UTF-8 working in Java webapps?
Spring MVC UTF-8
Encoding

Serving static /public/ file from Play 2 Scala controller

What is the preferred method to serve a static file from a Play Framework 2 Scala controller?
The file is bundled with my application, so it's not possible to hardcode a filesystem absolute /path/to/the/file, because its location depends on where the Play app happens to be installeld.
The file is placed in the public/ dir, but not in app/assets/, because I don't want Play to compile it.
(The reason I don't simply add a route to that file, is that one needs to login before accessing that file, otherwise it's of no use.)
Here is what I've done so far, but this breaks on my production server.
object Application ...
def viewAdminPage = Action ... {
... authorization ...
val adminPageFile = Play.getFile("/public/admin/index.html")
Ok.sendFile(adminPageFile, inline = true)
}
And in my routes file, I have this line:
GET /-/admin/ controllers.Application.viewAdminPage
The problem is that on my production server, this error happens:
FileNotFoundException: app1/public/admin/index.html
Is there some other method, rather than Play.getFile and OK.sendFile, to specify which file to serve? That never breaks in production?
(My app is installed in /some-dir/app1/ and I start it from /some-dir/ (without app1/) — perhaps everything would work if I instead started the app from /some-dir/app1/. But I'd like to know how one "should" do, to serve a static file from inside a controller? So that everything always works also on the production servers, regardless of from where I happen to start the application)
Check Streaming HTTP responses doc
def index = Action {
Ok.sendFile(
content = new java.io.File("/tmp/fileToServe.pdf"),
fileName = _ => "termsOfService.pdf"
)
}
You can add some random string to the fileName (individual for each logged user) to avoid sharing download link between authenticated and non-authinticated users and also make advanced download stats.
I did this: (but see the Update below!)
val fileUrl: java.net.URL = this.getClass().getResource("/public/admin/file.html")
val file = new java.io.File(adminPageUrl.toURI())
Ok.sendFile(file, inline = true)
(this is the controller, which is (and must be) located in the same package as the file that's being served.)
Here is a related question: open resource with relative path in java
Update
Accessing the file via an URI causes an error: IllegalArgumentException: URI is not hierarchical, if the file is then located inside a JAR, which is the case if you run Play like so: play stage and then target/start.
So instead I read the file as a stream, converted it to a String, and sent that string as HTML:
val adminPageFileString: String = {
// In prod builds, the file is embedded in a JAR, and accessing it via
// an URI causes an IllegalArgumentException: "URI is not hierarchical".
// So use a stream instead.
val adminPageStream: java.io.InputStream =
this.getClass().getResourceAsStream("/public/admin/index.html")
io.Source.fromInputStream(adminPageStream).mkString("")
}
...
return Ok(adminPageFileString) as HTML
Play has a built-in method for this:
Ok.sendResource("public/admin/file.html", classLoader)
You can obtain a classloader from an injected Environment with environment.classLoader or from this.getClass.getClassLoader.
The manual approach for this is the following:
val url = Play.resource(file)
url.map { url =>
val stream = url.openStream()
val length = stream.available
val resourceData = Enumerator.fromStream(stream)
val headers = Map(
CONTENT_LENGTH -> length.toString,
CONTENT_TYPE -> MimeTypes.forFileName(file).getOrElse(BINARY),
CONTENT_DISPOSITION -> s"""attachment; filename="$name"""")
SimpleResult(
header = ResponseHeader(OK, headers),
body = resourceData)
The equivalent using the assets controller is this:
val name = "someName.ext"
val response = Assets.at("/public", name)(request)
response
.withHeaders(CONTENT_DISPOSITION -> s"""attachment; filename="$name"""")
Another variant, without using a String, but by streaming the file content:
def myStaticRessource() = Action { implicit request =>
val contentStream = this.getClass.getResourceAsStream("/public/content.html")
Ok.chunked(Enumerator.fromStream(contentStream)).as(HTML)
}

HttpClient Response Message Size

I have a webapi
public ISearchProviderCommandResult ExecuteCommand(ISearchProviderCommand searchCommand)
{
//serialize the object before sending it in
JavaScriptSerializer serializer = new JavaScriptSerializer();
string jsonInput = serializer.Serialize(searchCommand);
HttpClient httpClient = new HttpClient() { BaseAddress = new Uri(ServiceUrl), MaxResponseContentBufferSize = 256000 };
StringContent content = new StringContent(jsonInput, Encoding.UTF8, "application/json");
HttpResponseMessage output = httpClient.PostAsync(ServiceUrl, content).Result;
//deserialize the output of the webapi call
SearchProviderCommandResult searchResult = serializer.Deserialize<SearchProviderCommandResult>(output.Content.ReadAsStringAsync().Result);
return searchResult;
}
on my local machine whether I set the MaxResponseContentBufferSize or not, it seems to retrieve data the way I want it. However on our build environment, If I dont set the MaxResponseContentBufferSize , I get this error:
Cannot write more bytes to the buffer than the configured maximum buffer size: 65536.
After looking on google, I decided to set the MaxResponseContentBufferSize to an arbitrary 256000 value. Even though this works on my local machine, on the build box I get this error:
Method not found: 'Void System.Net.Http.HttpClient.set_MaxResponseContentBufferSize(Int64)
I have no idea what to do now.
Look at this thread on forums.asp.net. It seems there is some issue with .net 4.5 beta version on your build environment. There is surely a mismatch of dlls on your local and your build environment

How can I read SOAP-Headers and add FaultHeaders to a response sent by an AXIS 2 Web Service

I have a WSDL that defines a custom SOAP-header that the client needs to send and a SOAP-Fault header that the server could send as a response.
Now I have a problem. I cannot for the life of me fathom how to set SOAP-Fault-headers on a response generated with AXIS 2 (Version 1.6.1) or read SOAP-Headers that come with a request.
Can anyone point me in the right direction?
Thank you very much in advance.
If is security related you should look to Rampart.
If not, try looking into
ClientSide:
From your stub, retrieve the ServiceClient via _getServiceClient().
enter link description here
ServerSide:
If I recall correctly is done via MessageContext, so from axiscontext opbtain current message context.
Add custom fault to soap response. This can be done in one of two ways.
1) Simply throwing a Java exception with a message will generate a simple Axis2 fault
Example:
throw new java.lang.UnsupportedOperationException("Please implement " +
this.getClass().getName() + "#SomeOperationName");
Also please note: If you generated your service using the Axis2 WSDL2JAVA utility, the line above will be added to the MyServiceName_Skeleton source for each defined WSDL Operation.
Once the .aar is deployed, connectivity to each operation can be verified using a web browser, e.g. https://server:port/axis2/services/MyServiceName?SomeOperationName.
2) Ensure that the WSDL defines an optional (occurs:0) custom Fault structure. This can be sent to client with any other required (and empty) elements.
Example:
com.some.service.operation.SomeOperationNameResponse_Type OPRT = new com.some.service.operation.SomeOperationNameResponse_Type();
com.some.service.SomeOperationNameResponse OPR = new com.some.service.SomeOperationNameResponse();
.
.
.
if ((rcStatusString.equals("Succeeded")) || (rcStatusString.equals("Warning"))) {
<build happy path response>
} else if (rcStatusString.equals("Failed")) {
final MYFault fault = new MYFault();
final MYFault_Type faultType = new MYFault_Type();
final MYFaultList faultList = new MYFaultList();
final MYFaultList_Type faultListType = new MYFaultList_Type();
faultType.setFaultCode("10100");
faultType.setFaultSubcode("9999");
faultType.setFaultType(FaultType_Enum.SYSTEM);
faultType.setFaultReasonText("Some Operation Failed");
faultType.setSeverity(FaultSeverity_Enum.CRITICAL_ERROR);
//fault.setMYFault(faultType);
faultListType.addMYFault(faultType);
OTHRTYPE.setAValue("");
OPRT.setAValueType(OTHRTYPE);
OPRT.setMYFaultList(faultListType);
} else {
throw new java.lang.UnsupportedOperationException(
"MYSERVICE: [Some Operation] Session: "+sessVal+" Request ID: "+rcRequestId+" Unrecognized Completion Status ["+rcStatusString+"]");
}
OPR.setSomeOperationResponse(OPRT);
return OPR;
}

How do I handle/fix "Error getting response stream (ReadDone2): ReceiveFailure" when using MonoTouch?

I am using MonoTouch to build an iPhone app. In the app I am making Web Requests to pull back information from the web services running on our server.
This is my method to build the request:
public static HttpWebRequest CreateRequest(string serviceUrl, string methodName, JsonObject methodArgs)
{
string body = "";
body = methodArgs.ToString();
HttpWebRequest request = WebRequest.Create(serviceUrl) as HttpWebRequest;
request.ContentLength = body.Length; // Set type to POST
request.Method = "POST";
request.ContentType = "text/json";
request.Headers.Add("X-JSON-RPC", methodName);
StreamWriter strm = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
strm.Write(body);
strm.Close();
return request;
}
Then I call it like this:
var request = CreateRequest(URL, METHOD_NAME, args);
request.BeginGetResponse (new AsyncCallback(ProcessResponse), request);
And ProcessResponse looks like this:
private void ProcessResponse(IAsyncResult result)
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result)) // this is where the exception gets thrown
{
using (StreamReader strm = new System.IO.StreamReader(response.GetResponseStream()))
{
JsonValue value = JsonObject.Load(strm);
// do stuff...
strm.Close();
} // using
response.Close();
} // using
Busy = false;
}
catch(Exception e)
{
Console.Error.WriteLine (e.Message);
}
}
There is another question about this issue for Monodroid and the answer there suggested explicitly closing the output stream. I tried this but it doesn't solve the problem. I am still getting a lot of ReadDone2 errors occurring.
My workaround at the moment involves just re-submitting the Web Request if an error occurs and the second attempt seems to work in most cases. These errors only happen when I am testing on the phone itself and never occur when using the Simulator.
Whenever possible try to use WebClient since it will deal automatically with a lot of details (including streams). It also makes it easier to make your request async which is often helpful for not blocking the UI.
E.g. WebClient.UploadDataAsync looks like a good replacement for the above. You will get the data, when received from the UploadDataCompleted event (sample here).
Also are you sure your request is always and only using System.Text.Encoding.ASCII ? using System.Text.Encoding.UTF8 is often usedm, by default, since it will represent more characters.
UPDATE: If you send or receive large amount to byte[] (or string) then you should look at using OpenWriteAsync method and OpenWriteCompleted event.
This is a bug in Mono, please see https://bugzilla.xamarin.com/show_bug.cgi?id=19673