Commit Graph

261 Commits

Author SHA1 Message Date
Erik Dubbelboer 4cf334be95 bug: SetBodySizePoolLimit data race — plain int written without synchronization (#2252) (#2282) 2026-06-06 11:29:55 +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 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 3c43293b0c Prevent chunk extension request smuggling (#2165) 2026-03-28 03:10:11 +01:00
Erik Dubbelboer f0d5d9a5cb Add WithLimit methods for uncompression (#2147)
* 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
2026-02-22 18:13:40 +01:00
Erik Dubbelboer c2b317d47d Go 1.26 and golangci-lint updates (#2146)
Keep Go 1.24 compatibility for now (by not using `wg.Go()`).
2026-02-21 10:28:39 +01:00
Erik Dubbelboer f18eb9ef0c Reject backslash absolute URIs and cache parse errors (#2075)
Keep our server behaviour the same as net/http.
2025-10-05 02:47:11 +02:00
Erik Dubbelboer 4d25421ae5 Drop Go 1.23 support (#2065)
The Go team doesn't support this version anymore. This is required to
update our golang.org/x/... dependencies.
2025-09-10 22:16:01 +02:00
Erik Dubbelboer f9d84d7c52 Rewrite header parsing to improve spec compliance (#2030)
This change updates header parsing to match the behavior of net/http more closely.

**Breaking change**: headers delimited by `\n` (instead of `\r\n`) are no longer supported.

Previously, fasthttp accepted `\n` as a delimiter, which is not spec compliant.
This made it difficult to correctly parse headers containing both `\n` and `\r\n`.
2025-08-12 15:49:35 +02:00
Kashiwa eb1f908d97 refact: eliminate duplication in Request/Response via struct embedding (#2027)
* refact: Eliminate duplication in Request/Response headers via struct embedding

* revert: SetMultipartFormBoundaryBytes

* refact: rename the params of SetProtocol and SetProtocolBytes
2025-07-05 07:51:46 +02:00
Erik Dubbelboer d356cacd84 Implement io.StringWriter on some more types (#2023)
In theory this can optimize some code paths where a string first needs
to be converted to a []byte to use the normal Write method. By
implementing WriteString this extra copy isn't needed. Internall we
don't do the copy and just use s2b instead.
2025-06-19 08:59:25 +02:00
Max Denushev 41a1449627 feat: move user values to Request structure (#1999)
Co-authored-by: Max Denushev <denushev@tochka.com>
2025-05-03 15:10:15 +09:00
osxtest 1345f42ede Add support for streaming identity-encoded or unknown length response bodies (#2000) 2025-05-03 13:51:32 +09:00
zhangyongding 86fa5635ec client: Modify some interfaces to be exportable (#1936)
* client: Client {} supports custom Transport

* client: Modify some interfaces to be exportable
2025-01-15 04:37:04 +01:00
Jeppe Bonde Weikop 7b74fc9845 fix: lenient chunk extension parsing leading to request smuggling issues (#1899)
* fix request smuggling issue

* correct broken error messages

* fix lint
2024-11-24 20:10:50 +08:00
Oleksandr Redko bc70d31d17 refactor: fix revive.indent-error-flow lint issues (#1896) 2024-11-10 20:09:27 +08:00
Kashiwa f6ba4abd2d perf: improve copyZeroAlloc for File and TCPConn (#1893)
Improve performance of `copyZeroAlloc` function

```
goos: linux
goarch: amd64
pkg: github.com/valyala/fasthttp
cpu: QEMU Virtual CPU version 2.5+
                                       │   old6.txt    │              new7.txt               │
                                       │    sec/op     │   sec/op     vs base                │
CopyZeroAllocOSFileToBytesBuffer-8        1.802µ ±  3%   1.303µ ± 2%  -27.69% (p=0.000 n=25)
CopyZeroAllocBytesBufferToOSFile-8        1.066µ ± 17%   1.048µ ± 1%   -1.69% (p=0.043 n=25)
CopyZeroAllocOSFileToStringsBuilder-8     9.477µ ±  0%   1.345µ ± 2%  -85.81% (p=0.000 n=25)
CopyZeroAllocIOLimitedReaderToOSFile-8    1.031µ ±  1%   1.092µ ± 4%   +5.92% (p=0.000 n=25)
CopyZeroAllocOSFileToOSFile-8            12.132µ ±  1%   2.386µ ± 2%  -80.33% (p=0.000 n=25)
CopyZeroAllocOSFileToNetConn-8            2.009µ ±  2%   1.995µ ± 2%        ~ (p=0.733 n=25)
CopyZeroAllocNetConnToOSFile-8            21.86µ ±  2%   20.21µ ± 1%   -7.56% (p=0.000 n=25)
geomean                                   3.728µ         2.121µ       -43.11%

                                       │    old6.txt    │                 new7.txt                  │
                                       │      B/op      │     B/op      vs base                     │
CopyZeroAllocOSFileToBytesBuffer-8         40.00 ± 0%       0.00 ±  0%  -100.00% (p=0.000 n=25)
CopyZeroAllocBytesBufferToOSFile-8         0.000 ± 0%      0.000 ±  0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocOSFileToStringsBuilder-8    32.04Ki ± 0%     0.00Ki ±  0%  -100.00% (p=0.000 n=25)
CopyZeroAllocIOLimitedReaderToOSFile-8     0.000 ± 0%      0.000 ±  0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocOSFileToOSFile-8            32.06Ki ± 0%     0.00Ki ±  0%  -100.00% (p=0.000 n=25)
CopyZeroAllocOSFileToNetConn-8             96.00 ± 0%      96.00 ±  0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocNetConnToOSFile-8            16.000 ± 6%      8.000 ± 12%   -50.00% (p=0.000 n=25)
geomean                                               ²                 ?                       ² ³
¹ all samples are equal
² summaries must be >0 to compute geomean
³ ratios must be >0 to compute geomean

                                       │   old6.txt   │                new7.txt                 │
                                       │  allocs/op   │ allocs/op   vs base                     │
CopyZeroAllocOSFileToBytesBuffer-8       4.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocBytesBufferToOSFile-8       0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocOSFileToStringsBuilder-8    5.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocIOLimitedReaderToOSFile-8   0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocOSFileToOSFile-8            8.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocOSFileToNetConn-8           6.000 ± 0%     6.000 ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocNetConnToOSFile-8           2.000 ± 0%     1.000 ± 0%   -50.00% (p=0.000 n=25)
geomean                                             ²               ?                       ² ³
¹ all samples are equal
² summaries must be >0 to compute geomean
³ ratios must be >0 to compute geomean
```

```
goos: windows
goarch: amd64
pkg: github.com/valyala/fasthttp
cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
                                       │  old_win.txt  │             new_win.txt              │
                                       │    sec/op     │    sec/op     vs base                │
CopyZeroAllocOSFileToBytesBuffer-8        4.347µ ±  7%   4.220µ ± 11%        ~ (p=0.211 n=25)
CopyZeroAllocBytesBufferToOSFile-8        1.408µ ± 12%   1.460µ ±  7%        ~ (p=0.427 n=25)
CopyZeroAllocOSFileToStringsBuilder-8    17.448µ ±  5%   3.613µ ±  9%  -79.29% (p=0.000 n=25)
CopyZeroAllocIOLimitedReaderToOSFile-8    1.324µ ±  8%   1.257µ ±  6%   -5.06% (p=0.024 n=25)
CopyZeroAllocOSFileToOSFile-8            19.953µ ±  8%   4.846µ ±  7%  -75.71% (p=0.000 n=25)
CopyZeroAllocOSFileToNetConn-8            18.18µ ±  8%   18.22µ ±  7%        ~ (p=0.405 n=25)
CopyZeroAllocNetConnToOSFile-8            74.75µ ±  2%   68.10µ ±  3%   -8.90% (p=0.000 n=25)
geomean                                   8.720µ         5.579µ        -36.02%

                                       │  old_win.txt   │                new_win.txt                │
                                       │      B/op      │     B/op      vs base                     │
CopyZeroAllocOSFileToBytesBuffer-8         8.000 ± 0%       0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocBytesBufferToOSFile-8         0.000 ± 0%       0.000 ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocOSFileToStringsBuilder-8    32.01Ki ± 0%      0.00Ki ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocIOLimitedReaderToOSFile-8     9.000 ± 0%       0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocOSFileToOSFile-8            32.02Ki ± 0%      0.00Ki ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocOSFileToNetConn-8           32.02Ki ± 0%     32.02Ki ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocNetConnToOSFile-8           32.02Ki ± 0%     32.02Ki ± 0%    -0.00% (p=0.012 n=25)
geomean                                               ²                 ?                       ² ³
¹ all samples are equal
² summaries must be >0 to compute geomean
³ ratios must be >0 to compute geomean

                                       │ old_win.txt  │               new_win.txt               │
                                       │  allocs/op   │ allocs/op   vs base                     │
CopyZeroAllocOSFileToBytesBuffer-8       1.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocBytesBufferToOSFile-8       0.000 ± 0%     0.000 ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocOSFileToStringsBuilder-8    2.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocIOLimitedReaderToOSFile-8   2.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocOSFileToOSFile-8            3.000 ± 0%     0.000 ± 0%  -100.00% (p=0.000 n=25)
CopyZeroAllocOSFileToNetConn-8           3.000 ± 0%     3.000 ± 0%         ~ (p=1.000 n=25) ¹
CopyZeroAllocNetConnToOSFile-8           3.000 ± 0%     3.000 ± 0%         ~ (p=1.000 n=25) ¹
geomean                                             ²               ?                       ² ³
¹ all samples are equal
² summaries must be >0 to compute geomean
³ ratios must be >0 to compute geomean
```
2024-11-08 06:02:43 +01:00
Agustin Arce 0b74893830 feat (request): expose req timeout (#1878)
* feat (request): expose req timeout as string

* refactor (http): update return type of GetTimeOut

* docs (http): add doc to GetTimeOut
2024-10-05 15:49:40 +02:00
newacorn d5c7d8953d fix: The client write operation did not immediately return upon encountering an RST packet. (#1849)
The current client implementation does not immediately return when encountering an RST packet while sending a request, but instead ignores it. This behavior is inconsistent with the net/http package and does not make logical sense.
2024-08-31 14:52:13 +02:00
Erik Dubbelboer df8335f9ab A response without a body can't have trailers (#1825) 2024-08-20 23:10:04 +02:00
Kashiwa 9df444bdd2 Reduce the size of ResponseHeader and RequestHeader (#1826)
* Reduce sizeof ResponseHeader and RequestHeader

+ Reduce ResponseHeader from 320 to 312 bytes
+ Reduce RequestHeader from 360 to 352 bytes
+ In the benchmark tests, although there is no significant performance improvement, it theoretically reduces memory usage by 2.2% to 2.5%.

* Remove redundant comment
2024-08-20 23:02:30 +02:00
newacorn a1db411cc2 StreamRequestBody shouldn't read more data than actual need. (#1819)
* The StreamRequestBody should not read content beyond what is required.

The StreamRequestBody feature on the server side should not read content that does not belong to the current request body.This is more logical and consistent with the result of not using the StreamRequestBody feature.Fixes: https://github.com/valyala/fasthttp/issues/1816.

* Update server_test.go

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

* Update http.go

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

---------

Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>
2024-08-11 15:35:28 +02:00
Juan Calderon-Perez 1fb3453165 Use Named Fields and Align Structures to Reduce Memory Usage (#1814)
* Use Named fields and Align Structures to Reduce Memory Usage

* Remove extra spaces
2024-08-02 22:26:52 +02:00
Kashiwa 86c7e844f4 Optimize struct field order to reduce memory usage (#1809)
1. Reduce RequestHeader from 368 bytes to 360 bytes
2. Reduce Request from 816 bytes to 800 bytes
3. Reduce Response from 432 bytes to 416 bytes
4. Reduce Client from 312 bytes to 288 bytes
5. Reduce HostClient from 416 bytes to 392 bytes
6. Reduce PipelineClient from 176 bytes to 168 bytes
7. Reduce pipelineConnClient from 216 bytes to 208 bytes
8. Reduce Cookie from 232 bytes to 224 bytes
9. Reduce FS from 184 bytes to 160 bytes
10. Reduce fsHandler from 168 bytes to 160 bytes
11. Reduce ResponseHeader from 328 bytes to 320 bytes
12. Reduce headerScanner from 128 bytes to 120 bytes
13. Reduce TCPDialer from 104 bytes to 96 bytes
14. Reduce workerPool from 152 btyes to 144 btyes
2024-07-20 19:20:26 +02:00
Max Denushev 57b9352ad1 fix: propagate body stream error to close function (#1743) (#1757)
* fix: propagate body stream error to close function (#1743)

* fix: http test

* fix: close body stream with error in encoding functions

* fix: lint

---------

Co-authored-by: Max Denushev <denushev@tochka.com>
2024-04-22 08:45:33 +02:00
Oleksandr Redko e88bd48f45 refactor: do not return error as it is always nil (#1759) 2024-04-21 19:57:04 +02:00
Oleksandr Redko bbc7bd04e2 refactor: rename error local variables (#1738) 2024-03-25 14:30:27 +01:00
Oleksandr Redko 7e1fb71854 Enable perfsprint linter; fix up lint issues (#1727) 2024-03-02 16:21:23 +01:00
Oleksandr Redko 3166afd835 Enable few gocritic checks; fix up issues (#1728) 2024-03-02 16:19:05 +01:00
Co1a 5f81476d7c feat:support zstd compress and uncompressed (#1701)
* 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>
2024-02-21 07:21:52 +01:00
Oleksandr Redko 190204cf1a Upgrade golangci-lint to v1.56.2; fix gocritic issues (#1722) 2024-02-21 05:51:28 +01:00
Oleksandr Redko 28615eba55 Change empty string checks to be more idiomatic (#1684) 2024-01-04 15:05:38 +01:00
Oleksandr Redko 9d6b470260 chore: Add missing dots at the end of comments (#1677) 2023-12-13 13:56:24 +08:00
Jille Timmermans 0caa3b9bc1 writeBodyFixedSize: Only do an early flush if the reader is an *os.File (#1674)
or an *io.LimitedReader of an *os.File (because that's also supported by
https://cs.opensource.google/go/go/+/refs/tags/go1.21.4:src/bufio/bufio.go;l=784)

I think that having to flush less often outweighs the overhead of the
extra check. The appended data is known to be large, but it might still
save us a syscall by allowing it to buffer more.
2023-12-02 18:59:46 +01:00
Jille Timmermans 2ac2a3911b copyZeroAlloc: Try WriteTo and ReadFrom before acquiring a buffer (#1673)
These are the same statements at the beginning of io.CopyBuffer, but
by doing them ourselves first we trade off a little cpu for not holding
the 4kb buffer during the write.
2023-12-02 18:05:12 +01:00
Oleksandr Redko f196617f55 chore: Use 'any' instead of 'interface{}' (#1666)
gofmt -w -r "interface{} -> any" -l .
2023-11-24 11:33:04 +01:00
Scott Kidder 42bd7bb7e2 Allow redirect URI path to not be normalized. (#1638)
* Allow redirect URI path to not be normalized.

* Introduce DisableRedirectPathNormalizing field to Request

* Use field name as start of comment.

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

---------

Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>
2023-10-30 19:08:51 +01:00
Armin Becher 34e7da1f1b Allow connection close for custom streams (#1603)
* feat: allow connection close for custom streams

* fix: avoid req access since might already be released

* fix: fix aloc test fails

* fix: race condition when clossing body stream
2023-09-02 17:56:18 +02:00
Oleksandr Redko 9aa666e814 Enable gocritic linter; fix lint issues (#1612) 2023-08-29 20:08:37 +02:00
Erik Dubbelboer 4b0e6c7f7d Update ErrNoMultipartForm
Make it a more descriptive error message.

Closes #1606
2023-08-16 19:57:20 +02:00
Erik Dubbelboer 1c85d43dfe Fix round2
- don't limit it to 32 bits
- give it a proper name
- don't over-allocate too much
2023-07-08 12:40:36 +02:00
AutumnSun 0d0bbfee5a Auto add 'Vary' header after compression (#1585)
* Auto add 'Vary' header after compression

Add config `SetAddVaryHeaderForCompression` to enable
'Vary: Accept-Encoding' header when compression is used.

* feat: always set the Vary header

* create and use `ResponseHeader.AddVaryBytes`

* not export 'AddVaryBytes'
2023-07-02 12:40:26 +02:00
Oleksandr Redko ffdf59d04c Enable gofumpt linter; format code gofumpt -w . (#1576) 2023-06-13 15:18:59 +02:00
Abe Saiovici d76662b46d Fixed transfer-encoding for empty chunked payload (#1536) 2023-04-12 22:51:30 +02:00
Anthony-Dong 6b958c2c22 support response body stream (#1414)
* feat: support response body stream

* style: add header interface

* Update http.go

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

* feat: support request、response、client stream

* fix: close reader bug

---------

Co-authored-by: fanhaodong.516 <fanhaodong.516@bytedance.com>
Co-authored-by: Erik Dubbelboer <erik@dubbelboer.com>
2023-04-05 18:56:31 +02:00
Moritz Poldrack d0f2727a4d get rid of some panics (#1526)
* 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
2023-03-30 03:38:28 +02:00
Oleksandr Redko 4e8c92b2ef http.go: close form file if copyZeroAlloc fails (#1498) 2023-03-03 20:48:32 +01:00
Oleksandr Redko e15a810a98 docs: fix grammar issues and typos in comments (#1492) 2023-02-13 10:43:44 +08:00
Oleksandr Redko 934f04e330 Refactor golangci-lint config and remove redundant nolints (#1486)
* Refactor golangci-lint config

- Use golangci-lint-action for GitHub workflow.
- Add additional golangci-lint run options.
- Remove unused nolint directives.

* Revert exclude-use-default option
2023-02-11 15:35:15 +08:00
Oleksandr Redko f84e2346ba Rename unexported funcs, vars to match common Go (#1488)
See https://github.com/golang/go/wiki/CodeReviewComments#initialisms
and https://go.dev/doc/effective_go#mixed-caps
2023-02-10 21:34:49 +08:00