forked from a8m/documentdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
request.go
128 lines (109 loc) · 3.26 KB
/
request.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
package documentdb
import (
"bytes"
"fmt"
"net/http"
"net/url"
"strings"
"time"
)
const (
HEADER_XDATE = "X-Ms-Date"
HEADER_AUTH = "Authorization"
HEADER_VER = "X-Ms-Version"
HEADER_CONTYPE = "Content-Type"
HEADER_CONLEN = "Content-Length"
HEADER_IS_QUERY = "X-Ms-Documentdb-Isquery"
HEADER_UPSERT = "x-ms-documentdb-is-upsert"
HEADER_PARTITION_KEY = "x-ms-documentdb-partitionkey"
HEADER_MAX_ITEM_COUNT = "x-ms-max-item-count"
HEADER_CONTINUATION = "x-ms-continuation"
HEADER_CONSISTENCY = "x-ms-consistency-level"
HEADER_SESSION = "x-ms-session-token"
HEADER_CROSSPARTITION = "x-ms-documentdb-query-enablecrosspartitions"
HEADER_IFMATCH = "If-Match"
HEADER_IF_NONE_MATCH = "If-None-Match"
HEADER_IF_MODIFIED_SINCE = "If-Modified-Since"
HEADER_ACTIVITY_ID = "x-ms-activity-id"
HEADER_SESSION_TOKEN = "x-ms-session-token"
HEADER_REQUEST_CHARGE = "x-ms-request-charge"
HEADER_A_IM = "A-IM"
HEADER_PARTITION_KEY_RANGE_ID = "x-ms-documentdb-partitionkeyrangeid"
SupportedVersion = "2017-02-22"
)
// Request Error
type RequestError struct {
Code string `json:"code"`
Message string `json:"message"`
}
// Implement Error function
func (e RequestError) Error() string {
return fmt.Sprintf("%v, %v", e.Code, e.Message)
}
// Resource Request
type Request struct {
rId, rType string
*http.Request
}
// Return new resource request with type and id
func ResourceRequest(link string, req *http.Request) *Request {
rId, rType := parse(link)
return &Request{rId, rType, req}
}
// Add 3 default headers to *Request
// "x-ms-date", "x-ms-version", "authorization"
func (req *Request) DefaultHeaders(mKey *Key) (err error) {
req.Header.Add(HEADER_XDATE, formatDate(time.Now()))
req.Header.Add(HEADER_VER, SupportedVersion)
b := buffers.Get().(*bytes.Buffer)
b.Reset()
b.WriteString(req.Method)
b.WriteRune('\n')
b.WriteString(req.rType)
b.WriteRune('\n')
b.WriteString(req.rId)
b.WriteRune('\n')
b.WriteString(req.Header.Get(HEADER_XDATE))
b.WriteRune('\n')
b.WriteString(req.Header.Get("Date"))
b.WriteRune('\n')
sign, err := authorize(bytes.ToLower(b.Bytes()), mKey)
if err != nil {
return err
}
buffers.Put(b)
req.Header.Add(HEADER_AUTH, url.QueryEscape("type=master&ver=1.0&sig="+sign))
return
}
// Add headers for query request
func (req *Request) QueryHeaders(len int) {
req.Header.Add(HEADER_CONTYPE, "application/query+json")
req.Header.Add(HEADER_IS_QUERY, "true")
req.Header.Add(HEADER_CONLEN, string(len))
}
func parse(id string) (rId, rType string) {
if strings.HasPrefix(id, "/") == false {
id = "/" + id
}
if strings.HasSuffix(id, "/") == false {
id = id + "/"
}
parts := strings.Split(id, "/")
l := len(parts)
if l%2 == 0 {
rId = parts[l-2]
rType = parts[l-3]
} else {
rId = parts[l-3]
rType = parts[l-2]
}
return
}
func formatDate(t time.Time) string {
t = t.UTC()
return t.Format("Mon, 02 Jan 2006 15:04:05 GMT")
}
type queryPartitionKeyRangesRequest struct {
Ranges []PartitionKeyRange `json:"PartitionKeyRanges,omitempty"`
Count int `json:"_count,omitempty"`
}