Java Apache HTTPClient do not encode POST entity - java

I have an endpoint that requires an 'authenticity_token' that is in the format like:
Iq2rNXN+OxERv+s6TSloJfKkPZVvqnWe1m0NfODB5OI=
However, sometimes it has "special" characters, such as:
E7IzeP73OgPGgXM/up295ky1mMQMio2Nb8HMLxJFyfw=
This gets encoded to:
E7IzeP73OgPGgXM%26%2347%3Bup295ky1mMQMio2Nb8HMLxJFyfw%3D
For some reason, the endpoint does not like the encoding of those special characters and will think the token is invalid. Is it possible to add a POST variable that does not encode specific values? I am currently doing something like:
HttpPost post = new HttpPost(URL + NEW_FINDING);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("foo", foo));
nvps.add(new BasicNameValuePair("authenticity_token", authenticityToken));
post.setEntity(new UrlEncodedFormEntity(nvps));

You can always use ByteArrayEntity or StringEntity instead of UrlEncodedFormEntity and do the encoding yourself. It should look something like foo=var1&bar=var2.
You have to set Content-Type=application/x-www-form-urlencoded
You may want to find out what your endpoint expects as a charset parameter for the application/x-www-form-urlencoded value of the Content-Type header. Then pass it as a parameter to the UrlEncodedFormEntity constructor. This should be the right fix.

Related

How to make Java HttpPost NOT include url in body

We have some old java code that POSTs some fields and values to a dotnet5 web api - The api is having problems dealing with the body of the POST as it includes the url/uri as the first part of the body.
The Java sends: http://127.0.0.1:5555?producerRef=GREEN&systemId=78&status=false
But the api is expecting something like: producerRef=GREEN&systemId=78&status=false
as per https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST#example. If we send a test message via Postman then the api has no problems.
This is the Java code:
List<NameValuePair> params = new ArrayList<NameValuePair>(queryParams.size());
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
// the address is just that, there's NO parameters
HttpPost post = new HttpPost(this.cmAddress.toURI());
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
post.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
CloseableHttpResponse response = httpClient.execute(post);
It's quite simple, but always adds the url to the start of the body of the request. If this is the only way to produce this, what could I do to produce something that looks like this: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST#example
Many Thanks.
This request seems like a GET request rather than a POST since the request params are in the URL. i don't know about the specifications of the Api you're using, but you can try OKHTTP, you can easily copy the code directly from postman
Postman Get example:
Your issue seems to be at below line
HttpPost post = new HttpPost(this.cmAddress.toURI());
This is the only place which will set the POST url ( another way is to use setURI which is not called anywhere in the code sample you have shared).
If you can use a debugger try checking the value of cmAdress variable

How do I add UrlEncodedFormEntity to a MultipartEntityBuilder

I have a file that I want to upload so I have your standard MultipartEntityBuilder like this:
MultipartEntityBuilder multiPartEntity = MultipartEntityBuilder.create();
multiPartEntity.addBinaryBody("file", file);
I also have some form params that I send with the POST like this:
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("userId",userId));
postParameters.add(new BasicNameValuePair("taskId",taskId));
new UrlEncodedFormEntity(postParameters)
Both work individually, My question how do I do both in one call? I need to fold one into the other so I can make this in one HttpPost() call.
You seem to be confusing the application/x-www-form-urlencoded and multipart/form-data content types. When sending a multipart request, you are using multipart/form-data, in which case you don't need to URL encode the content. Just set the text directly
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.addBinaryBody("file", file);
multipartEntityBuilder.addTextBody("userId", "someIdWith#url$encodable<>characters");
See the specification for more details.

How can i change charset encoding in HTTP response in Java

I have to fetch some JSON object from a remote server and for that i am using this function which is working great except that for sometime some weird data is getting fetched which i believe is because it is using ASCII charset to decode.
Please find below thw method that i am using
public HttpResponse call(String serviceURL,String serviceHost,String namespace,String methodName,String payloadKey, String payloadValue) throws ClientProtocolException,IOException,JSONException
{
HttpResponse response = null;
HttpContext HTTP_CONTEXT = new BasicHttpContext();
HTTP_CONTEXT.setAttribute(CoreProtocolPNames.USER_AGENT, "Mozilla/5.0");
HttpPost httppost = new HttpPost(serviceURL);
httppost.setHeader("User-Agent",Constants.USER_AGENT_BROWSER_FIREFOX);
httppost.setHeader("Accept", "application/json, text/javascript, */*");
httppost.setHeader("Accept-Language","en-US,en;q=0.8");
httppost.setHeader("Content-Encoding", "foo-1.0");
httppost.setHeader("Content-Type", "application/json; charset=UTF-8");
httppost.setHeader("X-Requested-With","XMLHttpRequest");
httppost.setHeader("Host",serviceHost);
httppost.setHeader("X-Foo-Target", String.format("%s.%s", namespace,methodName));
/*Making Payload*/
JSONObject objectForPayload = new JSONObject();
objectForPayload.put(payloadKey, payloadValue);
StringEntity stringentity = new StringEntity(objectForPayload.toString());
httppost.setEntity(stringentity);
response = client.execute(httppost);
return response;
}
All these headers that i am passing are correct and i have verified the same via inspect element in Google chrome or Firebug plugin if you are familiar with Mozilla.
Now the problem is that most of the time i am getting the readable data but sometimes i do get unreadable data.
I debugged using eclipse and noticed that the charset under wrappedEntity is showing as "US-ASCII". I am attaching a jpg for reference
Can someone please tell me how can i change the charset from ASCII to UTF-8 of the response before i do response = client.execute(httppost); .
PS:As you have noticed that i am passing charset=utf-8 in the header and that i have already verified using firebug and google chrome that i am passing the exact headers .
Please zoom in to see the image more clearly
Thanks in advance
i was able to resolve the issue just mentioning it for people that may face similar issue.
after getting the response first get the entity by using
HttpEntity entity = response.getEntity();
and since my response was a json object convert entity to string but using "UTF-8" something like this
responseJsonObject = new JSONObject(EntityUtils.toString(entity,"UTF-8"));
previously i was just doing
responseJsonObject = new JSONObject(EntityUtils.toString(entity));
I don't think it's a problem with your headers, I think it's a problem with your string. Just having the header say it's utf-8 doesn't mean the string you write is utf-8, and that depends a lot on how the string was encoded and what's in the "payloadValue"
That said, you can always re-encode the thing correctly before sending it across the wire, for example:
objectForPayload.put(payloadKey, payloadValue);
StringEntity stringentity = new StringEntity(
new String(
objectForPayload.toString().getBytes(),
"UTF8"));
See if that works for you.
You may need to add an "Accept-Encoding"-header and set this to "UTF-8"
Just for the record: the "Content-Encoding" header field is incorrect - a correct server would reject the request as it contains an undefined content coding format.
Furthermore, attaching a charset parameter to application/json is meaningless.
bourne already answered that in the above comment though.
Changing entity = IOUtils.toString(response.getEntity().getContent())
TO entity = EntityUtils.toString(response.getEntity(),"UTF-8")
did the trick.

Setting HttpClient POST Request body without "="

I need to make POST request with body like this:
{"a":[12345]}
If I try to build POST requests like this:
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("{\"u\":[123]}", ""));
httpost.setEntity(new UrlEncodedFormEntity(nvps));
it, of course, makes a POST request body with a "=" delimeter
{"a":[12345]}=
How do I make it right?
Try using StringEntity, created with your JSON payload, instead of your current use of UrlEncodedFormEntity, NameValuePair et al.

# converted to %40 in HTTPPost request

i m trying to send post request to webservice..
when i add special character # in parameter it is coverted to %40.i have checked server side..they are getting %40 instead of #.
can any one help me??
here is my code..
httpclient = new DefaultHttpClient();
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("Email", "abc#gmail.com"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = httpclient.execute(httppost,responseHandler);
i have also tried this method to prevent my parameter from encoding.
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.PLAIN_TEXT_TYPE));
but it raised unsupported encoded algorithm
pls help me out of this.
You're using UrlEncodedFormEntity, which will URL-encode the content. Turning # into %40 is normal with this encoding. The recipient should be able to decode that automatically, although you may have to use the correct content type for it to do so, probably application/x-www-form-urlencoded.
You can use
URLDecoder.decode("urlcontext", "UTF-8");
to remove any special character from the url which your passing
You need to use something such as URLDecoder on your server side so that you can convert the %40 back to #. The same applies for other special characters.
Use URLDecoder.decode(url) this will be helpful.
I'm definitly late for this party, but I had a similar issue. If you want to decode your url string you need to use decodeURIComponent(url). Where url is the string you are trying to decode.
W3schools does a great job of explaining it. https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_decodeuricomponent

Categories

Resources