lambda/rapidcore/standalone/util.go (93 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package standalone
import (
"encoding/json"
"fmt"
"io"
"net/http"
log "github.com/sirupsen/logrus"
"go.amzn.com/lambda/rapi/model"
)
const (
DoneFailedHTTPCode = 502
)
type ErrorType int
const (
ClientInvalidRequest ErrorType = iota
)
func (t ErrorType) String() string {
switch t {
case ClientInvalidRequest:
return "Client.InvalidRequest"
}
return fmt.Sprintf("Cannot stringify standalone.ErrorType.%d", int(t))
}
type ResponseWriterProxy struct {
Body []byte
StatusCode int
header http.Header
}
func (w *ResponseWriterProxy) Header() http.Header {
if w.header == nil {
w.header = http.Header{}
}
return w.header
}
func (w *ResponseWriterProxy) Write(b []byte) (int, error) {
w.Body = b
return 0, nil
}
func (w *ResponseWriterProxy) WriteHeader(statusCode int) {
w.StatusCode = statusCode
}
func (w *ResponseWriterProxy) IsError() bool {
return w.StatusCode != 0 && w.StatusCode/100 != 2
}
func readBodyAndUnmarshalJSON(r *http.Request, dst interface{}) *ErrorReply {
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
return newErrorReply(ClientInvalidRequest, fmt.Sprintf("Failed to read full body: %s", err))
}
if err = json.Unmarshal(bodyBytes, dst); err != nil {
return newErrorReply(ClientInvalidRequest, fmt.Sprintf("Invalid json %s: %s", string(bodyBytes), err))
}
return nil
}
type ErrorReply struct {
model.ErrorResponse
}
type RuntimeErrorReply struct {
Payload []byte
}
func (e *RuntimeErrorReply) Send(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
w.Write(e.Payload)
}
func newErrorReply(errType ErrorType, errMsg string) *ErrorReply {
return &ErrorReply{ErrorResponse: model.ErrorResponse{ErrorType: errType.String(), ErrorMessage: errMsg}}
}
func (e *ErrorReply) Send(w http.ResponseWriter, r *http.Request) {
http.Error(w, e.ErrorType, 400)
bodyJSON, err := json.Marshal(*e)
if err != nil {
http.Error(w, "Invalid format", 500)
log.Errorf("Failed to Marshal(%#v): %s", e, err)
} else {
w.Write(bodyJSON)
}
}
type SuccessReply struct {
Body []byte
}
func (s *SuccessReply) Send(w http.ResponseWriter, r *http.Request) {
w.Write(s.Body)
}
type FailureReply struct {
Body []byte
}
func (s *FailureReply) Send(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(DoneFailedHTTPCode)
w.Write(s.Body)
}
type Reply interface {
Send(http.ResponseWriter, *http.Request)
}