log/request_size.go (27 lines of code) (raw):

package log import "net/http" const ( // newLineBytes is the number of bytes for a newline: // HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all // // protocol elements except the entity-body (see appendix 19.3 for // tolerant applications). newLineBytes = 2 // requestLineSpaceBytes is the number of bytes in a separator between fields in request line. requestLineSpaceBytes = 1 // headerSeparatorBytes is the number of bytes in a separator between header and its value `X: Y`. headerSeparatorBytes = 2 hostHeaderExtraBytes = len("Host: ") ) // computeApproximateRequestSize will calculate the approximate request size, // including the request line, headers and ContentLength (if set). // Inspired by: https://github.com/prometheus/client_golang/blob/331dfab0cc853dca0242a0d96a80184087a80c1d/prometheus/promhttp/instrument_server.go#L409 // but more accurate as it includes whitespace. // We do this because it makes verification easier for test data, as we can simply use `len(string)`. func computeApproximateRequestSize(r *http.Request, bodyByteCount int64) int64 { var s int64 // Request Line s += int64(len(r.Method) + requestLineSpaceBytes) if r.URL != nil { s += int64(len(r.URL.String()) + requestLineSpaceBytes) } s += int64(len(r.Proto) + newLineBytes) // Headers if r.Host != "" { s += int64(hostHeaderExtraBytes + len(r.Host) + newLineBytes) } for name, values := range r.Header { for _, value := range values { s += int64(len(name) + headerSeparatorBytes + len(value) + newLineBytes) } } // Include the trailing newline after the request headers. s += newLineBytes // Body s += bodyByteCount return s }