我们有一个通过HTTP公开的RESTful API,它以自然的方式利用HTTP状态行(状态代码和原因短语)将API结果传递给客户端(http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html)。
例如,我们有一个并发错误的状态行:
HTTP / 1.1 409资源由其他用户更新。重新加载并重试。
最近发现这些消息将呈现给针对我们的API构建的应用程序的最终用户,这意味着我们需要对它们进行本地化。 我想知道在这种情况下这是否是一种被接受的方法,特别是考虑到这些消息的非ASCII字符集,或者原因短语(状态描述)是否应仅保留为低级别消息和任何内容'应用程序屏幕的方式应该在响应正文中传递?如果我们选择本地化理由短语部分,有什么东西可以在以后咬我们吗?
在这种情况下,我们希望使用响应主体将新版本的资源传递给API客户端,并且包含其他数据并不能很好地发挥其作用。
答案 0 :(得分:4)
在原因短语中没有达成一致的方式来传递非ASCII字符,所以如果它需要在实验环境之外工作,我会非常小心地依赖它。
将本地化消息移动到响应正文中将更加可靠。
答案 1 :(得分:3)
您将从RFC中了解到:
状态代码供...使用 自动机和Reason-Phrase是 供人类用户使用
因此,尽管仍然是用户友好的,但仍然值得尝试在简短和重要之间找到平衡点。我见过的许多网络服务都有一个状态节点(xml或json),其中包含代码和更人性化的消息,作为响应数据的一部分。
一个潜在的问题:在我们的一个RESTful API中,我们定制了原因短语以帮助调试。我们正在使用Pingdom监视正常运行时间,如果状态与RFC中建议的状态相匹配,则错误地仅接受服务可用 - (即200 OK
)。在向他们指出这是不正确的之后,我被提到了RFC(!),尽管他们最终承认他们误解了它。
答案 2 :(得分:0)
最佳实践似乎是为此使用ASCII英文消息,并假定浏览器做正确的事情,根本不显示这些短语(请参见下面的详细信息)。
HTTP/1.1 RFC 2616中定义的HTTP 1.1响应行的当前状态以及RFC 7230和7231中的更新如下:
HTTP-Version Status-Code Reason-Phrase CRLF
Reason-Phrase
是TEXT
和CR
字符以外的任何LF
。 RFC 7230实际上说客户端应该忽略原因短语内容。浏览器不应再向用户显示这些原因短语。它们旨在用于基于文本的浏览器。但是,在现代浏览器仍可能向用户显示原因短语的任何情况下,我都找不到清晰的文档。TEXT
规则仅用于描述性字段内容和消息解析器不打算解释的值。仅在根据RFC 2047的规则进行编码时,*TEXT
的单词才能包含ISO-8859-1(根据RFC 2616)之外的字符集中的字符。=?iso-8859-1?q?test_S=EEne_li=F0e?=
或=?utf-8?b?dGVzdCBTw65uZSBsacOwZSDhmqDhm4fhmrsgz4PPgM6vz4TOuQ==?=
。这是其他HTTP标头的编码方式,但当前的浏览器(在Chrome和Firefox上进行了测试)似乎不支持此功能这是我用来测试的一个非常简单的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()