contentencoding

package module
v0.0.0-...-9ea4a77 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2022 License: MIT Imports: 6 Imported by: 1

README

go-content-encoding

ci go.dev reference codecov Go Report Card

Description

go-content-encoding provides net/http compatible middleware for HTTP Content-Encoding.
It also provides the functionality to customize the decoder.
By default, br(brotli), gzip and zstd(zstandard) are supported.

Example

package contentencoding_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	contentencoding "github.com/johejo/go-content-encoding"
)

func ExampleDecode() {
	handler := func(w http.ResponseWriter, r *http.Request) {
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			panic(err)
		}
		log.Println(b) // decoded body
	}

	mux := http.NewServeMux()
	decode := contentencoding.Decode()
	mux.Handle("/", decode(http.HandlerFunc(handler)))
}

func ExampleWithDecoder() {
	customDecoder := &contentencoding.Decoder{
		Encoding: "custom",
		Handler: func(w http.ResponseWriter, r *http.Request) error {
			b, err := ioutil.ReadAll(r.Body)
			if err != nil {
				return err
			}
			r.Body = ioutil.NopCloser(strings.NewReader(string(b) + "-custom"))
			return nil
		},
	}
	mux := http.NewServeMux()
	dm := contentencoding.Decode(contentencoding.WithDecoder(customDecoder))
	mux.Handle("/", dm(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			panic(err)
		}
		fmt.Println(string(b))
	})))
	rec := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("test"))
	req.Header.Set("Content-Encoding", "custom")
	mux.ServeHTTP(rec, req)

	// Output:
	// test-custom
}

func ExampleWithErrorHandler() {
	mux := http.NewServeMux()
	errHandler := contentencoding.ErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {
		w.WriteHeader(999) // custom error code
	})
	dm := contentencoding.Decode(contentencoding.WithErrorHandler(errHandler))
	mux.Handle("/", dm(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})))
	rec := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("test")) // not compressed
	req.Header.Set("Content-Encoding", "gzip")
	mux.ServeHTTP(rec, req)
	fmt.Println(rec.Code)

	// Output:
	// 999
}

License

MIT

Author

Mitsuo Heijo (@johejo)

Documentation

Overview

Package contentencoding provides net/http compatible middleware for HTTP Content-Encoding. It also provides the functionality to customize the decoder. By default, br(brotli), gzip and zstd(zstandard) are supported.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode

func Decode(opts ...Option) func(next http.Handler) http.Handler

Decode returns net/http compatible middleware that automatically decodes body detected by Content-Encoding. By default, br(brotli), gzip and zstd(zstandard) are supported.

Example
package main

import (
	"io/ioutil"
	"log"
	"net/http"

	contentencoding "github.com/johejo/go-content-encoding"
)

func main() {
	handler := func(w http.ResponseWriter, r *http.Request) {
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			panic(err)
		}
		log.Println(b) // decoded body
	}

	mux := http.NewServeMux()
	decode := contentencoding.Decode()
	mux.Handle("/", decode(http.HandlerFunc(handler)))
}
Output:

func DefaultErrorHandler

func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error)

DefaultErrorHandler is ErrorHandler that will used by default.

Types

type Decoder

type Decoder struct {
	// Encoding is a string used for Content-Encoding matching.
	Encoding string
	// Handler will be called when Encoding matches the Content-Encoding.
	Handler func(w http.ResponseWriter, r *http.Request) error
}

Decoder is custom decoder for user defined Content-Encoding. If the Content-Encoding matches Encoding, Handler is called.

type ErrorHandler

type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)

ErrorHandler is a type used to customize error handling.

type Option

type Option func(cfg *config)

Option is option for Decode.

func WithDOptions

func WithDOptions(dopts ...zstd.DOption) Option

WithDOptions returns a Option to customize zstd decoder with zstd.DOptions. See https://pkg.go.dev/github.com/klauspost/compress/zstd?tab=doc#DOption.

func WithDecoder

func WithDecoder(decoders ...*Decoder) Option

WithDecoder returns a Option to use Decode with Decoder.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"

	contentencoding "github.com/johejo/go-content-encoding"
)

func main() {
	customDecoder := &contentencoding.Decoder{
		Encoding: "custom",
		Handler: func(w http.ResponseWriter, r *http.Request) error {
			b, err := ioutil.ReadAll(r.Body)
			if err != nil {
				return err
			}
			r.Body = ioutil.NopCloser(strings.NewReader(string(b) + "-custom"))
			return nil
		},
	}
	mux := http.NewServeMux()
	dm := contentencoding.Decode(contentencoding.WithDecoder(customDecoder))
	mux.Handle("/", dm(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			panic(err)
		}
		fmt.Println(string(b))
	})))
	rec := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("test"))
	req.Header.Set("Content-Encoding", "custom")
	mux.ServeHTTP(rec, req)

}
Output:

test-custom

func WithErrorHandler

func WithErrorHandler(eh ErrorHandler) Option

WithErrorHandler returns a Option to customize error handling.

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"

	contentencoding "github.com/johejo/go-content-encoding"
)

func main() {
	mux := http.NewServeMux()
	errHandler := contentencoding.ErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {
		w.WriteHeader(999) // custom error code
	})
	dm := contentencoding.Decode(contentencoding.WithErrorHandler(errHandler))
	mux.Handle("/", dm(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})))
	rec := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("test")) // not compressed
	req.Header.Set("Content-Encoding", "gzip")
	mux.ServeHTTP(rec, req)
	fmt.Println(rec.Code)

}
Output:

999

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL