Search code examples
javaandroidhttpserverandroid-volley

Volley throws AuthFailureError


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);
}

Solution

  • 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.