I'm running into a strange problem using HttpClient. I am using a DefaultHttpClient() with HttpPost. I was using HttpGet with 100% success but now trying to switch to HttpPost as the REST API I'm using wants POST parameters rather than GET. (Only for some API calls though so I know that the GET calls were working fine so it's not a fault of the API).
Also, I tried using HttpPost on a simple php script I wrote that looks for a POST parameter 'var' and echoes it to screen, passing this parameters as follows worked fine:
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
postMethod = new HttpPost("http://www.examplewebsite.com");
nameValuePairs.add(new BasicNameValuePair("var", "lol"));
try {
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpClient.execute(postMethod, responseHandler);
Log.i("RESTMethod", response);
...
The problem is that when I tried and do the same call to the API (but with the params changed to the API params obviously) I get the following error:
Authentication error: Unable to respond to any of these challenges: {}
The page I am requesting is an HTTPS page, could this be the problem?
But doing the same type of POST request to a raw HTTP page on the API gives the same error, unless I comment out the StringEntity part and then it runs (but returns xml and I want to pass a parameter to request the data in JSON).
This seems like a really strange problem (the non-https part) but couldn't really find any help on this problem so sorry if the answer is out there.
Any ideas?
Thanks in advance,
Infinitifzz
EDIT: Okay I'm getting nowhere so I thought if I directed you to the API it might shed some light, it's the 8Tracks API and as you can see you need to pass a dev key (api_key) for all requests and I the part I'm stuck on is using https to log a user in with: http://www.8tracks.com/sessions.xml" part.
Hope this helps somehow because I am at a dead end.
Thanks,
Infinitifizz
Authentication error: Unable to
respond to any of these challenges: {}
This error message means that the server responded with 401 (Unauthorized) status code but failed to provide a single auth challenge (WWW-Authenticate header) thus making it impossible for HttpClient to automatically recover from the authentication failure.
Most likely application expects some soft of credentials in the HTML form enclosed in the HTTP POST request.
Don't you have to declare the port and protocol? I'm just swagging this code so please don't be upset if it doesn't immediatley compile correctly. Also, I usually supply a UsernamePasswordCredentials to my setCredentials() but I imagine it's the same.
HttpHost host = new HttpHost("www.foo.com", 443, "https");
// assemble your GET or POST
client.getCredentialsProvider().setCredentials(new AuthScope(host.getHostName(), host.getPort()));
HttpResponse response = client.execute(host, [HttpPost or HttpGet]);
More info about setCredentials here.
Here's how I ended up with similar problem:
DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(username, password));
Thanks to Ryan for right direction.
Not specifying a Callback URL for my Twitter App resulted in the same error for me:
Authentication error: Unable to respond to any of these challenges: {oauth=WWW-Authenticate: OAuth realm="https://api.twitter.com"}
Setting a callback URL on Twitter fixed the problem
Related
I am using Apache httpClient library in my android project to send get/post requests to the server. My server is set up using apache namevirtualhost - there are multiple virtual hosts on the same server.
For those not familiar with how apache namevirtualhost works, the simple explanation is that there are multiple configurations defined in the server config, and apache uses Host request header to determine which configuration to use. When multiple hosts are defined, the first one is considered default and all requests with Host request header not explicitly matching one of the defined namevirtualhosts will be handled using the default configuration.
Now, the server I'm trying to connect to is not the default one. When my app runs and the request is made to the server, it does not go to my virtual host but instead is handled by the default one, resulting in the certificate name mismatch. (Note that I do have the correct certificates set up.)
Here's my code - copy/paste, except for the actual URL:
String targetUrl = getTargetUrl();
//this returns something like https://www.example.com/api/1/orders (without spaces, of course)
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(targetUrl);
List<NameValuePair> data = new ArrayList<NameValuePair>(1);
data.add(new BasicNameValuePair("orders", json.toString()));
data.add(new BasicNameValuePair("username", username));
data.add(new BasicNameValuePair("password", password));
post.setEntity(new UrlEncodedFormEntity(data));
HttpResponse response = client.execute(post);
This results in an error message saying that certificate name doesn't match the requested url and shows the requested url and the certificate url - the certificate url is the default one in the apache config.
I added this code right before the line to execute the request:
Header[] hds = post.getAllHeaders();
for(Header h : hds) {
Log.d("PasteneOrers", h.getName() + ": " + h.getValue());
}
to see what headers are included. Interesting, Host header is not shown. I then added this code before executing the request:
URL url = new URL(targetUrl);
post.setHeader("Host", url.getHost());
Now the above debugging output correctly shows the Host header - but it doesn't help and the request is still going to the default one.
To verify that this is not a problem with the server misconfiguration, I copied the target URL and pasted it into the browser running on the same android emulator - this works correctly and I get the right results. Hence it's definitely something in my code - but what? At this point I'm stuck. Any suggestions would be appreciated.
In the interest of others having this problem, I couldn't resolve it with apache httpclient. I switched to using HttpUrlConnection and everything worked correctly.
I am having the following API call:
http://rollout.gr/api/?query={%22search%22:%22places%22,%22page%22:1}
This API call is executed correctly in my browser. But when I use a DefaultHttpClient to execute this url in my Android application, I get a null response.
I suppose the problem is the JSON data in the HTTP url. Thus, I would like to ask which is the proper way to handle such url in an Android application?
Thanks a lot in advance!
The accolades aren't valid URL characters. The browser is userfriendly enough to automatically URL-encode them, but DefaultHttpClient isn't. The correct line to use from code is:
http://rollout.gr/api/?query=http://rollout.gr/api/?query=%7b%22search%22:%22places%22,%22page%22:1%7d
Note the encoding for the accolades (%7b, %7d).
Your problem may be the strictmode here.
I recommend to do http request in threads or asynctasks. strictmode doesnt let app do http reauest in uithread. maybe your console shows a warning and you get null from http response because of this.
This project may solve your problem:
http://loopj.com/android-async-http/
Not knowing your particular HTTP initialization code, I'm going to assume you didn't provide an explicit JSON accept header. A lot of REST endpoints require this.
httpget.setHeader("Accept", "application/json");
I am working on an app which shall log in to a web site (via http://......?password=xyz).
I use DefaultHttpClient for this.
Along with the GET response, the website sends a cookie, which I want to store for further POST requests.
My problem is that client.getCookieStore().getCookies() always receives an empty list of cookies.
If I open http://www.google.com (insted of my intended website), I receive the cookies properly, but the website I am working with, seems to send the cookie in some other way (it's a MailMan mailing list moderating page)
I can see the respective cookie in Firefox cookie manager, but not in Firebug network/cookie panel (why?). InternetExplorer HttpWatchProfessional however shows the cookie when recording the traffic....
There is some small difference, I observed between the cookies www.google.com sent and my target website: In HttpWatchProfessional, those cookies from google are marked as "Direction: sent", while the cookie from my website are marked as "Direction: Received".
(how can the google cookies be sent, while I cleared browser/cookie cache just before?)
Can someone explain the difference to me?
My code is the following:
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse execute = client.execute(httpGet);
List<Cookie> cookies = client.getCookieStore().getCookies();
After further investigation, I found out that the cookie was received, but actually rejected by the httpclient, due to a path the cookie, which differed to that from the called URL.
I found the solution at:
https://stackoverflow.com/a/8280340/1083345
I'm writing an Android app that should get data from a certain web application. That web app is based on Servlets and JSP, and it's not mine; it's a public library's service. What is the most elegant way of getting this data?
I tried writing my own Servlet to handle requests and responses, but I can't get it to work. Servlet forwarding cannot be done, due to different contexts, and redirection doesn't work either, since it's a POST method... I mean, sure, I can write my own form that access the library's servlet easily enough, but the result is a jsp page.. Can I turn that page into a string or something? Somehow I don't think I can.. I'm stuck.
Can I do this in some other way? With php or whatever? Or maybe get that jsp page on my web server, and then somehow extract data from it (with jQuery maybe?) and send it to Android? I really don't want to display that jsp page in a browser to my users, I would like to take that data and create my own objects with it..
Just send a HTTP request programmatically. You can use Android's builtin HttpClient API for this. Or, a bit more low level, the Java's java.net.URLConnection (see also Using java.net.URLConnection to fire and handle HTTP requests). Both are capable of sending GET/POST requests and retrieving the response back as an InputStream, byte[] or String.
At most simplest, you can perform a GET as follows:
InputStream responseBody = new URL("http://example.com").openStream();
// ...
A POST is easier to be performed with HttpClient:
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("name1", "value1"));
params.add(new BasicNameValuePair("name2", "value2"));
HttpPost post = new HttpPost("http://example.com");
post.setEntity(new UrlEncodedFormEntity(params));
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
InputStream responseBody = response.getEntity().getContent();
// ...
If you need to parse the response as HTML (I'd however wonder if that "public library service" (is it really public?) doesn't really offer XML or JSON services which are way much easier to parse), Jsoup may be a life saver as to traversing and manipulating HTML the jQuery way. It also supports sending POST requests by the way, only not as fine grained as with HttpClient.
I'm building an Android app that runs off of a rails server. At first, when I tried to post simple String data to the server, I ran into an InvalidAuthenticityToken issue, but realized that I can bypass the authentication by setting the content type to "json"
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(Constants.REST_HOST + "/add_comment");
post.addHeader("Content-Type", "application/json");
The next step was trying to get upload profile picture working. However, when I tried uploading a photo via a MultipartEntity post, setting the content type to "json" causes the following error
StandardError (Invalid JSON string):
but not setting the content type brings back the InvalidAuthenticityToken exception. What's the correct way to post an image to a rails server from a foreign Java client?
ActionController::InvalidAuthenticityToken
(ActionController::InvalidAuthenticityToken):
Based on Jesse's suggestion, I ended up using
protect_from_forgery :except => :upload_avatar_pic
to disable authenticity check, but only for a specific function, so checks for browser requests are still validated.
You can disable authenticity checking on API non-get calls from non-web clients. You can do this in a before filter
class ApiController < ApplicationController
skip_before_filter :verify_authenticity_token
def create
#or whatever
end
end
The problem solved by Jesse Wolgamott said, but the page show "You are being redirected" message when I submit the form (Update,create,show). In before that the page redirected correctly. I am using rails 2.3.8.how to resolve this?