I am using Volley to upload pictures from Android application to server. In case when I have more than 3 pictures for upload, Volley throws AuthFailureError, even though I don't use any kind of authentication. For each picture, I am using separate request, which is sent when I receive response for previous one. Here is a code. Does anyone know what is the problem? Or shall I simply switch to Retrofit? Thanks!
private void sendRequest(String control){
Toast.makeText(MainReviewActivity.this, control, Toast.LENGTH_LONG).show();
//Toast.makeText(AfterLoginActivity.this, control, Toast.LENGTH_LONG).show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, UploadUrl, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
waiting_search_results = 0;
JSONObject jsonObject = new JSONObject(response);
String Response = jsonObject.getString("response");
if (control.equals("review_page_restaurant_search") || control.equals("review_page_meal_search")){
prepareSearchResultDataFromServer(control, Response);
} else{
if (control.equals("review_page_perform_review")){
if (Response.equals("Success")){
// check if there are pics to send
Log.d("debug:", "Perform review - positive resp received");
enablePicSending = 1;
} else{
loadingDialog.dismissDialog();
Toast.makeText(MainReviewActivity.this, "Greška u slanju ocene, pokušajte ponovo", Toast.LENGTH_LONG).show();
}
} else{
// control equals "review_page_upload_pic"
Log.d("debug:", "Uploading pic - resp received");
waitingPicSendingResp = 0;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(final VolleyError error) {
loadingDialog.dismissDialog();
Log.d("debug:", "Error occurred: " + error);
//Bundle bundle = new Bundle();
//bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "string");
//bundle.putString(FirebaseAnalytics.Param.CONTENT, "Volley failed during: " + control + ", reason: " + error);
//mFirebaseAnalytics.logEvent("Sending_failed", bundle);
Toast.makeText(MainReviewActivity.this, error.toString(), Toast.LENGTH_LONG).show();
if (control.equals("review_page_upload_pic")){
Toast.makeText(MainReviewActivity.this, "Slanje slika nije uspelo, pokušajte ponovo", Toast.LENGTH_LONG).show();
} else{
if (control.equals("review_page_perform_review")){
Toast.makeText(MainReviewActivity.this, "Slanje ocene nije uspelo, pokušajte ponovo", Toast.LENGTH_LONG).show();
} else{
Toast.makeText(MainReviewActivity.this, "Greška u komunikaciji", Toast.LENGTH_LONG).show();
}
}
finish();
}
})
{
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("control", control);
params.put("city", selectedCity);
if (control.equals("review_page_restaurant_search")){
params.put("search_word", search_word);
} else{
if (control.equals("review_page_meal_search")){
params.put("search_word", search_word);
params.put("restaurant", selectedRestaurant);
} else{
if (control.equals("review_page_perform_review")){
params.put("reviewer_pic", reviewer_pic);
params.put("reviewer_name", person_name);
params.put("reviewer_nick", reviewer_nick);
params.put("review_date", date);
params.put("restaurant", selectedRestaurant);
params.put("ambient", ambientGrade);
params.put("quick", quickGrade);
params.put("ratio", ratioGrade);
params.put("personnel", personnelGrade);
params.put("restaurant_comment", restaurantComment);
params.put("meal", selectedMeal);
params.put("amount", amountGrade);
params.put("taste", tasteGrade);
params.put("price", priceGrade);
params.put("meal_comment", mealComment);
} else{
if (control.equals("review_page_upload_pic")){
Log.d("debug:", "Triggering pic sending: " + picType);
Log.d("debug:", "Restaurant: " + selectedRestaurant);
Log.d("debug:", "Meal: " + selectedMeal);
//Bundle bundle = new Bundle();
//bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "string");
//bundle.putString(FirebaseAnalytics.Param.CONTENT, "Triggering pic sending: " + picType + ", restaurant: " + selectedRestaurant + ", meal: " + selectedMeal);
//mFirebaseAnalytics.logEvent("Pic_sending", bundle);
params.put("type", picType);
params.put("pic", pic);
params.put("restaurant", selectedRestaurant);
params.put("meal", selectedMeal);
} else{
// should not happen
}
}
}
}
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", "Mozilla/5.0");
return headers;
}
@Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded";
}
};
RequestQueue requestQueue = Volley.newRequestQueue(MainReviewActivity.this);
requestQueue.add(stringRequest);
}
EDIT
I read more about Authentication failure
and I noticed in documentation that when that happens, server shall provide WWW-Authenticate
response header, so I tried to read it with parseNetworkResponse
function. In the moment of Toasting (i.e. the moment after parsing the latest network response), my observations are following: WWW-Authenticate
header is missing, some pictures are not uploaded to server, server provided response 200, but Volley called onErrorResponse method (from which I am Toasting). How is it possible to receive response 200, but AuthFailureError is detected in OnErrorResponse method? New code, with parsing network response and debug Toasts:
private void sendRequest(String control){
//Toast.makeText(MainReviewActivity.this, control, Toast.LENGTH_LONG).show();
//Toast.makeText(AfterLoginActivity.this, control, Toast.LENGTH_LONG).show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, UploadUrl, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
waiting_search_results = 0;
JSONObject jsonObject = new JSONObject(response);
String Response = jsonObject.getString("response");
if (control.equals("review_page_restaurant_search") || control.equals("review_page_meal_search")){
prepareSearchResultDataFromServer(control, Response);
} else{
if (control.equals("review_page_perform_review")){
if (Response.equals("Success")){
// check if there are pics to send
Log.d("debug:", "Perform review - positive resp received");
enablePicSending = 1;
} else{
loadingDialog.dismissDialog();
Toast.makeText(MainReviewActivity.this, "Greška u slanju ocene, pokušajte ponovo", Toast.LENGTH_LONG).show();
}
} else{
// control equals "review_page_upload_pic"
success_count++;
//Toast.makeText(MainReviewActivity.this, Response, Toast.LENGTH_LONG).show();
Log.d("debug:", "Uploading pic - resp received");
waitingPicSendingResp = 0;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(final VolleyError error) {
loadingDialog.dismissDialog();
Log.d("debug:", "Error occurred: " + error);
error_count++;
Toast.makeText(MainReviewActivity.this, "Parse count: " + String.valueOf(parse_count), Toast.LENGTH_LONG).show();
Toast.makeText(MainReviewActivity.this, "Error count: " + String.valueOf(error_count), Toast.LENGTH_LONG).show();
Toast.makeText(MainReviewActivity.this, "Success count: " + String.valueOf(success_count), Toast.LENGTH_LONG).show();
for (int i = 0; i < names.length; i++){
Toast.makeText(MainReviewActivity.this, "Name: " + names[i] + " Value: " + values[i], Toast.LENGTH_LONG).show();
}
//Toast.makeText(MainReviewActivity.this, "Success: " + String.valueOf(success_count) + " Error: " + String.valueOf(error_count) + "Parse: " + String.valueOf(parse_count), Toast.LENGTH_LONG).show();
//Toast.makeText(MainReviewActivity.this, error.getCause().toString(), Toast.LENGTH_LONG).show();
//Toast.makeText(MainReviewActivity.this, error.getCause().getMessage(), Toast.LENGTH_LONG).show();
//Toast.makeText(MainReviewActivity.this, error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
//Bundle bundle = new Bundle();
//bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "string");
//bundle.putString(FirebaseAnalytics.Param.CONTENT, "Volley failed during: " + control + ", reason: " + error);
//mFirebaseAnalytics.logEvent("Sending_failed", bundle);
//Toast.makeText(MainReviewActivity.this, error.toString(), Toast.LENGTH_LONG).show();
if (control.equals("review_page_upload_pic")){
Toast.makeText(MainReviewActivity.this, "Slanje pojedinih slika nije uspelo, ali je ocena poslata uspešno", Toast.LENGTH_LONG).show();
} else{
if (control.equals("review_page_perform_review")){
Toast.makeText(MainReviewActivity.this, "Slanje ocene nije uspelo, pokušajte ponovo", Toast.LENGTH_LONG).show();
} else{
Toast.makeText(MainReviewActivity.this, "Greška u komunikaciji", Toast.LENGTH_LONG).show();
}
}
finish();
}
})
{
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("control", control);
params.put("city", selectedCity);
if (control.equals("review_page_restaurant_search")){
params.put("search_word", search_word);
} else{
if (control.equals("review_page_meal_search")){
params.put("search_word", search_word);
params.put("restaurant", selectedRestaurant);
} else{
if (control.equals("review_page_perform_review")){
params.put("reviewer_pic", reviewer_pic);
params.put("reviewer_name", person_name);
params.put("reviewer_nick", reviewer_nick);
params.put("review_date", date);
params.put("restaurant", selectedRestaurant);
params.put("ambient", ambientGrade);
params.put("quick", quickGrade);
params.put("ratio", ratioGrade);
params.put("personnel", personnelGrade);
params.put("restaurant_comment", restaurantComment);
params.put("meal", selectedMeal);
params.put("amount", amountGrade);
params.put("taste", tasteGrade);
params.put("price", priceGrade);
params.put("meal_comment", mealComment);
} else{
if (control.equals("review_page_upload_pic")){
Log.d("debug:", "Triggering pic sending: " + picType);
Log.d("debug:", "Restaurant: " + selectedRestaurant);
Log.d("debug:", "Meal: " + selectedMeal);
//Bundle bundle = new Bundle();
//bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "string");
//bundle.putString(FirebaseAnalytics.Param.CONTENT, "Triggering pic sending: " + picType + ", restaurant: " + selectedRestaurant + ", meal: " + selectedMeal);
//mFirebaseAnalytics.logEvent("Pic_sending", bundle);
params.put("type", picType);
params.put("pic", pic);
params.put("restaurant", selectedRestaurant);
params.put("meal", selectedMeal);
} else{
// should not happen
}
}
}
}
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", "Mozilla/5.0");
headers.put("Content-Type", "application/x-www-form-urlencoded");
return headers;
}
@Override
public String getBodyContentType()
{
return "application/x-www-form-urlencoded";
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
parse_count++;
names = new String[response.allHeaders.size()];
values = new String[response.allHeaders.size()];
for (int i = 0; i < response.allHeaders.size(); i++){
names[i] = response.allHeaders.get(i).getName();
values[i] = response.allHeaders.get(i).getValue();
Log.d("debug:", "parse_count" + parse_count);
Log.d("debug:", "names" + i + ": " + names[i]);
Log.d("debug:", "values" + i + ": " + values[i]);
}
return super.parseNetworkResponse(response);
}
};
RequestQueue requestQueue = Volley.newRequestQueue(MainReviewActivity.this);
requestQueue.add(stringRequest);
}
Thanks everyone for answers. The problem was in ModSecurity, an Apache module that works as a web application firewall. I contacted hosting provider and they told be that was the issue.
If you are experiencing the same issue, check your server logs and provide them to your hosting provider to investigate if this is your issue.