github.com/Kong/go-pdk@v0.11.0/request/request.go (about)

     1  /*
     2  Client request module.
     3  
     4  A set of functions to retrieve information about the incoming requests made by clients.
     5  */
     6  package request
     7  
     8  import (
     9  	"errors"
    10  	"io/ioutil" //nolint:all // TODO: update to remove deprecated dependency
    11  
    12  	"github.com/Kong/go-pdk/bridge"
    13  	"github.com/Kong/go-pdk/server/kong_plugin_protocol"
    14  	"google.golang.org/protobuf/types/known/structpb"
    15  )
    16  
    17  // Holds this module's functions.  Accessible as `kong.Request`
    18  type Request struct {
    19  	bridge.PdkBridge
    20  }
    21  
    22  // kong.Request.GetScheme() returns the scheme component of the request’s URL.
    23  // The returned value is normalized to lower-case form.
    24  func (r Request) GetScheme() (s string, err error) {
    25  	return r.AskString(`kong.request.get_scheme`, nil)
    26  }
    27  
    28  // kong.Request.GetHost() returns the host component of the request’s URL,
    29  // or the value of the “Host” header. The returned value is normalized
    30  // to lower-case form.
    31  func (r Request) GetHost() (host string, err error) {
    32  	return r.AskString(`kong.request.get_host`, nil)
    33  }
    34  
    35  // kong.Request.GetPort() returns the port component of the request’s URL.
    36  func (r Request) GetPort() (int, error) {
    37  	return r.AskInt(`kong.request.get_port`, nil)
    38  }
    39  
    40  // kong.Request.GetForwardedScheme() returns the scheme component
    41  // of the request’s URL, but also considers X-Forwarded-Proto if it
    42  // comes from a trusted source. The returned value is normalized to lower-case.
    43  //
    44  // Whether this function considers X-Forwarded-Proto or not depends
    45  // on several Kong configuration parameters:
    46  //
    47  //   - trusted_ips
    48  //   - real_ip_header
    49  //   - real_ip_recursive
    50  //
    51  // Note: support for the Forwarded HTTP Extension (RFC 7239) is not offered yet
    52  // since it is not supported by ngx_http_realip_module.
    53  func (r Request) GetForwardedScheme() (s string, err error) {
    54  	return r.AskString(`kong.request.get_forwarded_scheme`, nil)
    55  }
    56  
    57  // kong.Request.GetForwardedHost() returns the host component of the request’s URL
    58  // or the value of the “host” header. Unlike kong.Request.GetHost(), this function
    59  // will also consider X-Forwarded-Host if it comes from a trusted source.
    60  // The returned value is normalized to lower-case.
    61  //
    62  // Whether this function considers X-Forwarded-Proto or not depends
    63  // on several Kong configuration parameters:
    64  //
    65  //   - trusted_ips
    66  //   - real_ip_header
    67  //   - real_ip_recursive
    68  //
    69  // Note: we do not currently offer support for Forwarded HTTP Extension (RFC 7239)
    70  // since it is not supported by ngx_http_realip_module.
    71  func (r Request) GetForwardedHost() (host string, err error) {
    72  	return r.AskString(`kong.request.get_forwarded_host`, nil)
    73  }
    74  
    75  // kong.Request.GetForwardedPort() returns the port component of the request’s URL,
    76  // but also considers X-Forwarded-Host if it comes from a trusted source.
    77  //
    78  // Whether this function considers X-Forwarded-Proto or not depends
    79  // on several Kong configuration parameters:
    80  //
    81  //   - trusted_ips
    82  //   - real_ip_header
    83  //   - real_ip_recursive
    84  //
    85  // Note: we do not currently offer support for Forwarded HTTP Extension (RFC 7239)
    86  // since it is not supported by ngx_http_realip_module.
    87  func (r Request) GetForwardedPort() (int, error) {
    88  	return r.AskInt(`kong.request.get_forwarded_port`, nil)
    89  }
    90  
    91  // kong.Request.GetHttpVersion() returns the HTTP version
    92  // used by the client in the request, returning values
    93  // such as "1"", "1.1", "2.0", or nil for unrecognized values.
    94  func (r Request) GetHttpVersion() (version float64, err error) {
    95  	return r.AskNumber(`kong.request.get_http_version`, nil)
    96  }
    97  
    98  // kong.Request.GetMethod() returns the HTTP method of the request.
    99  // The value is normalized to upper-case.
   100  func (r Request) GetMethod() (m string, err error) {
   101  	return r.AskString(`kong.request.get_method`, nil)
   102  }
   103  
   104  // kong.Request.GetPath() returns the path component of the request’s URL.
   105  // It is not normalized in any way and does not include the querystring.
   106  func (r Request) GetPath() (string, error) {
   107  	return r.AskString(`kong.request.get_path`, nil)
   108  }
   109  
   110  // kong.Request.GetPathWithQuery() returns the path, including
   111  // the querystring if any. No transformations/normalizations are done.
   112  func (r Request) GetPathWithQuery() (string, error) {
   113  	return r.AskString(`kong.request.get_path_with_query`, nil)
   114  }
   115  
   116  // kong.Request.GetRawQuery() returns the query component of the request’s URL.
   117  // It is not normalized in any way (not even URL-decoding of special characters)
   118  // and does not include the leading ? character.
   119  func (r Request) GetRawQuery() (string, error) {
   120  	return r.AskString(`kong.request.get_raw_query`, nil)
   121  }
   122  
   123  // kong.Request.GetQueryArg() returns the value of the specified argument,
   124  // obtained from the query arguments of the current request.
   125  //
   126  // The returned value is either a string, a boolean true if
   127  // an argument was not given a value, or nil if no argument with name was found.
   128  //
   129  // If an argument with the same name is present multiple times in the querystring,
   130  // this function will return the value of the first occurrence.
   131  func (r Request) GetQueryArg(k string) (string, error) {
   132  	return r.AskString(`kong.request.get_query_arg`, bridge.WrapString(k))
   133  }
   134  
   135  // kong.Request.GetQuery() returns a map of query arguments
   136  // obtained from the querystring. Keys are query argument names.
   137  // Values are either a string with the argument value, a boolean true
   138  // if an argument was not given a value, or an array if an argument
   139  // was given in the query string multiple times. Keys and values are
   140  // unescaped according to URL-encoded escaping rules.
   141  //
   142  // Note that a query string `?foo&bar` translates to two boolean true arguments,
   143  // and ?foo=&bar= translates to two string arguments containing empty strings.
   144  //
   145  // The max_args argument specifies the maximum number of returned arguments.
   146  // Must be greater than 1 and not greater than 1000, or -1 to specify the
   147  // default limit of 100 arguments.
   148  func (r Request) GetQuery(max_args int) (map[string][]string, error) {
   149  	if max_args == -1 {
   150  		max_args = 100
   151  	}
   152  
   153  	arg := kong_plugin_protocol.Int{V: int32(max_args)}
   154  	out := new(structpb.Struct)
   155  	err := r.Ask("kong.request.get_query", &arg, out)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	return bridge.UnwrapHeaders(out), nil
   161  }
   162  
   163  // kong.Request.GetHeader() returns the value of the specified request header.
   164  //
   165  // The returned value is either a string, or can be nil if a header with name
   166  // was not found in the request. If a header with the same name is present
   167  // multiple times in the request, this function will return the value of the
   168  // first occurrence of this header.
   169  //
   170  // Header names in are case-insensitive and are normalized to lowercase,
   171  // and dashes (-) can be written as underscores (_); that is, the header
   172  // X-Custom-Header can also be retrieved as x_custom_header.
   173  func (r Request) GetHeader(k string) (string, error) {
   174  	return r.AskString(`kong.request.get_header`, bridge.WrapString(k))
   175  }
   176  
   177  // kong.Request.GetHeaders() returns a map holding the request headers.
   178  // Keys are header names. Values are either a string with the header value,
   179  // or an array of strings if a header was sent multiple times. Header names
   180  // in this table are case-insensitive and are normalized to lowercase,
   181  // and dashes (-) can be written as underscores (_); that is, the header
   182  // X-Custom-Header can also be retrieved as x_custom_header.
   183  //
   184  // The max_args argument specifies the maximum number of returned headers.
   185  // Must be greater than 1 and not greater than 1000, or -1 to specify the
   186  // default limit of 100 headers.
   187  func (r Request) GetHeaders(max_headers int) (map[string][]string, error) {
   188  	if max_headers == -1 {
   189  		max_headers = 100
   190  	}
   191  
   192  	arg := kong_plugin_protocol.Int{V: int32(max_headers)}
   193  	out := new(structpb.Struct)
   194  	err := r.Ask("kong.request.get_headers", &arg, out)
   195  	if err != nil {
   196  		return nil, err
   197  	}
   198  
   199  	return bridge.UnwrapHeaders(out), nil
   200  }
   201  
   202  // kong.Request.GetRawBody() returns the plain request body.
   203  //
   204  // If the body has no size (empty), this function returns an empty string.
   205  //
   206  // If the size of the body is greater than the Nginx buffer size
   207  // (set by client_body_buffer_size), this function will fail
   208  // and return an error message explaining this limitation.
   209  func (r Request) GetRawBody() ([]byte, error) {
   210  	out := new(kong_plugin_protocol.RawBodyResult)
   211  	err := r.Ask(`kong.request.get_raw_body`, nil, out)
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  
   216  	switch x := out.Kind.(type) {
   217  	case *kong_plugin_protocol.RawBodyResult_Content:
   218  		return x.Content, nil
   219  
   220  	case *kong_plugin_protocol.RawBodyResult_BodyFilepath:
   221  		return ioutil.ReadFile(x.BodyFilepath)
   222  
   223  	case *kong_plugin_protocol.RawBodyResult_Error:
   224  		return nil, errors.New(x.Error)
   225  
   226  	default:
   227  		return out.GetContent(), nil
   228  	}
   229  }
   230  
   231  // kong.Request.GetUriCaptures() returns the catured URI fragements.
   232  //
   233  //
   234  func (r Request) GetUriCaptures() ([][]byte, map[string][]byte, error) {
   235  	out := new(kong_plugin_protocol.UriCapturesResult)
   236  	err := r.Ask("kong.request.get_uri_captures", nil, out)
   237  	if err != nil {
   238  		return nil, nil, err
   239  	}
   240  	return out.Unnamed, out.Named, nil
   241  }
   242  
   243  // TODO get_body