github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/applicationproxy/pingrequest/pingrequest.go (about)

     1  package pingrequest
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"errors"
     7  	"net/http"
     8  
     9  	"github.com/vmihailenco/msgpack"
    10  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    11  )
    12  
    13  // PingHeaderKey holds the value for aporeto ping.
    14  const PingHeaderKey = "X-APORETO-PING"
    15  
    16  // CreateRaw is same as 'Create' but will return raw bytes of
    17  // the request (wire format) returned by 'Create'.
    18  func CreateRaw(host string, pingPayload *policy.PingPayload) ([]byte, error) {
    19  
    20  	req, err := Create(host, pingPayload)
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  
    25  	var buf bytes.Buffer
    26  	if err := req.Write(&buf); err != nil {
    27  		return nil, err
    28  	}
    29  
    30  	return buf.Bytes(), nil
    31  }
    32  
    33  // ExtractRaw is same as 'Extract' but will parse the raw
    34  // bytes of the request passed and calls 'Validate'.
    35  func ExtractRaw(rawReq []byte) (*policy.PingPayload, error) {
    36  
    37  	buf := bytes.NewBuffer(rawReq)
    38  	req, err := http.ReadRequest(bufio.NewReader(buf))
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	return Extract(req)
    44  }
    45  
    46  // Create creates a new http request with the given host.
    47  // It encodes the pingPayload passed with msgpack encoding and
    48  // adds the data bytes to the header with key 'X-APORETO-PING'.
    49  // It also returns the request.
    50  func Create(host string, pingPayload *policy.PingPayload) (*http.Request, error) {
    51  
    52  	req, err := http.NewRequest("GET", host, nil)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	payload, err := encode(pingPayload)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	req.Header.Add(PingHeaderKey, string(payload))
    63  
    64  	return req, nil
    65  }
    66  
    67  // Extract verifies If the given request has the header
    68  // 'X-APORETO-PING'. If it doesn't returns error, If it did have
    69  // the header, it will try to decode the data using msgpack
    70  // encoding and will return the ping payload.
    71  func Extract(req *http.Request) (*policy.PingPayload, error) {
    72  
    73  	payload := req.Header.Get(PingHeaderKey)
    74  	if payload == "" {
    75  		return nil, errors.New("missing ping payload in header")
    76  	}
    77  
    78  	pingPayload, err := decode([]byte(payload))
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	return pingPayload, nil
    84  }
    85  
    86  func encode(pingPayload *policy.PingPayload) ([]byte, error) {
    87  	return msgpack.Marshal(pingPayload)
    88  }
    89  
    90  func decode(data []byte) (*policy.PingPayload, error) {
    91  
    92  	pingPayload := &policy.PingPayload{}
    93  
    94  	if err := msgpack.Unmarshal(data, pingPayload); err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	return pingPayload, nil
    99  }