github.com/skabbes/up@v0.2.1/internal/proxy/request.go (about)

     1  package proxy
     2  
     3  import (
     4  	"encoding/base64"
     5  	"net/http"
     6  	"net/url"
     7  	"strings"
     8  
     9  	"github.com/pkg/errors"
    10  )
    11  
    12  // NewRequest returns a new http.Request from the given Lambda event.
    13  func NewRequest(e *Input) (*http.Request, error) {
    14  	// path
    15  	u, err := url.Parse(e.Path)
    16  	if err != nil {
    17  		return nil, errors.Wrap(err, "parsing path")
    18  	}
    19  
    20  	// querystring
    21  	q := u.Query()
    22  	for k, v := range e.QueryStringParameters {
    23  		q.Set(k, v)
    24  	}
    25  	u.RawQuery = q.Encode()
    26  
    27  	// base64 encoded body
    28  	body := e.Body
    29  	if e.IsBase64Encoded {
    30  		b, err := base64.StdEncoding.DecodeString(body)
    31  		if err != nil {
    32  			return nil, errors.Wrap(err, "decoding base64 body")
    33  		}
    34  		body = string(b)
    35  	}
    36  
    37  	// new request
    38  	req, err := http.NewRequest(e.HTTPMethod, u.String(), strings.NewReader(body))
    39  	if err != nil {
    40  		return nil, errors.Wrap(err, "creating request")
    41  	}
    42  
    43  	// remote addr
    44  	req.RemoteAddr = e.RequestContext.Identity.SourceIP
    45  
    46  	// header fields
    47  	for k, v := range e.Headers {
    48  		req.Header.Set(k, v)
    49  	}
    50  
    51  	// custom fields
    52  	req.Header.Set("X-Request-Id", e.RequestContext.RequestID)
    53  	req.Header.Set("X-Stage", e.RequestContext.Stage)
    54  
    55  	// host
    56  	req.URL.Host = req.Header.Get("Host")
    57  	req.Host = req.URL.Host
    58  
    59  	// user
    60  	auth := req.Header.Get("Authorization")
    61  	if auth != "" {
    62  		user, pass, err := basic(auth)
    63  		if err != nil {
    64  			return nil, errors.Wrap(err, "parsing basic auth")
    65  		}
    66  		req.URL.User = url.UserPassword(user, pass)
    67  	}
    68  
    69  	// TODO: pass the original json input
    70  	return req, nil
    71  }
    72  
    73  // basic auth parser.
    74  func basic(s string) (user, pass string, err error) {
    75  	p := strings.SplitN(s, " ", 2)
    76  
    77  	if len(p) != 2 || p[0] != "Basic" {
    78  		return "", "", errors.New("malformed")
    79  	}
    80  
    81  	b, err := base64.StdEncoding.DecodeString(p[1])
    82  	if err != nil {
    83  		return "", "", errors.Wrap(err, "decoding")
    84  	}
    85  
    86  	pair := strings.SplitN(string(b), ":", 2)
    87  	return pair[0], pair[1], nil
    88  }