摘要
本文原创,转载请注明地址: http://kymjs.com/code/2016/02/25/01
从 Volley 源码中延伸学习到的 HTTP 请求头的知识
- 事情缘起
- 曲折的故事
- 连蒙带猜
- 原来如此
事情缘起
之所以有这个笔记,是因为这条 Issue: RxVolley #6
在浏览 Volley 代码的时候,产生了一个疑惑
在 HttpHeaderParser
中有这么一段代码
//... headerValue = headers.get("Cache-Control"); if (headerValue != null) { hasCacheControl = true; String[] tokens = headerValue.split(","); for (int i = 0; i < tokens.length; i++) { String token = tokens[i].trim(); if (token.equals("no-cache") || token.equals("no-store")) { return null; } else if (token.startsWith("max-age=")) { try { maxAge = Long.parseLong(token.substring(8)); } catch (Exception e) { } } else if (token.startsWith("stale-while-revalidate=")) { try { staleWhileRevalidate = Long.parseLong(token.substring(23)); } catch (Exception e) { } } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) { mustRevalidate = true; } } } //...
这段代码主要用途是在 http 请求响应后,服务器返回的响应数据中如果响应头中声明了 Cache-Control
则按照服务器端的规则处理缓存数据。
问题在于,这里使用的是 headers.get("Cache-Control")
其中 headers 是一个 Map
,那么如果服务器返回的响应头的 key 是一段小写的字符串 cache-control
,那么用这个方法岂不是无法正常读取到 value 了?
曲折的故事
可是,接口返回的数据头中是使用小写的 cache-control
。 使用 Volley 请求这个接口,却发现 HttpHeaderParser
正常工作,并没有出现我们想象中的 headers.get("Cache-Control")
找不到对应 value 的情况。
查看代码, HttpHeaderParser
的参数 headers 是在 Request#parseNetworkResponse()
中被传入的。
而进一步查看是在 NetworkDispatcher
中调用了 parseNetworkResponse() ,代码如下
// Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request); request.addMarker("network-http-complete"); // If the server returned 304 AND we delivered a response already, // we're done -- don't deliver a second identical response. if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); continue; } // Parse the response here on the worker thread. Response<?> response = request.parseNetworkResponse(networkResponse);
原来这个值是由 mNetwork.performRequest(request)
返回的
再找到 BasicNetwork#performRequest()
,似乎并没有做什么特殊处理啊,为什么这段代码能正常工作呢?
连蒙带猜
难道本身拿到的数据就是大写的 Cache-Control
?
赶紧用 Postman 看一看
果然是我想多了
不行,我就是要试试,找到最初发起网络请求的 HurlStack
类,把网络请求返回的请求头数据都给打印出来
// Initialize HttpResponse with data from the HttpURLConnection. ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); int responseCode = connection.getResponseCode(); if (responseCode == -1) { // -1 is returned by getResponseCode() if the response code could not be retrieved. // Signal to the caller that something was wrong with the connection. throw new IOException("Could not retrieve response code from HttpUrlConnection."); } StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(), connection.getResponseMessage()); BasicHttpResponse response = new BasicHttpResponse(responseStatus); if (hasResponseBody(request.getMethod(), responseStatus.getStatusCode())) { response.setEntity(entityFromConnection(connection)); } for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) { if (header.getKey() != null) { Header h = new BasicHeader(header.getKey(), header.getValue().get(0)); Log.i("kymjs", header.getKey()+"===="+header.getValue().get(0)) response.addHeader(h); } } return response;
我操,为什么又变成了大写的。
原来如此
连蒙带猜的,服务器接口返回的是小写,数据请求拿到的是大小,这特么说明在网络过程中数据发生了变化啊。
赶紧去查查 Http 1.1 协议: https://tools.ietf.org/html/rfc7230
https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html3.2 Header Fields
Each header field consists of a case-insensitive field name followed by a colon (“:”), optional leading whitespace, the field value, and optional trailing whitespace.
4.2 Message Headers
HTTP header fields, which include general-header (section 4.5), request-header (section 5.3), response-header (section 6.2), and entity-header (section 7.1) fields, follow the same generic format as that given in Section 3.1 of RFC 822 [9]. Each header field consists of a name followed by a colon (“:”) and the field value. Field names are case-insensitive.
大意就是说:HTTP头字段遵循相同的通用格式,字段名称是不区分大小写的。
原来如此,那么通用格式肯定就是指 Cache-Control
这种首字母大写的格式了。
wiki百科查一下,是这样。 HTTP头字段列表 回应字段: https://zh.wikipedia.org/wiki/HTTP%E5%A4%B4%E5%AD%97%E6%AE%B5%E5%88%97%E8%A1%A8
了却了心中的一个疑问,真舒服~
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!