diff --git a/README.md b/README.md
index ceff543..fce28d9 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,7 @@ The following flags are supported:
| `--show-details` | show request details in the error page response (if supported by the template) | `false` | `SHOW_DETAILS` |
| `--proxy-headers="…"` | HTTP headers listed here will be proxied from the original request to the error page response (comma-separated list) | `X-Request-Id,X-Trace-Id,X-Amzn-Trace-Id` | `PROXY_HTTP_HEADERS` |
| `--rotation-mode="…"` | templates automatic rotation mode (disabled/random-on-startup/random-on-each-request/random-hourly/random-daily) | `disabled` | `TEMPLATES_ROTATION_MODE` |
+| `--read-buffer-size="…"` | per-connection buffer size in bytes for reading requests, this also limits the maximum header size (increase this buffer if your clients send multi-KB Request URIs and/or multi-KB headers (e.g., large cookies), note that increasing this value will increase memory consumption) | `5120` | `READ_BUFFER_SIZE` |
### `build` command (aliases: `b`)
@@ -90,7 +91,7 @@ The following templates are built-in and available for use without any additiona
> [!NOTE]
> The `cat` template is the only one of those that fetches resources (the actual cat pictures)
-> from external servers - all other templates are self contained.
+> from external servers - all other templates are self-contained.
diff --git a/internal/cli/serve/command.go b/internal/cli/serve/command.go
index 9d01d60..80acc7c 100644
--- a/internal/cli/serve/command.go
+++ b/internal/cli/serve/command.go
@@ -22,9 +22,9 @@ type command struct {
opt struct {
http struct { // our HTTP server
- addr string
- port uint16
- // readBufferSize uint
+ addr string
+ port uint16
+ readBufferSize uint
}
}
}
@@ -140,6 +140,15 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit,gocy
return nil
},
}
+ readBufferSizeFlag = cli.UintFlag{
+ Name: "read-buffer-size",
+ Usage: "per-connection buffer size in bytes for reading requests, this also limits the maximum header size " +
+ "(increase this buffer if your clients send multi-KB Request URIs and/or multi-KB headers (e.g., " +
+ "large cookies), note that increasing this value will increase memory consumption)",
+ Value: 1024 * 5, //nolint:mnd // 5 KB
+ Sources: env("READ_BUFFER_SIZE"),
+ OnlyOnce: true,
+ }
)
// override some flag usage messages
@@ -157,6 +166,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit,gocy
Action: func(ctx context.Context, c *cli.Command) error {
cmd.opt.http.addr = c.String(addrFlag.Name)
cmd.opt.http.port = uint16(c.Uint(portFlag.Name))
+ cmd.opt.http.readBufferSize = uint(c.Uint(readBufferSizeFlag.Name))
cfg.L10n.Disable = c.Bool(disableL10nFlag.Name)
cfg.DefaultCodeToRender = uint16(c.Uint(defaultCodeToRenderFlag.Name))
cfg.RespondWithSameHTTPCode = c.Bool(sendSameHTTPCodeFlag.Name)
@@ -282,6 +292,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit,gocy
&showDetailsFlag,
&proxyHeadersListFlag,
&rotationModeFlag,
+ &readBufferSizeFlag,
},
}
@@ -290,7 +301,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit,gocy
// Run current command.
func (cmd *command) Run(ctx context.Context, log *logger.Logger, cfg *config.Config) error { //nolint:funlen
- var srv = appHttp.NewServer(log)
+ var srv = appHttp.NewServer(log, cmd.opt.http.readBufferSize)
if err := srv.Register(cfg); err != nil {
return err
diff --git a/internal/http/server.go b/internal/http/server.go
index 7b1df00..faf591a 100644
--- a/internal/http/server.go
+++ b/internal/http/server.go
@@ -28,11 +28,10 @@ type Server struct {
}
// NewServer creates a new HTTP server.
-func NewServer(log *logger.Logger) Server {
+func NewServer(log *logger.Logger, readBufferSize uint) Server {
const (
- readTimeout = 30 * time.Second
- writeTimeout = readTimeout + 10*time.Second // should be bigger than the read timeout
- maxHeaderBytes = (1 << 20) * 5 //nolint:mnd // 5 MB
+ readTimeout = 30 * time.Second
+ writeTimeout = readTimeout + 10*time.Second // should be bigger than the read timeout
)
return Server{
@@ -40,7 +39,7 @@ func NewServer(log *logger.Logger) Server {
server: &fasthttp.Server{
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
- ReadBufferSize: maxHeaderBytes,
+ ReadBufferSize: int(readBufferSize),
DisablePreParseMultipartForm: true,
NoDefaultServerHeader: true,
CloseOnShutdown: true,
diff --git a/internal/http/server_test.go b/internal/http/server_test.go
index 754c640..96981b9 100644
--- a/internal/http/server_test.go
+++ b/internal/http/server_test.go
@@ -20,7 +20,7 @@ import (
// TestRouting in fact is a test for the whole server, because it tests all the routes and their handlers.
func TestRouting(t *testing.T) {
var (
- srv = appHttp.NewServer(logger.NewNop())
+ srv = appHttp.NewServer(logger.NewNop(), 1025*5)
cfg = config.New()
)