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

时间:2018-06-28 16:50:45

标签: java android

我一直在这个站点和其他站点中搜索有关使用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请求转换为邮递员中的请求,并且在那里也很好用。有人对我哪里出问题有任何见识吗?

编辑:Here's a link to the api as requested

2 个答案:

答案 0 :(得分:0)

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

您将使用这种方法。

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

请注意,对我来说,如您所见,对于生产环境或较低环境,我有不同的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密钥。

答案 1 :(得分:0)

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

  

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

根据API documentationx-remote-user-id不是必需的。也许这就是您的请求返回400错误的原因

相关问题