Repository: caddyserver/caddy
File: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go (Go)

Code before:
	if t.Root == "" {
		t.Root = "{http.vars.root}"
	}

	version, _ := caddy.Version()
	t.serverSoftware = "Caddy/" + version

	// Set a relatively short default dial timeout.
	// This is helpful to make load-balancer retries more speedy.
	if t.DialTimeout == 0 {
		t.DialTimeout = caddy.Duration(3 * time.Second)
	}

	return nil
}

// RoundTrip implements http.RoundTripper.
func (t Transport) RoundTrip(r *http.Request) (*http.Response, error) {
	server := r.Context().Value(caddyhttp.ServerCtxKey).(*caddyhttp.Server)

	// Disallow null bytes in the request path, because
	// PHP upstreams may do bad things, like execute a
	// non-PHP file as PHP code. See #4574
	if strings.Contains(r.URL.Path, "\x00") {
		return nil, caddyhttp.Error(http.StatusBadRequest, fmt.Errorf("invalid request path"))
	}

	env, err := t.buildEnv(r)
	if err != nil {
		return nil, fmt.Errorf("building environment: %v", err)
	}

	ctx := r.Context()

	// extract dial information from request (should have been embedded by the reverse proxy)
	network, address := "tcp", r.URL.Host
	if dialInfo, ok := reverseproxy.GetDialInfo(ctx); ok {
		network = dialInfo.Network
		address = dialInfo.Address
	}

	logCreds := server.Logs != nil && server.Logs.ShouldLogCredentials
	loggableReq := caddyhttp.LoggableHTTPRequest{
		Request:              r,
		ShouldLogCredentials: logCreds,
	}
	loggableEnv := loggableEnv{vars: env, logCredentials: logCreds}

	logger := t.logger.With(
		zap.Object("request", loggableReq),
		zap.Object("env", loggableEnv),

Review comment (suggestion):
Technically the newline between the comments breaks the godoc

```suggestion
// DefaultBufferSizes enables request buffering for fastcgi if not configured.
// This is because most fastcgi servers are php-fpm that require the content length to be set to read the body, golang
// std has fastcgi implementation that doesn't need this value to process the body, but we can safely assume that's
// not used.
// http3 requests have a negative content length for GET and HEAD requests, if that header is not sent.
// see: https://github.com/caddyserver/caddy/issues/6678#issuecomment-2472224182
// Though it appears even if CONTENT_LENGTH is invalid, php-fpm can handle just fine if the body is empty (no Stdin records sent).
// php-fpm will hang if there is any data in the body though, https://github.com/caddyserver/caddy/issues/5420#issuecomment-2415943516
// TODO: better default buffering for fastcgi requests without content length, in theory a value of 1 should be enough, make it bigger anyway
```

Code after:
	if t.Root == "" {
		t.Root = "{http.vars.root}"
	}

	version, _ := caddy.Version()
	t.serverSoftware = "Caddy/" + version

	// Set a relatively short default dial timeout.
	// This is helpful to make load-balancer retries more speedy.
	if t.DialTimeout == 0 {
		t.DialTimeout = caddy.Duration(3 * time.Second)
	}

	return nil
}

// DefaultBufferSizes enables request buffering for fastcgi if not configured.
// This is because most fastcgi servers are php-fpm that require the content length to be set to read the body, golang
// std has fastcgi implementation that doesn't need this value to process the body, but we can safely assume that's
// not used.
// http3 requests have a negative content length for GET and HEAD requests, if that header is not sent.
// see: https://github.com/caddyserver/caddy/issues/6678#issuecomment-2472224182
// Though it appears even if CONTENT_LENGTH is invalid, php-fpm can handle just fine if the body is empty (no Stdin records sent).
// php-fpm will hang if there is any data in the body though, https://github.com/caddyserver/caddy/issues/5420#issuecomment-2415943516

// TODO: better default buffering for fastcgi requests without content length, in theory a value of 1 should be enough, make it bigger anyway
func (t Transport) DefaultBufferSizes() (int64, int64) {
	return 4096, 0
}

// RoundTrip implements http.RoundTripper.
func (t Transport) RoundTrip(r *http.Request) (*http.Response, error) {
	server := r.Context().Value(caddyhttp.ServerCtxKey).(*caddyhttp.Server)

	// Disallow null bytes in the request path, because
	// PHP upstreams may do bad things, like execute a
	// non-PHP file as PHP code. See #4574
	if strings.Contains(r.URL.Path, "\x00") {
		return nil, caddyhttp.Error(http.StatusBadRequest, fmt.Errorf("invalid request path"))
	}

	env, err := t.buildEnv(r)
	if err != nil {
		return nil, fmt.Errorf("building environment: %v", err)
	}

	ctx := r.Context()

	// extract dial information from request (should have been embedded by the reverse proxy)
	network, address := "tcp", r.URL.Host
	if dialInfo, ok := reverseproxy.GetDialInfo(ctx); ok {