CURL — using notes

Photo by AbsolutVision on Unsplash

Intro

Test Environment

Let’s start

version: '3.7'
services:
jenkins:
image: jenkins/jenkins:lts
privileged: true
user: root
ports:
- 8081:8080
- 50000:50000
container_name: jenkins
volumes:
- /tmpy:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- /usr/local/bin/docker:/usr/local/bin/docker

GET

root@vagrant:/home/vagrant/jenkins# curl http://192.168.123.123:8081/api/json | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 605 100 605 0 0 61489 0 --:--:-- --:--:-- --:--:-- 75625
{
"_class": "hudson.model.Hudson",
"assignedLabels": [
{
"name": "master"
}
],
"mode": "NORMAL",
"nodeDescription": "the master Jenkins node",
"nodeName": "",
"numExecutors": 2,
"description": null,
"jobs": [],
"overallLoad": {},
"primaryView": {
"_class": "hudson.model.AllView",
"name": "all",
"url": "http://192.168.123.123:8081/"
},
"quietDownReason": null,
"quietingDown": false,
"slaveAgentPort": 50000,
"unlabeledLoad": {
"_class": "jenkins.model.UnlabeledLoadStatistics"
},
"url": "http://192.168.123.123:8081/",
"useCrumbs": true,
"useSecurity": true,
"views": [
{
"_class": "hudson.model.AllView",
"name": "all",
"url": "http://192.168.123.123:8081/"
}
]
}
root@vagrant:/home/vagrant/jenkins#

Output to file

root@vagrant:/home/vagrant/jenkins# curl http://192.168.123.123:8081/api/json -o result
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 605 100 605 0 0 53653 0 --:--:-- --:--:-- --:--:-- 60500
root@vagrant:/home/vagrant/jenkins# cat result | jq .
{
"_class": "hudson.model.Hudson",
"assignedLabels": [
{
"name": "master"
}
],
"mode": "NORMAL",
"nodeDescription": "the master Jenkins node",
"nodeName": "",
"numExecutors": 2,
"description": null,
"jobs": [],
"overallLoad": {},
"primaryView": {
"_class": "hudson.model.AllView",
"name": "all",
"url": "http://192.168.123.123:8081/"
},
"quietDownReason": null,
"quietingDown": false,
"slaveAgentPort": 50000,
"unlabeledLoad": {
"_class": "jenkins.model.UnlabeledLoadStatistics"
},
"url": "http://192.168.123.123:8081/",
"useCrumbs": true,
"useSecurity": true,
"views": [
{
"_class": "hudson.model.AllView",
"name": "all",
"url": "http://192.168.123.123:8081/"
}
]
}

Progress Meter

root@vagrant:/home/vagrant/jenkins# curl http://192.168.123.123:8081/api/json -o result -#
######################################################################## 100.0%
#Without -s
root@vagrant:/home/vagrant/jenkins# curl http://192.168.123.123:8089/api/json -0
curl: (7) Failed to connect to 192.168.123.123 port 8089: Connection refused
root@vagrant:/home/vagrant/jenkins#
#With -s
root@vagrant:/home/vagrant/jenkins# curl -s http://192.168.123.123:8089/api/json -0
root@vagrant:/home/vagrant/jenkins#
root@vagrant:/home/vagrant/jenkins# curl -Ss http://192.168.123.123:8089/api/json -0
curl: (7) Failed to connect to 192.168.123.123 port 8089: Connection refused
root@vagrant:/home/vagrant/jenkins#

Check the HTTP Headers

root@vagrant:/home/vagrant/jenkins# curl -I -s  http://192.168.123.123:8081/api/json
HTTP/1.1 200 OK
Date: Thu, 29 Apr 2021 18:53:59 GMT
X-Content-Type-Options: nosniff
X-Jenkins: 2.277.3
X-Jenkins-Session: 7679bd14
X-Frame-Options: deny
Content-Type: application/json;charset=utf-8
Content-Length: 605
Server: Jetty(9.4.39.v20210325)
root@vagrant:/home/vagrant/jenkins# curl -i -s  http://192.168.123.123:8081/api/json?
HTTP/1.1 200 OK
Date: Thu, 29 Apr 2021 18:55:13 GMT
X-Content-Type-Options: nosniff
X-Jenkins: 2.277.3
X-Jenkins-Session: 7679bd14
X-Frame-Options: deny
Content-Type: application/json;charset=utf-8
Content-Length: 605
Server: Jetty(9.4.39.v20210325)
{"_class":"hudson.model.Hudson","assignedLabels":[{"name":"master"}],"mode":"NORMAL","nodeDescription":"the master Jenkins node","nodeName":"","numExecutors":2,"description":null,"jobs":[],"overallLoad":{},"primaryView":{"_class":"hudson.model.AllView","name":"all","url":"http://192.168.123.123:8081/"},"quietDownReason":null,"quietingDown":false,"slaveAgentPort":50000,"unlabeledLoad":{"_class":"jenkins.model.UnlabeledLoadStatistics"},"url":"http://192.168.123.123:8081/","useCrumbs":true,"useSecurity":true,"views":[{"_class":"hudson.model.AllView","name":"all","url":"http://192.168.123.123:8081/"}]}root@vagrant:/home/vagrant/jenkins#
root@vagrant:/home/vagrant/jenkins#
root@vagrant:/home/vagrant/jenkins# curl -v -s  http://192.168.123.123:8081/api/json?
* Trying 192.168.123.123...
* Connected to 192.168.123.123 (192.168.123.123) port 8081 (#0)
> GET /api/json? HTTP/1.1
> Host: 192.168.123.123:8081
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 29 Apr 2021 18:56:59 GMT
< X-Content-Type-Options: nosniff
< X-Jenkins: 2.277.3
< X-Jenkins-Session: 7679bd14
< X-Frame-Options: deny
< Content-Type: application/json;charset=utf-8
< Content-Length: 605
< Server: Jetty(9.4.39.v20210325)
<
* Connection #0 to host 192.168.123.123 left intact
{"_class":"hudson.model.Hudson","assignedLabels":[{"name":"master"}],"mode":"NORMAL","nodeDescription":"the master Jenkins node","nodeName":"","numExecutors":2,"description":null,"jobs":[],"overallLoad":{},"primaryView":{"_class":"hudson.model.AllView","name":"all","url":"http://192.168.123.123:8081/"},"quietDownReason":null,"quietingDown":false,"slaveAgentPort":50000,"unlabeledLoad":{"_class":"jenkins.model.UnlabeledLoadStatistics"},"url":"http://192.168.123.123:8081/","useCrumbs":true,"useSecurity":true,"views":[{"_class":"hudson.model.AllView","name":"all","url":"http://192.168.123.123:8081/"}]}
root@vagrant:/home/vagrant/jenkins#

Check more HTTP packet data

Trace

root@vagrant:/home/vagrant# curl -sS  http://192.168.123.123:8081 -X POST -F "test=test" --trace trace.log -o /dev/null
root@vagrant:/home/vagrant# cat trace.log | head
== Info: Rebuilt URL to: http://192.168.123.123:8081/
== Info: Trying 192.168.123.123...
== Info: Connected to 192.168.123.123 (192.168.123.123) port 8081 (#0)
=> Send header, 214 bytes (0xd6)
0000: 50 4f 53 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d POST / HTTP/1.1.
0010: 0a 48 6f 73 74 3a 20 31 39 32 2e 31 36 38 2e 31 .Host: 192.168.1
0020: 32 33 2e 31 32 33 3a 38 30 38 31 0d 0a 55 73 65 23.123:8081..Use
0030: 72 2d 41 67 65 6e 74 3a 20 63 75 72 6c 2f 37 2e r-Agent: curl/7.
0040: 34 37 2e 30 0d 0a 41 63 63 65 70 74 3a 20 2a 2f 47.0..Accept: */
0050: 2a 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 *..Content-Lengt
root@vagrant:/home/vagrant#

Trace-ascii

root@vagrant:/home/vagrant# curl -sS  http://192.168.123.123:8081 -X POST -F "test=test" --trace-ascii trace-ascii.log -o /dev/null
root@vagrant:/home/vagrant# cat trace-ascii.log | head
== Info: Rebuilt URL to: http://192.168.123.123:8081/
== Info: Trying 192.168.123.123...
== Info: Connected to 192.168.123.123 (192.168.123.123) port 8081 (#0)
=> Send header, 214 bytes (0xd6)
0000: POST / HTTP/1.1
0011: Host: 192.168.123.123:8081
002d: User-Agent: curl/7.47.0
0046: Accept: */*
0053: Content-Length: 143
0068: Expect: 100-continue
root@vagrant:/home/vagrant#

POST

import jenkins.model.Jenkins
def instance = Jenkins.instance
instance.setCrumbIssuer(null)
root@vagrant:/home/vagrant# curl -sS -w '\n' -X POST '192.168.123.123:8081'

POST with parameters

root@vagrant:/home/vagrant# curl -w '\n' 'http://192.168.123.123:8081/createItem' --data 'name=Example_FreeStyle_JOb&mode=hudson.model.FreeStyleProject&Submit=OK' -XPOST
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/api/json' | jq .jobs
[
{
"_class": "hudson.model.FreeStyleProject",
"name": "Example_FreeStyle_JOb",
"url": "http://192.168.123.123:8081/job/Example_FreeStyle_JOb/",
"color": "notbuilt"
}
]
root@vagrant:/home/vagrant#

URL encoding and parameterized POST

root@vagrant:/home/vagrant# curl -w '\n' 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/configSubmit' --data 'json=%7b%22properties%22%3a+%7b%22hudson-model-ParametersDefinitionProperty%22%3a+%7b%22parameterized%22%3a+%7b%22parameter%22%3a+%7b%22name%22%3a+%22FileParameter%22%2c+%22description%22%3a+%22%22%2c+%22stapler-class%22%3a+%22hudson.model.FileParameterDefinition%22%2c+%22%24class%22%3a+%22hudson.model.FileParameterDefinition%22%7d%7d%7d%7d%7d%0d%0a&Submit=Save' -XPOSTroot@vagrant:/home/vagrant#
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/api/json' | jq .actions
[
{
"_class": "hudson.model.ParametersDefinitionProperty",
"parameterDefinitions": [
{
"_class": "hudson.model.FileParameterDefinition",
"defaultParameterValue": null,
"description": "",
"name": "",
"type": "FileParameterDefinition"
}

]
},
{},
{},
{
"_class": "org.jenkinsci.plugins.displayurlapi.actions.JobDisplayAction"
},
{
"_class": "com.cloudbees.plugins.credentials.ViewCredentialsAction"
}
]
root@vagrant:/home/vagrant#
curl -w '\n' 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/configSubmit' --data-urlencode 'json={"properties": {"hudson-model-ParametersDefinitionProperty": {"parameterized": {"parameter": {"name": "FileParameter", "description": "Test description in Jenkins", "stapler-class": "hudson.model.FileParameterDefinition", "$class": "hudson.model.FileParameterDefinition"}}}}}' -d 'Submit=Save' -XPOST
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/api/json' | jq .actions
[
{
"_class": "hudson.model.ParametersDefinitionProperty",
"parameterDefinitions": [
{
"_class": "hudson.model.FileParameterDefinition",
"defaultParameterValue": null,
"description": "Test description in Jenkins",
"name": "",
"type": "FileParameterDefinition"
}
]
},
{},
{},
{
"_class": "org.jenkinsci.plugins.displayurlapi.actions.JobDisplayAction"
},
{
"_class": "com.cloudbees.plugins.credentials.ViewCredentialsAction"
}
]
root@vagrant:/home/vagrant#

Upload file with POST

#Prepare file
root@vagrant:/home/vagrant# echo "Some test file" > test.txt
#Run Job
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/build' -X POST -F "file=@test.txt" -F 'json={"parameter": [{"name":"FileParameter", "file":"file"}]}'
#Check if job are running
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/api/json' | jq .builds
[
{
"_class": "hudson.model.FreeStyleBuild",
"number": 1,
"url": "http://192.168.123.123:8081/job/Example_FreeStyle_JOb/1/"
}
]
#Check parameters file
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/job/Example_FreeStyle_JOb/1/parameters/parameter/test.txt/test.txt'
Some test file
root@vagrant:/home/vagrant#
root@vagrant:/home/vagrant#

CURL and Authentication

root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/api/json' -I
HTTP/1.1 403 Forbidden
Date: Sat, 01 May 2021 15:03:40 GMT
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID.d9cf535a=node01gq5wts64izzk1b1uuc4l048uj18.node0; Path=/; HttpOnly
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html;charset=utf-8
X-Hudson: 1.395
X-Jenkins: 2.277.3
X-Jenkins-Session: 7679bd14
X-Hudson-CLI-Port: 50000
X-Jenkins-CLI-Port: 50000
X-Jenkins-CLI2-Port: 50000
Content-Length: 561
Server: Jetty(9.4.39.v20210325)
root@vagrant:/home/vagrant#

BASIC authentication

root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/api/json' -I -I -u testuser:P@ssw0rd_123
HTTP/1.1 200 OK
Date: Sat, 01 May 2021 15:07:33 GMT
X-Content-Type-Options: nosniff
X-Jenkins: 2.277.3
X-Jenkins-Session: 7679bd14
X-Frame-Options: deny
Content-Type: application/json;charset=utf-8
Content-Length: 882
Server: Jetty(9.4.39.v20210325)
root@vagrant:/home/vagrant#
root@vagrant:/home/vagrant# curl -sS 'http://192.168.123.123:8081/api/json' -I -I -u testuser
Enter host password for user 'testuser':
HTTP/1.1 200 OK
Date: Sat, 01 May 2021 15:10:14 GMT
X-Content-Type-Options: nosniff
X-Jenkins: 2.277.3
X-Jenkins-Session: 7679bd14
X-Frame-Options: deny
Content-Type: application/json;charset=utf-8
Content-Length: 882
Server: Jetty(9.4.39.v20210325)
root@vagrant:/home/vagrant#
curl -sS 'http://user:password@localhost:8081/api/json' -I

Other frequently used options

Summary

--

--

DevOps Consultant. I’m strongly focused on automation, security, and reliability.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Maciej

DevOps Consultant. I’m strongly focused on automation, security, and reliability.