-
Notifications
You must be signed in to change notification settings - Fork 86
/
StandaloneWSRequest.scala
290 lines (242 loc) · 7.39 KB
/
StandaloneWSRequest.scala
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*
* Copyright (C) Lightbend Inc. <https://www.lightbend.com>
*/
package play.api.libs.ws
import java.net.URI
import scala.concurrent.Future
import scala.concurrent.duration.Duration
/**
* A WS Request builder.
*/
trait StandaloneWSRequest {
// There is an issue with type members, because when you stack `Self` references,
// they don't have a connection to each other that ties them back to the parent
// `Self` reference. The way around this is to do F-bounded polymorphism directly
// on the type member, which roots it to the parent and doesn't mess up the type
// signature the way that a self-recursive type parameter would. The implementation
// will always bind this to a relevant type, so we only have to make the compiler
// happy here.
type Self <: StandaloneWSRequest { type Self <: StandaloneWSRequest.this.Self }
type Response <: StandaloneWSResponse
/**
* The base URL for this request
*/
def url: String
/**
* The URI for this request
*/
def uri: URI
/**
* The content type for this request, if any is defined.
*/
def contentType: Option[String]
/**
* The method for this request
*/
def method: String
/**
* The body of this request
*/
def body: WSBody
/**
* The headers for this request
*/
def headers: Map[String, Seq[String]]
/**
* Get the value of the header with the specified name. If there are more than one values
* for this header, the first value is returned. If there are no values, than a None is
* returned.
*
* @param name the header name
* @return the header value
*/
def header(name: String): Option[String] = headerValues(name).headOption
/**
* Get all the values of header with the specified name. If there are no values for
* the header with the specified name, than an empty sequence is returned.
*
* @param name the header name.
* @return all the values for this header name.
*/
def headerValues(name: String): Seq[String] = headers.getOrElse(name, Seq.empty)
/**
* The query string for this request
*/
def queryString: Map[String, Seq[String]]
/**
* The cookies for this request
*/
def cookies: Seq[WSCookie]
/**
* A calculator of the signature for this request
*/
def calc: Option[WSSignatureCalculator]
/**
* The authentication this request should use
*/
def auth: Option[(String, String, WSAuthScheme)]
/**
* Whether this request should follow redirects
*/
def followRedirects: Option[Boolean]
/**
* The timeout for the request
*/
def requestTimeout: Option[Duration]
/**
* The virtual host this request will use
*/
def virtualHost: Option[String]
/**
* The proxy server this request will use
*/
def proxyServer: Option[WSProxyServer]
/**
* sets the signature calculator for the request
* @param calc the signature calculator
*/
def sign(calc: WSSignatureCalculator): Self
/**
* sets the authentication realm
*/
def withAuth(username: String, password: String, scheme: WSAuthScheme): Self
/**
* Returns this request with the given headers, discarding the existing ones.
*
* @param headers the headers to be used
*/
def withHttpHeaders(headers: (String, String)*): Self
/**
* Returns this request with the given headers, preserving the existing ones.
*
* @param hdrs the headers to be added
*/
def addHttpHeaders(hdrs: (String, String)*): Self = {
val newHeaders = headers.toList.flatMap { param =>
param._2.map(p => param._1 -> p)
} ++ hdrs
withHttpHeaders(newHeaders: _*)
}
/**
* Returns this request with the given query string parameters, discarding the existing ones.
*
* @param parameters the query string parameters
*/
def withQueryStringParameters(parameters: (String, String)*): Self
/**
* Returns this request with the given query string parameters, preserving the existing ones.
*
* @param parameters the query string parameters
*/
def addQueryStringParameters(parameters: (String, String)*): Self = {
val newQueryStringParams = queryString.toList.flatMap { param =>
param._2.map(p => param._1 -> p)
} ++ parameters
withQueryStringParameters(newQueryStringParams: _*)
}
/**
* Returns this request with the given cookies, discarding the existing ones. In general, cookies set on a request
* are used only on that request and then discarded. But when `play.ws.ahc.useCookieStore` is enabled, there will be a
* global cookie store that keeps cookies between requests.
*
* @param cookies the cookies to be used
*/
def withCookies(cookies: WSCookie*): Self
/**
* Returns this request with the given query string parameters, preserving the existing ones.
*
* @param cookies the cookies to be used
*/
def addCookies(cookies: WSCookie*): Self = {
withCookies(this.cookies ++ cookies: _*)
}
/**
* Sets whether redirects (301, 302) should be followed automatically
*/
def withFollowRedirects(follow: Boolean): Self
/**
* Sets whether url encoding should be disabled
*/
def withDisableUrlEncoding(disableUrlEncoding: Boolean): Self
/**
* Sets the maximum time you expect the request to take.
* Use Duration.Inf to set an infinite request timeout.
* Warning: a stream consumption will be interrupted when this time is reached unless Duration.Inf is set.
*/
def withRequestTimeout(timeout: Duration): Self
/**
* Adds a filter to the request that can transform the request for subsequent filters.
*/
def withRequestFilter(filter: WSRequestFilter): Self
/**
* Sets the virtual host to use in this request
*/
def withVirtualHost(vh: String): Self
/**
* Sets the proxy server to use in this request
*/
def withProxyServer(proxyServer: WSProxyServer): Self
/**
* Sets the url for this request.
*/
def withUrl(url: String): Self
/**
* Sets the method for this request
*/
def withMethod(method: String): Self
/**
* Sets the body for this request.
*/
def withBody[T: BodyWritable](body: T): Self
/**
* Performs a GET.
*/
def get(): Future[Response]
/**
* Performs a PATCH request.
*
* @param body the payload body submitted with this request
* @return a future with the response for the PATCH request
*/
def patch[T: BodyWritable](body: T): Future[Response]
/**
* Performs a POST request.
*
* @param body the payload body submitted with this request
* @return a future with the response for the POST request
*/
def post[T: BodyWritable](body: T): Future[Response]
/**
* Performs a PUT request.
*
* @param body the payload body submitted with this request
* @return a future with the response for the PUT request
*/
def put[T: BodyWritable](body: T): Future[Response]
/**
* Perform a DELETE on the request asynchronously.
*/
def delete(): Future[Response]
/**
* Perform a HEAD on the request asynchronously.
*/
def head(): Future[Response]
/**
* Perform a OPTIONS on the request asynchronously.
*/
def options(): Future[Response]
/**
* Executes the given HTTP method.
* @param method the HTTP method that will be executed
* @return a future with the response for this request
*/
def execute(method: String): Future[Response]
/**
* Execute this request
*/
def execute(): Future[Response]
/**
* Execute this request and stream the response body.
*/
def stream(): Future[Response]
}