Commit Graph

1965 Commits

Author SHA1 Message Date
dependabot[bot] 5be41c4aee chore(deps): bump golang.org/x/sys from 0.45.0 to 0.46.0 (#2289)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.45.0 to 0.46.0.
- [Commits](https://github.com/golang/sys/compare/v0.45.0...v0.46.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-09 17:30:46 +08:00
Y.Horie cb4dc24ca0 fix(client): switch to GET on 303 redirect per RFC 9110 (#2265)
Per RFC 9110 section 15.4.4, a 303 (See Other) response must be followed
by a body-less GET regardless of the original method. Handle 303
explicitly: change any non-GET/HEAD method to GET and always drop the
body, including when the original request was already a GET/HEAD.

Clear every header that frames the dropped body: Content-Length and
Content-Type, plus Transfer-Encoding and Trailer (per RFC 9112 a body is
signaled by Content-Length or Transfer-Encoding, and a Trailer only
applies to a chunked body). 301/302 keep their POST-to-GET behavior, and
307/308 still preserve the method and body.

Fixes #2240

Signed-off-by: Y.Horie <u5.horie@gmail.com>
2026-06-08 10:00:17 +08:00
Vladislav Sedov fa2b76590b fix double release of streamed client response body (#2211)
Clear the response body stream when the client streaming wrapper is closed directly via CloseWithError. This prevents ReleaseResponse from closing the same underlying requestStream again.
2026-06-07 10:11:17 +02:00
Y.Horie 60f78f517d fix(fs): remove temporary file when compression fails (#2264)
compressFileNolock created a ".tmp" file but left it on disk when the
compression copy, os.Chtimes, or os.Rename step failed, leaking partial
files that accumulate over time. Remove the temporary file in each error
path.

Fixes #2239

Signed-off-by: Y.Horie <u5.horie@gmail.com>
2026-06-07 06:36:59 +02:00
Erik Dubbelboer ebaf0e20f8 security: TLS verification silently disabled for malformed addresses (#2236) (#2274) 2026-06-06 16:31:37 +02:00
Erik Dubbelboer ab3bc8550d bug: filesLockMap grows unboundedly, leaking memory (#2256) (#2286) 2026-06-06 11:30:52 +02:00
Erik Dubbelboer 44115f3838 bug: file descriptor leak on z/OS s390x when FcntlInt fails (#2255) (#2285) 2026-06-06 11:30:35 +02:00
Erik Dubbelboer f3f769f74c security: SO_REUSEADDR on Windows enables port hijacking (#2254) (#2284) 2026-06-06 11:30:23 +02:00
Erik Dubbelboer d132fea936 bug: file descriptor leak in prefork parent process (#2253) (#2283) 2026-06-06 11:30:11 +02:00
Erik Dubbelboer 4cf334be95 bug: SetBodySizePoolLimit data race — plain int written without synchronization (#2252) (#2282) 2026-06-06 11:29:55 +02:00
Erik Dubbelboer bac672751b bug: AppendCert/AppendCertEmbed not thread-safe (#2251) (#2281) 2026-06-06 11:29:39 +02:00
Erik Dubbelboer 31f7138f8c bug: closeIdleConns TOCTOU race with serveConn idle timestamp (#2250) (#2280) 2026-06-06 11:29:29 +02:00
Erik Dubbelboer 1899b234a1 bug: fasthttpproxy dialers return nil DialFunc on error, causing panic (#2248) (#2279) 2026-06-06 11:28:48 +02:00
Erik Dubbelboer 4b198af059 bug: fasthttpadaptor writer leak, data race, and crash on handler panic (#2246) (#2278) 2026-06-06 11:28:23 +02:00
Erik Dubbelboer 4ef0547d4c bug: InMemoryListener deadlock under high concurrency (#2245) (#2277) 2026-06-06 11:28:07 +02:00
Erik Dubbelboer da69ed9d3f bug: body stream leak in compression methods when response is discarded (#2244) (#2276) 2026-06-06 11:26:48 +02:00
Erik Dubbelboer 21f66e0a2f bug: double concurrency counter increment in ServeConn causes counter leak (#2238) (#2275) 2026-06-06 11:26:22 +02:00
Erik Dubbelboer 82190178c8 bug: TCPDialer.tcpAddrsClean() goroutine leaks — no shutdown mechanism (#2222) (#2273) 2026-06-06 11:25:39 +02:00
Erik Dubbelboer eee784158a bug: data race on pipeline client c.chR during worker drain (#2220) (#2272) 2026-06-06 11:24:52 +02:00
Erik Dubbelboer 289229aad3 bug: FS cache cleaner goroutine leaks when CleanStop is nil (default) (#2218), #2247 (#2271) 2026-06-06 11:00:24 +02:00
dependabot[bot] 6c530c5b81 chore(deps): bump securego/gosec from 2.27.0 to 2.27.1 (#2267)
Bumps [securego/gosec](https://github.com/securego/gosec) from 2.27.0 to 2.27.1.
- [Release notes](https://github.com/securego/gosec/releases)
- [Commits](https://github.com/securego/gosec/compare/v2.27.0...v2.27.1)

---
updated-dependencies:
- dependency-name: securego/gosec
  dependency-version: 2.27.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-04 11:50:24 +08:00
Y.Horie 46bfd1b9d8 fix(server): return ErrMissingFile when MultipartForm.File is nil (#2260)
RequestCtx.FormFile previously returned (nil, nil) when the parsed
multipart form had a nil File map: the code returned the err variable
from the preceding successful MultipartForm() call, which is always
nil at that point. Callers checking `if err != nil` proceeded with a
nil *multipart.FileHeader, causing nil pointer dereferences downstream.

Return ErrMissingFile instead, matching the existing semantics for the
missing-key case immediately below. Fixes #2235.

Signed-off-by: Y.Horie <u5.horie@gmail.com>
2026-06-02 19:35:29 +08:00
dependabot[bot] a7d4e8d770 chore(deps): bump securego/gosec from 2.26.1 to 2.27.0 (#2261)
Bumps [securego/gosec](https://github.com/securego/gosec) from 2.26.1 to 2.27.0.
- [Release notes](https://github.com/securego/gosec/releases)
- [Commits](https://github.com/securego/gosec/compare/v2.26.1...v2.27.0)

---
updated-dependencies:
- dependency-name: securego/gosec
  dependency-version: 2.27.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-02 19:33:16 +08:00
dependabot[bot] bf00c3e2df chore(deps): bump golang.org/x/net from 0.54.0 to 0.55.0 (#2207)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.54.0 to 0.55.0.
- [Commits](https://github.com/golang/net/compare/v0.54.0...v0.55.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.55.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 04:42:04 +02:00
dependabot[bot] e4e2651d9f chore(deps): bump golang.org/x/sys from 0.44.0 to 0.45.0 (#2208)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.44.0 to 0.45.0.
- [Commits](https://github.com/golang/sys/compare/v0.44.0...v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 04:34:06 +02:00
dependabot[bot] 533beb9338 chore(deps): bump golang.org/x/crypto from 0.51.0 to 0.52.0 (#2209)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.51.0 to 0.52.0.
- [Commits](https://github.com/golang/crypto/compare/v0.51.0...v0.52.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.52.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 04:33:48 +02:00
dependabot[bot] 54d5dbb463 chore(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.2.1 (#2210)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 9.2.0 to 9.2.1.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v9.2.0...v9.2.1)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-24 04:33:30 +02:00
Ali 6d7682aa72 client: add aggregate connection count metrics (#2201)
* client: add aggregate connection count metrics

* client: remove redundant TestClientConnectionCountsEmpty
2026-05-17 12:14:05 +09:00
Erik Dubbelboer c1e4fdd5b5 Update to go1.25 as minimal version (#2205) 2026-05-16 04:08:08 +02:00
Erik Dubbelboer e9208ecebf Revert "feat(prefork): graceful shutdown, leak fixes, hook robustness" commit
This commit was added right before the pull was merged and wasn't
reviewed.

This reverts commit 262ea09c9e.
v1.71.0
2026-05-02 14:09:35 +02:00
RW 481e579af9 feat(prefork): Enhance prefork management with WatchMaster, CommandProducer, and Windows support (#2180)
* feat(prefork): add WatchMaster and callback support for child process management

* feat(prefork): add CommandProducer for customizable child process commands

* refactor(prefork): improve comments and parameter order in ListenAndServeTLS

* refactor(prefork): enhance logging message and clarify OnChildRecover callback comment

* fix(prefork): add Windows support to watchMaster

On Windows, os.Getppid() returns a static PID that doesn't change when
the parent exits (no reparenting). Use FindProcess+Wait instead, which
correctly detects parent exit. Also document why masterPID comparison
works for Docker containers (master PID 1 case).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(prefork): extract listenAsChild to eliminate DRY violation

The three ListenAndServe* methods had identical child setup code
(listen, set ln, watch master). Extract to listenAsChild() for
cleaner code. Also add comment for the magic file descriptor number 3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(prefork): restore upstream ListenAndServeTLS parameter order

Keep upstream's (addr, certKey, certFile) signature to avoid breaking
callers. Fix the doc comment to match the actual parameter order instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(prefork): address lint errors and review feedback

Lint fixes:
- Remove unused Reuseport field write in test (govet/unusedwrite)
- Replace fmt.Errorf with errors.New for static errors (perfsprint)

Review feedback (Copilot):
- Validate CommandProducer returns a started command (nil/Process check)
- Clarify ListenAndServeTLS doc: parameter order and internal forwarding
- Use hermetic test binary re-exec instead of external 'go' binary
- Rename misleading test to reflect what it actually asserts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(prefork): address maintainer review feedback

- watchMaster: log errors from FindProcess/Wait instead of swallowing
- watchMaster: don't call OnMasterDeath if FindProcess fails
- OnChildRecover: change signature to func(pid int), drop unused error return
- OnChildSpawn: add comment clarifying deferred cleanup handles the child
- CommandProducer: improve docs describing contract and use cases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(prefork): address erikdubbelboer review feedback

- OnChildRecover: signature changed to func(oldPid, newPid int) so
  callers can track which process was replaced
- OnChildSpawn: also called for recovered children (a recovered child
  is still a spawned child)
- watchMaster: call OnMasterDeath when FindProcess fails (process is
  most likely gone)
- CommandProducer: document that FASTHTTP_PREFORK_CHILD=1 must be set
  in the child env, and what the default does when nil

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(prefork): avoid zombie processes and replace shallow tests

- Move Wait() goroutine before OnChildSpawn so Kill()+Wait() works
  correctly if a callback fails and the deferred cleanup runs
- Add Wait() call in deferred cleanup after Kill() to reap children
- Same fix in recovery loop
- Remove shallow callback tests that only tested Go compiler
- Add Test_Prefork_Lifecycle: runs full prefork with CommandProducer,
  verifies callbacks fire in correct order with correct arguments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(prefork): ensure recovery default stays positive

* test(prefork): isolate lifecycle tests

* fix(prefork): tighten recovery callback flow

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-02 13:17:27 +02:00
Erik Dubbelboer 805cd10465 Add note on MaxResponseBodySize compatibility with StreamResponseBody
When `StreamResponseBody` is set the user is supposed to limit the reads
they are doing themselves.

Limiting the reads to `MaxResponseBodySize` would break backwards
compatibility.
2026-05-02 07:11:35 +02:00
dependabot[bot] 5b5c1be52c chore(deps): bump github.com/klauspost/compress from 1.18.5 to 1.18.6 (#2196)
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.18.5 to 1.18.6.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Commits](https://github.com/klauspost/compress/compare/v1.18.5...v1.18.6)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-version: 1.18.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 17:24:53 +09:00
dependabot[bot] d6a99db432 chore(deps): bump securego/gosec from 2.25.0 to 2.26.1 (#2195)
Bumps [securego/gosec](https://github.com/securego/gosec) from 2.25.0 to 2.26.1.
- [Release notes](https://github.com/securego/gosec/releases)
- [Commits](https://github.com/securego/gosec/compare/v2.25.0...v2.26.1)

---
updated-dependencies:
- dependency-name: securego/gosec
  dependency-version: 2.26.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-29 09:04:46 +02:00
Erik Dubbelboer f36c900902 header: match net/http CL+TE handling (#2190)
Match net/http behavior when requests or responses contain both
Content-Length and Transfer-Encoding.

Parse and validate Content-Length even when Transfer-Encoding is present, so
invalid lengths are rejected. For valid Content-Length with chunked
Transfer-Encoding, keep chunked framing as authoritative. Also apply the same
precedence when RequestHeader.DisableSpecialHeader is used.
2026-04-28 04:33:01 +02:00
Erik Dubbelboer 0b4cede30f header: reject unsupported response Transfer-Encoding (#2192)
Reject HTTP/1.1 response Transfer-Encoding values unless they are a single
chunked header, matching net/http's strict transfer parser behavior.

This prevents arbitrary or compound response Transfer-Encoding values from
being silently normalized to chunked and avoids desync/body parsing ambiguity
when parsing upstream responses.
2026-04-28 04:28:05 +02:00
Erik Dubbelboer c497746f7d http: reject whitespace before chunk extensions (#2193)
Reject space and tab between the chunk-size and chunk-extension separator while
preserving net/http-compatible trailing OWS before CRLF.

This avoids parser divergence for chunk lines such as "3 ;ext\r\n" without
breaking the existing acceptance of padded chunk-size lines like "3 \r\n".
Add parser regression coverage for both accepted and rejected forms.
2026-04-28 04:27:54 +02:00
Erik Dubbelboer 97b38d3a48 server: document SaveMultipartFile path trust requirement 2026-04-27 07:36:20 +02:00
Yevgeniy Miretskiy 19e4b24955 feat: add ExpectHandler for richer Expect: 100-continue handling (#2175)
* feat: add ExpectHandler for richer Expect: 100-continue handling

ContinueHandler only returns a bool, limiting the server to either
accepting (100) or rejecting with 417. ExpectHandler allows returning
any HTTP status code, and closes the connection on rejection since
the client may have already started sending body data per RFC 9110.

ExpectHandler takes precedence when both handlers are set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: use *RequestCtx in ExpectHandler for richer access

Allows callers to inspect RemoteAddr, TLS state, or any other
connection metadata alongside headers, addressing reviewer feedback.
Documents that the response must not be modified by the handler.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* Update server.go

Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>

* Update server.go

Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>
2026-04-27 05:58:04 +02:00
Erik Dubbelboer 00410e7309 Sanitize cookie setters to prevent CRLF injection (#2185)
Prevent cookie APIs from serializing embedded CR or LF bytes into
Cookie and Set-Cookie header lines.

Route Cookie key, value, domain, and path setters, parsed cookie
fields, and RequestHeader/ResponseHeader SetCookie paths through the
existing newline sanitization. Sanitize paths after normalization so
percent-decoded CR/LF bytes cannot bypass the guard.

Thanks to @vnykmshr for reporting this issue.
2026-04-27 05:29:14 +02:00
Erik Dubbelboer 3ac3b24635 server: keep hijacked reader out of pool (#2184)
When KeepHijackedConns is enabled, the hijacked connection may outlive the
HijackHandler. The wrapper continues reading through the buffered reader
after the handler returns, so returning that reader to the pool can let
another connection reset it while the hijacked connection is still in use.

Keep the buffered reader owned by the escaped hijacked connection in
keep-open mode. Add a regression test that forces reader-pool reuse
and verifies buffered data remains available after the handler returns.
2026-04-27 05:28:40 +02:00
Erik Dubbelboer 19b39dd08a Sanitize redirect Location header to prevent CRLF injection (#2186)
Route RequestCtx.Redirect Location updates through the canonical response
header setter so CR and LF bytes are normalized before serialization.

Add regression coverage for query-only and fragment-only redirects containing
CRLF, and verify the serialized response cannot emit an injected header line.
2026-04-27 05:28:30 +02:00
Erik Dubbelboer b8d29bee6e header: reject pre-colon whitespace in request headers (#2187)
Reject request header field names with whitespace immediately before the
colon instead of trimming them before special-header handling.

This prevents parser differentials for malformed framing and routing
headers such as Content-Length, Transfer-Encoding, and Host when a frontend
forwards raw invalid request headers.

Keep the existing response and trailer compatibility behavior unchanged, and
add regression coverage for both header-only parsing and full request body
reads.
2026-04-27 05:28:18 +02:00
Erik Dubbelboer 52131689e9 header: reject invalid trailer names (#2188)
Validate trailer names added through AddTrailerBytes before storing them
for Trailer header serialization.

Trim OWS around comma-separated trailer names, reject names containing
bytes outside the HTTP field-name token set, and keep the existing
forbidden-trailer filtering in place. This prevents CRLF injection through
dynamic trailer names while preserving valid trailer declarations.

Add request and response regression coverage for invalid trailer names and
tab-trimmed OWS.
2026-04-27 05:28:07 +02:00
Erik Dubbelboer 1f00bc7c28 server: apply ReadTimeout before first byte with ReduceMemoryUsage (#2183)
On new connections with ReduceMemoryUsage enabled, serveConn could reach
acquireByteReader before installing a read deadline. That left the first
blocking read outside ReadTimeout and allowed silent clients to keep the
connection open until some external timeout closed it.

Apply ReadTimeout before the first read on a new connection, while keeping
the existing idle-timeout behavior for keep-alive requests. Add a regression
test that verifies the server closes a silent ReduceMemoryUsage connection
after the first-byte timeout.
2026-04-25 03:02:03 +02:00
Erik Dubbelboer 3eab931bf1 Sanitize first-line header setters to prevent CRLF injection (#2182)
Prevent request and response first-line setters from serializing
embedded CR or LF bytes into the start line.

Route SetMethod, SetRequestURI, SetProtocol, and SetStatusMessage
through the existing newline sanitization used by other header-value
setters. This preserves behavior for valid inputs while preventing
header injection through malformed first-line values.

Thanks to @vnykmshr for reporting this issue.
2026-04-25 03:01:52 +02:00
Erik Dubbelboer 6cd91f311b Match net/http sensitive header redirect policy (#2181)
* Match net/http sensitive header redirect policy

Strip sensitive headers in DoRedirects matching net/http's redirect policy.

Reported by @vnykmshr

* Add more headers
2026-04-25 03:01:41 +02:00
Max Denushev c2e2a6c3e5 feat(client): add RetryIfErrUpstream function to handle upstream information (#2176)
* feat(client): add RetryIfErrUpstream function to handle upstream information on retry

* feat(client): lint

* feat(client): review comment fixes

* feat(client): lint

* feat(client): lint

---------

Co-authored-by: Max Denushev <denushev@tochka.com>
2026-04-20 15:38:48 +09:00
Erik Dubbelboer 534461ad12 fasthttpproxy: reject CRLF in HTTP proxy CONNECT target (#2174)
Reject dial target addresses containing CR or LF before building the
HTTP CONNECT request in httpProxyDial.

This prevents header injection through HTTP proxies when callers pass
unsanitized target addresses via low-level dial paths such as
HostClient.Addr or direct proxy dialer usage.

Reported by https://github.com/OLU-DEVX
v1.70.0
2026-04-05 07:03:35 +02:00
Erik Dubbelboer 267e740f56 fs: reject '..' path segments in rewritten paths (#2173)
Rewritten FS paths were only checked for the "/../" substring, which
allowed leading "../" values to bypass the traversal guard.

Reject any rewritten path containing a ".." path segment before joining
it with FS.Root. This closes the PathRewrite/NewPathPrefixStripper escape
in the default OS-backed handler and keeps rewritten paths within the
intended static root.

This vulnerability was discovered and reported by bugbunny.ai
2026-04-05 07:03:25 +02:00