Utilities API Reference

This page documents utility functions for Request Forge.

to_curl

to_curl(request)

Convert HttpRequest to cURL command string.

Parameters:

request (HttpRequest) – The HTTP request to convert

Returns:

cURL command string

Return type:

str

This utility function converts an HttpRequest object into an equivalent cURL command that can be executed in a shell. Useful for debugging and sharing request details.

Features:

  • Handles all HTTP methods

  • Includes headers

  • Handles query parameters

  • Includes request body (JSON and form data)

  • Handles file uploads

  • Includes authentication

  • Includes timeout

  • Properly quotes and escapes values

Example:

from requestforge import HttpRequest, HttpMethod
from requestforge.utils import to_curl

request = HttpRequest(
    method=HttpMethod.POST,
    url='https://api.example.com/users',
    headers={'Authorization': 'Bearer token123'},
    json_data={'name': 'John Doe', 'email': 'john@example.com'}
)

curl_command = to_curl(request)
print(curl_command)

Output:

curl -X 'POST' \
     -H 'Authorization: Bearer token123' \
     -H 'Content-Type: application/json' \
     --data '{"name": "John Doe", "email": "john@example.com"}' \
     'https://api.example.com/users'

GET Request

from requestforge import HttpRequest, HttpMethod
from requestforge.utils import to_curl

request = HttpRequest(
    method=HttpMethod.GET,
    url='https://api.example.com/users',
    params={'page': 1, 'limit': 10},
    headers={'Accept': 'application/json'}
)

print(to_curl(request))

Output:

curl -X 'GET' \
     -H 'Accept: application/json' \
     'https://api.example.com/users?page=1&limit=10'

POST with JSON

request = HttpRequest(
    method=HttpMethod.POST,
    url='https://api.example.com/users',
    headers={'Authorization': 'Bearer token'},
    json_data={'name': 'John', 'age': 30}
)

print(to_curl(request))

Output:

curl -X 'POST' \
     -H 'Authorization: Bearer token' \
     -H 'Content-Type: application/json' \
     --data '{"name": "John", "age": 30}' \
     'https://api.example.com/users'

POST with Form Data

request = HttpRequest(
    method=HttpMethod.POST,
    url='https://api.example.com/login',
    data={'username': 'john', 'password': 'secret123'}
)

print(to_curl(request))

Output:

curl -X 'POST' \
     --data 'username=john&password=secret123' \
     'https://api.example.com/login'

With Authentication

# Bearer token
request = HttpRequest(
    method=HttpMethod.GET,
    url='https://api.example.com/protected',
    headers={'Authorization': 'Bearer abc123'}
)

print(to_curl(request))

Output:

curl -X 'GET' \
     -H 'Authorization: Bearer abc123' \
     'https://api.example.com/protected'
# Basic auth
request = HttpRequest(
    method=HttpMethod.GET,
    url='https://api.example.com/protected',
    auth=('username', 'password')
)

print(to_curl(request))

Output:

curl -X 'GET' \
     -u 'username:password' \
     'https://api.example.com/protected'

File Upload

request = HttpRequest(
    method=HttpMethod.POST,
    url='https://api.example.com/upload',
    files={'document': 'path/to/file.pdf'}
)

print(to_curl(request))

Output:

curl -X 'POST' \
     -F 'document=@path/to/file.pdf' \
     'https://api.example.com/upload'

With Timeout

request = HttpRequest(
    method=HttpMethod.GET,
    url='https://api.example.com/slow',
    timeout=30.0
)

print(to_curl(request))

Output:

curl -X 'GET' \
     --max-time 30.0 \
     'https://api.example.com/slow'

Complex Example

request = HttpRequest(
    method=HttpMethod.PUT,
    url='https://api.example.com/users/123',
    params={'notify': 'true'},
    headers={
        'Authorization': 'Bearer token',
        'Content-Type': 'application/json',
        'X-Request-ID': 'abc-123'
    },
    json_data={
        'name': 'Jane Doe',
        'email': 'jane@example.com',
        'tags': ['admin', 'premium']
    },
    timeout=60.0
)

print(to_curl(request))

Output:

curl -X 'PUT' \
     -H 'Authorization: Bearer token' \
     -H 'Content-Type: application/json' \
     -H 'X-Request-ID: abc-123' \
     --data '{"name": "Jane Doe", "email": "jane@example.com", "tags": ["admin", "premium"]}' \
     --max-time 60.0 \
     'https://api.example.com/users/123?notify=true'

Usage in Debugging

Logging Requests

import logging
from requestforge import HttpClient, HttpRequest, HttpMethod
from requestforge.utils import to_curl

logger = logging.getLogger(__name__)

def debug_request(request: HttpRequest):
    """Log request as cURL command."""
    curl = to_curl(request)
    logger.debug(f"Request: {curl}")

# Usage
request = HttpRequest(
    method=HttpMethod.POST,
    url='https://api.example.com/users',
    json_data={'name': 'John'}
)

debug_request(request)
response = client.request(request)

Custom Hook

from requestforge.interfaces import RequestHookInterface
from requestforge.utils import to_curl

class CurlLoggingHook(RequestHookInterface):
    """Hook that logs all requests as cURL commands."""

    def before_request(self, request, context):
        curl = to_curl(request)
        print(f"[CURL] {curl}")
        return request

# Usage
config = (
    HttpClientConfigBuilder()
    .with_base_url('https://api.example.com')
    .with_request_hook(CurlLoggingHook())
    .build()
)

client = HttpClient(config)
response = client.get('/users')  # Prints cURL command

Error Reporting

from requestforge import HttpClientException
from requestforge.utils import to_curl

try:
    response = client.request(request)
except HttpClientException as e:
    # Include cURL command in error report
    curl = to_curl(request)
    logger.error(
        f"Request failed: {e.message}",
        extra={
            'curl_command': curl,
            'error': str(e)
        }
    )

Testing Support

import pytest
from requestforge.utils import to_curl

def test_request_format():
    """Test that request is formatted correctly."""
    request = HttpRequest(
        method=HttpMethod.POST,
        url='https://api.example.com/users',
        json_data={'name': 'Test'}
    )

    curl = to_curl(request)

    # Verify command structure
    assert curl.startswith("curl -X 'POST'")
    assert 'https://api.example.com/users' in curl
    assert '--data' in curl
    assert 'name' in curl

Sharing Requests

from requestforge.utils import to_curl

def share_request(request):
    """Generate shareable cURL command for request."""
    curl = to_curl(request)

    print("Copy and paste this command to reproduce the request:")
    print()
    print(curl)
    print()
    print("You can save it to a file and execute:")
    print("$ bash request.sh")

    # Optionally save to file
    with open('request.sh', 'w') as f:
        f.write('#!/bin/bash\n')
        f.write(curl)
        f.write('\n')

# Usage
request = HttpRequest(...)
share_request(request)

HttpRequest Extension

The to_curl() utility is also available as a method on HttpRequest:

from requestforge import HttpRequest, HttpMethod

request = HttpRequest(
    method=HttpMethod.GET,
    url='https://api.example.com/users'
)

# Call directly on request object
curl = request.to_curl()
print(curl)

This is equivalent to:

from requestforge.utils import to_curl

curl = to_curl(request)
print(curl)

Implementation Notes

Quoting:

The function uses shlex.quote() to properly escape and quote values for shell safety.

Headers:

All headers are included with -H flag. Content-Type is automatically added for JSON requests.

Query Parameters:

Parameters are URL-encoded and appended to the URL.

Request Body:

  • JSON data uses --data with JSON-encoded string

  • Form data uses --data with URL-encoded string

  • Files use -F for multipart uploads

Authentication:

  • Bearer tokens included in Authorization header

  • Basic auth uses -u flag

  • Custom auth headers included as regular headers

Special Characters:

All special characters are properly escaped for shell execution.

Limitations

  1. File Content: File uploads show file path, not actual content

  2. Binary Data: Binary request bodies may not be representable in cURL

  3. Session Cookies: Does not include session cookies from client

  4. SSL Options: Does not include custom SSL/TLS settings

See Also