Volley没有正确处理多值头文件

时间:2016-06-29 19:33:23

标签: android rest android-volley hateoas

我目前正在尝试按照HATEOAS原则模块实现一个RESTful Client,以便在我的Android App中使用。在我的方法中我使用了Google的Volley。 我已经扩展了Volley的Request类来提供自定义的Response对象。 以下是两个类:

自定义请求类:

public class RestRequest extends Request<RestResponse>
{
    private final Map<String, String> headers;
    private final Response.Listener<RestResponse> listener;

    public RestRequest(int requestType, String url, Map<String, String> headers,
                       Response.Listener<RestResponse> listener,
                       Response.ErrorListener error)
    {
        super(requestType, url, error);
        this.listener = listener;
        this.headers = headers;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError
    {
        return this.headers != null ? this.headers : super.getHeaders();
    }

    @Override
    protected Response<RestResponse> parseNetworkResponse(NetworkResponse response)
    {
        String responseBody = null;
        try
        {
            responseBody = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        }
        catch (UnsupportedEncodingException e)
        {
            responseBody = new String(response.data);
        }
        for (Map.Entry<String, String> entry : response.headers.entrySet())
        {
            System.out.println(entry.getKey() + " " + entry.getValue());
        }
        return Response.success(new RestResponse(response.headers,
                                                 responseBody), HttpHeaderParser.parseCacheHeaders(response));
    }

    @Override
    protected void deliverResponse(RestResponse response)
    {
        listener.onResponse(response);
    }
}

自定义响应类:

public class RestResponse
{
    private Map<String, String> responseHeaders;
    private String responseBody;

    public RestResponse(Map<String, String> responseHeaders, String responseBody)
    {
        this.responseHeaders = responseHeaders;
        this.responseBody = responseBody;
    }

    public Map<String, String> getResponseHeaders()
    {
        return responseHeaders;
    }

    public String getResponseBody() {
        return responseBody;
    }
}

正如您所看到的,我尝试保存在RestResponse类中保存ResponseHeaders和ResponseBody。使用我的RestRequest类,我的请求都得到了正确处理而没有错误。

我面临的唯一问题是ResponseHeaders没有正确保存,或者至少是我在做错事的地方。但正如你在

中看到的那样

protected Response<RestResponse> parseNetworkResponse(NetworkResponse response)

我正在为我创建的RestResponse对象提供来自response.headers的ResponseHeaders。

查看包含标题的检索到的地图会显示以下内容:

I/System.out: Content-Length 0
I/System.out: Date Wed, 29 Jun 2016 17:27:59 GMT
I/System.out: link <https://LINK_1>;rel="link-1"
I/System.out: Server Apache-Coyote/1.1
I/System.out: X-Android-Received-Millis 1467221322063
I/System.out: X-Android-Response-Source NETWORK 200
I/System.out: X-Android-Selected-Protocol http/1.1
I/System.out: X-Android-Sent-Millis 1467221322031

但它应该在链接标题中返回更多链接,就像通过Postman发出请求一样:

Content-Length →0
Date →Wed, 29 Jun 2016 17:33:22 GMT
Server →Apache-Coyote/1.1
link →<LINK_1>;rel="link-1", <LINK_2>;rel="link-2", <LINK_3>;rel="link-3"

我显然用占位符替换了实际的链接,但其他一切都来自真正的调用。 Volley总是给我一个链接而且我不知道为什么。在Volley内部执行是错误的还是我在这里做错了什么? 提前谢谢!

编辑: 添加了根据日志放置的System.out.print。

1 个答案:

答案 0 :(得分:0)

我认为这个问题确实存在于Volley。我查看了Volley的源代码,其中创建了NetworkResponse对象,并发现来自HttpResponse对象的Header []正在转换为Map。由于Maps只能使用唯一键,因此会导致错误行为,因为Link标头可以是多值的。 想象一下,将以下标题放入地图中,其中headername是键,标题值是值。

link: <http://example.com>; rel="example"
link: <http://example1.com>; rel="example1"
link: <http://example2.com>; rel="example2"

由于默认的Map行为,显然只剩下一个链接头。