HTTP REQUESTS
Request Body
Overview
Karate makes it easy to work with various request body formats including JSON, XML, GraphQL, and form data. The framework's native support for complex data types eliminates the need for string manipulation and escaping.
JSON Request Bodies
Inline JSON
# Simple JSON object
* request { name: 'John', age: 30 }
# Complex nested structure
* request {
user: {
name: 'Alice',
profile: {
email: 'alice@example.com',
preferences: { theme: 'dark' }
}
},
metadata: { created: '2024-01-01' }
}
```gherkin
### JSON from Variables
```gherkin
# Define and use JSON variable
* def userData = {
id: 123,
name: 'Bob',
roles: ['user', 'admin']
}
* request userData
# Modify before sending
* def template = { name: '', email: '', active: true }
* set template.name = 'Charlie'
* set template.email = 'charlie@example.com'
* request template
```gherkin
### Dynamic JSON Construction
```gherkin
# Using embedded expressions
* def userId = 123
* def timestamp = new Date().getTime()
* request {
id: '#(userId)',
name: '#(userName)',
created: '#(timestamp)',
metadata: '#({ source: "api", version: 2 })'
}
# Using JavaScript functions
* def generateUser = function(name) {
return {
id: java.util.UUID.randomUUID() + '',
name: name,
created: new Date().toISOString()
}
}
* request generateUser('David')
```gherkin
### JSON from Files
```gherkin
# Read from file
* request read('classpath:payloads/user.json')
# With embedded expressions
* def userId = 123
* request read('user-template.json') # File can contain #(userId)
# Merge multiple sources
* def base = read('base-request.json')
* def overrides = { status: 'active', priority: 'high' }
* request karate.merge(base, overrides)
```gherkin
## XML Request Bodies
### Inline XML
```gherkin
# Simple XML
* request <user><name>John</name><age>30</age></user>
# Multi-line XML
* request
"""
<user>
<profile>
<name>Alice</name>
<email>alice@example.com</email>
</profile>
<settings>
<notifications>true</notifications>
</settings>
</user>
"""
```gherkin
### XML with Namespaces
```gherkin
# SOAP request with namespaces
* request
"""
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:web="http://www.example.com/webservice">
<soap:Header>
<web:Authentication>
<web:Username>admin</web:Username>
<web:Password>secret</web:Password>
</web:Authentication>
</soap:Header>
<soap:Body>
<web:GetUserRequest>
<web:UserId>123</web:UserId>
</web:GetUserRequest>
</soap:Body>
</soap:Envelope>
"""
```gherkin
### Dynamic XML
```gherkin
# Using embedded expressions
* def orderId = 'ORD-12345'
* def amount = 99.99
* request
"""
<order>
<id>#(orderId)</id>
<amount>#(amount)</amount>
<timestamp>#(new Date().toISOString())</timestamp>
</order>
"""
# Building XML programmatically
* def createOrder = function(id, items) {
return '<order><id>' + id + '</id><items>' +
items.map(function(i){ return '<item>' + i + '</item>' }).join('') +
'</items></order>';
}
* request createOrder('123', ['item1', 'item2'])
```gherkin
## Form Data
### URL-Encoded Forms
```gherkin
# Simple form submission
* path '/login'
* form field username = 'john'
* form field password = 'secret123'
* form field remember = 'true'
* method post
# Multiple fields at once
* form fields { username: 'admin', password: 'admin123', role: 'admin' }
# Dynamic form data
* def loginData = {
username: userEmail,
password: userPassword,
csrf_token: csrfToken
}
* form fields loginData
```gherkin
### Form Arrays and Multi-Values
```gherkin
# Multi-select checkboxes
* form field colors = ['red', 'blue', 'green']
* form field categories = ['electronics', 'books']
# Dynamic multi-values
* def selectedOptions = ['option1', 'option3', 'option5']
* form field selected = selectedOptions
```gherkin
## GraphQL Requests
### Basic GraphQL Query
```gherkin
# Define query
* text query =
"""
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
title
content
}
}
}
"""
# Send request
* def variables = { id: '123' }
* request { query: '#(query)', variables: '#(variables)' }
* method post
```gherkin
### GraphQL Mutations
```gherkin
# Mutation with variables
* text mutation =
"""
mutation CreatePost($input: PostInput!) {
createPost(input: $input) {
id
title
content
author {
name
}
}
}
"""
* def postInput = {
title: 'New Post',
content: 'Post content here',
authorId: '456',
tags: ['tech', 'api']
}
* request {
query: '#(mutation)',
variables: { input: '#(postInput)' }
}
* method post
```gherkin
### GraphQL Fragments
```gherkin
# Using fragments
* text queryWithFragment =
"""
fragment UserFields on User {
id
name
email
}
query GetUsers {
users {
...UserFields
posts {
title
}
}
}
"""
* request { query: '#(queryWithFragment)' }
```gherkin
## Complex Request Patterns
### Conditional Request Bodies
```gherkin
# Build request based on conditions
* def includeMetadata = true
* def baseRequest = { name: 'Test', type: 'basic' }
* if (includeMetadata) karate.set('baseRequest.metadata', { source: 'api' })
* request baseRequest
# Environment-specific payloads
* def payload = karate.env == 'prod'
? { level: 'minimal', safe: true }
: { level: 'debug', safe: false, verbose: true }
* request payload
```gherkin
### Template-Based Requests
```gherkin
# Define reusable template
* def orderTemplate = {
orderId: '#(orderId)',
customer: '#(customerId)',
items: '#(items)',
total: '#(calculateTotal(items))',
timestamp: '#(new Date().toISOString())'
}
# Use template
* def orderId = 'ORD-001'
* def customerId = 'CUST-123'
* def items = [{ id: 'ITEM-1', qty: 2, price: 10.00 }]
* def calculateTotal = function(items) {
return items.reduce(function(sum, item) {
return sum + (item.qty * item.price);
}, 0);
}
* request orderTemplate
```gherkin
### Streaming and Large Payloads
```gherkin
# Large JSON from file
* def largeData = read('classpath:data/large-payload.json')
* request largeData
# Binary data
* def imageBytes = read('classpath:images/test.png')
* request imageBytes
# Streaming text
* def csvData = karate.readAsString('classpath:data/records.csv')
* header Content-Type = 'text/csv'
* request csvData
```gherkin
## Request Body Validation
### Pre-Request Validation
```gherkin
# Validate before sending
* def requestData = { email: userEmail, age: userAge }
* match requestData.email == '#regex .+@.+\\..+'
* assert requestData.age >= 18
* request requestData
# Schema validation
* def schema = { name: '#string', age: '#number', email: '#regex .+@.+' }
* def userData = { name: 'John', age: 25, email: 'john@example.com' }
* match userData == schema
* request userData
```gherkin
### Dynamic Validation
```gherkin
# Validate required fields
* def validateRequest = function(req) {
if (!req.name || req.name.length < 2) {
karate.fail('Name is required and must be at least 2 characters');
}
if (!req.email || !req.email.includes('@')) {
karate.fail('Valid email is required');
}
return true;
}
* def requestData = { name: 'Jo', email: 'john@example.com' }
* eval validateRequest(requestData)
* request requestData
```gherkin
## Performance Optimization
### Request Compression
```gherkin
# Enable gzip compression
* header Content-Encoding = 'gzip'
* header Accept-Encoding = 'gzip, deflate'
* request largePayload
# Compress large JSON
* def compressed = karate.compress(JSON.stringify(largeObject))
* request compressed
```gherkin
### Batch Requests
```gherkin
# Send multiple items in one request
* def items = []
* def createItem = function(i) {
return { id: i, name: 'Item ' + i, value: Math.random() * 100 }
}
* eval for(var i = 0; i < 100; i++) items.push(createItem(i))
* request { batch: items }
```gherkin
### Efficient Data Generation
```gherkin
# Reuse data structures
Background:
* def baseUser = read('classpath:templates/user.json')
* def generateUser = function(overrides) {
return karate.merge(baseUser, overrides)
}
Scenario: Create multiple users
* def user1 = generateUser({ name: 'Alice' })
* request user1
* method post
* def user2 = generateUser({ name: 'Bob', role: 'admin' })
* request user2
* method post
```gherkin
## Best Practices
### Request Organization
```gherkin
# ✅ Good: Clear structure
* def requestBody = {
user: buildUser(),
metadata: getMetadata(),
options: { validate: true }
}
* request requestBody
# ❌ Avoid: Inline complexity
* request { user: { name: getName(), email: getEmail(), profile: { ... } } }
```gherkin
### Error Prevention
```gherkin
# ✅ Good: Validate data types
* def age = parseInt(ageString)
* def price = parseFloat(priceString)
* request { age: age, price: price }
# ✅ Good: Handle nulls
* def optionalField = karate.get('optionalData', {})
* request { required: 'value', optional: optionalField }
```gherkin
### Maintainability
```gherkin
# ✅ Good: Use meaningful variable names
* def customerProfile = buildCustomerProfile()
* def orderDetails = createOrderDetails()
* request { customer: customerProfile, order: orderDetails }
# ✅ Good: Document complex logic
* def calculateDiscount = function(price, tier) {
// Premium tier gets 20%, regular gets 10%
return tier === 'premium' ? price * 0.8 : price * 0.9;
}
```gherkin
## Next Steps
- Learn about [File Uploads](/docs/http-requests/file-uploads) for multipart requests
- Explore [Response Handling](/docs/http-responses/status-codes) for validation
- Understand [Assertions](/docs/assertions/match-keyword) for response testing