You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Volley GET请求返回406错误,对应curl请求正常

问题分析与解决方案

首先,你的核心问题出在请求头和请求体的混淆,以及缺少必要的Accept请求头,这直接导致了服务器返回406错误(服务器无法提供客户端可接受的响应格式)。

错误点拆解

  1. 请求头错误放入请求体:你把Content-Type、Auth-Token这些本该放在请求头里的字段,错误地添加到了请求体的JSONObject中。服务器无法识别这些作为业务参数的头信息,导致认证和格式校验失败。
  2. 缺少Accept请求头:406错误的本质是服务器不知道该返回什么格式的响应给客户端,添加Accept: application/json头可以明确告诉服务器我们只接受JSON格式的响应。
  3. GET请求带请求体的Volley处理:虽然HTTP标准允许GET请求带请求体,但Volley的JsonObjectRequest需要正确区分请求头和请求体,不能混在一起。

修正后的代码实现

首先,拆分请求头和请求体,重写getHeaders方法来设置头信息,请求体只保留业务参数:

// 1. 构造仅包含业务参数的请求体
JSONObject requestBody = new JSONObject();
try {
    requestBody.put("detail", "Y");
} catch(JSONException e) {
    Log.d(TAG, e.getMessage());
}

// 2. 创建JsonObjectRequest并重写getHeaders方法设置请求头
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, searchRequest, requestBody,
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                searchDialog.dismiss();
                Log.d(TAG, String.valueOf(response));
            }
        }, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        searchDialog.dismiss();
        // 你的错误处理逻辑保持不变
        if( error instanceof NetworkError) {
            Log.d(TAG, error.toString());
            Log.d(TAG, "Request to "+searchRequest+" FAILED...");
        } else if( error instanceof ServerError) {
            Log.d(TAG, "Request to "+searchRequest+" FAILED...");
            Log.d(TAG, error.toString());
        } else if( error instanceof AuthFailureError) {
            Log.d(TAG, error.toString());
            Log.d(TAG, "Request to "+searchRequest+" FAILED...");
        } else if( error instanceof ParseError) {
            Log.d(TAG, error.toString());
            Log.d(TAG, "Request to "+searchRequest+" FAILED...");
        } else if( error instanceof NoConnectionError) {
            Log.d(TAG, error.toString());
            Log.d(TAG, "Request to "+searchRequest+" FAILED...");
        } else if( error instanceof TimeoutError) {
            Log.d(TAG, error.toString());
            Log.d(TAG, "Request to "+searchRequest+" FAILED...");
        }
    }
}) {
    // 重写getHeaders方法,设置正确的请求头
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Auth-Token", token);
        headers.put("Accept", "application/json"); // 关键:添加这个头解决406错误
        return headers;
    }
};

RequestQueue searchRequestQueue = Volley.newRequestQueue(MainActivity.this);
searchRequestQueue.add(jsonObjectRequest);

为什么登录请求能成功?

你的登录请求是POST方法,服务器对POST请求的参数校验可能更宽松,允许Content-Type出现在请求体中,但GET请求的服务器逻辑通常更严格,必须严格区分请求头和请求体,所以登录请求的巧合成功不能作为参考。

额外注意事项

  • 确认服务器确实支持GET请求带请求体(你的curl请求成功说明是支持的),如果后续还是有问题,可以考虑把请求改为POST(如果API允许的话),因为GET带请求体并不是所有服务器框架都推荐的做法。
  • 检查token变量是否正确传递,确保和curl中使用的token完全一致。

内容的提问来源于stack exchange,提问作者DevOpsSauce

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 21:42:38