如何从jenkins工作流调用REST



我想知道如何从(groovy)Jenkins工作流脚本调用REST API。我可以执行"sh‘curl-X POST…’"——它是有效的,但将请求构建为curl命令很麻烦,处理响应也很复杂。我更喜欢原生的groovyHTTP客户端来用Groovy编程——我应该从哪一个开始?由于脚本是在Jenkins中运行的,因此需要将所有需要的依赖jar复制到Jenkins上的groovy安装中,因此需要一些轻量级的东西。

不导入任何包的原生Groovy代码:

// GET
def get = new URL("https://httpbin.org/get").openConnection();
def getRC = get.getResponseCode();
println(getRC);
if(getRC.equals(200)) {
    println(get.getInputStream().getText());
}

// POST
def post = new URL("https://httpbin.org/post").openConnection();
def message = '{"message":"this is a message"}'
post.setRequestMethod("POST")
post.setDoOutput(true)
post.setRequestProperty("Content-Type", "application/json")
post.getOutputStream().write(message.getBytes("UTF-8"));
def postRC = post.getResponseCode();
println(postRC);
if(postRC.equals(200)) {
    println(post.getInputStream().getText());
}

有一个内置步骤可用,它使用Jenkins HTTP请求插件进行HTTP请求。

插件:https://wiki.jenkins-ci.org/display/JENKINS/HTTP+请求+插件

步骤文档:https://jenkins.io/doc/pipeline/steps/http_request/#httprequest-执行http请求并返回响应对象

插件github页面示例:

def response = httpRequest "http://httpbin.org/response-headers?param1=${param1}"
println('Status: '+response.status)
println('Response: '+response.content)

我在安装HTTPBuilder库时遇到了问题,所以我最终使用了更基本的URL类来创建HttpUrlConnection。

HttpResponse doGetHttpRequest(String requestUrl){    
    URL url = new URL(requestUrl);    
    HttpURLConnection connection = url.openConnection();    
    connection.setRequestMethod("GET");    
    //get the request    
    connection.connect();    
    //parse the response    
    HttpResponse resp = new HttpResponse(connection);    
    if(resp.isFailure()){    
        error("nGET from URL: $requestUrln  HTTP Status: $resp.statusCoden  Message: $resp.messagen  Response Body: $resp.body");    
    }    
    this.printDebug("Request (GET):n  URL: $requestUrl");    
    this.printDebug("Response:n  HTTP Status: $resp.statusCoden  Message: $resp.messagen  Response Body: $resp.body");    
    return resp;    
}  
/**    
 * Posts the json content to the given url and ensures a 200 or 201 status on the response.    
 * If a negative status is returned, an error will be raised and the pipeline will fail.    
 */    
HttpResponse doPostHttpRequestWithJson(String json, String requestUrl){    
    return doHttpRequestWithJson(json, requestUrl, "POST");    
}    
/**    
 * Posts the json content to the given url and ensures a 200 or 201 status on the response.    
 * If a negative status is returned, an error will be raised and the pipeline will fail.    
 */    
HttpResponse doPutHttpRequestWithJson(String json, String requestUrl){    
    return doHttpRequestWithJson(json, requestUrl, "PUT");    
}
/**    
 * Post/Put the json content to the given url and ensures a 200 or 201 status on the response.    
 * If a negative status is returned, an error will be raised and the pipeline will fail.    
 * verb - PUT or POST    
 */    
HttpResponse doHttpRequestWithJson(String json, String requestUrl, String verb){    
    URL url = new URL(requestUrl);    
    HttpURLConnection connection = url.openConnection();    
    connection.setRequestMethod(verb);    
    connection.setRequestProperty("Content-Type", "application/json");    
    connection.doOutput = true;    
    //write the payload to the body of the request    
    def writer = new OutputStreamWriter(connection.outputStream);    
    writer.write(json);    
    writer.flush();    
    writer.close();    
    //post the request    
    connection.connect();    
    //parse the response    
    HttpResponse resp = new HttpResponse(connection);    
    if(resp.isFailure()){    
        error("n$verb to URL: $requestUrln    JSON: $jsonn    HTTP Status: $resp.statusCoden    Message: $resp.messagen    Response Body: $resp.body");    
    }    
    this.printDebug("Request ($verb):n  URL: $requestUrln  JSON: $json");    
    this.printDebug("Response:n  HTTP Status: $resp.statusCoden  Message: $resp.messagen  Response Body: $resp.body");    
    return resp;    
}  
class HttpResponse {    
    String body;    
    String message;    
    Integer statusCode;    
    boolean failure = false;    
    public HttpResponse(HttpURLConnection connection){    
        this.statusCode = connection.responseCode;    
        this.message = connection.responseMessage;    
        if(statusCode == 200 || statusCode == 201){    
            this.body = connection.content.text;//this would fail the pipeline if there was a 400    
        }else{    
            this.failure = true;    
            this.body = connection.getErrorStream().text;    
        }    
        connection = null; //set connection to null for good measure, since we are done with it    
    }       
}

然后我可以使用以下内容进行GET:HttpResponse resp = doGetHttpRequest("http://some.url");

使用JSON数据的PUT使用如下内容:HttpResponse resp = this.doPutHttpRequestWithJson("{"propA":"foo"}", "http://some.url");

您尝试过Groovy的HTTPBuilder类吗?例如:

@Grapes(
    @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')
)
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def http = new HTTPBuilder("http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo")
http.request(POST, JSON ) { req ->
    body = []
    response.success = { resp, reader ->
        println "$resp.statusLine   Respond rec"
    }
}

在I/O调用时阻塞主线程不是一个好主意。

将I/O操作委派到shell步骤是当前推荐的方式。

另一种需要发展的方式是增加一个新的步骤。顺便说一句,尽管完整的REST客户端有自己的插件,但有一项举措是在管道脚本中添加一组要安全使用的通用步骤。

使用Basic Auth头执行GET。

def accessToken = "ACCESS_TOKEN".bytes.encodeBase64().toString()
def req = new URL("https://raw.githubusercontent.com/xxxx/something/hosts").openConnection();
req.setRequestProperty("Authorization", "Basic " + accessToken)
def content = req.getInputStream().getText()

最新更新