1package mocks
2
3// Copyright 2017 Microsoft Corporation
4//
5//  Licensed under the Apache License, Version 2.0 (the "License");
6//  you may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at
8//
9//      http://www.apache.org/licenses/LICENSE-2.0
10//
11//  Unless required by applicable law or agreed to in writing, software
12//  distributed under the License is distributed on an "AS IS" BASIS,
13//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14//  See the License for the specific language governing permissions and
15//  limitations under the License.
16
17import (
18	"fmt"
19	"io"
20	"net/http"
21	"time"
22)
23
24const (
25	// TestAuthorizationHeader is a faux HTTP Authorization header value
26	TestAuthorizationHeader = "BEARER SECRETTOKEN"
27
28	// TestBadURL is a malformed URL
29	TestBadURL = "                               "
30
31	// TestDelay is the Retry-After delay used in tests.
32	TestDelay = 0 * time.Second
33
34	// TestHeader is the header used in tests.
35	TestHeader = "x-test-header"
36
37	// TestURL is the URL used in tests.
38	TestURL = "https://microsoft.com/a/b/c/"
39
40	// TestAzureAsyncURL is a URL used in Azure asynchronous tests
41	TestAzureAsyncURL = "https://microsoft.com/a/b/c/async"
42
43	// TestLocationURL is a URL used in Azure asynchronous tests
44	TestLocationURL = "https://microsoft.com/a/b/c/location"
45)
46
47const (
48	headerLocation   = "Location"
49	headerRetryAfter = "Retry-After"
50)
51
52// NewRequest instantiates a new request.
53func NewRequest() *http.Request {
54	return NewRequestWithContent("")
55}
56
57// NewRequestWithContent instantiates a new request using the passed string for the body content.
58func NewRequestWithContent(c string) *http.Request {
59	r, _ := http.NewRequest("GET", "https://microsoft.com/a/b/c/", NewBody(c))
60	return r
61}
62
63// NewRequestWithCloseBody instantiates a new request.
64func NewRequestWithCloseBody() *http.Request {
65	return NewRequestWithCloseBodyContent("request body")
66}
67
68// NewRequestWithCloseBodyContent instantiates a new request using the passed string for the body content.
69func NewRequestWithCloseBodyContent(c string) *http.Request {
70	r, _ := http.NewRequest("GET", "https://microsoft.com/a/b/c/", NewBodyClose(c))
71	return r
72}
73
74// NewRequestForURL instantiates a new request using the passed URL.
75func NewRequestForURL(u string) *http.Request {
76	return NewRequestWithParams("GET", u, NewBody(""))
77}
78
79// NewRequestWithParams instantiates a new request using the provided parameters.
80func NewRequestWithParams(method, u string, body io.Reader) *http.Request {
81	r, err := http.NewRequest(method, u, body)
82	if err != nil {
83		panic(fmt.Sprintf("mocks: ERROR (%v) parsing testing URL %s", err, u))
84	}
85	return r
86}
87
88// NewResponse instantiates a new response.
89func NewResponse() *http.Response {
90	return NewResponseWithContent("")
91}
92
93// NewResponseWithBytes instantiates a new response with the passed bytes as the body content.
94func NewResponseWithBytes(input []byte) *http.Response {
95	return &http.Response{
96		Status:     "200 OK",
97		StatusCode: 200,
98		Proto:      "HTTP/1.0",
99		ProtoMajor: 1,
100		ProtoMinor: 0,
101		Body:       NewBodyWithBytes(input),
102		Request:    NewRequest(),
103	}
104}
105
106// NewResponseWithContent instantiates a new response with the passed string as the body content.
107func NewResponseWithContent(c string) *http.Response {
108	return &http.Response{
109		Status:     "200 OK",
110		StatusCode: 200,
111		Proto:      "HTTP/1.0",
112		ProtoMajor: 1,
113		ProtoMinor: 0,
114		Body:       NewBody(c),
115		Request:    NewRequest(),
116	}
117}
118
119// NewResponseWithStatus instantiates a new response using the passed string and integer as the
120// status and status code.
121func NewResponseWithStatus(s string, c int) *http.Response {
122	resp := NewResponse()
123	resp.Status = s
124	resp.StatusCode = c
125	return resp
126}
127
128// NewResponseWithBodyAndStatus instantiates a new response using the specified mock body,
129// status and status code
130func NewResponseWithBodyAndStatus(body *Body, c int, s string) *http.Response {
131	resp := NewResponse()
132	resp.Body = body
133	resp.ContentLength = body.Length()
134	resp.Status = s
135	resp.StatusCode = c
136	return resp
137}
138
139// SetResponseHeader adds a header to the passed response.
140func SetResponseHeader(resp *http.Response, h string, v string) {
141	if resp.Header == nil {
142		resp.Header = make(http.Header)
143	}
144	resp.Header.Set(h, v)
145}
146
147// SetResponseHeaderValues adds a header containing all the passed string values.
148func SetResponseHeaderValues(resp *http.Response, h string, values []string) {
149	if resp.Header == nil {
150		resp.Header = make(http.Header)
151	}
152	for _, v := range values {
153		resp.Header.Add(h, v)
154	}
155}
156
157// SetAcceptedHeaders adds the headers usually associated with a 202 Accepted response.
158func SetAcceptedHeaders(resp *http.Response) {
159	SetLocationHeader(resp, TestURL)
160	SetRetryHeader(resp, TestDelay)
161}
162
163// SetLocationHeader adds the Location header.
164func SetLocationHeader(resp *http.Response, location string) {
165	SetResponseHeader(resp, http.CanonicalHeaderKey(headerLocation), location)
166}
167
168// SetRetryHeader adds the Retry-After header.
169func SetRetryHeader(resp *http.Response, delay time.Duration) {
170	SetResponseHeader(resp, http.CanonicalHeaderKey(headerRetryAfter), fmt.Sprintf("%v", delay.Seconds()))
171}
172