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>
* 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>
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.
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.
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.
ServeFile and ServeFS interpret the path as a URI, so percent-encoded
sequences are decoded and characters like '?' and '#' act as URI
delimiters. This makes it impossible to serve files whose names
contain those characters.
Changing this behavior would be backwards incompatible. So instead the
new ServeFileLiteral, ServeFSLiteral and SendFileLiteral are added.
The new Literal variants percent-encode the path before setting it as
the request URI, preserving every byte of the original filesystem path.
Thanks to @thesmartshadow for reporting this issue.
* Add WithLimit methods for uncompression
The current uncompress methods don't enforce a memory limit and are
susceptible to things like zip bombs. This pull introduces new methods
so retain backwards compatibility. The old methods might be deprecated
in the future.
* Fix suggestion
Locking and unlocking a mutex multiple times per request is a major
slowdown that we can avoid with clever use of atomics.
Before:
```
BenchmarkServerGet100ReqPerConn10KClients-12 84167428 867.7 ns/op
```
After:
```
BenchmarkServerGet100ReqPerConn10KClients-12 187397954 386.3 ns/op
```
* fix: ShutdownWithContext and ctx.Done() exist race.
* fix: Even if ln.Close() err, the Shutdown process should still proceed.
* refactor: remove END label.
In the current implementation, there are several places where it's assumed that SetReadDeadline and similar functions logically won't affect a closed connection. However, these assumptions may not hold in certain specific situations. Therefore, instead of asserting that such errors will never occur, simply return the errors encountered during the execution of these methods.
* Fix possible race condition on request ctx done #1662
* Fix possible race condition on request ctx done #1662
* Fix Comment
* fix remove the use of lock
* fix remove Comment
* feat:support zstd compress and uncompressed
* fix:real & stackless write using different pool to avoid get stackless.writer
* fix:zstd normalize compress level
* Change empty string checks to be more idiomatic (#1684)
* chore:lint fix and rebase with master
* chore:remove 1.18 test & upgrade compress version
* fix:error default compress level
* Fix lint
---------
Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>
A few lines later we check if `s.ReduceMemoryUsage && hijackHandler == nil`
and call releaseWriter. We need to flush the buffer before returning it
to the pool to avoid the data getting lost.
* client: simplify (*HostClient).do()
Remove an allocation in favour of deferring a call to release the
response.
* client: remove panic in dialAddr
Return an error instead of panicking if the user supplied a nonsensical
DialFunc.
* compression: remove panic on invalid compression level
If a compression level exceeding gzip's boundaries is provided, fasthttp
will panic. Instead it would be better to handle this error for them by
limiting it to the minimum or maximum value, depending on the direction
the user has exceeded the limits.
Clamp the value of gzip to always be between gzip.BestSpeed and
gzip.BestCompression.
* peripconn: remove panic on negative connection count
When a negative count is reached when unregistering a connection, a
panic is caused even though data-integrity is not at risk.
Replace the panic() with a simple clamp on the value to ensure the
value does not exceed it's expected lower bounds.
References: #1504
* compress: remove error on failed nonblocking writes
Since there is no way of handling or even logging non-critical errors in
stateless non-blocking writecalls, just drop them and hope the user
notices and tries again.
* workerPool: remove panic on redundant Start and Stop calls
Instead of panicking for invalid behaviour, it's preferable to just turn
the function into a noop.
* http: remove panic on invalid form boundary
* http: remove panic on negative reads
Since bufio already panics on negative reads, it is not necessary to do
so as well. If the length is zero and for some reason no error is
returned, readBodyIdentity and appendBodyFixedSize now errors in these
cases.
Link: https://github.com/golang/go/blob/851f6fd61425c810959c7ab51e6dc86f8a63c970/src/bufio/bufio.go#L246
* fs: remove panic on negative reader count
When a negative count is reached when unregistering a reader, a panic is
thrown even though data-integrity is not at risk.
Replace the panic() with a simple clamp on the value to ensure the
value does not exceed it's expected lower bounds.
* server: remove panic in favour of a segfault
Panicking with "BUG: " obscures the error. As the segfault causes a
panic anyway, just let the chaos unfold.
* server: remove panic in favour of returning an error
Writing on a timed-out response is not endangering data integrity and
just fails.
* chore: add comments to all panics
* chore: fix minor typo