curl / hurl commands I often use for testing


curl with certificates and XML-Payload

curl -k -vv --cert /PATH/TO/CERT/XYZ.cer:PASSWORD --key /PATH/TO/KEY/XYZ.key --cacert /PATH/TO/CAS/XYZ.pem --data-binary "@test.xml" https://SOAP-ENDPOINT.de:12345/CC

curl to get token and call api

replace CLIENT, API_GATEWAY, PASSWORD, HOST-GWURI and HOST accordingly.

bash(linux):

ACCESS_TOKEN=$(curl -u "CLIENT:PASSWORD" \
-X POST 'https://HOST/auth/realms/cit2/protocol/openid-connect/token' \
-d grant_type=client_credentials -d client_id=CLIENT \
-d client_secret=PASSWORD | jq -r '.access_token' )

curl -w "dns: %{time_namelookup}, tcp_con: %{time_connect}, ssl_con: %{time_appconnect}, start: %{time_starttransfer}" \
--insecure -v https://HOST-GWURI/UserRolesAndPermissions/v1/permission?fields=queryCache,fullSize&limit=1&offset=500 \
-H"Authorization: Bearer $ACCESS_TOKEN" -H"X-Request-ID: 234234234234234234234234234234234234"

cmd (multiline windows):

curl -u "CLIENT:PASSWORD" ^
-X POST https://HOST/auth/realms/cit2/protocol/openid-connect/token ^
-d grant_type=client_credentials -d client_id=CLIENT ^
-d client_secret=PASSWORD | jq -r ".access_token" > token.secret
 
for /f %i in ('type token.secret') do set "ACCESS_TOKEN=%i"

OHA example

  • winget install –id hatoo.oha
  • winget install –id jqlang.jq
oha --insecure -c6 -z1m https://API_GATEWAY/AccountManagement/v2/partyAccount/billingAccount/0000000004 -H"Authorization: Bearer %ACCESS_TOKEN%"

hurl example with a token request for testing purposes

  • winget install hurl / sudo apt-get install hurl
  • https://hurl.dev/docs
  • hurl -v billingAccount-oauth.hurl
cat billingAccount-oauth.hurl

# Get an authorization token and store it in "jwt_token"
POST https://HOST/auth/realms/cit2/protocol/openid-connect/token
[FormParams]
grant_type: client_credentials
client_id: CLIENTID
client_secret: PASSWORD
[BasicAuth]
CLIENTID: PASSWORD

HTTP 200
[Captures]
jwt_token: jsonpath "$.access_token"
 
 
 
GET https://GW/AccountManagement/v2/partyAccount/billingAccount?customerNr=1831084780&limit=11&offset=0
User-Agent: Frank
Authorization: Bearer {{jwt_token}}
X-Request-ID: 234234234234234234234234234234234234
 
[Options]
insecure: true
 
HTTP 200
[Asserts]
header "Content-Type" == "application/json;charset=UTF-8"
jsonpath "$.[0].financialAccountNr" == "2298506192"
 
 
 
GET https://GW/AccountManagement/v2/partyAccount/billingAccount?customerNr=1941081174
User-Agent: Frank
Authorization: Bearer {{jwt_token}}
X-Request-ID: Request-RANDOM-NUMBER
 
[Options]
insecure: true
 
HTTP 200
[Asserts]
header "Content-Type" == "application/json;charset=UTF-8"
jsonpath "$" count == 7780
 
 
 
GET https://GW/ccountManagement/v2/partyAccount/billingAccount?customerNr=1941081174&limit=1000&offset=7000
User-Agent: Frank
Authorization: Bearer {{jwt_token}}
X-Request-ID: Request-RANDOM-NUMBER
 
[Options]
insecure: true
 
HTTP 206
[Asserts]
header "Content-Type" == "application/json;charset=UTF-8"
jsonpath "$" count == 780
header "X-Total-Count" == "7780"

Simple script cmd/bash

cmd:

hurl -v billingAccount-oauth.hurl
if NOT %errorlevel% == 0 echo ERROR billingAccount

bash:

hurl -v billingAccount-oauth.hurl
if [ $? != 0 ] ; then echo "ERROR billingAccount"; fi

python

test.urls:

GET:/AccountManagement/v2/financialAccount/921210248331695202110
GET:/AgreementManagement/v1/agreementSpecifications?agreementType=InvoiceContract&owner=1
GET:/PartyManagement/v4/parties/9221690093
GET:/ProductInventoryManagement/v3/product?fields=customerNumber=XXXX1663950,productStatus=active,productRelationships=true
...

url-test.py:

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
 
# Deaktiviere SSL-Warnungen
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
 
import random
import time
import sys
import concurrent.futures
import os
 
def generate_x_request_id():
    x_request_id = ''.join([str(random.randint(0, 9)) for _ in range(40)])
    return x_request_id
 
if len(sys.argv) < 2:
    print("Bitte geben Sie den Dateinamen als Befehlszeilenargument an.")
    sys.exit(1)
 
filename = sys.argv[1]
 
# Lesen der Datei
try:
    with open(filename, 'r') as file:
        urls = file.readlines()
except FileNotFoundError:
    print(f"Die Datei '{filename}' konnte nicht gefunden werden.")
    sys.exit(1)
 
# Definieren der zu setzenden HTTP-Header
headers = {
    'Authorization': 'Basic XXXXXXXXXXXXXXXXXXX',
 #  'Authorization': 'Bearer YYYYYYYYYYYYYYYXXXXXXX',
    'X-System-ID': '1'
}
 
base_url = 'https://localhost:20205/crm_restserver'
 
# Funktion zum Senden der HTTP-Anfragen
def send_request(url):
    start_time = time.time()
    full_url = base_url + url.strip()
    x_request_id = generate_x_request_id()
    headers['X-Request-ID'] = x_request_id
    response = requests.get(full_url, headers=headers, verify=False)
    response_size = len(response.content)
    duration = time.time() - start_time
    print(f"Request URL: {full_url}   Code: {response.status_code}   {duration:.4f} seconds   {response_size} bytes", flush=True)
 
max_threads = 6
counter = 0
 
def submit_request(url):
    try:
        send_request(url)
    except Exception as e:
        print(f"Fehler beim Bearbeiten der URL '{url}': {e}")
        os._exit(0)
 
start_all = time.time()
 
with concurrent.futures.ThreadPoolExecutor(max_workers=max_threads) as executor:
    for url in urls:
        url = url.strip()
        if len(url) > 1:
            if url[0] !='#':
                counter = counter + 1
                clean_url = url.strip().split(':')[1]
                executor.submit(submit_request, clean_url)
 
durationAll = time.time() - start_all
print(f"Urls processed: {counter}   took {durationAll:.4f} seconds")
  • python url-test.py test.urls