I am using graph API of Facebook and I call it through camel framework. My query has non ASCII characters (e.g. küçük). I am getting the following exception:-
Cause:
org.apache.commons.httpclient.URIException: Invalid query
at org.apache.commons.httpclient.URI.parseUriReference(URI.java:2049)
at org.apache.commons.httpclient.URI.<init>(URI.java:147)
at org.apache.commons.httpclient.HttpMethodBase.getURI
at org.apache.commons.httpclient.HttpClient.executeMethod
at org.apache.commons.httpclient.HttpClient.executeMethod
at org.apache.camel.component.http.HttpProducer.executeMethod
at org.apache.camel.component.http.HttpProducer.process
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:122)
Does camel support non ASCII characters in URI? If not, what other things can be done?
example URL: https://graph.facebook.com/?ids=http://www.example.com/küçük
"URL encoding replaces non ASCII characters with a "%" followed by hexadecimal digits." (more info here)
You could try this:
URL url = new URL(uri.toASCIIString());
or maybe
String xstr = URLEncoder.encode("维", "utf-8");
So this is what we were able to do to fix the issue.
In Apache Camel, the HTTP_URI component does not accept any special characters, even after encoding them. This is a bug in Camel which is not yet closed.
Fortunately for us, the special characters would only appear in the Query String of the URL and not the main URI part. Camel provides another component HTTP_QUERY, which can successfully parse and understand encoded UTF-8 characters. By setting it in the Header, we were able to get rid of the issue.
So basically first we encode the URL to UTF-8 and then set the HTTP_QUERY value as query string. This worked like charm.
e.g. (Scala)
.setHeader(Exchange.HTTP_QUERY, _.in[HttpRequest].uri.split(?).head)
.setHeader(Exchange.HTTP_URI, _.in[HttpRequest].uri)
Use encodeURIComponent(url) it will work
Related
I'm trying to upload a file using multipart/form-data to a Camel route.
All is good, however, I can't get the original file name.
Camel version is: 3.14.1
Update
With the following modification to the route. I managed to process binary files (getting the file name and storing them). However, with text files, the file is appended with the boundary footer:
------WebKitFormBoundary7BH9nQ2RqDXvTRAJ--
The route definition:
rest("/v1/file-upload-form")
.post()
.consumes(MediaType.MULTIPART_FORM_DATA_VALUE)
.route()
.process((exchange) -> {
InputStream is = exchange.getIn().getBody(InputStream.class);
MimeBodyPart mimeMessage = new MimeBodyPart(is);
DataHandler dh = mimeMessage.getDataHandler();
exchange.getIn().setBody(dh.getInputStream());
exchange.getIn().setHeader(Exchange.FILE_NAME, dh.getName());
})
.to("file://" + incomingFolder);
Thank you in advance
Edwardo
Edit: Since you have everything else already working, I'd recommend the Stream Caching option.
As Nicolas suggested, checkout Camel's MIME Multipart data format.
Also, the reason you're getting "Missing start boundary" is because your processor is consuming the InputStream. You can try to reset() it, but it might be better to just consume the InputStream once, or enable Stream Caching.
Instead of stream caching, you could also just convert the stream to a string. Before your processor, add:
.convertBodyTo(String.class)
The string can be read over and over. If you still get the missing start boundary error, try logging the body before the unmarshal operation. Make sure the message is intact and that it indeed contains the start boundary.
I have the following route in my AngularJS application
var accountactivation = {
name: 'accountactivation',
url: '/activate/:code',
templateUrl: 'views/account/activation.html',
controller: 'AccountActivationController',
authenticate: false
};
Added like this to the router
$stateProvider.state(accountactivation)
This is a account activation system, where :code is the activation code. This code is URL encoded.
The problem : sometime :code contains % character. Then the navigator is redirected to login instead of displaying the account activation page.
Example of routes
http://localhost:9000/#!/activate/c43q6zb2 works correctly
http://localhost:9000/#!/activate/c43q6zb2% is redirected to login (sometimes lead to a blank page)
http://localhost:9000/#!/activate/c43q6zb2Fxb%2FxQkjc2qnjc39QEYTQtpVmgWbw2gzNII0z8QRFrRhz%2FNC4LxzqBIYw5tqM9NaY8ejTxIRXQCfTh8hFszyARL%2Ff9MoOp2MvzNulqefVczsuGpZA8RZArQk doesn't work either
Is it possible to allow angularjs routes to have parameters containing prcentages signs ?
How I encode my activation key : For info, I'm using java URLEncoder with UTF-8 encoding charset
Thank you for your help :)
https://en.wikipedia.org/wiki/Percent-encoding
Because the percent character ( % ) serves as the indicator for percent-encoded octets, it must be percent-encoded as %25 for that octet to be used as data within a URI.
So it seems your URI is invalid with just a %. You need to encode it properly. Either use %25 so it will decode as %, or remove it...
My website has a search form where someone can search a URL beginning with http:// like this:
https://www.google.com
which should then be encoded and appended as a query parameter value like this:
localhost:4000/api/https%3A%2F%2Fwww.google.com
When I run it (above) locally, it works, but when deployed (below):
https://api.mysite.com/search/api/https%3A%2F%2Fwww.google.com%2F
=> returns 404.
If I type this in:
http://localhost:4000/api/https://www.google.com
I get this error:
Phoenix.Router.NoRouteError at GET /api/v1/https://www.google.com
no route found for GET /api/v1/https:/www.google.com (ExternalPing.Router)
I'm not sure if these are related. What is the correct way to append a url as a query parameter value?
I have already tried encoding with URI.encode and URI.encode_www_form but they didn't resolve this
Now you haven't posted your server code, so I am just going to assume here.
I think the problem is that you didn't encode the second string, since it contains / in the url you have problems.
The url is:
http://localhost:4000/api/https://www.google.com
The server will interpret it wrong. So you are asking for a route called:
/api/https:/
With a parameter called /www.google.com
You need to encode the query string.
But again this is guessing since I have no idea how your server looks.
I just tried calling an endpoint at my iis server with a unencoded url as a parameter, and this is what it gave me back:
<Error>
<Message>The request is invalid.</Message>
</Error>
Backbone keeps decoding my query string params. For example when I do
var query_string = encodeURIComponent('New York')
Backbone.history.navigate('search?location='+query_string, {trigger: true})
I get an URL with path:
/#search?location=New York
instead of
/#search?location=New%20York
I'm not using pushState and I've read that in 1.0.0 version he decodes the fragment in the URL. So any suggestions how can I achieve this, or something similar maybe?
Unicode characters in location.pathname are percent encoded so they're
decoded for comparison.
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1587
You might have to fork the library and remove or modify decodeFragment method.
I have a simple Restlet service hosted on AppEngine. This performs basic CRUD operations with strings and is working well with all sorts of UTF-8 characters when I test it with curl (for all the verbs).
This is consumed by a simple restlet client hosted in a servlet on another AppEngine app:
// set response type
resp.setContentType("application/json");
// Create the client resource
ClientResource resource = new ClientResource(Messages.SERVICE_URL + "myentity/id");
// Customize the referrer property
resource.setReferrerRef("myapp");
// Write the response
resource.get().write(resp.getWriter());
The above is pretty much all I have in the servlet. Very plain.
The servlet is invoked via jquery ajax, and the json that I get back is well formed and everything, but the problem is that UTF-8 encoded strings are coming back scrambled, for example:
Université de Montréal becomes Universit?? de Montr??al.
I tried adding this line in the servlet (before everything else):
resp.setCharacterEncoding("UTF-8");
But the only diference is that instead of getting ?? I get Universitᅢᄅ de Montrᅢᄅal (I don't even know what kind of characters those are, asian I suppose).
I am 100% sure the restlet service is OK, because other than debugging it line by line I am able to test it from cmd line with curl and it's returning well formed strings.
By looking at the http header of the response from firefox (when calling the servlet via javascript) I can see the encoding is indeed UTF-8, as expected. After hours of struggling reading every possible related article I came across this restlet discussion and noticed that indeed I do have Transfer-Encoding: chunked on the http header of the response. I tried the proposed solutions (override ClientResource.toRepresentation, didn't do any good so I tried restlet 2.1 as susggested with ClientResource.setRequestEntityBuffering(true), no luck there either) but I am not convinced my issue is related to Transfer-Encoding: chunked at all.
At this point I am out of ideas, and I would really appreciate any suggestions! O_o
UPDATE:
I tried doing a manual GET with a classic UrlConnection and the string is coming back alright:
URL url = new URL(Messages.SERVICE_URL + "myentity/id");
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
resp.getWriter().print(writer.toString());
So much for being all RESTful and fancy ...but still I have no clue why the original version doesn't work! :/
I tried doing a manual GET with a classic UrlConnection and the string is coming back alright:
URL url = new URL(Messages.SERVICE_URL + "myentity/id");
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
resp.getWriter().print(writer.toString());
So much for being all RESTful and fancy ...but still I have no clue why the original version doesn't work! :/
Does your response contain the appropriate "Content-Type" header? It should be something like "Content-Type: application/json; charset=UTF-8" (note the charset).
Try starting your development server and retrieving your resource from the command line using cURL and inspecting the headers, e.g. curl -i http://localhost:8080/myentity/id. In theory browsers should assume UTF-8 for JSON, but I wouldn't trust on that.