blob: 987a998a5bb148e64dcf1f8a109486a2ea968f90 [file] [log] [blame]
Jakub Josef79ecec32017-02-17 14:36:28 +01001package com.mirantis.mk
2/**
3 *
4 * HTTP functions
5 *
6 */
7
8/**
9 * Make generic HTTP call and return parsed JSON
10 *
11 * @param url URL to make the request against
12 * @param method HTTP method to use (default GET)
13 * @param data JSON data to POST or PUT
14 * @param headers Map of additional request headers
Vasyl Saienkoe36ab7c2017-07-17 14:35:48 +030015 * @param read_timeout http session read timeout
Jakub Josef79ecec32017-02-17 14:36:28 +010016 */
Jakub Josefdb779dd2017-04-24 12:58:33 +020017@NonCPS
Vasyl Saienkoe36ab7c2017-07-17 14:35:48 +030018def sendHttpRequest(url, method = 'GET', data = null, headers = [:], read_timeout=-1) {
Jakub Josef79ecec32017-02-17 14:36:28 +010019 def connection = new URL(url).openConnection()
Vasyl Saienkoe36ab7c2017-07-17 14:35:48 +030020
21 if (read_timeout != -1){
22 connection.setReadTimeout(read_timeout*1000)
23 }
Jakub Josef79ecec32017-02-17 14:36:28 +010024 if (method != 'GET') {
25 connection.setRequestMethod(method)
26 }
27
28 if (data) {
29 headers['Content-Type'] = 'application/json'
30 }
31
32 headers['User-Agent'] = 'jenkins-groovy'
33 headers['Accept'] = 'application/json'
34
35 for (header in headers) {
36 connection.setRequestProperty(header.key, header.value)
37 }
38
39 if (data) {
40 connection.setDoOutput(true)
41 if (data instanceof String) {
42 dataStr = data
43 } else {
44 dataStr = new groovy.json.JsonBuilder(data).toString()
45 }
Jakub Josef66976f62017-04-24 16:32:23 +020046 if(env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true"){
47 println("[HTTP] Request URL: ${url}, method: ${method}, headers: ${headers}, content: ${dataStr}")
48 }
Jakub Josef79ecec32017-02-17 14:36:28 +010049 def output = new OutputStreamWriter(connection.outputStream)
Jakub Josef79ecec32017-02-17 14:36:28 +010050 output.write(dataStr)
51 output.close()
52 }
53
54 if ( connection.responseCode == 200 ) {
55 response = connection.inputStream.text
56 try {
57 response_content = new groovy.json.JsonSlurperClassic().parseText(response)
58 } catch (groovy.json.JsonException e) {
59 response_content = response
60 }
Jakub Josef66976f62017-04-24 16:32:23 +020061 if(env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true"){
62 println("[HTTP] Response: code ${connection.responseCode}")
63 }
Jakub Josef79ecec32017-02-17 14:36:28 +010064 return response_content
65 } else {
Jakub Josef66976f62017-04-24 16:32:23 +020066 if(env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true"){
67 println("[HTTP] Response: code ${connection.responseCode}")
68 }
Jakub Josef79ecec32017-02-17 14:36:28 +010069 throw new Exception(connection.responseCode + ": " + connection.inputStream.text)
70 }
Jakub Josef79ecec32017-02-17 14:36:28 +010071}
72
73/**
74 * Make HTTP GET request
75 *
76 * @param url URL which will requested
77 * @param data JSON data to PUT
78 */
79def sendHttpGetRequest(url, data = null, headers = [:]) {
80 return sendHttpRequest(url, 'GET', data, headers)
81}
82
83/**
84 * Make HTTP POST request
85 *
86 * @param url URL which will requested
87 * @param data JSON data to PUT
Vasyl Saienkoe36ab7c2017-07-17 14:35:48 +030088 * @param read_timeout http session read timeout
Jakub Josef79ecec32017-02-17 14:36:28 +010089 */
Vasyl Saienkoe36ab7c2017-07-17 14:35:48 +030090def sendHttpPostRequest(url, data = null, headers = [:], read_timeout=-1) {
91 return sendHttpRequest(url, 'POST', data, headers, read_timeout)
Jakub Josef79ecec32017-02-17 14:36:28 +010092}
93
94/**
95 * Make HTTP PUT request
96 *
97 * @param url URL which will requested
98 * @param data JSON data to PUT
99 */
100def sendHttpPutRequest(url, data = null, headers = [:]) {
101 return sendHttpRequest(url, 'PUT', data, headers)
102}
103
104/**
105 * Make HTTP DELETE request
106 *
107 * @param url URL which will requested
108 * @param data JSON data to PUT
109 */
110def sendHttpDeleteRequest(url, data = null, headers = [:]) {
111 return sendHttpRequest(url, 'DELETE', data, headers)
112}
113
114/**
115 * Make generic call using Salt REST API and return parsed JSON
116 *
117 * @param master Salt connection object
118 * @param uri URI which will be appended to Salt server base URL
119 * @param method HTTP method to use (default GET)
120 * @param data JSON data to POST or PUT
121 * @param headers Map of additional request headers
122 */
123def restCall(master, uri, method = 'GET', data = null, headers = [:]) {
124 def connection = new URL("${master.url}${uri}").openConnection()
125 if (method != 'GET') {
126 connection.setRequestMethod(method)
127 }
128
129 connection.setRequestProperty('User-Agent', 'jenkins-groovy')
130 connection.setRequestProperty('Accept', 'application/json')
131 if (master.authToken) {
132 // XXX: removeme
133 connection.setRequestProperty('X-Auth-Token', master.authToken)
134 }
135
136 for (header in headers) {
137 connection.setRequestProperty(header.key, header.value)
138 }
139
140 if (data) {
141 connection.setDoOutput(true)
142 if (data instanceof String) {
143 dataStr = data
144 } else {
145 connection.setRequestProperty('Content-Type', 'application/json')
146 dataStr = new groovy.json.JsonBuilder(data).toString()
147 }
148 def out = new OutputStreamWriter(connection.outputStream)
149 out.write(dataStr)
150 out.close()
151 }
152
153 if ( connection.responseCode >= 200 && connection.responseCode < 300 ) {
154 res = connection.inputStream.text
155 try {
156 return new groovy.json.JsonSlurperClassic().parseText(res)
157 } catch (Exception e) {
158 return res
159 }
160 } else {
161 throw new Exception(connection.responseCode + ": " + connection.inputStream.text)
162 }
163}
164
165/**
166 * Make GET request using Salt REST API and return parsed JSON
167 *
168 * @param master Salt connection object
169 * @param uri URI which will be appended to Salt server base URL
170 */
171def restGet(master, uri, data = null) {
172 return restCall(master, uri, 'GET', data)
173}
174
175/**
176 * Make POST request using Salt REST API and return parsed JSON
177 *
178 * @param master Salt connection object
179 * @param uri URI which will be appended to Docker server base URL
180 * @param data JSON Data to PUT
181 */
182def restPost(master, uri, data = null) {
183 return restCall(master, uri, 'POST', data, ['Accept': '*/*'])
184}
Jakub Josefab6bf1a2017-03-17 15:46:06 +0100185
186/**
Oleg Iurchenko85bb5d72018-02-15 16:45:22 +0200187 * Make DELETE request using Salt REST API and return parsed JSON
188 *
189 * @param master Salt connection object
190 * @param uri URI which will be appended to Salt server base URL
191 */
192def restDelete(master, uri, data = null) {
193 return restCall(master, uri, 'DELETE', data)
194}
195
196/**
Jakub Josefab6bf1a2017-03-17 15:46:06 +0100197 * Set HTTP and HTTPS proxy for running JVM
198 * @param host HTTP proxy host
199 * @param port HTTP proxy port
200 * @param nonProxyHosts proxy excluded hosts, optional, default *.local
201 */
202def enableHttpProxy(host, port, nonProxyHosts="*.local"){
203 System.getProperties().put("proxySet", "true")
204 System.getProperties().put("http.proxyHost", host)
205 System.getProperties().put("http.proxyPort", port)
206 System.getProperties().put("https.proxyHost", host)
207 System.getProperties().put("https.proxyPort", port)
208 System.getProperties().put("http.nonProxyHosts", nonProxyHosts)
209 System.getProperties().put("https.nonProxyHosts", nonProxyHosts)
210}
211/**
212 * Disable HTTP and HTTPS proxy for running JVM
213 */
214def disableHttpProxy(){
215 System.getProperties().put("proxySet", "false")
216 System.getProperties().remove("http.proxyHost")
217 System.getProperties().remove("http.proxyPort")
218 System.getProperties().remove("https.proxyHost")
219 System.getProperties().remove("https.proxyPort")
220 System.getProperties().remove("http.nonProxyHosts")
221 System.getProperties().remove("https.nonProxyHosts")
222}
Alexander Evseev6ef58892018-04-17 17:46:40 +0200223
224/**
225 * Make HTTP request to the specified URL
226 *
227 * @param url URL to do HTTP request to
228 * @param method HTTP method to execute (`GET` by default)
229 * @param credsId Jenkins credentials ID to use for authorization
230 * @param pushData Data to send
231 * @param pushType MIME-type of pushData
232 * @param params Custom HTTP-headers
233 *
234 * @return Array containing return code and text
235 *
236 * @exception org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException
237 */
238def methodCall(String url, String method = 'GET', String credsId = '',
239 String pushData = '', String pushType = '', Map params = [:]) {
240
241 // Connection object
242 def httpReq = new URI(url).normalize().toURL().openConnection()
243 httpReq.setRequestMethod(method)
244
245 // Timeouts
246 httpReq.setConnectTimeout(10*1000) // milliseconds
247 httpReq.setReadTimeout(600*1000) // milliseconds
248
249 // Add authentication data
250 if (credsId) {
251 String authHeader = ''
252 def cred = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
253 com.cloudbees.plugins.credentials.impl.BaseStandardCredentials.class,
254 jenkins.model.Jenkins.instance).findAll {it.id == credsId}[0]
255 if (cred.class == com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl.class) {
256 authHeader = 'Basic ' + "${cred.getUsername()}:${cred.getPassword()}".getBytes('UTF-8').encodeBase64().toString()
257 } else if (cred.class == org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl.class) {
258 authHeader = 'Bearer ' + cred.getSecret()
259 //params << ['X-JFrog-Art-Api': cred.getSecret()]
260 }
261 params << ['Authorization': authHeader]
262 }
263
264 // Add custom headers if any
265 for (param in params) {
266 httpReq.setRequestProperty(param.key, param.value.toString())
267 }
268
269 // Do request
270 try {
271 if (pushData) {
272 httpReq.setRequestProperty('Content-Type', pushType ?: 'application/x-www-form-urlencoded')
273 if (method == 'GET') { // override incorrect method if pushData is passed
274 httpReq.setRequestMethod('POST')
275 }
276 httpReq.setDoOutput(true)
277 httpReq.getOutputStream().write(pushData.getBytes('UTF-8'))
278 } else {
279 httpReq.connect()
280 }
281 } catch (org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException e) {
282 throw e // show sandbox errors
283 } catch (Exception e) {
284 echo "Cauhgt '${e.class.name}' error: ${e.getMessage()}"
285 return [ -1, e.getMessage() ]
286 }
287
288 // Handle return data
289 int respCode = httpReq.getResponseCode()
290 String respText = ''
291 if (respCode >= 400) {
292 respText = httpReq.getErrorStream().getText() ?: httpReq.getResponseMessage()
293 } else {
294 respText = httpReq.getInputStream().getText()
295 }
296
297 // Return result as a tuple of response code and text
298 return [respCode, respText]
299}
300
301/**
302 * Make HTTP GET request to the specified URL
303 *
304 * @param url URL to do HTTP request to
305 * @param credsId Jenkins credentials ID to use for authorization
306 * @param params Custom HTTP-headers
307 *
308 * @return Array containing return code and text
309 */
310def doGet(String url, String credsId = '', Map params = [:]) {
311 return methodCall(url, 'GET', credsId, null, null, params)
312}
313
314/**
315 * Make HTTP POST request to the specified URL
316 *
317 * @param url URL to do HTTP request to
318 * @param credsId Jenkins credentials ID to use for authorization
319 * @param pushData Data to send
320 * @param pushType MIME-type of pushData
321 * @param params Custom HTTP-headers
322 *
323 * @return Array containing return code and text
324 */
325def doPost(String url, String credsId = '',
326 String pushData = '', String pushType = '', Map params = [:]) {
327 return methodCall(url, 'POST', credsId, pushData, pushType, params)
328}
329
330/**
331 * Make HTTP PUT request to the specified URL
332 *
333 * @param url URL to do HTTP request to
334 * @param credsId Jenkins credentials ID to use for authorization
335 * @param pushData Data to send
336 * @param pushType MIME-type of pushData
337 * @param params Custom HTTP-headers
338 *
339 * @return Array containing return code and text
340 */
341def doPut(String url, String credsId = '',
342 String pushData = '', String pushType = '', Map params = [:]) {
343 return methodCall(url, 'PUT', credsId, pushData, pushType, params)
344}
345
346/**
347 * Make HTTP DELETE request to the specified URL
348 *
349 * @param url URL to do HTTP request to
350 * @param credsId Jenkins credentials ID to use for authorization
351 * @param params Custom HTTP-headers
352 *
353 * @return Array containing return code and text
354 */
355def doDelete(String url, String credsId = '', Map params = [:]) {
356 return methodCall(url, 'DELETE', credsId, null, null, params)
357}