Request Configuration

The request block defines the outgoing HTTP request. Gherkio supports full-featured HTTP client configurations including custom verbs, header maps, service targeting, and flexible request body encodings.


🌐 HTTP Request Key Reference

KeyTypeRequiredDescriptionExample
methodstringYesHTTP Method (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)method: GET
urlstringYesTarget path (relative to baseUrl) or fully qualified absolute URLurl: /v1/profile
querymap[string]stringNoQuery parameters appended to the URL. Supports variable interpolation in values.query: { status: available, limit: "10" }
servicestringNoTarget service key to override default baseUrlservice: payment
headersobjectNoMap of custom key-value HTTP headersheaders: { Content-Type: application/json }
bodyanyNoRequest payload. Can be JSON objects, lists, strings, or numbers(See below)
timeoutstringNoRequest-specific HTTP timeout overridetimeout: 45s

🛠️ Detailed Usage & Examples

Targeting Specific Services

If your system uses a microservice architecture, map service endpoints in your environment file (e.g. environments/staging.yaml):

baseUrl: https://staging.host.com
services:
  users: https://users-staging.host.com
  billing: https://billing-staging.host.com
```text

Invoke service routing in your YAML request:
```yaml
steps:
  - request:
      service: users            # Resolves to https://users-staging.host.com/v1/profile
      method: GET
      url: /v1/profile
```text

### JSON Request Payload

JSON bodies are defined natively in Gherkio YAML and fully support runtime variable interpolation:

```yaml
steps:
  - request:
      method: POST
      url: /register
      headers:
        Content-Type: application/json
      body:
        username: $randomEmail   # Interpolated using built-in generator
        profile:
          firstName: "John"
          lastName: "Doe"
          age: ${randomInt(18,65)}
```text

### Query Parameters (`query`)

Use the `query` block to append URL query parameters instead of embedding them directly in the URL string. This keeps URLs clean and allows variable interpolation for dynamic values:

```yaml
steps:
  - request:
      method: GET
      url: /pets/findByStatus
      query:
        status: available
        limit: "10"
    expect:
      status: 200
```text

Query parameter values support full variable interpolation:

```yaml
steps:
  - request:
      method: GET
      url: /users
      query:
        role: $userRole
        page: "${randomInt(1,5)}"
    expect:
      status: 200
```text

---

### Multipart Form Data (`multipart`)

To test form-based submissions or file uploads, Gherkio features an elegant `multipart` block. When `multipart` is defined, Gherkio automatically builds the boundary formatting and sets the proper standard HTTP header (`multipart/form-data; boundary=...`) for you.

You can mix raw fields and multiple file attachments inside a single payload:

```yaml
steps:
  - request:
      method: POST
      url: /v1/user/profile
      multipart:
        fields:
          username: "john_doe"
          role: $accounts.admin.role   # Support dynamic variables
        files:
          # 1. Simple path string syntax:
          avatar: "assets/john-avatar.png"
          
          # 2. Advanced schema mapping (with custom MIME types and filenames):
          document:
            path: "assets/resume.pdf"
            contentType: "application/pdf"
            filename: "john_doe_cv.pdf"
    expect:
      status: 200
      body.updated: true
```text

#### 📁 Assets Directory Location & Project Tree

File attachments specified under `multipart.files` are resolved relative to your project workspace root directory (the parent directory of `.gherkio/`). By convention, create an `assets/` directory at your project root to store test media files (images, avatars, PDFs):

You can configure that default directory in `.gherkio/config.yaml`:

```yaml
assets:
  path: assets
```text

The path is relative to the project root, although an absolute directory is also accepted. With this configuration, a multipart value such as `avatar: "john-avatar.png"` resolves to `<projectRoot>/assets/john-avatar.png`. If `assets.path` is omitted, the existing project-root and fixtures lookup behavior remains unchanged.

```text
my-api-tests/                      <-- Project Workspace Root
├── .gherkio/                      <-- Gherkio Test Engine Config & Suites
│   ├── config.yaml
│   ├── environments/
│   │   └── local.yaml
│   └── tests/
│       └── user/
│           └── upload-avatar.yaml
└── assets/                        <-- Assets Directory for Multipart File Uploads
    ├── john-avatar.png
    ├── sample-image.jpg
    └── resume.pdf
```text

#### Custom Assets Directory

To keep upload fixtures inside `.gherkio`, set a custom path relative to the project root:

```yaml
# .gherkio/config.yaml
assets:
  path: .gherkio/test-assets
```text

The corresponding project structure is:

```text
my-api-tests/
└── .gherkio/
    ├── config.yaml
    ├── test-assets/
    │   ├── avatars/
    │   │   └── john.png
    │   └── documents/
    │       └── resume.pdf
    └── tests/
        └── upload.yaml
```text

Files are then referenced relative to the configured directory:

```yaml
multipart:
  files:
    avatar: "avatars/john.png"
    resume:
      path: "documents/resume.pdf"
      contentType: "application/pdf"
```text

The resolved paths are `.gherkio/test-assets/avatars/john.png` and `.gherkio/test-assets/documents/resume.pdf` under the project root.

An absolute assets directory is also supported when the files live outside the project:

```yaml
assets:
  path: /opt/gherkio/shared-assets
```text

In that case, `avatar: "avatars/john.png"` resolves to `/opt/gherkio/shared-assets/avatars/john.png`. Absolute paths make a configuration machine-specific, so relative paths are preferable for repositories and CI environments.

#### 💡 Key Details & File Path Resolution:

- **`multipart.fields`**: A flat map of key-value string pairs representing text form fields.
- **`multipart.files`**: A map of files. The field key is the form property name (e.g. `avatar`).
- **Flexible Directory Paths**: You can configure **any custom directory or path name** in your scenario step (e.g. `"assets/avatar.png"`, `"media/uploads/doc.pdf"`, or `"fixtures/test.csv"`).
- **Configured Assets Directory**: A bare relative file such as `"avatar.png"` is also looked up under the optional `assets.path` from `.gherkio/config.yaml`.
- **Search & Resolution Order**: When resolving a file, Gherkio automatically looks up the file in the following order:
  1. **Absolute Path**: If an absolute path is specified (e.g. `/tmp/test-image.png`)
  2. **Declared Path**: `<projectRoot>/<declared-path>` (e.g. `my-project/assets/john-avatar.png` or `my-project/custom-folder/file.jpg`)
  3. **Configured Assets Directory**: `<projectRoot>/<assets.path>/<declared-path>` when configured
  4. **Project Fixtures Fallback**: `<projectRoot>/fixtures/<filename>`
  5. **Gherkio Fixtures Fallback**: `<projectRoot>/.gherkio/fixtures/<filename>`
  6. **Current Working Directory**: Relative path from where `gherkio run` was executed.
- **MIME Type**: The simple string syntax uses `application/octet-stream`. Use the advanced map syntax (`path`, `contentType`, `filename`) when the receiving API requires a specific MIME type such as `image/png` or `application/pdf`.



---

### 🔄 Declarative Collection Projections (`transform`)

Gherkio allows you to dynamically filter, slice, project, and reshape array collections from your saved variables directly into your request payload target path before the HTTP request is dispatched.

#### Transform Block Key Reference:
| Key | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `from` | `string` | Yes | The source collection variable name (must start with `$`). |
| `as` | `string` | No | Variable alias to represent each element context during transformation (defaults to `"item"`). |
| `where` | `object` | No | Map of filters applying standard Gherkio matchers. |
| `limit` | `int` | No | Maximum count of matching projected elements to output. |
| `select` | `object` | Yes | Custom structural schema mapping. Supports recursive/nested projection maps. |

#### ⚡ Explicit Type Casting inside Projections
When mapping data from target APIs to your request payloads, different endpoints might expect different types. Gherkio provides explicit type-casting functions inside the projection's `select` block:
*   **`$string(var)`**: Converts a field to a string (e.g., `$string(item.id)` turns `1001` to `"1001"`).
*   **`$int(var)`**: Coerces/parses a field value into an integer.
*   **`$float(var)`**: Coerces/parses a field value into a float64.
*   **`$bool(var)`**: Coerces/parses truthy string or integer values into a boolean.

#### 🌀 Conditional Value Selection (`$if`)
Values can vary conditionally using the **`$if(condition, thenValue, elseValue)`** function. This works inside transform `select` blocks and also directly in request `body` strings.

*   **`condition`**: A scoped variable path to evaluate for truthiness (e.g. `item.is_answered` or `is_active`).
*   **`thenValue`**: Value expression used when the condition is truthy.
*   **`elseValue`**: Value expression used when the condition is falsy (optional — if omitted, evaluates to `null`).

Truthiness rules: `nil`, `false`, `0`, and `""` are falsy; all other values are truthy.

**Inside transform `select` (scoped to item alias):**
```yaml
select:
  # Map different fields based on question type
  answer_value: "$if(q.is_answered, q.free_text_answer, q.default_answer)"
  
  # Use type casting inside conditionals
  quantity: "$if(item.in_stock, $int(item.qty), 0)"
  
  # No else clause — returns null when condition is falsy
  optional_field: "$if(item.has_value, item.value)"
```text

**Inside request `body` (use `$` prefix for variable references):**
```yaml
body:
  # Conditionally map based on a saved variable
  status: "$if(is_admin, $admin_endpoint, $user_endpoint)"
  
  # Use type casting with conditionals
  count: "$if(has_items, $int(item_count), 0)"
```text

#### Complete Example:
```yaml
steps:
  # Step 1: Fetch details
  - request:
      method: GET
      url: /surveys/132
    save:
      raw_questions: body.questions

  # Step 2: Reshape and submit survey answers
  - request:
      method: POST
      url: /surveys/132/submit
      body:
        survey_id: 132
      transform:
        # Dynamically inject the projected array under body.answers
        answers:
          from: $raw_questions
          as: q
          where:
            q.is_required: true
          limit: 10
          select:
            # Explicitly cast integer id from details response to string for submission!
            question_id: "$string(q.id)"
            
            # Coerce the sequence number to integer
            seq: "$int(q.seq)"
            
            # Static values and clean variable mapping
            is_answered: true
            free_text_answer: q.user_response
```text


---

### 💡 Type Preservation & Explicit Casting in Standard Bodies

Outside of the `transform` projection block, Gherkio automatically preserves the original type of standalone variables mapped inside the HTTP request `body`:
*   If you map a saved integer variable: `employee_id: $employee_id`, Gherkio keeps the value as a JSON number (`1234`) in the outgoing request payload.
*   If you explicitly want to coerce it to a string (or other types), wrap the variable in a casting operator inside the request body:
    ```yaml
    body:
      emp_id: "$string(employee_id)"   # Outgoing payload: "emp_id": "1234"
      status: "$bool(is_active)"       # Outgoing payload: "status": true
    ```