I tried to create a post with the following...
HttpPost httppost = new HttpPost(URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httppost.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
String length = String.valueOf(httppost.getEntity().getContentLength());
httppost.setHeader(HTTP.CONTENT_LEN, length); //If commented out it works
but when I try to run the request I get the following error...
10-11 22:05:02.940: W/System.err(4203): org.apache.http.client.ClientProtocolException
I am guessing this is because the content length is wrong.
Apache HttpClient (even its fork shipped with Android) always calculates content length based on the properties of the enclosed HTTP entity. One does not need (and should not) set Content-Length and Transfer-Encoding headers manually.
Related
I am trying to fire an API in which I need to add two headers i.e token and deviceid. Below is my code to add header:
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(nameValuePairs[0].get(0).getValue().toString());
nameValuePairs[0].remove(0);
ResponseHandler<String> res = new BasicResponseHandler();
// set header
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpPost.setHeader("deviceid", "358978060711939");
httpPost.setHeader("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJHVUlEIjoiYjdlNjZiOWQtMjBjNy00MGI2LTliMzgtOTc3OGQ2OWIwM2E1IiwiRU5USVRZIjoiRUFCTSIsIlVOSVQiOiJVQk0yIiwiUk9MRU5BTUUiOiJTRUxGIiwiSUQiOiIwMDAyMzciLCJBTFRJRCI6IjMzMyIsIlVTRVJfTkFNRSI6IkFuaWwiLCJMT0dJTl9HVUlEX0tFWSI6ImU2NWM2YWEzLTZlNDItNDUyYS1hOGEwLWRlYzRhMGRiNTIxNyIsImlhdCI6MTQ1OTI0ODkyM30.m742d9xd6XlBBjZ3_ODWuoCEdWvSkhPAuNrDee1vi74");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs[0]));
response = httpClient.execute(httpPost, res);
In Response I am getting: org.apache.http.client.HttpResponseException: Not Found
When I replace token with any alpha numeric value then I am getting response with error message. But when I passed actual token value which is mentioned above I am getting exception. Even I tried with addHeader function also but getting same issue. I am unable to understand how to resolve this error.
it's the handler which is causing the error. Don't use.
You should either write your own handler or call execute without a handler.
httpClient.execute(httpPost);//remove the handler
I hope this is helpful. ThankYou
Your token seems to be incorrect. Header set in HTTP protocols has their own restrictions. To check it, just try to send your trim token (ex 30 chars).
If it don't helped, you have incorrect another parameters. Anyway, i would give you advice, to use Retrofit.
I am trying to connect to apache tomcat server using HTTP POST, when i see LOG file of server it showing GET /login/validate_doc.jsp HTTP/1.1" 200 685 ,
which means it is getting a GET request when i am sending using HttpPost and form parameters are not received by server.
my code is below:
HttpPost post_http=null;
post_http=new HttpPost("http://somexx.ac.in/medONmob/validate_doc.jsp");
try
{
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("username",username));
nameValuePairs.add(new BasicNameValuePair("password",password));
post_http.setEntity(new UrlEncodedFormEntity(nameValuePairs));
Where am i wrong ...??? Help me out please
Try specifying encoding when constructing UrlEncodedFormEntity. By default it is ISO-8859-1.
Also this will make your code future safe
Creating a UrlEncodedFormEntity from a List of NameValuePairs throws a NullPointerException
Given that you are using a post, then you probably are sending data on your request body, Am I right?, then you have to specify the content-type of the data you are sending in the headers, in order to execute a proper post:). For example if I am sending a json in the request body then I should add a header like this:
request.addHeader("content-type", "text/json");
Cheers
I have configured the apache httpClient like so:
HttpProtocolParams.setContentCharset(httpParameters, "UTF-8");
HttpProtocolParams.setHttpElementCharset(httpParameters, "UTF-8");
I also include the http header "Content-Type: application/json; charset=UTF-8" for all http post and put requests.
I am trying to send http post/put requests with a json body that contains special characters (ie. chinese characters via the Google Pinyin keyboard, symbols, etc.) The characters appear as gibberish in the logs but I think this is because DDMS does not support UTF-8, as descibed in this issue.
The problem is when the server receives the request, it sometimes doesn't see the characters at all (especially the Chinese characters), or it becomes meaningless garbage when we retrieve it through a GET request.
I also tried putting 250 non-ascii characters in a single field because that particular field should be able to take up to 250 characters. However, it fails to validate at the server side which claims that the 250 character limit has been exceeded. 250 ASCII characters work just fine.
The server dudes claim that they support UTF-8. They even tried simulating a post request that contains Chinese characters, and the data was received by the server just fine. However, the guy (a Chinese guy) is using a Windows computer with the Chinese language pack installed (I think, because he can type Chinese characters on his keyboard).
I'm guessing that the charsets being used by the Android client and the server (made by Chinese guys btw) are not aligned. But I do not know which one is at fault since the server dudes claim that they support UTF-8, and our rest client is configured to support UTF-8.
This got me wondering on what charset Android uses by default on all text input, and if it can be changed to a different one programatically. I tried to find resources on how to do this on input widgets but I did not find anything useful.
Is there a way to set the charset for all input widgets in Android? Or maybe I missed something in the rest client configuration? Or maybe, just maybe, the server dudes are not using UTF-8 at their servers and used Windows charsets instead?
Apparently, I forgot to set the StringEntity's charset to UTF-8. These lines did the trick:
httpPut.setEntity(new StringEntity(body, HTTP.UTF_8));
httpPost.setEntity(new StringEntity(body, HTTP.UTF_8));
So, there are at least two levels to set the charset in the Android client when sending an http post with non-ascii characters.
The rest client itself itself
The StringEntity
UPDATE: As Samuel pointed out in the comments, the modern way to do it is to use a ContentType, like so:
final StringEntity se = new StringEntity(body, ContentType.APPLICATION_JSON);
httpPut.setEntity(se);
I know this post is a bit old but nevertheless here is a solution:
Here is my code for posting UTF-8 strings (it doesn't matter if they are xml soap or json) to a server. I tried it with cyrillic, hash values and some other special characters and it works like a charm. It is a compilation of many solutions I found through the forums.
HttpParams httpParameters = new BasicHttpParams();
HttpProtocolParams.setContentCharset(httpParameters, HTTP.UTF_8);
HttpProtocolParams.setHttpElementCharset(httpParameters, HTTP.UTF_8);
HttpClient client = new DefaultHttpClient(httpParameters);
client.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_1);
client.getParams().setParameter("http.socket.timeout", new Integer(2000));
client.getParams().setParameter("http.protocol.content-charset", HTTP.UTF_8);
httpParameters.setBooleanParameter("http.protocol.expect-continue", false);
HttpPost request = new HttpPost("http://www.server.com/some_script.php?sid=" + String.valueOf(Math.random()));
request.getParams().setParameter("http.socket.timeout", new Integer(5000));
List<NameValuePair> postParameters = new ArrayList<NameValuePair>();
// you get this later in php with $_POST['value_name']
postParameters.add(new BasicNameValuePair("value_name", "value_val"));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters, HTTP.UTF_8);
request.setEntity(formEntity);
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String lineSeparator = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append(lineSeparator);
}
in.close();
String result = sb.toString();
I hope that someone will find this code helpful. :)
You should set charset of your string entity to UTF-8:
StringEntity stringEntity = new StringEntity(urlParameters, HTTP.UTF_8);
You can eliminate the server as the problem by using curl to send the same data.
If it works with curl use --trace to check the output.
Ensure you are sending the content body as bytes. Compare the HTTP request from Android with the output from the successful curl request.
Greetings,
I'm developing an Android app and need to open a url (with POST parameters) over https and get the response.
There's the added complication that I have a self-signed certificate. I also need to accept cookies.
Anyone have any ideas about where to get started?
Many thanks in advance,
Android comes with the apache commons http library included.
Setting up a https post request is quite easy:
HttpPost post = new HttpPost("https://yourdomain.com/yourskript.xyz");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("postValue1", "my Value"));
nameValuePairs.add(new BasicNameValuePair("postValue2", "2nd Value"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
String responseText = EntityUtils.toString(entity);
Android uses a version 4.x of the commons http library as all versions below 4.0 are out of their lifecycle.
I can't tell exactly how to register a self-signed certificate to the HttpClient, but mybe the commons http documentation helps:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
I managed to get it all working asyncronously with both cookies and unsigned https.
I used the code here:
http://masl.cis.gvsu.edu/2010/04/05/android-code-sample-asynchronous-http-connections/
and modified for unsigned https using Brian Yarger's code here:
Self-signed SSL acceptance on Android
(Add the above code to the beginning of run() in HttpConnection.java)
To get the cookies to work, I had to modify some code (POST snippet from HttpConnection.java):
case POST:
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(data));
httpPost.addHeader("Cookie", Cookie.getCookie());
response = httpClient.execute(httpPost);
Header[] headers=response.getAllHeaders();
for(int i=0;i<headers.length;i++){
if(headers[i].getName().equalsIgnoreCase("Set-Cookie")){
//Log.i("i",headers[i].getName()+"---"+headers[i].getValue());
Cookie.setCookie(headers[i].getValue());
break;
}
}
break;
Many thanks to everyone for pointing me in the direction,
Update:
Found the answer myself, see below :-)
Hi,
I'am currently coding an android app that submits stuff in the background using HTTP Post and AsyncTask. I use the org.apache.http.client Package for this. I based my code on this example.
Basically, my code looks like this:
public void postData() {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.137:8880/form");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("id", "12345"));
nameValuePairs.add(new BasicNameValuePair("stringdata", "AndDev is Cool!"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
Log.e(TAG,e.toString());
} catch (IOException e) {
Log.e(TAG,e.toString());
}
}
The problem is that the httpclient.execute(..) line takes around 1.5 to 3 seconds, and I do not understand why. Just requesting a page with HTTP Get takes around 80 ms or so, so the problem doesn't seem to be the network latency itself.
The problem doesn't seem to be on the server side either, I have also tried POSTing data to http://www.disney.com/ with similarly slow results. And Firebug shows 1 ms response time when POSTing data to my server locally.
This happens on the Emulator and with my Nexus One (both with Android 2.2).
If you want to look at the complete code, I've put it on GitHub.
It's just a dummy program to do HTTP Post in the background using AsyncTask on the push of a button. It's my first Android app, and my first java code for a long time. And incidentially, also my first question on Stackoverflow ;-)
Any ideas why httpclient.execute(httppost) takes so long?
Allright, I solved this myself with some more investigation. All I had to do was to add a parameter that sets the HTTP Version to 1.1, as follows:
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpClient httpclient = new DefaultHttpClient(params);
I found this thanks to the very nice HttpHelper Class from and-bookworm and some trial-and-error.
If I remember correctly, HTTP 1.0 opens a new TCP connection for every request. Does that explain the large delay?
A HTTP POST request now takes between 50 and 150 ms over WLAN and something between 300 and 500 ms over 3G.
i am not on android, but i faced exactly the same kind of problem on windows platform with httpclient 4.0.1, after quite a bit of head scratching, i found the solution.
HttpParams params = new BasicHttpParams();
//this how tiny it might seems, is actually absoluty needed. otherwise http client lags for 2sec.
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpClient httpClient = new DefaultHttpClient(params);
HttpResponse httpResponse;
HttpPost httpPost = new HttpPost("http://"+server+":"+port+"/");
StringEntity entity = new StringEntity(content, "utf-8");
entity.setContentType("text/plain; charset=utf-8");
httpPost.setEntity(entity);
httpResponse=httpClient.execute(httpPost);
String response = IOUtils.toString(httpResponse.getEntity().getContent(),encoding);
httpResponse.getEntity().consumeContent();
httpClient.getConnectionManager().shutdown();
return(response);
i have no idea why setting the parameters with HTTP1.1 version solves the problem. but it does.
also even weirder, the symptom did not show if executing an HTTP Get request.
anyhow, i hope this helps some out there !
h