I have a following class
public class MyHttpClient {
private static HttpClient httpClient = null;
public static HttpClient getHttpClient() {
if (httpClient == null)
httpClient = new DefaultHttpClient();
return httpClient;
}
public static String HttpGetRequest(String url) throws IOException {
HttpGet request = new HttpGet(url);
HttpResponse response = null;
InputStream stream = null;
String result = "";
try {
response = getHttpClient().execute(request);
if (response.getStatusLine().getStatusCode() != 200)
response = null;
else
stream = response.getEntity().getContent();
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(stream));
while ((line = rd.readLine()) != null) {
total.append(line);
}
// Return full string
result = total.toString();
} catch (ClientProtocolException e) {
response = null;
stream = null;
result = null;
} catch (IllegalStateException e) {
response = null;
stream = null;
result = null;
}
return result;
}
}
and a web-service which response header is (I can't provide direct link because of privacy)
Status: HTTP/1.1 200
OK Cache-Control: private
Content-Type: application/json;
charset=utf-8
Content-Encoding: gzip
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 03
Jul 2011 11:00:43 GMT
Connection: close
Content-Length: 8134
In the end I get as a result series of weird, unreadable characters (I should get regular JSON like I get in regular desktop browser).
Where is the problem? (The same code for ex. google.com works perfectly and I get nice result)
EDIT: Solution (see below for description)
Replace
HttpGet request = new HttpGet(url);
with
HttpUriRequest request = new HttpGet(url);
request.addHeader("Accept-Encoding", "gzip");
and replace
stream = response.getEntity().getContent();
with
stream = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
stream = new GZIPInputStream(stream);
}
The problem is here:
Content-Encoding: gzip
This means the weird characters you are getting are the gzip compressed version of the expected JSON. Your browser does the decmpression so there you see the decoded result. You should have a look at your request header and at the configuration of your server.
Well, gzip encoding is generally good practice - for JSON data (especially big one) it can actually get between 10x and 20x decrease in the amount of data to transfer (which is a GOOD THING).. So better is to let HttpClient to handle GZIP compression nicely. For example here:
http://forrst.com/posts/Enabling_GZip_compression_with_HttpClient-u0X
BTW. It seems wrong however on the server side to provide GZIP compressed data when the client does not say "Accept-Encoding: gzip", which seems to be the case... So some things have to be corrected on the server as well. The example above adds Accept-Encoding header for you.
Related
I am making an HttpGet request with "Authorization" as header attaching bearer token. I am getting a 401 unauthorized error all the time.
I have tried retrofit, it didn't work so I reverted back to basic HTTP client. Then after a lot of research found that there is some error with DefaultHttp. So I changed to HTTPUrlConnection. Even after doing all these, I am still getting an unauthorized 401 error. What could I possibly do wrong here? Because this error still persists, I decided to stick to HTTPUrlConnection or DefaultHTTP and stay away from libraries.
Here is my code with HttpUrlConnection
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection)
obj.openConnection();
con.setRequestMethod("GET");
String authString = "Bearer" + accessToken;
con.setRequestProperty("Authorization", authString);
int responseCode = con.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { // success
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
} else {
System.out.println("GET request not worked");
}
Here is my DefaultHttp request
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGetRequest = new HttpGet(url);
httpGetRequest.addHeader("Authorization","Bearer"+accessToken);
try {
HttpResponse response = client.execute(httpGetRequest);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new
InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
}
add a whitespace after Bearer cus as it stands your concatenating Bearer with the token as one string
Please use Fast Android Networking library its very easy to use and you can implement your logic in less than 5 mins. So please give it a try atleast. Below is the link to library:
https://github.com/amitshekhariitbhu/Fast-Android-Networking
The problem was resolved. I tried using retrofit and defaultHttpClient but both didn't worked for me because of some cookie issue. But using OKHttpClient it was straight forward and I was able to hit the server and get the response.
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(mURL)
.addHeader("Authorization", String.format("Bearer %s", bearerToken))
.build();
Response response = client.newCall(request).execute();
return response.body().string();
I am having the following problem and I am stuck in it from a while and don't know what is the problem
I am getting the error
org.json.JSONException: Unterminated object at character 1526, as following the print of the response string
and as following my method
public void getItemType(final Context context,final ItemTypeRequestUIListener uiListener) {
if (PhoneUtils.isNetworkAvailable(context) == true) {
new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
try {
DefaultHttpClient client = new DefaultHttpClient();
HttpPost request = new HttpPost(AppConstants.URL_DO_LIST_LOOKUP);
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
request.setEntity(new StringEntity(AppConstants.URL_DO_LIST_LOOKUP_ITEM_JSON_PARAM_FORMAT));
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
if (entity.getContentLength() != 0) {
Reader objectReader = new InputStreamReader(response.getEntity().getContent());
char[] buffer = new char[(int) response.getEntity().getContentLength()];
objectReader.read(buffer);
objectReader.close();
String str = new String(buffer);
str = str.replace("?", "");
Log.i("AMIRA", "TYPES RESPONSE : " + str);
JSONObject jsonResponse = new JSONObject(str);
uiListener.onRequestCompleted(ItemTypeResponse.parseJSONObject(jsonResponse),null);
}
} catch (Exception e) {
e.printStackTrace();
uiListener.onRequestCompleted(null,AppError.GENERAL_ERROR);
}
return null;
};
}.execute();
} else {
uiListener.onRequestCompleted(null, AppError.NO_INTERNET);
}
}
Can anyone please tell me what is the problem here ?
The most likely problem is that you are using the wrong character encoding to read the stream.
A line of code like this:
Reader objectReader = new InputStreamReader(response.getEntity().getContent());
is always dangerous because you are not explicitly specifying what character set to use.
You can try this:
Reader objectReader = new InputStreamReader(response.getEntity().getContent(), "UTF-8");
if you know your server is sending UTF-8 content.
The best way to handle this is to read the Content-Type header in the response which could be something like:
Content-Type: application/json; charset=UTF-8
Parse the string after "charset=" and pass that as the character set name.
In effect you are specifying the character set that the server said it is using.
But be careful: The charset parameter is optional and may not be present.
As an extreme fallback, you could catch the JSONException and retry the parse with a different encoding. You would have to buffer the response somewhere so that you could re-read it.
I make a GET request to a server using HttpUrlConnection.
After connecting:
I get response code: 200
I get response message: OK
I get input stream, no exception thrown but:
in a standalone program I get the body of the response, as expected:
{"name":"my name","birthday":"01/01/1970","id":"100002215110084"}
in a android activity, the stream is empty (available() == 0), and thus I can't get
any text out.
Any hint or trail to follow? Thanks.
EDIT: here it is the code
Please note: I use import java.net.HttpURLConnection; This is the standard
http Java library. I don't want to use any other external library. In fact
I did have problems in android using the library httpclient from apache (some of their anonymous .class can't be used by the apk compiler).
Well, the code:
URLConnection theConnection;
theConnection = new URL("www.example.com?query=value").openConnection();
theConnection.setRequestProperty("Accept-Charset", "UTF-8");
HttpURLConnection httpConn = (HttpURLConnection) theConnection;
int responseCode = httpConn.getResponseCode();
String responseMessage = httpConn.getResponseMessage();
InputStream is = null;
if (responseCode >= 400) {
is = httpConn.getErrorStream();
} else {
is = httpConn.getInputStream();
}
String resp = responseCode + "\n" + responseMessage + "\n>" + Util.streamToString(is) + "<\n";
return resp;
I see:
200
OK
the body of the response
but only
200
OK
in android
Trying the code of Tomislav I've got the answer.
My function streamToString() used .available() to sense if there is any data received,
and it returns 0 in Android. Surely, I called it too soon.
If I rather use readLine():
class Util {
public static String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
}
then, it waits for the data to arrive.
Thanks.
You can try with this code that will return response in String:
public String ReadHttpResponse(String url){
StringBuilder sb= new StringBuilder();
HttpClient client= new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
try {
HttpResponse response = client.execute(httpget);
StatusLine sl = response.getStatusLine();
int sc = sl.getStatusCode();
if (sc==200)
{
HttpEntity ent = response.getEntity();
InputStream inpst = ent.getContent();
BufferedReader rd= new BufferedReader(new InputStreamReader(inpst));
String line;
while ((line=rd.readLine())!=null)
{
sb.append(line);
}
}
else
{
Log.e("log_tag","I didn't get the response!");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
The Stream data may not be ready, so you should check in a loop that the data in the stream is available before attempting to access it.
Once the data is ready, you should read it and store in another place like a byte array; a binary stream object is a nice choice to read data as a byte array. The reason that a byte array is a better choice is because the data may be binary data like an image file, etc.
InputStream is = httpConnection.getInputStream();
byte[] bytes = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] temp = new byte[is.available()];
while (is.read(temp, 0, temp.length) != -1) {
baos.write(temp);
temp = new byte[is.available()];
}
bytes = baos.toByteArray();
In the above code, bytes is the response as byte array. You can convert it to string if it is text data, for example data as utf-8 encoded text:
String text = new String(bytes, Charset.forName("utf-8"));
I am trying to build a small application in which the application will communicate with a php script with the help of JSON objects. I successfully implemented the GET Request test application but using JSON with post is creating problems. The code generates no error but my php script reply with no nothing except an empty Array() which implies that nothing was sent over the connection with code:
<?php print_r($_REQUEST); ?>
and trying with
<?php print($_REQUEST['json']); ?>
throws HTML back to the application with json variable not found error.
I have already tried a few solutions mentioned here including: How to send a JSON object over Request with Android? and How to send a json object over httpclient request with android so it would be great if you can point out my mistake and can briefly describe what exactly I was doing wrong. Thanks.
Here is the code snippet for from where the JSON Object is converted into string and then attached to a Post variable.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppostreq = new HttpPost(wurl);
StringEntity se = new StringEntity(jsonobj.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httppostreq.setEntity(se);
//httppostreq.setHeader("Accept", "application/json");
//httppostreq.setHeader("Content-type", "application/json");
//httppostreq.setHeader("User-Agent", "android");
HttpResponse httpresponse = httpclient.execute(httppostreq);
HttpEntity resultentity = httpresponse.getEntity();
Here is TCP Stream Dump collected through wireshark if it can help:
POST /testmysql.php?test=true HTTP/1.1
Content-Length: 130
Content-Type: application/json;charset=UTF-8
Content-Type: application/json;charset=UTF-8
Host: 192.168.100.4
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
{"weburl":"hashincludetechnology.com","header":{"devicemodel":"GT-I9100","deviceVersion":"2.3.6","language":"eng"},"key":"value"}HTTP/1.1 200 OK
Date: Mon, 30 Apr 2012 22:43:10 GMT
Server: Apache/2.2.17 (Win32)
Content-Length: 34
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
Array
(
[test] => true
)
Test // echo statement left intentionally.
you are using PHP on the server side, so your HTTP entity must be a multipart encoded one. See this link. You are using a string entity, but this is not correct. It must be a MultipartEntity, which emulates what the browser does when you submit a form in a web page. MultipartEntity should be in httpmime jar.
Once you have your multipart entity, simply add a Part named "json", and set its contents to the string representation of your json-encoded object.
Note that this answer is because you use PHP on the server side, so you must use its "protocol" to read variables via $_REQUEST. If you used your own request parser oh the server side, even a StringEntity could be ok. See HTTP_RAW_POST_DATA
The below should work. Make sure to set the appropriate keys for what your form post is expecting at the top. Also I included how to send an image as well as other various json data, just delete those lines if that is not necessary.
static private String postToServerHelper(
String action,
JSONObject jsonData,
byte[] imageData){
// keys for sending to server
/** The key for the data to post to server */
final String KEY_DATA = "data";
/** The key for the action to take on server */
final String KEY_ACTION = "action";
/** The return code for a successful sync with server */
final int GOOD_RETURN_CODE = 200;
/** The key for posting the image data */
final String KEY_IMAGE = "imageData";
/** The image type */
final String FILE_TYPE = "image/jpeg";
/** The encoding type of form data */
final Charset ENCODING_TYPE = Charset.forName("UTF-8");
// the file "name"
String fileName = "yourFileNameHere";
// initialize result string
String result = "";
// initialize http client and post to correct page
HttpClient client = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://www.yourdomain.com/yourpage.php");
// set to not open tcp connection
httpPost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
// build the values to post, the action and the form data, and file data (if any)
MultipartEntity multipartEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
try{
multipartEntity.addPart(KEY_ACTION, new StringBody(action, ENCODING_TYPE));
multipartEntity.addPart(KEY_DATA, new StringBody(jsonData.toString(), ENCODING_TYPE));
if (imageData != null){
multipartEntity.addPart(KEY_IMAGE, new ByteArrayBody(imageData, FILE_TYPE, fileName));
}
}catch (Exception e){
return e.getMessage();
}
// set the values to the post
httpPost.setEntity(multipartEntity);
int statusCode= -1;
// send post
try {
// actual send
HttpResponse response = client.execute(httpPost);
// check what kind of return
StatusLine statusLine = response.getStatusLine();
statusCode = statusLine.getStatusCode();
// good return
if (statusCode == GOOD_RETURN_CODE) {
// read return
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line + "\n");
}
content.close();
result = builder.toString();
// bad return
} else {
return String.parse(statusCode);
}
// different failures
} catch (ClientProtocolException e) {
return e.getMessage();
} catch (IOException e) {
return e.getMessage();
}
// return the result
return result;
}
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
JSONObject clientList = new JSONObject ();
clientList.put("name","");
clientList.put("email","");
clientList.put("status","");
clientList.put("page","");
JSONObject listclient = new JSONObject ();
listclient.put("mydetail", clientList);
//--List nameValuePairs = new ArrayList(1);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("token", tokenid));
nameValuePairs.add(new BasicNameValuePair("json_data", listclient.toString()));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
Log.d("JSON",nameValuePairs.toString());
//-- Storing Response
HttpResponse httpResponse = httpClient.execute(httpPost);
I'm a novice with Java and Android, but not to programming and HTTP. This HTTP GET method, mostly copied from other examples using the Apache HTTP classes, only retrieves the first few K of a large webpage. I checked that the webpage does not have lines longer than 8192 bytes (is that possible?), but out of webpages around 40K I get back maybe 6K, maybe 20K. The number of bytes read does not seem to have a simple realtionship with the total webpage size, or the webpage modulus 8192, or with the webpage content.
Any ideas folks?
Thanks!
public static String myHttpGet(String url) throws Exception {
BufferedReader in = null;
try {
HttpClient client = getHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI(url));
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sbuffer = new StringBuffer("");
String line = "";
while ((line = in.readLine()) != null) {
sbuffer.append(line + "\n");
}
in.close();
String result = sbuffer.toString();
return result;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
No need to write you own HttpEntity-to-String code, try EntityUtils instead:
// this uses the charset the server encoded the entity in
String result = EntityUtils.toString(entity);
It looks as if the problem is with pages from a certain website starting Goo... I'm not having this problem with large pages from other sites. So the code is probably OK.