HTTPURLConnection - 400 Bad Request - android

I check this Post. But I don't still understand what the logical error could be. I am still getting this error. I tried to dump the emulator traffic. But I still don't get my head around what the problem could be.
From the traffic dump, this is what Android is sending as request to the server. You can see the response too:
GET /Authenticate/ HTTP/1.1
Authorization: Basic asdfasdfasdfas
Accept-Charset: UTF-8
Host: www.domain.com
User-Agent: Dalvik/1.4.0 (Linux; U; Android 2.3.3; sdk Build/GRI34)
Connection: Keep-Alive
Accept-Encoding: gzip
neQPˆ? 6 6 RT 4VRT 5 E (
» #ÍCl¦'
PÙ[ ˜ároP"8" neQPI " " RT 4VRT 5 E
¼ #ËVl¦'
PÙ[ ˜ároP"8«‹ HTTP/1.1 400 Bad Request
Date: Thu, 13 Sep 2012 04:47:42 GMT
Server: Apache/2.2.15 (CentOS)
Content-Length: 310
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at www.domain.com Port 80</address>
</body></html>
neQPé¬ 6 6 RT 4VRT 5 E (
½ #ÍAl¦'
PÙ[ ™îároP"8 , neQPéË # # RT 5RT 4V E (çØ# #³-
l¦'Ù[ Páro ™îP )E neQPéË # # RT 5RT 4V E (çÙ# #³,
l¦'Ù[ Páro ™ïP )D neQPö“
© © RT 5RT 4V E ›k‹# #¶Á
³ër,9Jr ‘Pÿÿ6B WRTE w [ * ¨­«º[ 09-13 04:47:41.822 446:0x1c7 D/400 ]
text/html; charset=iso-8859-1Bad Request
I don't know what those extra characters mean. But I was trying to identify the problem from it.
This is the basic code:
String credentials = username + ":" + password;
byte[] toencode = null;
try {
toencode = credentials.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
HttpURLConnection conn = null;
try {
//Utilities.isNetworkAvailable(context);
URL url = new URL(params[0]);
Log.d(params[0],"UR");
conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Basic " + Base64.encodeToString(toencode, Base64.DEFAULT));
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setRequestProperty("Host", "www.domain.com");
conn.setRequestMethod("GET");
conn.setDoOutput(true);
String data = conn.getInputStream().toString();
return data;
}
Any ideas?
Update
I checked Webserver Logs to see if the requests are hitting the server and if there was any problem with the request. This is what I see from error logs:
[Thu Sep 13 10:05:24 2012] [error] [client 91.222.195.132] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /Authenticate/
[Thu Sep 13 23:11:57 2012] [error] [client 91.222.195.132] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /Authenticate/
[Thu Sep 13 23:12:03 2012] [error] [client 91.222.195.132] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /Authenticate/
However I am setting the header property for the request.
Any ideas?

I figured out this myself. Its an issue with the order of setting headers.
Edit: Order I used.
URL url = new URL(strUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Host", "myhost.com");
conn.setRequestProperty("Authorization", "Basic " + Base64.encodeToString(toencode, Base64.DEFAULT));
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.3.1)");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setConnectTimeout (5000) ;
conn.setDoOutput(true);
conn.setDoInput(true);

I was also facing this issue, but i fixed it by changing my codes, now i am using following lines of codes
BufferedReader reader;
StringBuffer buffer;
String res = null;
try {
URL url = new URL(request_url);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(40000);
con.setConnectTimeout(40000);
con.setRequestMethod("GET");
con.setRequestProperty("Accept","application/json");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setDoInput(true);
con.setDoOutput(true);
int status = con.getResponseCode();
InputStream inputStream;
if (status == HttpURLConnection.HTTP_OK) {
inputStream = con.getInputStream();
} else {
inputStream = con.getErrorStream();
}
reader = new BufferedReader(new InputStreamReader(inputStream));
buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
res = buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return res;

Try this
static final String _url = "http://www.google.com";
static final String charset = "UTF-8";
// to build the query string that will send the message
private static String buildRequestString(String param1,
String param2, String param3, String param4, String param5)
throws UnsupportedEncodingException {
String[] params = new String[5]; //customize this as per your need
params[0] = param1;
params[1] = param2;
params[2] = param3;
params[3] = param4;
params[4] = param5;
String query = String.format(
"uid=%s&pwd=%s&msg=%s&phone=%s&provider=%s",
URLEncoder.encode(params[0], charset),
URLEncoder.encode(params[1], charset),
URLEncoder.encode(params[2], charset),
URLEncoder.encode(params[3], charset),
URLEncoder.encode(params[4], charset));
return query;
}
public static void doSomething(String param1, String param2,
String param3, String param4, String param5) throws Exception {
// To establish the connection and perform the post request
URLConnection connection = new URL(_url
+ "?"
+ buildRequestString(param1, param2, param3, param4,
param5)).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
// This automatically fires the request and we can use it to determine
// the response status
InputStream response = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(response));
// This stores the response code.
// Any call to br.readLine() after this is null.
responsecode = br.readLine();
// And this logs the already stored response code
Log.d("ServerResponse", responsecode);
responseInt = Integer.valueOf(responsecode).intValue();
}

Related

Please give very simple basic POST command code for android studio

I want to send a simple POST command to upload files. How can I write the code in android developer? Code should give the following POST request
POST /macros/s/AqtUErjtk/postform?no&func=uploadFiles HTTP/1.1
Host: xyz.website.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------236532717524914
Content-Length: 337
Cookie:
NID=106=gWQeUVIa2phdDJeXYdRFSPTnsklPrFVRwphw3G685QYZlDiZz7NK5PoJVEd1FYL6IqYoJ9fEtVHf0sKBIHq1wD1xr
Connection: close
Upgrade-Insecure-Requests: 1
-----------------------------236532717524914
Content-Disposition: form-data; name="_1_myFile"; filename="textfile.txt"
Content-Type: text/plain
Here is the text file content yoyoyoyoyoy
-----------------------------236532717524914--
In the following link you will see an example in which a POST is made:
https://community.particle.io/t/example-android-application-post-get/9355
This is the exact code extracted from the link above:
class PostClient extends AsyncTask<String, Void, String> {
public String doInBackground(String... IO) {
// Predefine variables
String io = new String(IO[0]);
URL url;
try {
// Stuff variables
url = new URL("https://api.spark.io/v1/devices/YOURCOREID/SCL/");
String param = "access_token=YOURACCESSTOKEN&params=d7,"+io;
Log.d(TAG, "param:" + param);
// Open a connection using HttpURLConnection
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setReadTimeout(7000);
con.setConnectTimeout(7000);
con.setDoOutput(true);
con.setDoInput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setFixedLengthStreamingMode(param.getBytes().length);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// Send
PrintWriter out = new PrintWriter(con.getOutputStream());
out.print(param);
out.close();
con.connect();
BufferedReader in = null;
if (con.getResponseCode() != 200) {
in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
Log.d(TAG, "!=200: " + in);
} else {
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
Log.d(TAG, "POST request send successful: " + in);
};
} catch (Exception e) {
Log.d(TAG, "Exception");
e.printStackTrace();
return null;
}
// Set null and we´e good to go
return null;
}
}
}
I hope it helps.

Getting Http status 400 in api 23 and below

I have to call one Rest API of GET request.
When I used emulator of API 24 it working fine. but same code on my phone i.e API 23 and API 18 it give 400 status i.e. bad request.
URL url = new URL(voids[0]);
Log.i("url", voids[0]);
//URL url = new URL(urlString);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.addRequestProperty("User-Agent", "REST");
System.setProperty("http.keepAlive", "false");
con.setRequestProperty("Accept", "*//*");
con.setConnectTimeout(10000);
con.setReadTimeout(10000);
con.setAllowUserInteraction(false);
con.setRequestMethod("GET");
responseCode = con.getResponseCode();
System.out.println("Sending get request : " + url);
System.out.println("Response code : " + responseCode);
// Reading response from input Stream
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null) {
response.append(output);
}
in.close();
System.out.println(response.toString());
Url : http://milk.gall5.com/api/SalePunch?CustomerID=1&Model={"CustomerID":"1","lstSalesPunchDetail":[{"ListManufacturer":[{"ManufactureID":1,"ManufacturerName":"Amul","One":40,"OneByFour":10,"OneByTwo":20,"QtyOne":0,"QtyOneByFour":23,"QtyOneByTwo":330,"visibilityOne":true,"visibilityOneByFour":true,"visibilityOneByTwo":true}],"ProductId":2,"ProductName":"Ton Milk"}]}
Try to encode the Model parameter of your URL first.
You can do that with the URLEncoder.encode() method

Android HttpUrlConnection Cannot Post - Error 403

I'm trying to issue a HttpPost against my webservice with spring security csrf.
first, I'm trying to recover the XSRF TOKEN through a GET request, like this
public static CookieManager xcsrfToken() throws IOException{
String token;
URL url = new URL(urlBase);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
CookieManager cookieManager = new CookieManager();
con.connect();
List<String> cookieHeader = con.getHeaderFields().get("Set-Cookie");
if (cookieHeader != null) {
for (String cookie : cookieHeader) {
cookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
}
}
System.out.println(con.getHeaderFields());
con.disconnect();
return cookieManager;
}
This is what i get from the con.getHeaderFields()
{null=[HTTP/1.1 200 OK], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Content-Language=[pt-BR], Content-Length=[973], Content-Type=[text/html;charset=ISO-8859-1], Date=[Wed, 19 Aug 2015 10:40:18 GMT], Expires=[0], Pragma=[no-cache], Server=[Apache-Coyote/1.1], Set-Cookie=[JSESSIONID=6C9326FBEEA14752068720006F2B5EAA; Path=/webapi/; HttpOnly, XSRF-TOKEN=07cbed7f-834e-4146-8537-0a6b5669f223; Path=/], X-Android-Received-Millis=[1439980819720], X-Android-Response-Source=[NETWORK 200], X-Android-Sent-Millis=[1439980819693], X-Content-Type-Options=[nosniff], X-Frame-Options=[DENY], X-XSS-Protection=[1; mode=block]}
The XSRF-TOKEN is in my cookie, ok!
If I print then with
System.out.println(cookieManager.getCookieStore().getCookies());
I got this
[JSESSIONID=5B1D3E2D3E7B3E1E6572A3839BFF3741, XSRF-TOKEN=4d4048bd-f21c-48c6-895e-5f67523ad963]
Now, I'm trying to issue a POST against the server, like this
public static HttpURLConnection makeRequest(String metodo, String uri, String requestBody) throws IOException{
URL url = new URL(urlBase + uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(!metodo.equals("GET"));
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Cookie", TextUtils.join("," , xcsrfToken().getCookieStore().getCookies()));
con.connect();
InputStream is = con.getErrorStream();
System.out.println(IOUtils.toString(is, "UTF-8"));
System.out.println(con.getHeaderFields());
return con;
}
But the header is comming back without the cookies
{null=[HTTP/1.1 403 Forbidden], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Content-Language=[en], Content-Length=[1149], Content-Type=[text/html;charset=utf-8], Date=[Wed, 19 Aug 2015 10:42:18 GMT], Expires=[0], Pragma=[no-cache], Server=[Apache-Coyote/1.1], X-Android-Received-Millis=[1439980939827], X-Android-Response-Source=[NETWORK 403], X-Android-Sent-Millis=[1439980939811], X-Content-Type-Options=[nosniff], X-Frame-Options=[DENY], X-XSS-Protection=[1; mode=block]}
And it says that don't have a CSRF valid token
Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.
In my webservice, the tokens is configured to rename to XSRF-TOKEN because of angularJs.
SOLUTION
public static void getTokens() throws IOException{
URL url = new URL(urlBase);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();
cookieManager = new CookieManager();
List<String> cookieHeader = con.getHeaderFields().get("Set-Cookie");
if (cookieHeader != null) {
for (String cookie : cookieHeader) {
String[] tokens = TextUtils.split(cookie, "=");
if (tokens[0].equals("JSESSIONID"))
cookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
if (tokens[0].equals("XSRF-TOKEN")) {
String[] tokenValue = TextUtils.split(tokens[1],";");
xsrfTOKEN = tokenValue[0];
}
}
}
con.disconnect();
}
Then, attach it to HttpUrlConnection
con.setRequestProperty("X-XSRF-TOKEN", xsrfTOKEN);
As I have experienced, we would need to submit the token as a request header. Spring expects its name to be X-CSRF-TOKEN by default. But people using AngularJS normally alter it to X-XSRF-TOKEN in Spring Security configuration.
But looking at your code, I couldn't figure out if you are sending that header.
If it would help, here is a snippet from my one project (using RestAssured):
if (xsrfToken != null && !ctx.getRequestMethod().equals(Method.GET))
requestSpec.header("X-XSRF-TOKEN", xsrfToken);

POST function for REST service returns empty response

I'm trying to do a post method for a REST service, but I'm not getting any response from server:
public JSONObject postValues (String strUrl, String strJsonArray) throws Exception{
JSONObject jsonObject = null;
URL url = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
strJsonArray = "data=" + strJsonArray;
Log.e("result",""+strJsonArray);
OutputStream os = conn.getOutputStream();
os.write(strJsonArray.getBytes());
os.flush();
conn.connect();
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
StringBuilder sb = new StringBuilder();
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
Log.e("output",output);
sb.append(output);
}
Log.e("output",sb.toString());
jsonObject = new JSONObject(sb.toString());
conn.disconnect();
return jsonObject;
}
When I see my logCat a get:
output {}
I know that the server is working right because I'm using the "advanced REST client" plugin of google chrome. If I call the URL manually (using the plugin of course)I get the desired answer:
{"message":"OK","code":200}
But if I try to use my function, my strJsonArray is inserted but I get an empty respond from server.
Is there anything wrong with my code?.
Everything looks good...
You could use Wireshark to capture the packets sent to and received from the server using an emulator and the chrome rest client. Then you can compare them and maybe find out what's wrong.
You could also check if theres something in the error stream (conn.getErrorStream()).

Basic authentication to access assembla rest apis from android

I want to use assembla apis from android environment for my project.
I am trying to do basic authentication as follow :
String authentication = "username:password";
String encoding = Base64.encodeToString(authentication.getBytes(), 0);
URL url = new URL("https://www.assembla.com/");
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Basic " + encoding);
conn.setDoOutput(true);
conn.connect();
System.out.println(conn.getResponseCode());
System.out.println(conn.getResponseMessage());
I am getting 400 and Bad Request in output.
is there something wrong with URL that i am using or some other thing is going wrong?
It looks like the question was answered here. You need to use Base64.NO_WRAP flag when encoding username-password pair:
String encoding = Base64.encodeToString(authentication.getBytes(), Base64.NO_WRAP);
By default the Android Base64 util adds a newline character to the end of the encoded string. This invalidates the HTTP headers and causes the "Bad request".
The Base64.NO_WRAP flag tells the util to create the encoded string without the newline character thus keeping the HTTP headers intact.
REST API with HTTP Authentication Output:- I got the result
String authentication = "username:password";
String encoding = Base64.encodeToString(authentication.getBytes(), Base64.NO_WRAP);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
conn.setRequestProperty ("Authorization", "Basic " + encoding);
conn.connect();
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write( data );
wr.flush();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
// Append server response in string
sb.append(line + "\n");
}
Content = sb.toString();

Categories

Resources