github.com/MontFerret/ferret@v0.18.0/pkg/drivers/request.go (about)

     1  package drivers
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/wI2L/jettison"
     7  
     8  	"github.com/MontFerret/ferret/pkg/runtime/core"
     9  	"github.com/MontFerret/ferret/pkg/runtime/values"
    10  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
    11  )
    12  
    13  // HTTPRequest HTTP request object.
    14  type (
    15  	HTTPRequest struct {
    16  		URL     string
    17  		Method  string
    18  		Headers *HTTPHeaders
    19  		Body    []byte
    20  	}
    21  	// requestMarshal is a structure that repeats HTTPRequest. It allows
    22  	// easily Marshal the HTTPRequest object.
    23  	requestMarshal struct {
    24  		URL     string       `json:"url"`
    25  		Method  string       `json:"method"`
    26  		Headers *HTTPHeaders `json:"headers"`
    27  		Body    []byte       `json:"body"`
    28  	}
    29  )
    30  
    31  func (req *HTTPRequest) MarshalJSON() ([]byte, error) {
    32  	if req == nil {
    33  		return values.None.MarshalJSON()
    34  	}
    35  
    36  	return jettison.MarshalOpts(requestMarshal(*req), jettison.NoHTMLEscaping())
    37  }
    38  
    39  func (req *HTTPRequest) Type() core.Type {
    40  	return HTTPRequestType
    41  }
    42  
    43  func (req *HTTPRequest) String() string {
    44  	return req.URL
    45  }
    46  
    47  func (req *HTTPRequest) Compare(other core.Value) int64 {
    48  	if other.Type() != HTTPRequestType {
    49  		return Compare(HTTPResponseType, other.Type())
    50  	}
    51  
    52  	// this is a safe cast. Only *HTTPRequest implements core.Value.
    53  	// HTTPRequest does not.
    54  	otherReq := other.(*HTTPRequest)
    55  
    56  	comp := req.Headers.Compare(otherReq.Headers)
    57  
    58  	if comp != 0 {
    59  		return comp
    60  	}
    61  
    62  	comp = values.NewString(req.Method).Compare(values.NewString(otherReq.Method))
    63  
    64  	if comp != 0 {
    65  		return comp
    66  	}
    67  
    68  	return values.NewString(req.URL).
    69  		Compare(values.NewString(otherReq.URL))
    70  }
    71  
    72  func (req *HTTPRequest) Unwrap() interface{} {
    73  	return req
    74  }
    75  
    76  func (req *HTTPRequest) Hash() uint64 {
    77  	return values.Parse(req).Hash()
    78  }
    79  
    80  func (req *HTTPRequest) Copy() core.Value {
    81  	cop := *req
    82  	return &cop
    83  }
    84  
    85  func (req *HTTPRequest) GetIn(ctx context.Context, path []core.Value) (core.Value, core.PathError) {
    86  	if len(path) == 0 {
    87  		return req, nil
    88  	}
    89  
    90  	segmentIdx := 0
    91  	segment := path[segmentIdx]
    92  
    93  	if typ := segment.Type(); typ != types.String {
    94  		return values.None, core.NewPathError(core.TypeError(typ, types.String), segmentIdx)
    95  	}
    96  
    97  	field := segment.String()
    98  
    99  	switch field {
   100  	case "url", "URL":
   101  		return values.NewString(req.URL), nil
   102  	case "method":
   103  		return values.NewString(req.Method), nil
   104  	case "headers":
   105  		if len(path) == 1 {
   106  			return req.Headers, nil
   107  		}
   108  
   109  		out, pathErr := req.Headers.GetIn(ctx, path[1:])
   110  
   111  		if pathErr != nil {
   112  			return values.None, core.NewPathErrorFrom(pathErr, segmentIdx)
   113  		}
   114  
   115  		return out, nil
   116  	case "body":
   117  		return values.NewBinary(req.Body), nil
   118  	}
   119  
   120  	return values.None, nil
   121  }