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