如何处理映射到相同响应的不同请求?

dax*_*xim 6 caching http

我正在设计一个 Web 服务。请求是幂等的,所以我选择了GET方法。响应计算起来相对昂贵,而且不小,所以我想正确缓存(在协议级别)。(不要担心我的记忆,我已经讲过了;我在这里的问题实际上也是关注整个网络。)

只有一个必需参数和一些可选参数,如果缺少则具有默认值。例如,以下两个映射到响应的相同表示。(如果这是处理界面的愚蠢方式,请提出更好的建议。)

GET /service?mandatory_parameter=some_data HTTP/1.1
GET /service?mandatory_parameter=some_data;optional_parameter=default1;another_optional_parameter=default2;yet_another_optional_parameter=default3 HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

但是,我想客户不知道这一点,并且会将它们分开处理,从而浪费缓存存储。我应该怎么做才能避免违反缓存黄金法则

  1. 组成一个规范的形式,记录它(例如,毕竟所有参数都是必需的,并且需要按特定顺序排序)并返回客户端错误,除非满足所需的形式?
  2. 而不是错误,永久重定向到请求的规范形式?
  3. 或者不介意请求的外观,并且只对ETag相同的响应做出相同的响应就足够了?

Bob*_*man 5

首先,不要在查询字符串中使用分号作为分隔符。您应该使用?来开始查询字符串并&分隔变量/值对。 RFC 3986没有明确规定您必须使用&,但由于application/x-www-form-urlencoded先例,绝大多数现有代码都使用此分隔符。

其次,您是对的,因为查询字符串中的参数会导致不同的 URI,因此,就缓存而言,是不同的资源。假设您想要最佳缓存性能,如果您知道已经指定了一个可选参数,并且它的包含是不必要的,并且不会影响将要传输的表示,那么您应该重定向到省略该参数的规范表示。(即,给定一个可选参数,其值设置为默认值。例如,如果您有http://example.com:80/,则可以标准化为,http://example.com/因为80是 HTTP 端口的默认值。由于您控制 URI 空间,因此您可以对查询参数执行相同的操作。)如果您包含的参数(可选或其他)以非规范顺序出现,您也应该为此重定向。如果您知道 URI 之间的关系是稳定的,则首选 301 重定向。否则,根据需要执行 302/307 重定向。我建议以与OAuth相同的方式定义规范形式:按字母顺序对每个参数进行排序,首先按键,然后按值。其他规范化操作也将在这里有所帮助。RFC 3986 有一整节关于URI 规范化这将与您相关。这种技术实际上只适用于 GET,一般不推荐在 PUT/POST/DELETE 上重定向。

第三,ETag 很棒,如果客户端和服务器都很好地实现,它们会提供巨大的性能改进。然而,不幸的是,双方都做得对的情况很少见。Last-Modified 同上。你应该追求这些,因为 CPU 和带宽的节省在它工作时是显着的,但它们本身是不够的。像 Cache-Control 这样的其他标头也是经常需要的。如果您打算深入了解这些内容,则值得熟悉RFC 2616 的第 13 节

最后,警告——您需要注意这些重定向的一个问题:尝试访问您的资源的客户端可能经常被重定向到其他位置。这引入了开销,如果客户端对同一资源发出后续请求,则只会为您带来总体节省,维护状态以避免后续重定向。除非您已经开源了一个利用缓存优化的参考客户端实现,否则您可能永远不会从这些调整中受益。