request.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package restful
  2. // Copyright 2013 Ernest Micklei. All rights reserved.
  3. // Use of this source code is governed by a license
  4. // that can be found in the LICENSE file.
  5. import (
  6. "compress/zlib"
  7. "net/http"
  8. )
  9. var defaultRequestContentType string
  10. // Request is a wrapper for a http Request that provides convenience methods
  11. type Request struct {
  12. Request *http.Request
  13. pathParameters map[string]string
  14. attributes map[string]interface{} // for storing request-scoped values
  15. selectedRoute *Route // is nil when no route was matched
  16. }
  17. func NewRequest(httpRequest *http.Request) *Request {
  18. return &Request{
  19. Request: httpRequest,
  20. pathParameters: map[string]string{},
  21. attributes: map[string]interface{}{},
  22. } // empty parameters, attributes
  23. }
  24. // If ContentType is missing or */* is given then fall back to this type, otherwise
  25. // a "Unable to unmarshal content of type:" response is returned.
  26. // Valid values are restful.MIME_JSON and restful.MIME_XML
  27. // Example:
  28. // restful.DefaultRequestContentType(restful.MIME_JSON)
  29. func DefaultRequestContentType(mime string) {
  30. defaultRequestContentType = mime
  31. }
  32. // PathParameter accesses the Path parameter value by its name
  33. func (r *Request) PathParameter(name string) string {
  34. return r.pathParameters[name]
  35. }
  36. // PathParameters accesses the Path parameter values
  37. func (r *Request) PathParameters() map[string]string {
  38. return r.pathParameters
  39. }
  40. // QueryParameter returns the (first) Query parameter value by its name
  41. func (r *Request) QueryParameter(name string) string {
  42. return r.Request.FormValue(name)
  43. }
  44. // QueryParameters returns the all the query parameters values by name
  45. func (r *Request) QueryParameters(name string) []string {
  46. return r.Request.URL.Query()[name]
  47. }
  48. // BodyParameter parses the body of the request (once for typically a POST or a PUT) and returns the value of the given name or an error.
  49. func (r *Request) BodyParameter(name string) (string, error) {
  50. err := r.Request.ParseForm()
  51. if err != nil {
  52. return "", err
  53. }
  54. return r.Request.PostFormValue(name), nil
  55. }
  56. // HeaderParameter returns the HTTP Header value of a Header name or empty if missing
  57. func (r *Request) HeaderParameter(name string) string {
  58. return r.Request.Header.Get(name)
  59. }
  60. // ReadEntity checks the Accept header and reads the content into the entityPointer.
  61. func (r *Request) ReadEntity(entityPointer interface{}) (err error) {
  62. contentType := r.Request.Header.Get(HEADER_ContentType)
  63. contentEncoding := r.Request.Header.Get(HEADER_ContentEncoding)
  64. // check if the request body needs decompression
  65. if ENCODING_GZIP == contentEncoding {
  66. gzipReader := currentCompressorProvider.AcquireGzipReader()
  67. defer currentCompressorProvider.ReleaseGzipReader(gzipReader)
  68. gzipReader.Reset(r.Request.Body)
  69. r.Request.Body = gzipReader
  70. } else if ENCODING_DEFLATE == contentEncoding {
  71. zlibReader, err := zlib.NewReader(r.Request.Body)
  72. if err != nil {
  73. return err
  74. }
  75. r.Request.Body = zlibReader
  76. }
  77. // lookup the EntityReader, use defaultRequestContentType if needed and provided
  78. entityReader, ok := entityAccessRegistry.accessorAt(contentType)
  79. if !ok {
  80. if len(defaultRequestContentType) != 0 {
  81. entityReader, ok = entityAccessRegistry.accessorAt(defaultRequestContentType)
  82. }
  83. if !ok {
  84. return NewError(http.StatusBadRequest, "Unable to unmarshal content of type:"+contentType)
  85. }
  86. }
  87. return entityReader.Read(r, entityPointer)
  88. }
  89. // SetAttribute adds or replaces the attribute with the given value.
  90. func (r *Request) SetAttribute(name string, value interface{}) {
  91. r.attributes[name] = value
  92. }
  93. // Attribute returns the value associated to the given name. Returns nil if absent.
  94. func (r Request) Attribute(name string) interface{} {
  95. return r.attributes[name]
  96. }
  97. // SelectedRoutePath root path + route path that matched the request, e.g. /meetings/{id}/attendees
  98. // If no route was matched then return an empty string.
  99. func (r Request) SelectedRoutePath() string {
  100. if r.selectedRoute == nil {
  101. return ""
  102. }
  103. // skip creating an accessor
  104. return r.selectedRoute.Path
  105. }
  106. // SelectedRoute returns a reader to access the selected Route by the container
  107. // Returns nil if no route was matched.
  108. func (r Request) SelectedRoute() RouteReader {
  109. if r.selectedRoute == nil {
  110. return nil
  111. }
  112. return routeAccessor{route: r.selectedRoute}
  113. }