首页 文章

Android Volley POST 请求返回错误 400(错误请求)

提问于
浏览
2

我正在尝试使用 Volley Library 使用 JAVA android 应用程序向 Azure IoT Hub 发出 POST 请求,但是我收到此错误:BasicNetwork.performRequest:https://elca-iot.azure-devices.net/devices/elca-main-device/messages/events?api-version=2016-02-03的意外响应代码 400)

要访问 IoT Hub,我需要使用我需要包含在请求标头中的 SAS 密钥。 android 应用程序代码如下:

RequestQueue queue = Volley.newRequestQueue(c);
    String url = "https://elca-iot.azure-devices.net/devices/" + deviceId + "/messages/events?api-version=2016-02-03)";
    // Request a string response from the provided URL.
    StringRequest stringRequest = new StringRequest(Request.Method.POST,
            url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            onPostResponse(response, c, true);
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("Error", error.getMessage());
            onPostResponse(error.getMessage(), c, false);
        }
    }) {
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            //params.put("Content-Type", "application/xml");
            params.put("Authorization", "[My SAS Key]");
            params.put("Cache-Control", "no-cache");
            return params;
        }
        /*
        @Override
        public Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("api-version","2016-02-03");
            return params;
        }*/
        @Override
        public String getBodyContentType() {
            return "application/text; charset=UTF-8";
        }
        @Override
        public byte[] getBody(){
            return "On".getBytes();
        }
    };
    try {
        Log.d("request", String.valueOf(stringRequest.getMethod()==Request.Method.POST));
    } catch (Exception authFailureError) {
        authFailureError.printStackTrace();
    }
    // Add the request to the RequestQueue.
    queue.add(stringRequest);

我尝试使用 POSTMAN 执行相同的请求并且它有效,我不知道为什么它不能使用 Android 应用程序。这是使用 POSTMAN 发出的请求的 http 代码:

POST /devices/elca-main-device/messages/events?api-version=2016-02-03 HTTP/1.1
Host: elca-iot.azure-devices.net
Authorization: [My SAS Key]
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: d0aa354a-f79c-e574-893a-c259232aa5cb

on

编辑:

POSTMAN 的屏幕截图

4 回答

  • 2

    似乎问题在于地图中的价值。 [1]无法逃脱。

    params.put("Authorization", "[My SAS Key]");
    

    我做的是,在创建参数时,我用 UTF-8 编码了键和值。

    params.put("Authorization", URLEncoder.encode("[My SAS Key]", "UTF-8"));
    

    我也在这个问题上挣扎了 3 天。这似乎是一种解决方法,但它对我有用。

  • 1

    似乎问题是body content type尝试在getHeadersgetBodyContentType中添加它

    @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                //params.put("Content-Type", "application/xml");
                params.put("Authorization", "[My SAS Key]");
                params.put("Cache-Control", "no-cache");
                params.put("Content-Type", "application/x-www-form-urlencoded");
                return params;
            }
            /*
            @Override
            public Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("api-version","2016-02-03");
                return params;
            }*/
            @Override
            public String getBodyContentType() {
                return "application/x-www-form-urlencoded; charset=UTF-8";
            }
    
  • 0

    根据 Azure IoTHub 的常见错误代码,400 错误代码表示"The body of the request is not valid; for example, it cannot be parsed, or the object cannot be validated."

    同时,作为常用参数和标题的官方 REST 参考说,"Set the Content-Type header to application/json."

    因此,请尝试更改您的代码,如下所示。

    • getHeaders方法中添加Content-Type标头。
    params.put("Content-Type", "application/json");
    
    • 更改getBodyContentType方法的 reture 值,并在getBody方法中使用getBytesUTF-8
    @Override
    public String getBodyContentType() {
        return "application/json; charset=UTF-8";
    }
    @Override
    public byte[] getBody(){
        return "On".getBytes("UTF-8");
    }
    
  • 0

    默认情况下,Android Volley POST 请求将 Content-Type 设置为值“application/json; charset=UTF-8”。如果您在请求调用中设置内容类型,它将覆盖您的内容类型。例如,如果您的发送请求为“Content-Type”,“application/json”,那么它会将内容类型设置为“application/json”。但如果你删除它然后自动设置为“application/json; charset=UTF-8”。这里的问题是如果你的后端 configured(written 由开发人员)只管理“application/json”请求然后默认调用“application/json; charset=UTF-8”将使你的 request.(Problem 与后端开发失败)。但这在 POSTMAN 中可以正常工作。所以无法弄清楚这里究竟出了什么问题。由于您可以通过将“Content-Type”设置为“application/json”来发送帖子请求,然后依赖于 Volley 版本,您的通话将会失败。只有 Volley 版本 1.1.1 才会支持覆盖。 ( 'com.android.volley:volley:1.1.1')。所以我的建议是你必须遵循 3 个步骤。

    • 发送你的 POST 请求没有 content-type 并检查响应。如果它是 400,则后端配置存在问题。

    • 在构建渐变中将您的齐射版本更改为“com.android.volley:volley:1.1.1”

    • 再次发送 POST 请求作为这样的标题。 customHeaders.put( “Content-Type”, “application/json”);

    它现在应该工作。

相关问题