| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- // Package requestcompression implements runtime support for smithy-modeled
- // request compression.
- //
- // This package is designated as private and is intended for use only by the
- // smithy client runtime. The exported API therein is not considered stable and
- // is subject to breaking changes without notice.
- package requestcompression
- import (
- "bytes"
- "context"
- "fmt"
- "github.com/aws/smithy-go/middleware"
- "github.com/aws/smithy-go/transport/http"
- "io"
- )
- const MaxRequestMinCompressSizeBytes = 10485760
- // Enumeration values for supported compress Algorithms.
- const (
- GZIP = "gzip"
- )
- type compressFunc func(io.Reader) ([]byte, error)
- var allowedAlgorithms = map[string]compressFunc{
- GZIP: gzipCompress,
- }
- // AddRequestCompression add requestCompression middleware to op stack
- func AddRequestCompression(stack *middleware.Stack, disabled bool, minBytes int64, algorithms []string) error {
- return stack.Serialize.Add(&requestCompression{
- disableRequestCompression: disabled,
- requestMinCompressSizeBytes: minBytes,
- compressAlgorithms: algorithms,
- }, middleware.After)
- }
- type requestCompression struct {
- disableRequestCompression bool
- requestMinCompressSizeBytes int64
- compressAlgorithms []string
- }
- // ID returns the ID of the middleware
- func (m requestCompression) ID() string {
- return "RequestCompression"
- }
- // HandleSerialize gzip compress the request's stream/body if enabled by config fields
- func (m requestCompression) HandleSerialize(
- ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler,
- ) (
- out middleware.SerializeOutput, metadata middleware.Metadata, err error,
- ) {
- if m.disableRequestCompression {
- return next.HandleSerialize(ctx, in)
- }
- // still need to check requestMinCompressSizeBytes in case it is out of range after service client config
- if m.requestMinCompressSizeBytes < 0 || m.requestMinCompressSizeBytes > MaxRequestMinCompressSizeBytes {
- return out, metadata, fmt.Errorf("invalid range for min request compression size bytes %d, must be within 0 and 10485760 inclusively", m.requestMinCompressSizeBytes)
- }
- req, ok := in.Request.(*http.Request)
- if !ok {
- return out, metadata, fmt.Errorf("unknown request type %T", req)
- }
- for _, algorithm := range m.compressAlgorithms {
- compressFunc := allowedAlgorithms[algorithm]
- if compressFunc != nil {
- if stream := req.GetStream(); stream != nil {
- size, found, err := req.StreamLength()
- if err != nil {
- return out, metadata, fmt.Errorf("error while finding request stream length, %v", err)
- } else if !found || size < m.requestMinCompressSizeBytes {
- return next.HandleSerialize(ctx, in)
- }
- compressedBytes, err := compressFunc(stream)
- if err != nil {
- return out, metadata, fmt.Errorf("failed to compress request stream, %v", err)
- }
- var newReq *http.Request
- if newReq, err = req.SetStream(bytes.NewReader(compressedBytes)); err != nil {
- return out, metadata, fmt.Errorf("failed to set request stream, %v", err)
- }
- *req = *newReq
- if val := req.Header.Get("Content-Encoding"); val != "" {
- req.Header.Set("Content-Encoding", fmt.Sprintf("%s, %s", val, algorithm))
- } else {
- req.Header.Set("Content-Encoding", algorithm)
- }
- }
- break
- }
- }
- return next.HandleSerialize(ctx, in)
- }
|