github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/httptransport/httpx/httpx_request_info.go (about)

     1  package httpx
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net/http"
     7  	"net/textproto"
     8  	"net/url"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/julienschmidt/httprouter"
    13  )
    14  
    15  func NewRequestInfo(r *http.Request) RequestInfo {
    16  	return &requestInfo{
    17  		recvts:  time.Now(),
    18  		request: r,
    19  	}
    20  }
    21  
    22  type WithFromRequestInfo interface {
    23  	FromRequestInfo(ri RequestInfo) error
    24  }
    25  
    26  type RequestInfo interface {
    27  	Context() context.Context
    28  	Values(in string, name string) []string
    29  	Header() http.Header
    30  	Body() io.ReadCloser
    31  }
    32  
    33  type requestInfo struct {
    34  	request *http.Request
    35  	recvts  time.Time
    36  	query   url.Values
    37  	cookies []*http.Cookie
    38  	params  httprouter.Params
    39  }
    40  
    41  func (ri *requestInfo) Header() http.Header { return ri.request.Header }
    42  
    43  func (ri *requestInfo) Context() context.Context { return ri.request.Context() }
    44  
    45  func (ri *requestInfo) Body() io.ReadCloser { return ri.request.Body }
    46  
    47  func (ri *requestInfo) Value(in string, name string) string {
    48  	values := ri.Values(in, name)
    49  	if len(values) == 0 {
    50  		return ""
    51  	}
    52  	return values[0]
    53  }
    54  
    55  func (ri *requestInfo) Values(in string, name string) []string {
    56  	switch in {
    57  	case "path":
    58  		v := ri.Param(name)
    59  		if v == "" {
    60  			return []string{}
    61  		}
    62  		return []string{v}
    63  	case "query":
    64  		return ri.QueryValues(name)
    65  	case "cookie":
    66  		return ri.CookieValues(name)
    67  	case "header":
    68  		return ri.HeaderValues(name)
    69  	}
    70  	return []string{}
    71  }
    72  
    73  func (ri *requestInfo) Param(name string) string {
    74  	if ri.params == nil {
    75  		params, ok := ri.request.Context().Value(httprouter.ParamsKey).(httprouter.Params)
    76  		if !ok {
    77  			params = httprouter.Params{}
    78  		}
    79  		ri.params = params
    80  	}
    81  	return ri.params.ByName(name)
    82  }
    83  
    84  func (ri *requestInfo) QueryValues(name string) []string {
    85  	if ri.query == nil {
    86  		ri.query = ri.request.URL.Query()
    87  
    88  		if ri.request.Method == http.MethodGet && len(ri.query) == 0 &&
    89  			ri.request.ContentLength > 0 {
    90  			if strings.HasPrefix(ri.request.Header.Get("Content-Type"), MIME_FORM_URLENCODED) {
    91  				data, err := io.ReadAll(ri.request.Body)
    92  				if err == nil {
    93  					ri.request.Body.Close()
    94  
    95  					query, e := url.ParseQuery(string(data))
    96  					if e == nil {
    97  						ri.query = query
    98  					}
    99  				}
   100  			}
   101  		}
   102  	}
   103  	return ri.query[name]
   104  }
   105  
   106  func (ri *requestInfo) HeaderValues(name string) []string {
   107  	return ri.request.Header[textproto.CanonicalMIMEHeaderKey(name)]
   108  }
   109  
   110  func (ri *requestInfo) CookieValues(name string) []string {
   111  	if ri.cookies == nil {
   112  		ri.cookies = ri.request.Cookies()
   113  	}
   114  
   115  	values := make([]string, 0)
   116  	for _, c := range ri.cookies {
   117  		if c.Name == name {
   118  			if c.Expires.IsZero() {
   119  				values = append(values, c.Value)
   120  			} else if c.Expires.After(ri.recvts) {
   121  				values = append(values, c.Value)
   122  			}
   123  		}
   124  	}
   125  	return values
   126  }