Skip to main content

HTTP RESPONSES

Response Handling

Access HTTP response data using built-in variables for status, headers, cookies, and timing—automatically populated after every request without manual parsing.

Benefits of Response Handling

  • Automatic population: All response variables populated instantly after each request
  • Type-safe access: Parsed response bodies with built-in JSON, XML, and binary support
  • Zero configuration: Access status, headers, cookies, and timing without setup

Response Body

Access the main response body with automatic parsing based on content type:

Feature: JSON response access

Scenario: Access response fields
Given url baseUrl
And path 'users', 123
When method get
Then status 200
* def userName = response.name
* def userEmail = response.profile.email
* match userName == '#string'

Use JsonPath shortcuts for concise property access:

Feature: JsonPath shortcuts

Scenario: Shorthand response access
Given url baseUrl
And path 'users', 123
When method get
Then status 200
* def name = $.name
* def email = $.profile.email
* match name == '#string'

Response Status

Access and validate HTTP status codes for conditional logic:

Feature: Status code handling

Scenario: Status validation
Given url baseUrl
And path 'users'
When method get
Then status 200
* def statusCode = responseStatus
* assert statusCode == 200
* match [200, 201, 204] contains responseStatus

Status-Based Conditional Logic

Handle different status codes with conditional logic:

Feature: Status-based logic

Scenario: Handle multiple statuses
Given url baseUrl
And path 'api/might-fail'
When method get
* if (responseStatus == 200)
"""
* match response.data == '#array'
* print 'Success: found', response.data.length, 'items'
"""
* if (responseStatus == 404)
"""
* match response.error == 'not_found'
* print 'Resource not found'
"""

Response Headers

Access response headers with case-insensitive helper method:

Feature: Header access

Scenario: Read response headers
Given url baseUrl
And path 'api/data'
When method get
Then status 200
* def contentType = karate.response.header('content-type')
* def cacheControl = karate.response.header('Cache-Control')
* match contentType == 'application/json'

Extract custom headers for tracking and debugging:

Feature: Custom header extraction

Scenario: Extract tracking headers
Given url baseUrl
And path 'api/tracking'
When method get
Then status 200
* def requestId = karate.response.header('X-Request-ID')
* def processingTime = karate.response.header('X-Processing-Time')
* print 'Request ID:', requestId
* print 'Processing time:', processingTime, 'ms'
* assert parseInt(processingTime) < 5000
Header Access
  • Use karate.response.header() for case-insensitive header access (recommended)
  • responseHeaders map is case-sensitive and returns arrays - access with [0] index
  • Example: responseHeaders['Content-Type'][0] vs karate.response.header('content-type')

Response Cookies

Extract and validate cookies from authentication and session management:

Feature: Cookie handling

Scenario: Extract session cookies
Given url baseUrl
And path 'auth/login'
And request { username: 'test', password: 'secret' }
When method post
Then status 200
* def sessionId = responseCookies['JSESSIONID'].value
* def csrfToken = responseCookies['csrf-token'].value
* match responseCookies contains { 'JSESSIONID': '#notnull' }

Access cookie properties for validation:

Feature: Cookie properties

Scenario: Validate cookie attributes
Given url baseUrl
And path 'auth/login'
And request { username: 'test', password: 'secret' }
When method post
Then status 200
* def sessionCookie = responseCookies['JSESSIONID']
* print 'Cookie domain:', sessionCookie.domain
* print 'Cookie path:', sessionCookie.path
* assert sessionCookie.value.length > 0

Response Performance

Monitor response times for performance validation and SLA compliance:

Feature: Performance monitoring

Scenario: Response time validation
Given url baseUrl
And path 'api/fast-endpoint'
When method get
Then status 200
And assert responseTime < 1000
* def executionTime = responseTime
* print 'API response time:', executionTime, 'ms'

Use response timing for conditional validation:

Feature: Performance-based logic

Scenario: Conditional performance checks
Given url baseUrl
And path 'api/variable-performance'
When method get
Then status 200
* if (responseTime < 500)
"""
* print 'Fast response detected'
"""
* if (responseTime > 2000)
"""
* print 'Slow response detected'
* match response.error == null
"""

Binary Response Data

Handle binary content like files, images, and PDFs:

Feature: Binary handling

Scenario: File download validation
Given url baseUrl
And path 'files/download', fileId
When method get
Then status 200
* def fileSize = responseBytes.length
* assert fileSize > 1000
* match responseBytes == read('expected-file.pdf')
* karate.write(responseBytes, 'target/downloaded-file.pdf')

Validate image downloads:

Feature: Image validation

Scenario: Image download
Given url baseUrl
And path 'images', imageId
When method get
Then status 200
* def imageSize = responseBytes.length
* assert imageSize > 0
* assert karate.response.header('Content-Type').startsWith('image/')
* print 'Downloaded image size:', imageSize, 'bytes'

Response Type Detection

Understand how Karate parsed the response for dynamic handling:

Feature: Content type detection

Scenario: Check response type
Given url baseUrl
And path 'api/users'
When method get
Then status 200
And match responseType == 'json'
* match response == '#object'

Handle mixed response types dynamically:

Feature: Dynamic type handling

Scenario: Process different formats
Given url baseUrl
And path 'api/flexible-endpoint'
And param format = 'json'
When method get
Then status 200
* if (responseType == 'json')
"""
* match response.data == '#array'
* def itemCount = response.data.length
"""
* if (responseType == 'xml')
"""
* def itemCount = karate.get('response/data/items').length
"""
* print 'Processed', itemCount, 'items'

XML Response Handling

Access XML responses using XPath expressions:

Feature: XML response access

Scenario: XPath shortcuts
Given url baseUrl
And path 'soap/users'
And request <getUserRequest><id>123</id></getUserRequest>
When soap action 'GetUser'
Then status 200
* def userId = /user/id
* def userName = /user/name
* match userId == '123'
* match userName == '#string'

Request Timing

Access the timestamp when the request was initiated for advanced timing analysis:

Feature: Request timestamp tracking

Scenario: Track request timing
* def startTime = new Date().getTime()

Given url baseUrl
And path 'api/slow-operation'
When method get
Then status 200
* def endTime = new Date().getTime()
* def clientSideTime = endTime - startTime
* print 'Client-side timing:', clientSideTime, 'ms'
* print 'Response time from Karate:', responseTime, 'ms'
* assert clientSideTime >= responseTime

Complete Response Context

Access all response variables together for comprehensive logging and debugging:

Feature: Complete response context

Scenario: Access all response variables
Given url baseUrl
And path 'api/complete-test'
When method get
Then status 200
* print 'Response Status:', responseStatus
* print 'Response Type:', responseType
* print 'Response Time:', responseTime, 'ms'
* def headerCount = Object.keys(responseHeaders).length
* print 'Response headers count:', headerCount
* def cookieNames = Object.keys(responseCookies)
* print 'Response cookies:', cookieNames
* def responseSummary = {
status: responseStatus,
type: responseType,
timing: responseTime,
headerCount: headerCount
}
* print 'Response summary:', responseSummary
Response Variable Lifecycle
  • Response variables are overwritten after each HTTP request
  • Store values in custom variables if you need them after subsequent requests
  • Cookies from responseCookies are automatically sent in future requests
  • Check responseType to determine how Karate parsed the response body

Next Steps

Master response handling and continue with: