【问题标题】:Localizing reason phrase in status line of the RESTful HTTP API reponse在 RESTful HTTP API 响应的状态行中本地化原因短语
【发布时间】:2011-03-07 09:30:07
【问题描述】:

我们有一个通过 HTTP 公开的 RESTful API,它以自然的方式利用 HTTP 状态行(状态代码和原因短语)将 API 结果传达给客户端 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html)。

例如,我们有以下并发错误的状态行:

HTTP/1.1 409 资源由其他用户更新。重新加载并重试。

最近事实证明,这些消息将呈现给根据我们的 API 构建的应用程序的最终用户,这意味着我们需要对它们进行本地化。 我想知道在这种情况下这是否是一种可接受的方法,特别是考虑到这些消息的非 ASCII 字符集,或者是否应该将原因短语(状态描述)仅保留为低级消息和任何将使其成为' 应该在响应正文中传递用户屏幕的方式?如果我们选择对原因短语部分进行本地化,以后有什么可以咬我们的吗?

在这种情况下,我们希望使用响应正文将新版本的资源传递给 API 客户端,并且包含其他数据并不能很好地配合它。

【问题讨论】:

    标签: http rest localization http-response-codes


    【解决方案1】:

    在原因短语中传递非 ASCII 字符没有公认的方法,所以如果它需要在实验环境之外工作,我会非常小心地依赖它。

    将本地化消息移动到响应正文中会更可靠。

    【讨论】:

      【解决方案2】:

      正如您从 RFC 中了解的那样:

      状态码供以下用户使用 自动机和原因短语是 面向人类用户

      因此,值得尝试在简短和中肯的内容之间找到平衡,同时保持用户友好。我见过的许多 Web 服务都有一个状态节点(xml 或 json),其中包含代码和更人性化的消息作为响应数据的一部分。

      一个潜在问题:在我们的一个 RESTful API 中,我们自定义了原因短语以帮助调试。我们使用 Pingdom 监控正常运行时间,它仅在状态与 RFC 中建议的匹配(即200 OK)时才错误地接受服务可用。在向他们指出这是不正确的之后,我被转介到了 RFC(!),尽管他们最终承认他们误解了它。

      【讨论】:

      • 关于外部工具的好提示 - 我不认为在使用非标准原因短语时这些可能会导致问题
      • 他们不应该 - Pingdom 误解了 RFC
      【解决方案3】:

      最好的做法似乎是为此使用 ASCII 英文消息,并假设浏览器正在做正确的事情并且根本不显示这些短语(请参阅下面的详细信息)。

      HTTP/1.1 RFC 2616 中定义的 HTTP 1.1 响应行的当前状态以及RFC 7230 和7231 中的更新如下:

      • 状态行的格式是HTTP-Version Status-Code Reason-Phrase CRLF
      • Reason-Phrase 是除CR 和LF 字符之外的任何TEXT。 RFC 7230 实际上说客户端应该忽略原因短语内容。浏览器不应再向用户显示这些原因短语;它们适用于基于文本的浏览器。但是,对于现代浏览器可能仍向用户显示原因短语的任何情况,我都找不到明确的文档。
      • TEXT 规则仅用于不打算由消息解析器解释的描述性字段内容和值。仅当根据RFC 2047 的规则进行编码时,*TEXT 的单词才可以包含来自 ISO-8859-1(根据 RFC 2616)以外的字符集的字符。
      • RFC 2047 指定如下语法:=?iso-8859-1?q?test_S=EEne_li=F0e?= 或 =?utf-8?b?dGVzdCBTw65uZSBsacOwZSDhmqDhm4fhmrsgz4PPgM6vz4TOuQ==?=。这是其他 HTTP 标头的编码方式,但当前浏览器似乎不支持(在 Chrome 和 Firefox 上测试)
      • 在 Chrome 和 Firefox 上的简短测试表明,根据 Javascript 控制台和网络选项卡中显示的内容,使用 UTF-8 或 ISO-8859-1 作为响应短语,您的里程可能会有所不同,但 RFC 2047 mime 样式编码从不工作。

      这是一个非常简单的 Python 3 服务器,我用来测试它(例如,转到 http://127.0.0.1:8080/UTF-8 或 http://127.0.0.1:8080/rfc2047):

      # -*- coding: utf-8 -*-
      import sys
      from email.header import *
      from http.server import HTTPServer, BaseHTTPRequestHandler
      from socketserver import ThreadingTCPServer
      
      class TestHTTPRequestHandler(BaseHTTPRequestHandler):
          def handle(self):
              data = str(self.request.recv(1024), 'ascii')
              print("Received request: %r" % data)
              if 'GET /' in data:
                  encoding = data[data.find('GET /')+4:]
                  encoding = encoding[:encoding.find(' ')].lstrip('/')
                  if '?' in encoding:
                      encoding = encoding[:encoding.find('?')]
              else:
                  encoding = "iso-8859-1"
              if encoding == 'favicon.ico':
                  self.request.sendall(b'HTTP/1.1 404 Not Found\r\n')
                  return
              reason_phrase = "test Sîne"
              if encoding == "rfc2047":
                  encoding = "utf-8"
                  reason_phrase = Header(reason_phrase, encoding).encode()
              response = (u"HTTP/1.1 500 %s\r\nContent-Length: 10\r\nContent-Type: text/plain; charset=%s\r\nConnection: Closed\r\n\r\n\"testSîn\"" % (reason_phrase, encoding))
              self.request.sendall(response.encode(encoding))
      
      server = ThreadingTCPServer(('127.0.0.1', 8080), TestHTTPRequestHandler)
      try:
          server.serve_forever()
      finally:
          server.server_close()
      

      【讨论】:

        猜你喜欢
        • 2015-11-28
        • 2020-12-11
        • 2022-11-11
        • 1970-01-01
        • 2017-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多