Empty Http Call but no error - java

I'm trying to call a webservice with my application, but I get no error, the URL is the good one and return something (via the browser), but I get no content.
try {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
int lenght = (int) entity.getContentLength();
is = entity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection" + e.toString());
}
lenght is equal to -1 due to the empty response he receives
Does the response from the url need to be HTML ? Or anything I output can be grab by the HttpClient ?

The response does not need to be HTML, but if the server side does not return a content-length header in the response, length will be negative.

The response does not necessarily need to be in HTML.
A negative value returned by getContentLength() means the content length is not returned by the server. It does not mean there is no content. It's possible to have content returned by the request, but still have a negative value returned by getContentLength().
You can still get the content returned by the request:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
entity.writeTo(baos);
String contentString = baos.toString();

Related

How to write / convert CURL for Android java

I am trying to implement the MOT history API https://dvsa.github.io/mot-history-api-documentation/ and they give an example using CURL which works with the supplied api key successfully when using an online CURL tool.
I am trying to implement this in Android and realise I have to use something like HttpPost rather than CURL, this is my code:
//Tried with full URL and by adding the registration as a header.
//HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration=" + reg_selected);
HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests");
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("Accept", "application/json+v6");
httpPost.addHeader("x-api-key", "abcdefgh123456");
httpPost.addHeader("registration", reg_selected);
StringEntity entity = new StringEntity(jsonObj.toString(), HTTP.UTF_8);
httpPost.setEntity(entity);
HttpClient client = new DefaultHttpClient();
try {
HttpResponse response = client.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
InputStream inputStream = response.getEntity().getContent();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String readLine = bufferedReader.readLine();
String jsonStr = readLine;
JSONObject myJsonObj = new JSONObject(jsonStr);
}else if (response.getStatusLine().getStatusCode() == 400){
//Bad Request Invalid data in the request. Check your URL and parameters
error_text = "Bad Request";
}else if (response.getStatusLine().getStatusCode() == 403){
//Unauthorised – The x-api-key is missing or invalid in the header
error_text = "Authentication error"; //<<<< FAILS HERE 403
}
response.getStatusLine().getStatusCode() returns • "403 – Unauthorised – The x-api-key is missing or invalid in the header".
However the x-api-key that I use works correctly with the online CURL test so the actual key is correct but how I am adding it to my android code request must be invalid or similar.
Can anyone throw any light as to the correct way to convert the CURL into Android java so that the server does not return 403?
Thanks
It's easy to do with Jsoup:
// CREATE CONNECTION
Connection conn=Jsoup.connect("URL_GOES_HERE");
// ADD POST/FORM DATA
conn.data("KEY", "VALUE");
// ADD HEADERS HERE
conn.header("KEY", "VALUE");
// SET METHOD AS POST
conn.method(Connection.Method.POST);
// ACCEPT RESPONDING CONTENT TYPE
conn.ignoreContentType(true);
try
{
// GET RESPONSE
String response = conn.execute().body();
// USE RESPONSE HERE
// CREATE JSON OBJECT OR ANYTHING...
} catch(HttpStatusException e)
{
int status = e.getStatusCode();
// HANDLE HTTP ERROR HERE
} catch (IOException e)
{
// HANDLE IO ERRORS HERE
}
Ps: I guess you are confused with Header and Post Data. The key etc (Credentials) must be used as Post Data and Content Type etc as Header.

Is there any way to get content-length without getting response body

I am using Apache HttpClient to download content from the server. I want to check the size before downloading content. I have used HTTPGet to download content and before processing the inputstream I am checking the content-length header but I see HTTPGet will download the body too even though we do not process.
var httpGet = httpGet(url);
try (final var closeableHttpResponse = closeableHttpClient.execute(httpGet);) {
final var statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
final var headers = getHeadersMap(closeableHttpResponse.getAllHeaders());
final var contentLength = Long.valueOf(headers.get("content-length"));
final var entity = closeableHttpResponse.getEntity();
if (<<contentLength validation>>)) {
// Not to process
} else {
final var inputstream = entity.getContent();
// Processing inputstream
EntityUtils.consumeQuietly(entity);
}
} catch (IOException e) {
// Error Handling
}
If I use HTTP Head it will give only headers. Is it a correct approach to determining response size?
There are some cases in which the content-length header doesn't have length. Is there any other way too for determine size before downloading if the content-length header doesn't have a length?

Android application doesn't read entire HTTP response

I have written a web-service in Java. This web-service is hosted in TOMCAT. I am returning a JSON string. The JSON string is as follows:
accountDetailsNodes = [{mobileNumber=01948330292, errorMessage=null, customerCode=59744000002, photo=a string of 35536 charaters , accountOpenDate=null, errorFlag=N, customerNumber=4, customerName=Md. Saifur Hossain , accountID=2, accountTypeId=13, accountTypeDescription=Savings Account, customerPointId=1, balance=100000037640.50, accountTile=Md. Saifur Hossain}]
The length of the JSON string is 32613. But the full response is not coming to android apps. I think there may be some limitation on sending response from Tomcat. How can I overcome this limitation of Tomcat?
Updated:
This is my code to generate JSON.
try {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
JSONObject json = new JSONObject();
CashDepositDao dao = new CashDepositDao();
for (CashDepositModel bo : dao.getAccountDetals(accountNo,branchCode)) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("accountTile", bo.getAccountTitle());
map.put("accountOpenDate", bo.getAccountOpenDate());
map.put("mobileNumber", bo.getMobileNumber());
map.put("balance", bo.getBalance());
map.put("accountTypeId", bo.getAccountTypeID());
map.put("accountTypeDescription", bo.getAccountTypeDescription());
map.put("accountID", bo.getAccountID());
map.put("customerNumber", bo.getCustomerNumber());
map.put("customerCode", bo.getCustomerCode());
map.put("customerName", bo.getCustomerName());
map.put("customerPointId", bo.getCustomerPointID());
map.put("photo", bo.getPhoto());
map.put("errorMessage", bo.getErrorMessage());
map.put("errorFlag", bo.getErrorFlage());
list.add(map);
json.put("accountDetailsNodes", list);
}
System.out.println("accountDetailsNodes = " + list);
response.addHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(json.toString());
response.getWriter().flush();
// System.out.println("Response Completed... ");
} catch (Exception ex) {
Logger.getLogger(SourecAccountDetailsSV.class.getName()).log(Level.SEVERE, null, ex);
}
Sending And Getting response from Mobile App:
I am sending and getting the response using the following code:
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
// Making HTTP request
try {
// check for request method
if(method == "POST"){
// request method is POST
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}else if(method == "GET"){
// request method is GET
DefaultHttpClient httpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
System.out.println(json);
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
I have printed the string received in this method . Surprisingly, the full string is not received in this method.
How can I overcome this limitation of tomcat ?
Tomcat can send arbitrary length strings, and even if there was a limit, it wouldn't be measured in kilobytes but in orders of magnitude more. There is no tomcat limitation that you need to overcome. If your browser receives the full string, so can any other app.
As you're using json.toString() anyways, you could explicitly set the Content-Length header and see if this makes a difference. Stop worrying about Tomcat and double check if your Android App has some problems parsing a json response of this size, or if any network component in between limits your response in some way.
Edit: It's not Tomcat's problem, it's on the Android side and your answer is in the comments to the question.
The first problem is in what's proposed as "duplicate" question: You must not compare String with == as you do. Add else System.out.print("unexpected"); to your first if/else block to illustrate.
The second problem is that we have no clue where you get is from. As it looks now, it could be overridden by parallel requests (it's probably a class member?) - or due to the wrong string comparison never be initialized at all (leading to your problem that you can't see any content at all on the Android side, despite tomcat sending it). Make it a local variable, as proposed by EJP in his/her comment.
I think there may be some limitation on sending response from Tomcat.
There isn't.
How can I overcome this limitation of Tomcat?
There is no such limitation.
I am sending and getting the response using the following code:
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
// Making HTTP request
try {
// check for request method
if(method == "POST"){
Here you are incorrectly comparing strings. You should use equals(), not ==.
// ...
}else if(method == "GET"){
Ditto.
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
Here you are using is which may not have been initialized at all. It appears to be a member variable, so it is probably still null, so at this point I would expect a NullPointerException. is should of course be a local variable in this method.
I have printed the string received in this method. Surprisingly, the full string is not received in this method.
What is surprising is that anything is received, if that's what you're claiming. I would have expected an NPE.

Why am I getting last response if my server doesn't work?

I use simple code to get XML content.
but I have a trouble if my server doesn't work, I get last success response.
I tried all methods:
send every time another URI
setHeader Cache-Content How to prevent Android from returning a cached response to my HTTP Request?
I tried even HttpURLConnection with GET.
but nothing helps
DefaultHttpClient client = new DefaultHttpClient();
String fullPath = path + name;
HttpGet request = new HttpGet(fullPath);
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
//....decode input string

How to send image with post request

I need to send post request with data in format like key=value and I am working that like ( url is url of ws and that is ok )
HttpEntityEnclosingRequestBase post=new HttpPost();
String result = "";
HttpClient httpclient = new DefaultHttpClient();
post.setURI(URI.create(url));
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
for (Entry<String, String> arg : args.entrySet()) {
nameValuePairs.add(new BasicNameValuePair(arg.getKey(), arg
.getValue()));
}
http.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response;
response = httpclient.execute(post);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
result = getStringFromStream(instream);
instream.close();
}
return result;
This is ok when I send String data. My question is what to modify when one parameter is picture adn others are strings ?
When you are using multiple data types to send over a HttpClient you must use MultipartEntityBuilder(Class in org.apache.http.entity.mime)
try this out
MultipartEntityBuilder s= MultipartEntityBuilder.create();
File file = new File("sample.jpeg");
String message = "This is a multipart post";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
System.out.println(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("upfile", file, ContentType.DEFAULT_BINARY, "sample.jpeg");
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
HttpEntity entity = builder.build();
httppost.setEntity(entity);
}
If you are looking to send the image as the data portion of the post request, you can follow some of the links posted in the comments.
If the image / binary data must absolutely be a header (which I wouldn't recommend), then you should use the encodeToString method inside of the Base64 Android class. I wouldn't recommend this for big images though since you need to load the entire image into memory as a byte array before you can even convert it to a string. Once you convert it to a string, its also 4/3 its previous size.
I think the answer you're looking for is in this post:
How to send an image through HTTPPost?
Emmanuel

Categories

Resources