写入输出流处理过程中出错

发布于 2024-11-29 21:47:22 字数 357 浏览 1 评论 0原文

我正在构建一个 httpserver 作为我的 java 学术课程的一部分, 服务器应该只支持基本的 GET 和 POST 请求。

我想知道是否有一种优雅的方法来处理将 html 文件流内容(以及在我已经发送响应标头之后)写入 HttpServer 输出流中间发生的错误。

通过优雅的方式,我指的是向用户显示或重定向到“内部服务器错误”错误页面。

我尝试重新发送带有 501 错误代码的 http 响应标头,但 java 抛出一个异常,声称标头已发送...

一种修复方法是将文件的内容读入内存,然后才发送标头和内容,但可能会出现其他问题,而且,我不想在将大文件作为响应发送出去之前将它们加载到内存中。

I'm building an httpserver as part of my academic java course,
The server should only support basic GET and POST requests.

I was wondering if there's an elegant way to handle an error which occures in the middle of writing an html file stream content (and after I've already sent the response headers) into the HttpServer output stream.

By elegant way I refer to showing or redirecting the user to a "Internal Server Error" error page.

I tried re-sending the http response headers with 501 error code, but java throws an exception which claims that the headers were already sent...

One fix would be to read the file's contents into memory, and only then sending the headers and the content, but other problems can arise, and furthermore, I don't want to load huge files into the memory before sending them out as a response.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

日记撕了你也走了 2024-12-06 21:47:22

响应状态一旦通过网络发送,就无法更改。因此,如果您发送了 200 OK 响应,之后您就无法改变主意。正如您所发现的,如果响应过程中发生错误,这就会出现问题。

据我所知,您唯一能做的就是发送分块响应。请参阅 RFC 2616 第 3.6.1 节:

分块编码修改消息正文,以便
将其作为一系列块传输,每个块都有自己的大小指示器,
后面是包含实体标头字段的可选尾部。这
允许动态生成的内容随
收件人验证其已收到所需的信息
完整的消息。

该预告片的目的是提供在发送实体主体之前无法计算的有关实体主体的信息。然而,第 7.1 节允许在此预告片中包含任何标头:

扩展头机制允许额外的实体头字段
可以在不改变协议的情况下定义,但是这些字段不能
假定可以被接收者识别。无法识别的标头
字段应该被接收者忽略并且必须由
透明代理。

因此,虽然您可以在响应期间发出错误信号,但必须在两个部分之间就如何发出信号达成一致。一般来说,您不能使用任何假设客户端会理解为发出错误情况信号的方法。

在带有 Content-length 标头的消息中提前结束连接是一种选择,但这是明确禁止的:

当消息中给出内容长度且消息正文为
允许,其字段值必须与中的 OCTET 数完全匹配
消息正文。 HTTP/1.1 用户代理必须在发生异常时通知用户
接收并检测到无效长度。

也就是说,虽然服务器发送的消息不得短于其所通告的消息,但客户端必须检查此错误情况并据此进行报告(代理甚至可以缓存此部分响应)。

Once the response status is sent on the wire, it cannot be changed. So if you sent a 200 OK response, you cannot change your mind afterwards. As you found, this presents a problem in case of errors that occur mid response.

As far as I know, the only think you can do is to send a chunked response. See section 3.6.1 of RFC 2616:

The chunked encoding modifies the body of a message in order to
transfer it as a series of chunks, each with its own size indicator,
followed by an OPTIONAL trailer containing entity-header fields. This
allows dynamically produced content to be transferred along with the
information necessary for the recipient to verify that it has received
the full message.

The purpose of this trailer is to give information about the entity body that cannot be calculated before the entity body is sent. However, section 7.1 allows any header to be included in this trailer:

The extension-header mechanism allows additional entity-header fields
to be defined without changing the protocol, but these fields cannot
be assumed to be recognizable by the recipient. Unrecognized header
fields SHOULD be ignored by the recipient and MUST be forwarded by
transparent proxies.

So while you can signal that an error has occurred mid response, it must be conventioned between the two parts how this is signaled. You cannot, in general, use any method you can assume the client will understand as signaling an error condition.

Ending the connection prematurely in a message with a Content-length header is an option, but one that is explicitly forbidden:

When a Content-Length is given in a message where a message-body is
allowed, its field value MUST exactly match the number of OCTETs in
the message-body. HTTP/1.1 user agents MUST notify the user when an
invalid length is received and detected.

That said, while the server must not send a message shorter than he advertises, the client must check for this error condition and reported as such (and proxies may even cache this partial response).

零度° 2024-12-06 21:47:22

通过优雅的方式,我指的是向用户显示或重定向到
“内部服务器错误”错误页面。

如果您无法发送“成功”响应,您将如何发送不同的响应?您所能做的就是记录下来然后忘记它。

By elegant way I refer to showing or redirecting the user to a
"Internal Server Error" error page.

If you can't send the 'success' response how are you going to send a different response? All you can do is log it and forget about it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文