Android - Volley library: Session expired issue in SSL production environment - android

I had 2 pages: first one is login page and second is category page. In login API after entering the credentials, I am getting the response as sesssion id from response header.
The sesssion id will be saved and it will use for further API calls. I am trying to call second API (category page). In this page, as an input am passing the saved session id in the request header. Getting response as "session expired". Also tried to pass Set-Cookie: PHPSESSID=d9f9sdkfjs9 in the request header. but it didn't work.
Note :
I am experiencing this issue in production environment only (SSL included)
I am using volley library for handling APIs.
public void fnCallLoginAPI() {
try {
//DEMO URL
//final String URL="http://demo.io/api/api.php?m=login";
//LIVE URL
final String URL = "https://www.live.com/shop/api/api.php?m=login";
final String requestBody = "email=abc.b#xyz.com" + "&password=43443==" + "&strPlatform=i" + "&strDeviceToken=null";
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String strResponse = response;
System.out.println("THE RESPONSE IS in PROFILE IS" + response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
})
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
headers.put("Cookie", "PHPSESSID=" + sessionID);
return headers;
}
#Override
public byte[] getBody() throws AuthFailureError {
byte[] body = new byte[0];
try {
System.out.println("THE REQIEST BODY IS" + requestBody);
body = requestBody.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e("TAG", "Unable to gets bytes from JSON", e.fillInStackTrace());
}
return body;
}
};
AppApplication.getInstance().addToRequestQueue(stringRequest, "assignment");
} catch (Exception e) {
}
}
public void fnCallCateGoryAPI(){
try { final String URL ="https://www.live.com/shop/api/api.php?m=getcategories";
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String strResponse = response;
System.out.println("THE RESPONSE IS in PROFILE IS" + response);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(strResponse);
sessionID = jsonObj.optString("session_id");
System.out.print("sessionID" + sessionID);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
})
{
};
AppApplication.getInstance().addToRequestQueue(stringRequest, "assignment");
} catch (Exception e) {}
}}

#fazil try after increasing the token expiration time from the backend

#fazil : I was facing something similar in my projects too and the reason i understood was actually due to multiple header values set under same key "Set-Cookie".
Please do check this in your logs.
Also, make sure that you have set the headers properly in your request(check the logs of request and response from your Server).
If everything implemented is correct and the issue is due to multiple values in the same header you need to check this implementation of volley : https://github.com/georgiecasey/android-volley-duplicateheadersfix

Related

How to use POST request in android Volley library with params and header?

I am trying to learn Volley library for posting data into webservices. I need to implement user registration form, following is the image of postman with parameters and header...
now problem is, i am getting below error
com.android.volley.ServerError
this is my code for volley post method.
public void postNewComment(){
try {
RequestQueue requestQueue = Volley.newRequestQueue(this);
String URL = "http://myurl/api/users";
JSONObject jsonBody = new JSONObject();
jsonBody.put("email", "test1#gmail.com");
jsonBody.put("user_type", "C");
jsonBody.put("company_id", "0");
jsonBody.put("status", "A");
jsonBody.put("password", "123456");
final String requestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("VOLLEY", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.e("VOLLEY", error.toString());
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
final Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Basic " + "My_auth_key");
headers.put("Content-Type", "application/json");
return headers;
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
// can get more details such as response.headers
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
}
}
please suggest where am i getting wrong. URL is working correct with postman, also as you can see i need to set 2 headers. I also tried this Url post method with AsyncTask and its working good. Now i need to implement this using volley library. kindly suggest. thank you.
this is my logcat error:
E/Volley: [81910] BasicNetwork.performRequest: Unexpected response code 405 for "Myurl"
**Try this one **
private void sendWorkPostRequest() {
try {
String URL = "";
JSONObject jsonBody = new JSONObject();
jsonBody.put("email", "abc#abc.com");
jsonBody.put("password", "");
jsonBody.put("user_type", "");
jsonBody.put("company_id", "");
jsonBody.put("status", "");
JsonObjectRequest jsonOblect = new JsonObjectRequest(Request.Method.POST, URL, jsonBody, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Toast.makeText(getApplicationContext(), "Response: " + response.toString(), Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
onBackPressed();
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
final Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Basic " + "c2FnYXJAa2FydHBheS5jb206cnMwM2UxQUp5RnQzNkQ5NDBxbjNmUDgzNVE3STAyNzI=");//put your token here
return headers;
}
};
VolleyApplication.getInstance().addToRequestQueue(jsonOblect);
} catch (JSONException e) {
e.printStackTrace();
}
// Toast.makeText(getApplicationContext(), "done", Toast.LENGTH_LONG).show();
}
}
I have an alternative answer that works pretty well for Android Volley+ library by dworks and Google: See HERE

How to make XML api request with header, body and params?

I am following using https://gist.github.com/itsalif/6149365 library for making XML requests.
It uses Simple-XML for serialising XML to Objects.
I am able to make XML request successfully when there is no header and parameters associate with the SOAP api. However I am unable get response while performing little complex request which consist of header and parameters.
My request format looks like this
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.holidaywebservice.com/HolidayService_v2/">
<SOAP-ENV:Body>
<ns1:GetHolidaysAvailable>
<ns1:countryCode>UnitedStates</ns1:countryCode>
</ns1:GetHolidaysAvailable>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Code
HashMap<String, String> mapData = new HashMap<>();
final String mRequestBody = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"http://www.holidaywebservice.com/HolidayService_v2/\">\n" +
" <SOAP-ENV:Body>\n" +
" <ns1:GetHolidaysAvailable>\n" +
" <ns1:countryCode>UnitedStates</ns1:countryCode>\n" +
" </ns1:GetHolidaysAvailable>\n" +
" </SOAP-ENV:Body>\n" +
"</SOAP-ENV:Envelope>";
SimpleXmlRequest dellaRequest = new SimpleXmlRequest<String>
(Request.Method.POST, "http://www.holidaywebservice.com//HolidayService_v2/HolidayService2.asmx?wsdl", String.class, headerDataMap, bodyDataMap,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("BaseActivity", "response = " + response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("BaseActivity", "Error:" + error.getMessage());
}
}
){
#Override
public byte[] getBody() throws AuthFailureError {
try {
return mRequestBody == null ? null : mRequestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
mRequestBody, "utf-8");
return null;
}
}
};
I am getting 400 response code i.e. BAD REQUEST, state that invalid input is provided e.g validation error or missing data.
This api working fine in Postman rest client. So I am not able to figure out what am I doing wrong.
You can use Volley to call this XML request effectively.
String url = "http://www.holidaywebservice.com/HolidayService_v2/HolidayService2.asmx";
//Volley request
StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Response", response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error", error.getMessage());
}
}) {
#Override
public String getBodyContentType() {
// set body content type
return "text/xml; charset=UTF-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return reqXML.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
// TODO consider if some other action should be taken
return null;
}
}
};
//
//Creating a Request Queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//Adding request to the queue
requestQueue.add(request);

Adding POST parameters to Android Volley JsonObjectRequest

Good afternoon everyone
I did a volley connection to my localserver. It turns out, the connection works fine but my parameters are not getting accepted in my MysqlPHP script.
I believe the parameters are not getting sent correctly.
Here is the code
try {
RequestQueue jr = Volley.newRequestQueue(this);
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username);
params.put("password", password);
Log.d("The paramet ready", "Ready to go");
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.POST, url, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("The response", response.toString());
progressDial.hide();
JSONArray json = null;
try {
json = response.getJSONArray("result");
} catch (JSONException e) {
e.printStackTrace();
}
try {
if (json.getString(0).equalsIgnoreCase("0")) {
Log.d("JsonString: -> ", json.toString());
progressDial.hide();
toast();
} else {
startagain();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
progressDial.hide();
}
}
);
jr.add(jsonObject);
I encountered a similar issue. I had a server API which returned a JSON Object response, so JsonObjectRequest was the go-to request type, but the server didn't like that my body was in JSON format, so I had to make a few changes to my request.
Here's what I did (adapted to your code):
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.POST, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("The response", response.toString());
progressDial.hide();
JSONArray json = null;
try {
json = response.getJSONArray("result");
} catch (JSONException e) {
e.printStackTrace();
}
try {
if (json.getString(0).equalsIgnoreCase("0")) {
Log.d("JsonString: -> ", json.toString());
progressDial.hide();
toast();
} else {
startagain();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
progressDial.hide();
}
}
)
{
#Override
public byte[] getBody()
{
try
{
final String body = "&username=" + username + // assumes username is final and is url encoded.
"&password=" + password // assumes password is final and is url encoded.
return body.getBytes("utf-8");
}
catch (Exception ex) { }
return null;
}
#Override
public String getBodyContentType()
{
return "application/x-www-form-urlencoded";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
return headers;
}
};
Here, I'm not sending any JSON Object as the post body, but instead, I'm creating the post body on my own, form url encoded.
I'm overriding the following methods:
getBody - I'm creating the body of the post exactly the way the server wanted it - form url encoded.
getBodyContentType - I'm telling the server what the content type of my body is
getHeaders - I'm telling the server to return the result in JSON format. This might not be necessary for you.
If your API return a JSON array, then you should use a JsonArrayRequest, not a JsonRequest.

error response with Json request to Disqus on Volley (Android)

I am trying to connectt to Disqus with their api
(Specifically I am calling to POST https://disqus.com/api/oauth/2.0/access_token/ )
I am using JsonObjectRequest with Volley library for the network calls.
My response is consistently an error with code 400:
11-19 12:48:17.119: E/Volley(16124): [107902] BasicNetwork.performRequest: Unexpected response code 400 for http://disqus.com/api/oauth/2.0/access_token/
I have tried to proxy the request in Charles to see more info, and got this as the error message:
And this is my request as it was recorded by Charles (As you can see I did add the parameter grant_type):
I am calling the same request in the iOS version of my app, and am using the same keys and information, and everything works there. This is why I assume the problem is somewhere in my code, perhaps in the way I add/encode/not encode my parameters... This is the code I use to send the request:
String url = "http://disqus.com/api/oauth/2.0/access_token/";
JSONObject jsonObj = new JSONObject();
try {
jsonObj.put("grant_type", "authorization_code");
jsonObj.put("client_id", publicKey());
jsonObj.put("client_secret", SecretKey());
jsonObj.put("redirect_uri", redirectUrl());
jsonObj.put("code", code);
} catch (JSONException e1) {
e1.printStackTrace();
}
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.POST,
url, jsonObj, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String refreshToekn = (String) response.get("refresh_token");
String accessToekn = (String) response.get("access_token");
String stam = refreshToekn+accessToekn;
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Error: " + error.getMessage());
}
});
VolleyController.getInstance().addToRequestQueue(jsonObjReq);
The call always falls into onErrorResponse
I have also tried to use StringRequest and add the parameters in the url with no successes
So I managed to get it to work, but I would love if someone could explain why my solution works.
Basically, instead of using JSONObject and passing it to JsonObjectRequest I used a StringRequest and overrode getParams.
Was I wrong trying to send a POST request with JsonObjectRequest?
This is the entire solution:
String url = "http://disqus.com/api/oauth/2.0/access_token/";
StringRequest stringReq = new StringRequest(Method.POST,
url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String string = response;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("error: " + error.getMessage());
}
}) {
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
params.put("grant_type", "authorization_code");
params.put("client_id", publicKey());
params.put("client_secret", SecretKey());
params.put("redirect_uri",redirectUrl());
params.put("code", code);
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
params.put("Content-Type","application/x-www-form-urlencoded");
return params;
}
};
VolleyController.getInstance().addToRequestQueue(stringReq);

Android Volley - BasicNetwork.performRequest: Unexpected response code 400

Problem statement:
I am trying to access an REST API that will return a JSON object for various HTTP status codes (400, 403, 200 etc) using Volley.
For any HTTP status other than 200, it seems the 'Unexpected response code 400' is a problem. Does anyone have a way to bypass this 'error'?
Code:
protected void getLogin() {
final String mURL = "https://somesite.com/api/login";
EditText username = (EditText) findViewById(R.id.username);
EditText password = (EditText) findViewById(R.id.password);
// Post params to be sent to the server
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username.getText().toString());
params.put("password", password.getText().toString());
JsonObjectRequest req = new JsonObjectRequest(mURL, new JSONObject(
params), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject obj = response
.getJSONObject("some_json_obj");
Log.w("myApp",
"status code..." + obj.getString("name"));
// VolleyLog.v("Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.w("error in response", "Error: " + error.getMessage());
}
});
// add the request object to the queue to be executed
AppController.getInstance().addToRequestQueue(req);
}
One way of doing this without changing Volley's source code is to check for the response data in the VolleyError and parse it your self.
As of f605da3 commit, Volley throws a ServerError exception that contains the raw network response.
So you can do something similar to this in your error listener:
/* import com.android.volley.toolbox.HttpHeaderParser; */
public void onErrorResponse(VolleyError error) {
// As of f605da3 the following should work
NetworkResponse response = error.networkResponse;
if (error instanceof ServerError && response != null) {
try {
String res = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, "utf-8"));
// Now you can use any deserializer to make sense of data
JSONObject obj = new JSONObject(res);
} catch (UnsupportedEncodingException e1) {
// Couldn't properly decode data to string
e1.printStackTrace();
} catch (JSONException e2) {
// returned data is not JSONObject?
e2.printStackTrace();
}
}
}
For future, if Volley changes, one can follow the above approach where you need to check the VolleyError for raw data that has been sent by the server and parse it.
I hope that they implement that TODO mentioned in the source file.
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
You need to add Content-Type to the header.
Me too got the same error but in my case I was calling url with blank spaces.
Then, I fixed it by parsing like below.
String url = "Your URL Link";
url = url.replaceAll(" ", "%20");
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
...
...
...
Try this ...
StringRequest sr = new StringRequest(type,url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// valid response
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// error
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
params.put("username", username);
params.put("password", password);
params.put("grant_type", "password");
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
// Removed this line if you dont need it or Use application/json
// params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
You mean that want to get status codes?
VolleyError has a member variable type of NetworkResponse and it is public.
You can access error.networkResponse.statusCode for http error code.
I hope it is helpful for you.
What I did was append an extra '/' to my url, e.g.:
String url = "http://www.google.com"
to
String url = "http://www.google.com/"
in my case, I was not writing reg_url with :8080 .
String reg_url = "http://192.168.29.163:8080/register.php";
change
public static final String URL = "http://api-Location";
to
public static final String URL = "https://api-Location"
it's happen because i'm using 000webhostapp app
Just to update all, after some deliberations, I have decided to use Async Http Client instead to solve my earlier problem. The library allows a cleaner approach (to me) to manipulate HTTP responses especially in cases where JSON objects are returned in all scenarios/HTTP statuses.
protected void getLogin() {
EditText username = (EditText) findViewById(R.id.username);
EditText password = (EditText) findViewById(R.id.password);
RequestParams params = new RequestParams();
params.put("username", username.getText().toString());
params.put("password", password.getText().toString());
RestClient.post(getHost() + "api/v1/auth/login", params,
new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers,
JSONObject response) {
try {
//process JSONObject obj
Log.w("myapp","success status code..." + statusCode);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onFailure(int statusCode, Header[] headers,
Throwable throwable, JSONObject errorResponse) {
Log.w("myapp", "failure status code..." + statusCode);
try {
//process JSONObject obj
Log.w("myapp", "error ..." + errorResponse.getString("message").toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}

Categories

Resources