Skip to content

Commit

Permalink
private: Adds support for httpChecksumRequired trait (aws#3272)
Browse files Browse the repository at this point in the history
  • Loading branch information
skotambkar authored May 26, 2020
1 parent 2d91254 commit bcb2cf3
Show file tree
Hide file tree
Showing 8 changed files with 501 additions and 158 deletions.
23 changes: 23 additions & 0 deletions aws/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,26 @@ func (es errors) Error() string {

return strings.Join(parts, "\n")
}

// CopySeekableBody copies the seekable body to an io.Writer
func CopySeekableBody(dst io.Writer, src io.ReadSeeker) (int64, error) {
curPos, err := src.Seek(0, sdkio.SeekCurrent)
if err != nil {
return 0, err
}

// copy errors may be assumed to be from the body.
n, err := io.Copy(dst, src)
if err != nil {
return n, err
}

// seek back to the first position after reading to reset
// the body for transmission.
_, err = src.Seek(curPos, sdkio.SeekStart)
if err != nil {
return n, err
}

return n, nil
}
53 changes: 53 additions & 0 deletions private/checksum/content_md5.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package checksum

import (
"crypto/md5"
"encoding/base64"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
)

const contentMD5Header = "Content-Md5"

// AddBodyContentMD5Handler computes and sets the HTTP Content-MD5 header for requests that
// require it.
func AddBodyContentMD5Handler(r *request.Request) {
// if Content-MD5 header is already present, return
if v := r.HTTPRequest.Header.Get(contentMD5Header); len(v) != 0 {
return
}

// if S3DisableContentMD5Validation flag is set, return
if aws.BoolValue(r.Config.S3DisableContentMD5Validation) {
return
}

// if request is presigned, return
if r.IsPresigned() {
return
}

// if body is not seekable, return
if !aws.IsReaderSeekable(r.Body) {
if r.Config.Logger != nil {
r.Config.Logger.Log(fmt.Sprintf(
"Unable to compute Content-MD5 for unseekable body, S3.%s",
r.Operation.Name))
}
return
}

h := md5.New()

if _, err := aws.CopySeekableBody(h, r.Body); err != nil {
r.Error = awserr.New("ContentMD5", "failed to compute body MD5", err)
return
}

// encode the md5 checksum in base64 and set the request header.
v := base64.StdEncoding.EncodeToString(h.Sum(nil))
r.HTTPRequest.Header.Set(contentMD5Header, v)
}
15 changes: 12 additions & 3 deletions private/model/api/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ type Operation struct {

EventStreamAPI *EventStreamAPI

IsEndpointDiscoveryOp bool `json:"endpointoperation"`
EndpointDiscovery *EndpointDiscovery `json:"endpointdiscovery"`
Endpoint *EndpointTrait `json:"endpoint"`
IsEndpointDiscoveryOp bool `json:"endpointoperation"`
EndpointDiscovery *EndpointDiscovery `json:"endpointdiscovery"`
Endpoint *EndpointTrait `json:"endpoint"`
IsHttpChecksumRequired bool `json:"httpChecksumRequired"`
}

// EndpointTrait provides the structure of the modeled endpoint trait, and its
Expand Down Expand Up @@ -310,6 +311,14 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` +
{{- range $_, $handler := $.CustomBuildHandlers }}
req.Handlers.Build.PushBackNamed({{ $handler }})
{{- end }}
{{- if .IsHttpChecksumRequired }}
{{- $_ := .API.AddSDKImport "private/checksum" }}
req.Handlers.Build.PushBackNamed(request.NamedHandler{
Name: "contentMd5Handler",
Fn: checksum.AddBodyContentMD5Handler,
})
{{- end }}
return
}
Expand Down
81 changes: 81 additions & 0 deletions service/s3/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bcb2cf3

Please sign in to comment.