httpuv emits duplicate 'Date' response header when one is already supplied

未关闭 适合新手
#447 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
64/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
cpp, r

调研方向

阅读src/httpresponse.h和src/webapplication.cpp中的头部处理,从listToResponse()及其对addHeader()和setHeader()的使用开始。issue还提到一条用于自定义头部的独立静态路径,可能需要调查。使用提供的R示例和curl复现;无论应用是否提供Date字段,响应中恰好包含一个有效的Date字段即为完成。

由索引模型根据 Issue 内容生成。

描述

Description

When an application response already includes a Date header, httpuv 1.6.17 sends a second Date field line, instead of preserving or replacing the supplied value.

Impact

RFC 9110 Sections 5.3 and 6.6.1 make Date a single HTTP-date field, not a list. Because Date is not list-valued, combining repeated lines with commas would produce a value that does not match the Date grammar. Clients, caches, or intermediaries may therefore reject or ignore the timestamp. This is an interoperability/conformance issue rather than an immediate security issue.

If the two dates differ, recipients that recover by selecting one field line may disagree about when the response originated; caches also use Date when calculating response age, so this can lead to inconsistent freshness handling.

Background

We found this while inspecting the raw response headers from our application during a cache-policy review. The application uses Plumber2, which runs on Fiery and uses reqres for request/response handling. The first Date is added by reqres 1.2.0 when it formats the response; our route does not set it. httpuv then adds a second Date to the wire response.

I searched the httpuv, Fiery, reqres, and Plumber2 issue trackers for matching reports and did not find one.

We reduced the behavior to the httpuv-only example below to isolate the HTTP server layer.

Environment

  • R 4.6.2
  • httpuv 1.6.17

Steps to reproduce

Save this as date-header-mwe.R:

message("Starting server at http://127.0.0.1:8081/ (press Ctrl+C to stop)")

httpuv::runServer(
	host = "127.0.0.1",
	port = 8081,
	app = list(
		call = function(req) {
			list(
				status = 200L,
				headers = list(
					# simulate an application-supplied Date. httpuv will add another Date automatically.
					Date = format(Sys.time(), "%a, %d %b %Y %H:%M:%S GMT", tz = "GMT")
				),
				body = ""
			)
		}
	)
)

Start the server:

Rscript date-header-mwe.R

In another process, send a request to the server:

curl -sS -D - -o /dev/null http://127.0.0.1:8081/

Actual behavior

HTTP/1.1 200 OK
Date: Thu, 05 Nov 2026 17:01:29 GMT
Date: Thu, 05 Nov 2026 17:01:29 GMT
Content-Length: 0

The date and header order may vary, but the response contains two Date field lines.

Expected behavior

HTTP/1.1 200 OK
Date: Thu, 05 Nov 2026 17:01:29 GMT
Content-Length: 0

The response should contain one valid Date field line. The server may use its own timestamp or an application-supplied timestamp, but should not emit both.

Possible patch

I'm personally new to httpuv, but to be as solution-oriented as possible, here's an AI-generated patch, which may fix this issue...

In v1.6.17, HttpResponse adds a default Date in its constructor (src/httpresponse.h). The listToResponse() path in src/webapplication.cpp then appends each R-supplied response header with addHeader(). For a supplied Date, using the existing case-insensitive setHeader() method instead would replace the default while preserving append behavior for other headers.

Illustrative patch for listToResponse() (a regression test should cover supplied and omitted Date):

diff --git a/src/webapplication.cpp b/src/webapplication.cpp
--- a/src/webapplication.cpp
+++ b/src/webapplication.cpp
@@
-    pResp->addHeader(
-      std::string((char*)headerNames[i], headerNames[i].size()),
-      Rcpp::as<std::string>(responseHeaders[i]));
+    const std::string name((char*)headerNames[i], headerNames[i].size());
+    const std::string value = Rcpp::as<std::string>(responseHeaders[i]);
+    if (to_lower(name) == "date") {
+      pResp->setHeader(name, value);
+    } else {
+      pResp->addHeader(name, value);
+    }

This covers the R response path shown above. Static-path custom headers are added through a separate code path and would need the same Date replacement if they are intended to support user-supplied Date values too.

主要语言
C
星标
252
派生
87
PR 合并指标
30 天内没有已合并 PR

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

rstudio/httpuv 的其他 Issue

查看 rstudio/httpuv 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。