HTTP REQUESTS
Making HTTP Requests
Overview
Karate provides a simple yet powerful syntax for constructing and executing HTTP requests. The core keywords url
, path
, method
, and request
form the foundation of API testing, with additional keywords for parameters, headers, and advanced scenarios.
Core Request Keywords
URL Configuration
The url
keyword sets the base URL for your API requests:
# Basic URL
* url 'https://api.example.com'
# Using variables
* url baseUrl
* url apiUrl + '/v1'
# Dynamic URL construction
* def environment = karate.env || 'dev'
* def apiUrl = environment == 'prod' ? 'https://api.prod.com' : 'https://api.dev.com'
* url apiUrl
```gherkin
> **Note**: Within a scenario, the URL remains constant until you use the `url` keyword again. This is ideal for setting the non-changing parts of your REST endpoints.
### Path Building
The `path` keyword constructs REST-style path parameters:
```gherkin
# Single path
* path '/users'
# Multiple segments
* path 'documents', documentId, 'download'
# Multi-line path building
* path 'api'
* path 'v1'
* path 'users'
* path userId
# Dynamic path with expressions
* def endpoint = 'users/' + userId + '/profile'
* path endpoint
```gherkin
**Path Features**:
- Automatically handles URL encoding
- Adds `/` between segments as needed
- Supports expressions that are evaluated
- Can be comma-delimited for convenience
### HTTP Methods
The `method` keyword triggers the actual HTTP request:
```gherkin
# Standard HTTP verbs
* method get
* method post
* method put
* method delete
* method patch
# Other supported verbs
* method options
* method head
* method connect
* method trace
```gherkin
> **Important**: The HTTP request is sent when the `method` keyword executes. Ensure all setup (url, path, headers, params) is complete before calling `method`.
### Request Body
The `request` keyword sets the request payload:
```gherkin
# JSON request (inline)
* request { name: 'Alice', age: 30 }
# JSON from variable
* def userData = { name: 'Bob', email: 'bob@example.com' }
* request userData
# XML request
* request
"""
<user>
<name>Charlie</name>
<email>charlie@example.com</email>
</user>
"""
# Request from file
* request read('user-payload.json')
# GraphQL request
* text query =
"""
{
user(id: "123") {
name
email
}
}
"""
* request { query: '#(query)' }
```gherkin
## Query Parameters
### Individual Parameters
Use the `param` keyword for query string parameters:
```gherkin
# Simple parameters
* param q = 'search term'
* param limit = 10
* param offset = 0
# Dynamic parameters
* param userId = currentUserId
* param timestamp = new Date().getTime()
# Null values are ignored
* def optionalParam = null
* param optional = optionalParam # This param won't be added
```gherkin
### Multiple Parameters
Use the `params` keyword for setting multiple parameters at once:
```gherkin
# JSON object
* params { q: 'karate', type: 'framework', active: true }
# From variable
* def searchParams = { query: 'test', page: 1, size: 20 }
* params searchParams
# Dynamic parameters with null handling
* def filters = {
status: 'active',
category: categoryId,
optional: null # This will be ignored
}
* params filters
```gherkin
## Complete Request Examples
### GET Request
```gherkin
Scenario: Get user by ID
* url 'https://api.example.com'
* path 'users', userId
* param include = 'profile,permissions'
* header Accept = 'application/json'
* method get
* status 200
* match response.id == userId
```gherkin
### POST Request
```gherkin
Scenario: Create new user
* url baseUrl
* path '/users'
* header Content-Type = 'application/json'
* request
"""
{
"name": "New User",
"email": "newuser@example.com",
"role": "member"
}
"""
* method post
* status 201
* match response.id == '#string'
* def createdId = response.id
```gherkin
### PUT Request with Dynamic Data
```gherkin
Scenario: Update user profile
* def updates = {
email: 'updated@example.com',
profile: {
bio: 'Updated bio',
location: 'New York'
}
}
* url apiUrl
* path 'users', userId, 'profile'
* request updates
* method put
* status 200
* match response.email == updates.email
```gherkin
### DELETE Request
```gherkin
Scenario: Delete user
* url baseUrl
* path '/users/', userId
* header Authorization = 'Bearer ' + authToken
* method delete
* status 204
```gherkin
### PATCH Request
```gherkin
Scenario: Partial update
* url apiUrl
* path 'users', userId
* request { status: 'inactive' }
* method patch
* status 200
* match response.status == 'inactive'
```gherkin
## Advanced Request Patterns
### Dynamic URL Building
```gherkin
Scenario: Dynamic endpoint selection
* def service = environment == 'prod' ? 'api' : 'api-dev'
* def version = apiVersion || 'v1'
* url 'https://' + service + '.example.com/' + version
* path 'users'
* method get
```gherkin
### Request with Query String
```gherkin
Scenario: Search with filters
* url baseUrl
* path '/search'
* params {
q: searchTerm,
type: 'user',
active: true,
created_after: '2023-01-01',
sort: 'name:asc'
}
* method get
* status 200
* assert response.results.length > 0
```gherkin
### GraphQL Request
```gherkin
Scenario: GraphQL query
* url graphqlUrl
* text query =
"""
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
title
published
}
}
}
"""
* def variables = { id: '123' }
* request { query: '#(query)', variables: '#(variables)' }
* method post
* status 200
* match response.data.user.id == '123'
```gherkin
### SOAP Request
```gherkin
Scenario: SOAP web service call
* url 'http://webservices.example.com/soap'
* header Content-Type = 'text/xml; charset=utf-8'
* header SOAPAction = 'http://example.com/GetUser'
* request
"""
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetUserRequest xmlns="http://example.com/users">
<UserId>123</UserId>
</GetUserRequest>
</soap:Body>
</soap:Envelope>
"""
* method post
* status 200
* match /Envelope/Body/GetUserResponse/User/Name == 'John Doe'
```gherkin
## Request Workflow Best Practices
### Proper Request Sequencing
```gherkin
# ✅ Good: Setup before method
Scenario: Correct sequence
* url baseUrl # 1. Set base URL
* path '/users' # 2. Build path
* param limit = 10 # 3. Add parameters
* header Accept = 'application/json' # 4. Set headers
* method get # 5. Execute request
* status 200 # 6. Validate response
# ❌ Bad: Method before complete setup
Scenario: Incorrect sequence
* url baseUrl
* method get # Missing path!
```gherkin
### Request Reusability
```gherkin
Background:
* url baseUrl
* def commonHeaders = { 'Accept': 'application/json', 'X-API-Version': '2.0' }
* headers commonHeaders
Scenario: Reuse common setup
* path '/users'
* method get
* status 200
Scenario: Another request with same setup
* path '/products'
* method get
* status 200
```gherkin
### Error Handling
```gherkin
Scenario: Handle various response codes
* url apiUrl
* path '/users/', userId
* method get
# Handle different scenarios
* if (responseStatus == 404) karate.fail('User not found')
* if (responseStatus == 401) karate.call('refresh-token.feature')
* if (responseStatus != 200) karate.fail('Unexpected status: ' + responseStatus)
```gherkin
## Debugging Requests
### Request Inspection
```gherkin
Scenario: Debug request details
* url 'https://api.example.com'
* path '/users'
* param debug = true
# Print request details before sending
* print 'Request URL:', url + path
* print 'Request params:', karate.get('params')
* method get
* print 'Response status:', responseStatus
* print 'Response time:', responseTime
```gherkin
### Using Request Hooks
```gherkin
# Configure request logging
* configure logPrettyRequest = true
* configure logPrettyResponse = true
Scenario: Request with detailed logging
* url apiUrl
* path '/debug'
* request { test: 'data' }
* method post
```gherkin
## Performance Considerations
### Connection Management
```gherkin
# Configure timeouts
* configure connectTimeout = 5000 # 5 seconds
* configure readTimeout = 30000 # 30 seconds
# Reuse connections
* configure reuseConnections = true
```gherkin
### Request Optimization
```gherkin
# Batch requests when possible
Scenario: Efficient multiple requests
* def userIds = [1, 2, 3, 4, 5]
* def users = []
# Instead of multiple individual requests
* url apiUrl
* path '/users/batch'
* request { ids: '#(userIds)' }
* method post
* status 200
* def users = response.users
```gherkin
## Advanced Authentication
### X509 Certificate Authentication (Mutual TLS)
For APIs requiring client certificate authentication, configure SSL with certificate details:
```gherkin
# PKCS12 certificate authentication
* configure ssl = {
keyStore: 'classpath:certstore.pfx',
keyStorePassword: 'certpassword',
keyStoreType: 'pkcs12'
}
# JKS certificate with trust store
* configure ssl = {
keyStore: 'classpath:client.jks',
keyStorePassword: 'client-pass',
keyStoreType: 'jks',
trustStore: 'classpath:trust.jks',
trustStorePassword: 'trust-pass'
}
# Trust all certificates (development only)
* configure ssl = { trustAll: true }
```gherkin
#### X509 Configuration Options
| Key | Type | Required | Description |
|-----|------|----------|-------------|
| `keyStore` | string | optional | Path to file containing client certificate |
| `keyStorePassword` | string | optional | Password for keyStore file |
| `keyStoreType` | string | optional | Format: 'pkcs12', 'jks', etc. |
| `trustStore` | string | optional | Path to trust chain file |
| `trustStorePassword` | string | optional | Password for trustStore |
| `trustStoreType` | string | optional | Trust store format |
| `trustAll` | boolean | optional | Trust all server certificates (default: false) |
| `algorithm` | string | optional | SSL algorithm (default: TLS) |
#### Global SSL Configuration
```javascript
// karate-config.js
function fn() {
var config = {};
// Environment-specific certificates
if (karate.env === 'prod') {
karate.configure('ssl', {
keyStore: 'classpath:prod-cert.pfx',
keyStorePassword: karate.properties['cert.password'],
keyStoreType: 'pkcs12'
});
} else {
// Development: trust all
karate.configure('ssl', { trustAll: true });
}
return config;
}
NTLM Authentication
For Windows domain authentication using NTLM:
# Basic NTLM authentication
* configure ntlmAuth = {
username: 'admin',
password: 'secret'
}
# Full NTLM configuration
* configure ntlmAuth = {
username: 'admin',
password: 'secret',
domain: 'my.domain',
workstation: 'my-pc'
}
# Disable NTLM
* configure ntlmAuth = null
```gherkin
#### NTLM Configuration Options
| Key | Type | Required | Description |
|-----|------|----------|-------------|
| `username` | string | required | NTLM username |
| `password` | string | required | NTLM password |
| `domain` | string | optional | Authentication domain |
| `workstation` | string | optional | Originating workstation |
#### Dynamic NTLM Configuration
```javascript
// karate-config.js
function fn() {
var config = {};
// Read credentials from environment
if (karate.properties['ntlm.enabled'] === 'true') {
karate.configure('ntlmAuth', {
username: java.lang.System.getenv('NTLM_USER'),
password: java.lang.System.getenv('NTLM_PASS'),
domain: java.lang.System.getenv('NTLM_DOMAIN')
});
}
return config;
}
Authentication Best Practices
# ✅ Good: Separate auth configuration
Background:
* def authConfig = call read('classpath:auth-config.feature')
* configure ssl = authConfig.sslConfig
* configure ntlmAuth = authConfig.ntlmConfig
# ✅ Good: Environment-specific auth
* def certPath = karate.env == 'prod' ? 'prod-cert.pfx' : 'test-cert.pfx'
* configure ssl = { keyStore: '#("classpath:" + certPath)', keyStorePassword: '#(certPass)' }
# ❌ Avoid: Hardcoded credentials
* configure ntlmAuth = { username: 'hardcoded', password: 'visible' }
```gherkin
> **Security Note**: Never commit certificates or passwords to version control. Use environment variables or secure vaults for sensitive data.
## System Properties for SSL and HTTP Proxy
Configure SSL certificates and HTTP proxies using Java system properties for advanced networking scenarios.
### SSL System Properties
Configure custom SSL trust stores and certificates via system properties:
| System Property | Description | Example |
|-----------------|-------------|---------|
| `javax.net.ssl.trustStore` | Path to trust store file | `/path/to/truststore.jks` |
| `javax.net.ssl.trustStorePassword` | Trust store password | `changeit` |
| `javax.net.ssl.keyStore` | Path to key store file | `/path/to/keystore.p12` |
| `javax.net.ssl.keyStorePassword` | Key store password | `mypassword` |
| `javax.net.ssl.keyStoreType` | Key store type | `PKCS12` or `JKS` |
#### Setting SSL Properties
```bash
# Maven with SSL properties
mvn test -DargLine="\
-Djavax.net.ssl.trustStore=/opt/certs/truststore.jks \
-Djavax.net.ssl.trustStorePassword=changeit \
-Djavax.net.ssl.keyStore=/opt/certs/client.p12 \
-Djavax.net.ssl.keyStorePassword=clientpass \
-Djavax.net.ssl.keyStoreType=PKCS12"
# Gradle with SSL properties
./gradlew test \
-Djavax.net.ssl.trustStore=/opt/certs/truststore.jks \
-Djavax.net.ssl.trustStorePassword=changeit
```gherkin
#### Programmatic SSL Configuration
```java
// In your test runner or setup
System.setProperty("javax.net.ssl.trustStore", "/opt/certs/truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStore", "/opt/certs/client.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "clientpass");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
HTTP Proxy System Properties
Configure HTTP and HTTPS proxy settings for corporate environments:
| System Property | Description | Example |
| -------------------- | --------------------- | ------------------- | ---------------- |
| http.proxyHost
| HTTP proxy hostname | proxy.company.com
|
| http.proxyPort
| HTTP proxy port | 8080
|
| https.proxyHost
| HTTPS proxy hostname | proxy.company.com
|
| https.proxyPort
| HTTPS proxy port | 8443
|
| http.proxyUser
| Proxy username | proxyuser
|
| http.proxyPassword
| Proxy password | proxypass
|
| http.nonProxyHosts
| Hosts to bypass proxy | localhost | \*.internal.com
|
Setting Proxy Properties
# Maven with proxy settings
mvn test -DargLine="\
-Dhttp.proxyHost=proxy.company.com \
-Dhttp.proxyPort=8080 \
-Dhttps.proxyHost=proxy.company.com \
-Dhttps.proxyPort=8443 \
-Dhttp.nonProxyHosts='localhost|*.internal.com'"
# Gradle with proxy settings
./gradlew test \
-Dhttp.proxyHost=proxy.company.com \
-Dhttp.proxyPort=8080 \
-Dhttps.proxyHost=proxy.company.com \
-Dhttps.proxyPort=8443
```gherkin
#### Programmatic Proxy Configuration
```java
// Configure proxy in test runner
System.setProperty("http.proxyHost", "proxy.company.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "proxy.company.com");
System.setProperty("https.proxyPort", "8443");
// Exclude internal hosts from proxy
System.setProperty("http.nonProxyHosts", "localhost|*.internal.com|192.168.*");
// Proxy authentication (if required)
System.setProperty("http.proxyUser", "proxyuser");
System.setProperty("http.proxyPassword", System.getenv("PROXY_PASSWORD"));
Karate-Specific Proxy Configuration
Configure proxy settings within Karate tests:
# Configure proxy for specific requests
* configure proxy = 'http://proxy.company.com:8080'
# Proxy with authentication
* configure proxy = { uri: 'http://proxy.company.com:8080', username: 'user', password: 'pass' }
# Conditional proxy based on environment
* def proxyConfig = karate.env == 'corp' ? 'http://proxy.company.com:8080' : null
* configure proxy = proxyConfig
# Disable proxy for specific scenario
* configure proxy = null
```gherkin
### Combined SSL and Proxy Configuration
```javascript
// In karate-config.js
function fn() {
var config = {};
// Configure SSL if in secure environment
if (karate.env == 'secure') {
karate.configure('ssl', {
trustStore: 'classpath:certs/truststore.jks',
trustStorePassword: karate.properties['ssl.trustpass'],
keyStore: 'classpath:certs/client.p12',
keyStorePassword: karate.properties['ssl.keypass'],
keyStoreType: 'PKCS12'
});
}
// Configure proxy if behind corporate firewall
if (karate.properties['use.proxy'] == 'true') {
config.proxyUrl = karate.properties['proxy.url'] || 'http://proxy:8080';
karate.configure('proxy', config.proxyUrl);
}
return config;
}
Troubleshooting SSL and Proxy Issues
# Debug SSL handshake issues
* configure ssl = true
* configure logPrettyRequest = true
* configure logPrettyResponse = true
# Test proxy connectivity
Scenario: Verify proxy configuration
* url 'http://httpbin.org/ip'
* method get
* status 200
* print 'Response from proxy:', response
# Debug certificate issues
Scenario: Test SSL connection
* configure ssl = { trustAll: true } # Temporary for debugging only!
* url 'https://secure-api.example.com'
* method get
* print 'SSL connection successful'
```gherkin
> **Warning**: Never use `trustAll: true` in production. It disables certificate validation and exposes you to man-in-the-middle attacks.
### Environment-Specific Configuration
```bash
# Development (no proxy, self-signed certs)
mvn test -Dkarate.env=dev \
-Djavax.net.ssl.trustStore=dev-truststore.jks
# Staging (corporate proxy)
mvn test -Dkarate.env=staging \
-Dhttp.proxyHost=proxy.staging.com \
-Dhttp.proxyPort=8080
# Production (mutual TLS, no proxy)
mvn test -Dkarate.env=prod \
-Djavax.net.ssl.keyStore=prod-client.p12 \
-Djavax.net.ssl.keyStorePassword="${PROD_CERT_PASS}"
```gherkin
## Next Steps
- Learn about [Headers and Authentication](/docs/http-requests/headers-auth) for secure API testing
- Explore [Request Body](/docs/http-requests/request-body) for complex payloads
- Understand [File Uploads](/docs/http-requests/file-uploads) for multipart requests