I'm trying to make a POST request using JSON with foreign characters, such as the Spanish n with the '~' over it, but I keep getting this request and response error:
POST ...
Accept: application/json
Content-Type: application/json; charset=UTF-8
Content-Length: 151
Content-Encoding: UTF-8
Host: ...
Connection: Keep-Alive
User-Agent: ..
{"numbers":"2","date":"2014-07-15T00:00:00+0000","description":" // this never gets closed
X-Powered-By: ...
Set-Cookie: ...
Cache-Control: ...
Date: Tue, 15 Jul 2014 15:19:12 GMT
Content-Type: application/json
Allow: GET, POST
{"status":"error",
"status_code":400,
"status_text":"Bad Request",
"current_content":"",
"message":"Could not decode JSON, malformed UTF-8 characters (incorrectly encoded?)"}
I can already make a successful POST request with normal ASCII characters, but now that I'm supporting foreign languages, I need to convert the foreign characters to UTF-8 (or whatever the correct encoding ends up being), unless there's a better way to do this.
Here's my code:
JSONObject jsonObject = new JSONObject();
HttpResponse resp = null;
String urlrest = // some url;
HttpPost p = new HttpPost(urlrest);
HttpClient hc = new DefaultHttpClient();
hc = sslClient(hc);
try
{
p.setHeader("Accept", "application/json");
p.setHeader("Content-Type", "application/json");
// setting TimeZone stuff
jsonObject.put("date", date);
jsonObject.put("description", description);
jsonObject.put("numbers", numbers);
String seStr = jsonObject.toString();
StringEntity se = new StringEntity(seStr);
// Answer: The above line becomes new StringEntity(seStr, "UTF-8");
Header encoding = se.getContentType();
se.setContentEncoding("UTF-8");
se.setContentType("application/json");
p.setEntity(se);
resp = hc.execute(p);
When I put a breakpoint and look at se before it's submitted, the characters look right.
UPDATE: code updated with answer a few lines above with a comment identifying it.
The new StringEntity constructor takes a "UTF-8" parameter.
Related
I have the following implementation to get token from form authentication.
The expected output is as follows:
However, when I run my implementation, I am getting as follows. In the response object, I do not see token. I am not an expert on Java, I wonder what I am missing.
Login form get: HTTP/1.1 200 OK
response: HttpResponseProxy{HTTP/1.1 200 OK [Cache-Control: max-age=0, Content-Type: application/json, Date: Fri, 04 Aug 2017 21:05:04 GMT, transaction_id: 729097fd-69ac-b813-26c7-015daf10ddfd, X-Powered-By: Express, Content-Length: 684, Connection: keep-alive] ResponseEntityProxy{[Content-Type: application/json,Content-Length: 684,Chunked: false]}}
Post logon cookies:
None
Here is the source code:
BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
HttpHost proxy = new HttpHost("xxx.xxx.xxx.com", 80, "http");
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
HttpUriRequest login = RequestBuilder.post()
.setUri(new URI("https://api.xxx.com:443/tokens"))
.addParameter("username", "stackoverflow")
.addParameter("password", "isbest!")
.setConfig(config)
.build();
CloseableHttpResponse response2 = httpclient.execute(login);
HttpEntity entity = response2.getEntity();
System.out.println("Login form get: " + response2.getStatusLine());
EntityUtils.consume(entity);
System.out.println("response: " + response2);
System.out.println("Post logon cookies:");
List<Cookie> cookies = cookieStore.getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
When you call EntityUtils#consume(HttpEntity), you are fully consuming the content of the response and closing the underlying stream. However, you haven't actually read the response data into any variable accessible by your code, so you no longer have any opportunity to look at it.
Instead, call one of the methods that fetches the response data. Options for this include HttpEntity#getContent() to access the response body as a raw InputStream or EntityUtils#toString(HttpEntity, Charset) to read the whole response body as a String. (In the latter case, be aware that reading the whole response body at once as a String will impact your process's memory footprint if the response body is large.) After calling either one of those, you can pass the retrieved content through your JSON parser of choice to retrieve the "token".
Once you're all done, it's still good practice to call EntityUtils#consume(HttpEntity) to guarantee cleanup of any underlying resources encapsulated by the entity, such as streams.
I am trying to post images to an confluence page as attachment to a content.
Here is the function of my java application:
public void postAttachment(File f, String comment) throws IOException {
if (!f.exists() || !f.canRead()) {
throw new IOException("Could not access file " + f.getAbsolutePath());
}
final FileBody bin = new FileBody(f);
final StringBody cmt = new StringBody(comment, ContentType.TEXT_PLAIN);
final HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("file", bin).addPart("comment", cmt).build();
final HttpPost post = new HttpPost(baseUrl + "/rest/api/content/" + contentid + "/child/attachment");
post.setEntity(reqEntity);
post.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(props.getString("confluence_user"),props.getString("confluence_password")), "UTF-8", false));
post.addHeader("X-Atlassian-Token:","no-check");
System.out.println("executing request " + post.getRequestLine());
final CloseableHttpClient httpclient = HttpClients.createDefault();
final CloseableHttpResponse response = httpclient.execute(post);
System.out.println(post.getRequestLine());
System.out.println(response.toString());
if (response.getStatusLine().getStatusCode() == 404) {
throw new IOException("Status 404 thrown!");
}
}
The output in the terminal is:
POST https://xxx.xxxx.de:443/rest/api/content/38262140/child/attachment
and then
HttpResponseProxy{HTTP/1.1 404 Not Found [Server: Apache-Coyote/1.1, X-ASEN: SEN-1343236, Set-Cookie: JSESSIONID=9DF46011711C2828977E17A945D023E1; Path=/; Secure; HttpOnly, X-Seraph-LoginReason: OK, X-AUSERNAME: xxxx, X-Content-Type-Options: nosniff, Content-Type: text/plain, Transfer-Encoding: chunked, Date: Tue, 27 Sep 2016 11:20:35 GMT] ResponseEntityProxy{[Content-Type: text/plain,Chunked: true]}}
(I changed the domain name and username just for this post..)
So all seems ok. If i copy the generated POST url and do a GET in the browser i get a json snippet with an attachment list, manually uploaded before. So the POST url should be ok.
I searched across the web but i cant find where i am wrong with my code.. Any Suggestions?
Confluence is strict in "X-Atlassian-Token" header value. You have extra : in header name.
Change
post.addHeader("X-Atlassian-Token:","no-check");
to
post.addHeader("X-Atlassian-Token","no-check");
This will create correct header, and 404 error will go away
I too am presently struggling to add attachments; now on to a 403 Forbidden...
I worked through my 404 finding that it was in my (bad) URL. However, your URL does appear correct. Any chance that Page ID is off or your authenticated user lacks permissions (globally, in the space, or at the page level)?
Edit: Oh! And, as mtheriault's post suggests, check the attachment size vis a vis your Confluence instance's "attachmentMaxSize".
I am trying to access this json file : http://www.cloudpricingcalculator.appspot.com/static/data/pricelist.json with Java.
But when I read it, sometimes it gives me a JSON string (that's ok) and sometimes it gives me something else and json.simple.parser throw an Unexpected character(<) at position 0.
Based on what I read on stackOverflow, it may be that it returns XML instead of JSON. As my url is "json", how is it possible ?
Here is the code i'm using :
String baseUrl = "http://www.cloudpricingcalculator.appspot.com/static/data/pricelist.json";
...
URL url = new URL(this.baseUrl);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String l;
String json = "";
System.out.println(url);
while((l=in.readLine()) != null){
System.out.println(l);
json+=l;
}
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(json);
and the log is <followed by an lot of squares and unknown characters like ÿÕ[s›È and an error Unexpected character () at position 0.
You are not taking into account the compression and encoding of the resource returned from the server. The response of a HEAD request is the following:
rpax#machine:~$ HEAD http://www.cloudpricingcalculator.appspot.com/static/data/pricelist.json
200 OK
Cache-Control: public, max-age=600
Connection: close
Date: Mon, 21 Aug 2017 12:02:14 GMT
Age: 112
ETag: "n_s_jQ"
Server: Google Frontend
Content-Encoding: gzip <---- *HERE*
Content-Length: 7902
Content-Type: application/json
Expires: Mon, 21 Aug 2017 12:12:14 GMT
...
For avoiding this issue, you can wrap the url stream into a GZIPInputStream :
GZIPInputStream gis = new GZIPInputStream(url.openStream());
BufferedReader in = new BufferedReader(new InputStreamReader(gis));
// ...
And the data returned when executing readline() will be decompressed.
I am using httpPut to java and I want to get the response code after I execute the command. What it gives me which is "response body" is:
HTTP/1.1 200 OK [Cache-Control: no-cache, no-store, must-revalidate, Pragma: no-cache, Expires: Thu, 01 Jan 1970 00:00:00 GMT, Content-Type: application/json, Transfer-Encoding: chunked, Server: Jetty(8.1.8.v20121106)]
But I only want 200! not the whole thing. Any help?
This is my code by the way:
String url = "http://localhost:80/api/clients/";
String clientID = "1234";
httpclient = new DefaultHttpClient();
HttpPut putRequest = new HttpPut(url + clientID);
putRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
putRequest.setHeader("Charset", "UTF-8");
System.out.println(putRequest);
// Add your data
putRequest.setEntity(new StringEntity(clientID, "UTF-8"));
HttpResponse responseBody = httpclient.execute(putRequest);
HTTPResonse having a method called getStatusLine() which return StatusLine Object.
And StatusLine have a method getStatusCode()
So, all you need to write is
HttpResponse responseBody = httpclient.execute(putRequest);
int resultCode = responseBody.getStatusLine().getStatusCode();//200 in your case
responseBody.getStatusLine().getStatusCode() should give you the responsecode of your request.
i'm trying to implements a POST request with HttpURLConnection. This is my code:
private static void call(String body) throws IOException{
HttpURLConnection con = null;
con = (HttpURLConnection)new URL("http://127.0.0.1:8080").openConnection();
con.setRequestProperty("Accept-Charset", "UTF-8");
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty("Accept", "application/json; charset=utf-8");
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(body);
wr.flush();
wr.close();
...
}
I post it to localhost just to sniff it with WireShark.
The problem is that when my body is a string containing characters like 'ò' 'à' 'è' 'ç' ... the request i see has le string correct with those characters replaced by dots.
example:
if body is "hèllo!" ---> the request body is "h.llo!"
Just for test i'm executing the above method in java main and i pass the parameter this way:
String pString = "{\"titlè\":\"Hèllo Wòrld!\"}";
String params = new String(pString.getBytes("UTF-8"),"UTF-8");
....
call(body);
and this is what i get in WireShark:
POST / HTTP/1.1
Accept-Charset: UTF-8
Content-Type: application/json; charset=utf-8
Accept: application/json; charset=utf-8
User-Agent: Java/1.6.0_43
Host: 127.0.0.1:8080
Connection: keep-alive
Content-Length: 24
{"titl.":"H.llo W.rld!"}
Any help would be appreciated.
Thank you
The internal string representation in Java is always UTF-16. So in your second example params = new String(pString.getBytes("UTF-8"),"UTF-8"); converts pString to a byte array with UTF-8 content and then back to UTF-16 which is stored in params.
Every encoding has to be done when strings enter or leave the VM. That means in your case you have to set the encoding when you write the body to the stream.
wr.write(body.getBytes("UTF-8"));