Rails 何时响应 'transfer-encoding' 与 'content-length'?
When does Rails respond with 'transfer-encoding' vs. 'content-length'?
我正在 Rails 版本 4.1.7/Nginx 上构建一个 API 来响应来自 iOS 应用程序的请求。我们在客户端看到一些奇怪的缓存,我们认为这与 Rails 发回的响应中的微小差异有关。我的问题...
1) 我想了解为什么对于完全相同的请求(仅更改了授权 header 值),Rails 有时发回 transfer-encoding: chunked
而 Content-Length: <number>
有时?我认为这可能与响应大小有关,但在下面粘贴的 header 示例响应中,body 中返回的数据完全相同。
2) 有没有办法强制使用Content-Length
?我们认为这将解决我们 iOS 应用程序中的缓存问题。
回复#1
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Mar 2015 00:59:31 GMT
ETag: "86f277ea63295460d4f3bed9a073eaa2"
Server: nginx/1.6.2
Status: 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: dd36f139-1986-4da6-9645-4438d41e74b0
X-Runtime: 0.123865
X-XSS-Protection: 1; mode=block
transfer-encoding: chunked
Connection: keep-alive
请求#2
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Mar 2015 00:59:36 GMT
ETag: "86f277ea63295460d4f3bed9a073eaa2"
Server: nginx/1.6.2
Status: 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: 0cfd7705-157b-41b5-aa36-739bc6f8302e
X-Runtime: 0.092672
X-XSS-Protection: 1; mode=block
Content-Length: 2234
Connection: keep-alive
根据 HTTP 1.1,这两种响应都是有效的,因此您需要修正您的客户端代码,使其能够同时处理这两种响应。尝试修复服务器以使其行为方式不会触发客户端中的错误是一个坏主意。
下一个版本的 nginx 可能会有所不同,您的用户甚至可能拥有更改传输的代理,也许只有当他们漫游并使用不同的提供商时。
如果你想在 header 上做一些 finger-printing,ETag-header 可能会帮助你,因为当响应的内容没有改变时,ETag 应该保持不变,不管转移。
服务器在调用动态页面时通常会分块发送,因为它不需要为整个页面创建缓冲区并等待生成所有页面。
如果服务器已经有缓冲区,通常会一次性发送响应,例如因为它在缓存中或者内容在文件中并且不是很大。一次发送效率更高,另一方面,用于缓冲输出的额外数据副本需要更多内存并且效率较低。所以服务器甚至可以根据可用内存来决定这一点。
我正在 Rails 版本 4.1.7/Nginx 上构建一个 API 来响应来自 iOS 应用程序的请求。我们在客户端看到一些奇怪的缓存,我们认为这与 Rails 发回的响应中的微小差异有关。我的问题...
1) 我想了解为什么对于完全相同的请求(仅更改了授权 header 值),Rails 有时发回 transfer-encoding: chunked
而 Content-Length: <number>
有时?我认为这可能与响应大小有关,但在下面粘贴的 header 示例响应中,body 中返回的数据完全相同。
2) 有没有办法强制使用Content-Length
?我们认为这将解决我们 iOS 应用程序中的缓存问题。
回复#1
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Mar 2015 00:59:31 GMT
ETag: "86f277ea63295460d4f3bed9a073eaa2"
Server: nginx/1.6.2
Status: 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: dd36f139-1986-4da6-9645-4438d41e74b0
X-Runtime: 0.123865
X-XSS-Protection: 1; mode=block
transfer-encoding: chunked
Connection: keep-alive
请求#2
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Mar 2015 00:59:36 GMT
ETag: "86f277ea63295460d4f3bed9a073eaa2"
Server: nginx/1.6.2
Status: 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: 0cfd7705-157b-41b5-aa36-739bc6f8302e
X-Runtime: 0.092672
X-XSS-Protection: 1; mode=block
Content-Length: 2234
Connection: keep-alive
根据 HTTP 1.1,这两种响应都是有效的,因此您需要修正您的客户端代码,使其能够同时处理这两种响应。尝试修复服务器以使其行为方式不会触发客户端中的错误是一个坏主意。 下一个版本的 nginx 可能会有所不同,您的用户甚至可能拥有更改传输的代理,也许只有当他们漫游并使用不同的提供商时。
如果你想在 header 上做一些 finger-printing,ETag-header 可能会帮助你,因为当响应的内容没有改变时,ETag 应该保持不变,不管转移。
服务器在调用动态页面时通常会分块发送,因为它不需要为整个页面创建缓冲区并等待生成所有页面。
如果服务器已经有缓冲区,通常会一次性发送响应,例如因为它在缓存中或者内容在文件中并且不是很大。一次发送效率更高,另一方面,用于缓冲输出的额外数据副本需要更多内存并且效率较低。所以服务器甚至可以根据可用内存来决定这一点。