728x90
개요
최근 jenkins CI/CD 파이프라인 코드를 다루게 되면서 curl을 사용하여 HTTP 요청을 보내게 될 일이 종종 있었습니다.
다만 curl에 익숙하지 않아 다양한 형태의 HTTP 요청을 보내는 코드를 작성하는 것이 어려웠는데요.
이번 기회에 groovy로 다양한 형태의 curl 요청 함수를 작성해보았습니다.
curl 함수
다음과 같은 4가지 형태의 curl 요청 함수를 작성해보았습니다.
- GET + query params
- POST + request body
- POST + form data
- POST + form data + file
GET + query params
<함수>
// GET 요청
def curlGet = { String url, Map params = [:], Map headers = [:] ->
String qs = params.collect { k, v -> "${k}=${v}" }.join("&")
String fullUrl = qs ? "${url}?${qs}" : url
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String cmd = """
curl -s -X GET \\
${headerStr} \\
"${fullUrl}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
<사용법>
println "===== GET TEST ====="
println curlGet(
"https://httpbin.org/get",
[q: "hello"],
["Accept": "application/json"]
)
POST + form data
<함수>
// POST 요청 + form-data
def curlPostForm = { String url, Map form = [:], Map headers = [:] ->
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String formStr = form.collect { k, v ->
"-F \"${k}=${v}\""
}.join(" ")
String cmd = """
curl -s -X POST \\
${headerStr} \\
${formStr} \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
<사용법>
// POST 요청 + form-data
def curlPostForm = { String url, Map form = [:], Map headers = [:] ->
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String formStr = form.collect { k, v ->
"-F \"${k}=${v}\""
}.join(" ")
String cmd = """
curl -s -X POST \\
${headerStr} \\
${formStr} \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
Post + request body
<함수>
// POST 요청 + JSON
def curlPostJson = { String url, Map body, Map headers = [:] ->
String json = groovy.json.JsonOutput.toJson(body)
Map finalHeaders = ["Content-Type": "application/json"] + headers
String headerStr = finalHeaders.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String cmd = """
curl -s -X POST \\
${headerStr} \\
-d '${json}' \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
println "===== POST JSON TEST ====="
println curlPostJson(
"https://httpbin.org/post",
[msg: "hello", list: [1,2,3]],
["Accept": "application/json"]
)
Post + form data + file
<함수>
// POST 요청 + form data + 파일 업로드
def curlPostFormWithFile = { String url, Map formData, String filePath, Map headers = [:] ->
// 헤더 문자열 구성
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
// form-data 문자열 구성
String formStr = formData.collect { k, v ->
"-F \"${k}=${v}\""
}.join(" ")
// curl 명령
String cmd = """
curl -s -X POST \\
${headerStr} \\
${formStr} \\
-F "file=@${filePath}" \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
<사용법>
println "===== POST JSON + FILE UPLOAD TEST ====="
println curlPostFormWithFile(
"https://httpbin.org/post",
[user: "hong", type: "upload-test"],
"test_upload.txt",
["Accept": "application/json"]
)
Jenkins pipeline 사용 예시
pipeline {
agent {
kubernetes {
label 'curl-test-pod'
defaultContainer 'tools'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: tools
image: alpine:latest
command:
- cat
tty: true
"""
}
}
stages {
stage('Setup & Curl Tests') {
steps {
container('tools') {
script {
// curl 설치
sh """
apk update
apk add --no-cache curl
"""
// GET 요청
def curlGet = { String url, Map params = [:], Map headers = [:] ->
String qs = params.collect { k, v -> "${k}=${v}" }.join("&")
String fullUrl = qs ? "${url}?${qs}" : url
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String cmd = """
curl -s -X GET \\
${headerStr} \\
"${fullUrl}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
// POST 요청 + form-data
def curlPostForm = { String url, Map form = [:], Map headers = [:] ->
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String formStr = form.collect { k, v ->
"-F \"${k}=${v}\""
}.join(" ")
String cmd = """
curl -s -X POST \\
${headerStr} \\
${formStr} \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
// POST 요청 + JSON
def curlPostJson = { String url, Map body, Map headers = [:] ->
String json = groovy.json.JsonOutput.toJson(body)
Map finalHeaders = ["Content-Type": "application/json"] + headers
String headerStr = finalHeaders.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
String cmd = """
curl -s -X POST \\
${headerStr} \\
-d '${json}' \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
// POST 요청 + form data + 파일 업로드
def curlPostFormWithFile = { String url, Map formData, String filePath, Map headers = [:] ->
// 헤더 문자열 구성
String headerStr = headers.collect { k, v ->
"-H \"${k}: ${v}\""
}.join(" ")
// form-data 문자열 구성
String formStr = formData.collect { k, v ->
"-F \"${k}=${v}\""
}.join(" ")
// curl 명령
String cmd = """
curl -s -X POST \\
${headerStr} \\
${formStr} \\
-F "file=@${filePath}" \\
"${url}"
"""
return sh(script: cmd.trim(), returnStdout: true).trim()
}
// 테스트용 파일 생성
sh "echo '테스트 파일입니다.' > test_upload.txt"
// 테스트 호출
println "===== GET TEST ====="
println curlGet(
"https://httpbin.org/get",
[q: "hello"],
["Accept": "application/json"]
)
println "===== POST FORM TEST ====="
println curlPostForm(
"https://httpbin.org/post",
[name: "hong", age: "20"],
["Accept": "application/json"]
)
println "===== POST JSON TEST ====="
println curlPostJson(
"https://httpbin.org/post",
[msg: "hello", list: [1,2,3]],
["Accept": "application/json"]
)
println "===== POST JSON + FILE UPLOAD TEST ====="
println curlPostFormWithFile(
"https://httpbin.org/post",
[user: "hong", type: "upload-test"],
"test_upload.txt",
["Accept": "application/json"]
)
}
}
}
}
}
}728x90