-
Notifications
You must be signed in to change notification settings - Fork 4
/
parsing.go
147 lines (123 loc) · 4.17 KB
/
parsing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Package htsrequest provides operations for parsing htsget-related
// parameters from the HTTP request, and performing validation and
// transformation
//
// Module parsing contains operations for parsing various parameter types
// from an HTTP request
package htsrequest
import (
"encoding/json"
"errors"
"net/http"
"net/url"
"reflect"
"github.com/ga4gh/htsget-refserver/internal/htsutils"
"github.com/go-chi/chi"
)
// parsePathParam parses a single url path parameter as a string
func parsePathParam(request *http.Request, key string) (string, bool) {
value := chi.URLParam(request, key)
found := false
if !htsutils.StringIsEmpty(value) {
found = true
}
return value, found
}
// parseQueryParam parses a single query string parameter as a string
func parseQueryParam(params url.Values, key string) (string, bool, error) {
if len(params[key]) == 1 {
return params[key][0], true, nil
}
if len(params[key]) > 1 {
return "", true, errors.New("too many values specified for parameter: " + key)
}
return "", false, nil
}
// parseHeaderParam parses a single header parameter as a string
func parseHeaderParam(request *http.Request, key string) (string, bool) {
value := request.Header.Get(key)
found := false
if !htsutils.StringIsEmpty(value) {
found = true
}
return value, found
}
// parsing of partial request body
// partialRequestBody interface enabling the return of a single attribute from
// the request body
type partialRequestBody interface {
getattr() reflect.Value
}
// partialRequestBodyFormat parses single format parameter from request body
type partialRequestBodyFormat struct {
Format *string `json:"format"`
}
// partialRequestBodyFields parses single fields parameter from request body
type partialRequestBodyFields struct {
Fields *[]string `json:"fields"`
}
// partialRequestBodyTags parses single tags parameter from request body
type partialRequestBodyTags struct {
Tags *[]string `json:"tags"`
}
// partialRequestBodyNoTags parses single notags parameter from request body
type partialRequestBodyNoTags struct {
NoTags *[]string `json:"notags"`
}
// partialRequestBodyRegions parses single regions parameter from request body
type partialRequestBodyRegions struct {
Regions *[]*Region `json:"regions"`
}
// getattr returns reflected format value
func (rb *partialRequestBodyFormat) getattr() reflect.Value {
return reflect.ValueOf(rb.Format)
}
// getattr returns reflected fields value
func (rb *partialRequestBodyFields) getattr() reflect.Value {
return reflect.ValueOf(rb.Fields)
}
// getattr returns reflected tags value
func (rb *partialRequestBodyTags) getattr() reflect.Value {
return reflect.ValueOf(rb.Tags)
}
// getattr returns reflected notags value
func (rb *partialRequestBodyNoTags) getattr() reflect.Value {
return reflect.ValueOf(rb.NoTags)
}
// getattr returns reflected regions value
func (rb *partialRequestBodyRegions) getattr() reflect.Value {
return reflect.ValueOf(rb.Regions)
}
// newPartialRequestBody constructs an empty partialRequestBody, holding a
// single parameter based on the passed key
func newPartialRequestBody(key string) partialRequestBody {
var prb partialRequestBody
switch key {
case "format":
prb = new(partialRequestBodyFormat)
case "fields":
prb = new(partialRequestBodyFields)
case "tags":
prb = new(partialRequestBodyTags)
case "notags":
prb = new(partialRequestBodyNoTags)
case "regions":
prb = new(partialRequestBodyRegions)
}
return prb
}
// parseReqBodyParam parses a single parameter from an overall request body
func parseReqBodyParam(requestBodyBytes []byte, key string) (reflect.Value, bool, error) {
// construct a single parameter, partial request body and unmarshal JSON
partialRequestBodyObj := newPartialRequestBody(key)
err := json.Unmarshal(requestBodyBytes, partialRequestBodyObj)
if err != nil {
msg := "Could not parse request body, offending attribute: '" + key + "'. Value is malformed or incorrect datatype"
return reflect.ValueOf(nil), false, errors.New(msg)
}
// checks if the value is nil (ie. a nil pointer means no value was found)
reflectedPtr := partialRequestBodyObj.getattr()
reflectedValue := reflectedPtr.Elem()
found := !reflectedPtr.IsNil()
return reflectedValue, found, nil
}