Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Go net/http middleware for decode http.Request.Body and encode http.ResponseWriter based on Accept-Encoding and Content-Encoding headers

License

Notifications You must be signed in to change notification settings

alexdyukov/httpencoder

Repository files navigation

httpencoder - golang net/http middleware for decode requests and encode responses based on Accept-Encoding and Content-Encoding headers

GoDoc Tests

Decoding client body

According to RFCs there is no 'Accept-Encoding' header at server side response. It means you cannot tell clients (browsers, include headless browsers like curl/python's request) that your server accept any encodings. But some of the backends (for example apache's mod_deflate) support decoding request body, thats why the same feature exists in this package.

Benchmarks

There is a little overhead to compare to if strings.Contains(request.Header.Get("Accept-Encoding"), "myencoding"):

$ go test -bench=. -benchmem -benchtime=10000000x
warning: GOPATH set to GOROOT (/home/user/go) has no effect
goos: linux
goarch: amd64
pkg: github.com/alexdyukov/httpencoder
cpu: AMD Ryzen 7 8845H w/ Radeon 780M Graphics
BenchmarkRaw-16 10000000 200.7 ns/op 720 B/op 5 allocs/op
BenchmarkIfedEncode-16 10000000 489.1 ns/op 1456 B/op 9 allocs/op
BenchmarkWrappedEncodeDecode-16 10000000 1083 ns/op 1569 B/op 15 allocs/op
BenchmarkWrappedDecode-16 10000000 391.4 ns/op 752 B/op 7 allocs/op
BenchmarkWrappedEncode-16 10000000 917.2 ns/op 1537 B/op 13 allocs/op
PASS
ok github.com/alexdyukov/httpencoder 30.844s

Examples

Gzip encoder/decoder:


type gzipper struct{}
func (gzipper) Encode(ctx context.Context, to io.Writer, from []byte) (err error) {
	gzipWriter := gzip.NewWriter(to)
	if _, err := gzipWriter.Write(from); err != nil {
		reqID := ctx.Value(contextValueKey)
		slog.Info("failed to gzip response", "request_id", reqID, "error", err.Error())
		return fmt.Errorf("Internal server error occur. Your request id %v. Try again later or feel free to contact us to get detailed info", reqID)
	}
	if err := gzipWriter.Flush(); err != nil {
		reqID := ctx.Value(contextValueKey)
		slog.Info("failed to flush gzipped response", "request_id", reqID, "error", err.Error())
		return fmt.Errorf("Internal server error occur. Your request id %v. Try again later or feel free to contact us to get detailed info", reqID)
	}
	return nil
}
func (gzipper) Decode(ctx context.Context, to io.Writer, from []byte) (err error) {
	gzipReader, err := gzip.NewReader(bytes.NewReader(from))
	if err != nil {
		reqID := ctx.Value(contextValueKey)
		slog.Info("failed to initialize gzip reader", "request_id", reqID, "error", err.Error())
		return fmt.Errorf("Internal server error occur. Your request id %v. Try again later or feel free to contact us to get detailed info", reqID)
	}
	_, err = io.Copy(to, gzipReader)
	if err != nil && !errors.Is(err, io.ErrUnexpectedEOF) {
		reqID := ctx.Value(contextValueKey)
		slog.Info("failed to read from gzip reader", "request_id", reqID, "error", err.Error())
		return fmt.Errorf("Internal server error occur. Your request id %v. Try again later or feel free to contact us to get detailed info", reqID)
	}
	return nil
}

License

MIT licensed. See the included LICENSE file for details.

About

Go net/http middleware for decode http.Request.Body and encode http.ResponseWriter based on Accept-Encoding and Content-Encoding headers

Topics

Resources

License

Stars

Watchers

Forks

Languages

AltStyle によって変換されたページ (->オリジナル) /