Posting JSON via AJAX accentuation problems - java

I'm having bad times when posting JSON via AJAX.
For testing purposes, the code below reproduces the problem, and was created in the Firefox Scratchpad (I'm using Backbone in the application layer):
var xhr = new XMLHttpRequest();
xhr.open("POST", "/my/api/url"); // could be PUT too
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({ test: "é" }));
Actually, no matter what accented string I use in my JSON, it's always sent incorrectly (I've tested in Firefox and Chrome, both latest versions) - I can see the request data wrong in Chrome DevTools/Firebug. What is sent in this case is é.
I have found an workaround in Java. I would not bother using it once or twice, however, seems like this is not going to be the case. There are still lots of stuff to do.
The workaround is the following:
test = new String(test.getBytes("ISO-8859-1"), "UTF-8");
Any further help would be appreciated.
My setup (if anyone needs):
Windows 7 x64
JDK 1.7 x64
JBoss 4.2.3
RESTEasy
MyEclipse 9.1
I'll be often updating this question with interesting data whenever they appear.

You are not passing the json properly
xhr.send(JSON.stringify({ test: "é" }));
also there should be qoutes for key like this { "test": "e" }
you can use variable
var jsonStr={ "test": "é" };
xhr.send(JSON.stringify(jsonStr));
I don't think you need to stringify json since you have set Content-Type to json, not sure about it though.
Hope it helped you...
Try sending the parameters this way
var params='json='+jsonStr;
xhr.send(params);

I've resolved my own problem. As I am using RESTEasy, one of my methods were using an interceptor MessageBodyReader. In this class, I was reading the body without using the request's encoding...
Was:
String body = new String(IOUtils.toByteArray(inputStream));
Become:
String body = new String(IOUtils.toByteArray(inputStream), request.getCharacterEncoding());

Related

Retrofit, IGDB Api - How to correctly pass Api Key?

I'm trying to make an query on the internet game database (IGDB) Api using retrofit. In the past, when I used other Api, such as the movie database (TMDB), the api-keys were always passed in as a query, so the interface would look something like this.
#GET("/3/movie/popular")
Call<MovieResults> getPopularMovie(
#Query("api_key") String apiKey,
#Query("language") String language,
#Query("page") int page
);
But with IGDB, I think they want me to pass in the api-key as a Header (I'm not 100% sure, please correct me if I'm wrong). I've never passed an api-key through a header before, so with some guesswork, following is what my interface looks like.
#Headers({
"Accept: application/json",
"user-key: b5bd50####################8b2"
})
#GET("/games")
Call<List<Game>> getGame();
Problem is, when I make the call, although the call ends up in onResponse, the response.body is always null.
So, I ran the code in de-bug mode, and i found this message:
response = Response{protocol=http/1.1, code=401, message=Unauthorized, url=http://v2000.igdb.com/games/}
I don't know what this means, but I am guessing that it isn't recognizing an authorised api-key?
Another interesting anomaly is that, the base url I pass in is:
"https://api-2445582011268.apicast.io/"
I don't know how that ended up being:
http://v2000.igdb.com/
If anyone have any experience with IGDB, please give me some help, will really appreciate it.
I have used this api with JAVA and i can confirm that you should send the API key in the header, so what you have done looks to be correct.
The base url you are getting is also wrong, try using https://api-endpoint.igdb.com/, it is the recommended url.
I can also recommend you to try the api using Postman, it is an excellent tool for testing.
If you are using java you might want to try their java wrapper

Java http post: Difference in reading bytes through curl and in java

I am stuck in a strange issue, I am posting some image data to a server, now I created the requested using curl and then traced back it.
Next was to create similar request in java.
The code posts raw binary image data to server, but when I compare the binary data in java to that posted by curl, there is a minute difference due to which I am getting 400 response code from server.
The difference I think is in few dots.
Below is the request generate by curl (linux).
Generate by curl
Now here is the request generate by Java, when I read bytes.
Click here
Java code looks something like this:
PrintWriter out = new PrintWriter(os);
out.println("POST /1izb0rx1 HTTP/1.1");
out.println("User-Agent: curl/7.35.0");
out.println("Host: requestb.in");
out.println("Accept: */*");
out.println("Content-Disposition:inline; filename=test.png");
out.println("Authorization: Basic YW5kcm9pZDpUZXN0dGVzdDExISE=");
out.println("Content-Length: "+"24143");
out.println("Content-Type: application/x-www-form-urlencoded");
out.println();
out.println("."+imgBytes);
Any idea what can be causing this issue ?
Thanks
So,
I got it working, the problem was that certain classes on Android are broken and not behaving as the way they behave on core Java.
The same code that was working on Java, wasn't working here, reason being, a change in header occurring here (On Android).
This issue is very well mentioned here also:
https://github.com/WP-API/WP-API/issues/1862
Thus I was facing a similar issue, and adding external updated jars were conflicting with the ones on Android.
Finally I used a small HTTP Request library: https://github.com/kevinsawicki/http-request
The code is below:
HttpRequest request = HttpRequest.post(url);
request.authorization("Basic "+ah);
request.part("file", fName+".png", "image/png", new File(file));
request.part("title", "test");
if(request.code()==201) {
StringWriter sw = new StringWriter();
request.receive(sw);
onMedia(Media.parse(new JsonParser().parse(sw.toString()).getAsJsonObject()));
}
Thanks
Do not use PrintWriter to send raw bytes.

How do I get Rest Assured to return the text (non-encrypted or streamed) value in my REST response?

I recently moved over to Java and am attempting to write some REST tests against the netflix REST service.
I'm having an issue in that my response using rest assured either wants to send a gzip encoded response or "InputStream", neither of which provide the actual XML text in the content of the response. I discovered the "Accept-Encoding" header yet making that blank doesn't seem to be the solution. With .Net I never had to mess with this and I can't seem to find the proper means of returning a human readable response.
My code:
RestAssured.baseURI = "http://api-public.netflix.com";
RestAssured.port = 80;
Response myResponse = given().header("Accept-Encoding", "").given().auth().oauth(consumerKey, consumerSecret, accessToken, secretToken).param("term", "star wars").get("/catalog/titles/autocomplete");
My response object has a "content" value with nothing but references to buffers, wrapped streams etc. Trying to get a ToString() of the response doesn't work. None of the examples I've seen seem to work in my case.
Any suggestions on what I'm doing wrong here?
This has worked for me:
given().config(RestAssured.config().decoderConfig(DecoderConfig.decoderConfig().noContentDecoders())).get(url)
I guess in Java land everything is returned as an input stream. Using a stream reader grabbed me the data I needed.
Until its version 1.9.0, Rest-assured has been providing by default in the requests the header "Accept-Encoding:gzip,deflate" with no way of changing it.
See
https://code.google.com/p/rest-assured/issues/detail?id=154
It works for me:
String responseJson = get("/languages/").asString();

Post JSON Data From Javascript To Java

I'm in need of some desperate help. I've been at this for 4 hours, and I'm getting pretty worn out. :/ Here's my situation:
I have a Javascript application that is making a POST request (using jQuery $.post) to an external site. On the external site I have Apache Camel running with Jetty to expose it to the web. The web services I wrote in Camel expect JSON data for all of the requests. For instance, one request needs an id, so I send it {"id": 10}.
Here's my issue: it doesn't work from Javascript. I have a few different tools that will send post requests for me (like the Poster extension for browsers). If I use Poster and set the body to {"id": 10}, it works just fine. I get that exact string in the service.
But, if I post from Javascript, I get something different. Posting the JSON object will give me the string "id=10" on my service side. (It's OK for this scenario, but I will need actual JSON objects eventually.) If I stringify the JSON object, I get the JSON string, only all of the characters are escaped. (Ex. "%7Bid%33...").
I swear I've tried every method possible for posting the data, but I either get the weird already parsed JSON, or the escaped string (or nothing at all). Is there some way I can have Javascript NOT parse the JSON object and just send it (like my posting tool does)? If not, is there a safe, efficient way to un-escape the JSON string that I get?
I really appreciate any help.
I feel like we need a little bit more information, but take a look at this javascript plugin. It may be your solution: https://github.com/flowersinthesand/jquery-stringifyJSON
Try using jQuery.ajax and setting processData to false (defaults to true):
$.ajax({
url: '/where/to/post',
type: 'POST',
data: {"id": 10},
processData: false
});
Usually, jQuery converts anything in data to query string format like id=10. The processData flag tells jQuery to interpret it literally as a json hashmap.
Posting the JSON object will give me the string "id=10" on my service side.
Javascript does not do your this conversion, so your server does it.
It is likely that your server reacts differently based on the content-type of your POST e.g. application/json vs text/plain or text/html, a common feature of REST based services.
The answers here gave me a few hints, but ultimately, it was a lot of tweaking before it would work correctly. I had to do 3 things:
Add processData: false.
Turn the JSON object into a JSON string. The request wouldn't fire if I left it as an object (even if I changed contentType to application/json).
Change the contentType to text/plain. This sent it as a raw string.
And that's what did the trick. I now get the JSON string I want on the server side.

Request methods on https-server

I don't know whether my title is correctly articulated, but I have following problem:
I have a self-written Java webserver, that handles incoming client requests. It works fine with all the request methods (GET, POST, HEAD, OPTIONS, DELETE, ...). It also works fine with sending files and stuff when I use http.
GET and POST also work when I call a page over https, but all the other request methods do not work (Nothing has changed within in the Javascript, that sends the requests to the server ... it just runs with SSL). I can't seem to find anything as to why that is the case. Do the request methods work differently when I add SSL? I thought it is merely an addition to make the communication more safe? Am I wrong?
EDIT: There are also differences between different browsers ... most don't even get to send the request, chrome got to readyState = 4 :( btw, I tested with Chrome 2.0, Firefox 3.0.11, Opera 9.63, IE7, IE8, Safari 3.2.1.
Hope someone can shed some light.
The request methods should work the same, as you expect be it HTTP or HTTPS.
It is really difficult for us to help you out because
you have a home grown web server which nobody knows but you, and
you've not included any error message from the client or logs from the server. "other request methods do not work" is just not descriptive enough. You are going to have to be much more detailed than that.
Assuming a connection issue, my I suggest you try your client on a well know web server to see if it can connect? The problem could be in the client.
The problem was in the call for the function!
The function is defined as follows:
function getHead( url, targetDiv ){
// generate the HTTPREQUESTOBJECT ... let's call it 'req'
req.open( "HEAD", url, true );
// some more magic happens with the response
}
I changed the call for the function from:
onclick="getHead( 'http://localhost/Home', 'optionsdiv' )
to:
onclick="getHead( 'localhost/Home', 'optionsdiv' )
The first call is of course only for http, not for https! so switching that made it work :)
Another method I found to work as well, was following: I add a try-catch like this:
try{
req.open( "HEAD", "https://"+url, true );
}
catch( err ){
req.open( "HEAD", "http://"+url, true );
}
Works almost perfectly on my end excpet the little browser-differences which drive me nuts!

Categories