繁体   English   中英

使用JSON正文发送POST请求时出现400响应

[英]400 response when sending POST request with JSON body

我一直在这个站点和其他站点中搜索有关使用JSON主体发出POST请求的解决方案,但是我发现的解决方案似乎对我不起作用。 作为参考,这是我使用终端上的curl发出的成功请求:

curl -I -X POST -H "x-app-id:myID" -H "x-app-key:myKey" 
-H "Content-Type:application/json" -H "x-remote-user-id:0" 
https://trackapi.nutritionix.com/v2/natural/exercise -d '{
 $+  "query":"ran 3 miles",
 $+  "gender":"female",
 $+  "weight_kg":72.5,
 $+  "height_cm":167.64,
 $+  "age":30
 $+ }'

我尝试将其转换为android应用程序的尝试使我陷入凌空,而四处搜寻导致我使用以下代码段:

try {
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    JSONObject jsonBody = new JSONObject();
    jsonBody.put("query", "ran 3 miles");
    jsonBody.put("gender", "female");
    jsonBody.put("weight_kg", 72.5);
    jsonBody.put("height_cm", 167.64);
    jsonBody.put("age", 30);
    final String mRequestBody = jsonBody.toString();
    String url = "https://trackapi.nutritionix.com/v2/natural/exercise";

    StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.i("LOG_RESPONSE", response);
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e("LOG_RESPONSE", error.getMessage());
        }
    }) {

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            params.put("x-app-id", "myID");
            params.put("x-app-key", "myKey");
            params.put("Content-Type", "application/json");
            params.put("x-remote-user-id", "0");
            return params;
        }

        @Override
        public String getBodyContentType() {
            return "application/json; charset=utf-8";
        }

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

        @Override
        protected Response<String> parseNetworkResponse(NetworkResponse response) {
            String responseString = "";
            if (response != null) {
                responseString = String.valueOf(response.statusCode);
            }
            return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
        }
    };

    requestQueue.add(stringRequest);
} catch (JSONException e) {
    e.printStackTrace();
}

API规定必须在正文中发送数据,这就是为什么我排除了getParams函数的原因。 该代码段似乎对互联网上的其他所有人都有效,但是我一直从中收到400条消息。 我也将相同的curl请求转换为邮递员中的请求,并且在那里也很好用。 有人对我哪里出问题有任何见解吗?

编辑: 这是根据要求到api的链接

我使用这种方法发送请求。

您将使用这种方法。

executePost("https://trackapi.nutritionix.com/v2/natural/exercise", mRequestBody, API_KEY);

请注意,对我来说,正如您将看到的,对于prod env或较低env,我有不同的API密钥。 因此,您可能不需要API_KEY部分...但是查看标头,您将.. :)

public static String executePost(String targetURL, String requestJSON, String apikey) {
        HttpURLConnection connection = null;
        InputStream is = null;

        try {
            //Create connection
            URL url = new URL(targetURL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            //TODO may be prod or preprod api key
            if (apikey.equals(Constants.APIKEY_PREPROD)) {
                connection.setRequestProperty("Authorization", Constants.APIKEY_PREPROD);
            }
            if (apikey.equals(Constants.APIKEY_PROD)){
                connection.setRequestProperty("Authorization", Constants.APIKEY_PROD);
            }
            connection.setRequestProperty("Content-Length", Integer.toString(requestJSON.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");  
            connection.setUseCaches(false);
            connection.setDoOutput(true);

            //Send request
            DataOutputStream wr = new DataOutputStream (
            connection.getOutputStream());
            wr.writeBytes(requestJSON);
            wr.close();

            //Get Response  

            try {
                is = connection.getInputStream();
            } catch (IOException ioe) {
                if (connection instanceof HttpURLConnection) {
                    HttpURLConnection httpConn = (HttpURLConnection) connection;
                    int statusCode = httpConn.getResponseCode();
                    if (statusCode != 200) {
                        is = httpConn.getErrorStream();
                    }
                }
            }

            BufferedReader rd = new BufferedReader(new InputStreamReader(is));


            StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
            String line;
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();
        } catch (Exception e) {

            e.printStackTrace();
            return null;

        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

我还想澄清一些其他内容。 此代码在我的本地计算机上使用,不面向客户。 代码的安全性不是,对于我的用例来说也不是问题。 确保安全存储API密钥。

您确定要在x-app-id和其他字段中传递正确的ID吗? 因为根据日志,它说"x-app-id" = "myId"您需要传递应用程序的实际ID。

另外,您已经在getBodyContentType()定义了content-type因此不要在getHeaders()提及它,或者相反。

并且根据API文档 ,不需要x-remote-user-id 也许这就是您的请求返回400错误的原因

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM