README.md

# Dream Mock Server

A general-purpose HTTP mock server developed by Dream that provides both streaming and non-streaming endpoints for testing HTTP clients.

## Overview

This module provides a comprehensive set of endpoints for testing HTTP clients:

- **Non-streaming endpoints** - Standard REST-like endpoints (GET, POST, PUT, DELETE)
- **Streaming endpoints** - Various streaming behaviors for testing chunked responses

All endpoints are deterministic and designed for testing, making them ideal for:

- **Testing** - Use as a test fixture for HTTP client integration tests
- **Demo** - Showcase Dream's HTTP capabilities with predictable behavior
- **Learning** - Study different HTTP patterns and error handling

## Running

### Standalone Mode

Start the server on port 3004:

```bash
make run
```

Then access endpoints at `http://localhost:3004/`

### Programmatic Mode

Use in tests or other applications:

```gleam
import dream_mock_server/server

pub fn my_test() {
  let assert Ok(handle) = server.start(3004)
  
  // Make HTTP requests to localhost:3004
  // ... test logic ...
  
  server.stop(handle)
}
```

## Non-Streaming Endpoints

### `GET /get`

**Returns JSON with request info**

- Returns: `{"method": "GET", "url": "/get", "headers": []}`
- Status: 200 OK
- Content-Type: `application/json`

**Use for:** Testing GET requests, JSON parsing

### `POST /post`

**Echoes request body as JSON**

- Returns: `{"method": "POST", "url": "/post", "data": "<request body>"}`
- Status: 201 Created
- Content-Type: `application/json`

**Use for:** Testing POST requests, request body handling

### `PUT /put`

**Echoes request body as JSON**

- Returns: `{"method": "PUT", "url": "/put", "data": "<request body>"}`
- Status: 200 OK
- Content-Type: `application/json`

**Use for:** Testing PUT requests

### `DELETE /delete`

**Returns success response**

- Returns: `{"method": "DELETE", "url": "/delete"}`
- Status: 200 OK
- Content-Type: `application/json`

**Use for:** Testing DELETE requests

### `GET /json`

**Returns simple JSON object**

- Returns: `{"message": "Hello, World!", "success": true}`
- Status: 200 OK
- Content-Type: `application/json`

**Use for:** Testing JSON parsing, simple responses

### `GET /text`

**Returns plain text**

- Returns: `"Hello, World!"`
- Status: 200 OK
- Content-Type: `text/plain`

**Use for:** Testing text responses

### `GET /uuid`

**Returns UUID-like string**

- Returns: `{"uuid": "123e4567-e89b-12d3-a456-426614174000"}`
- Status: 200 OK
- Content-Type: `application/json`

**Use for:** Testing small JSON responses

### `GET /`

**Info page** - Lists all available endpoints with descriptions

**Use for:** Documentation, service discovery

## Streaming Endpoints

### `GET /stream/fast`

**10 chunks at 100ms intervals**

- Fast streaming for quick response handling
- Total duration: ~1 second
- Each chunk: `"Chunk N\n"`

**Use for:** Testing fast streaming, basic functionality

### `GET /stream/slow`

**5 chunks at 2s intervals**

- Slow streaming for timeout handling
- Total duration: ~10 seconds
- Each chunk: `"Chunk N\n"`

**Use for:** Testing timeout handling, long-running streams

### `GET /stream/burst`

**7 chunks with variable delays (100-500ms)**

- Deterministic burst pattern for robustness testing
- Delays: `[100, 500, 200, 400, 100, 300, 200]` ms
- Each chunk: `"Burst N\n"`

**Use for:** Testing variable timing patterns, buffering behavior

### `GET /stream/error`

**3 chunks then 500 status**

- Returns HTTP 500 with partial content
- Simulates mid-stream error
- Each chunk: `"Error test chunk N\n"`

**Use for:** Testing error handling mid-stream

### `GET /stream/huge`

**100 chunks with 10ms delays**

- Large response for memory/performance testing
- Total duration: ~1 second
- Each chunk: `"Huge chunk N\n"`

**Use for:** Memory efficiency, performance testing

### `GET /stream/json`

**5 JSON objects at 200ms intervals**

- Structured data streaming
- Each chunk: `{"event":"chunk","number":N,"message":"JSON event N"}\n`
- Content-Type: `application/json`

**Use for:** Testing structured data streaming, JSON handling

### `GET /stream/binary`

**256 binary chunks with byte patterns**

- Non-text streaming
- Each chunk: 4 bytes with repeating pattern
- Content-Type: `application/octet-stream`

**Use for:** Testing binary data streaming

## Integration Tests

Run Cucumber integration tests:

```bash
make test-integration
```

Tests verify:
- All endpoints return correct status codes
- Content format and structure
- Chunk counts and timing
- Error handling
- JSON validity

## Usage Modes

### 1. Standalone Server

Fixed port 3004, runs indefinitely:

```bash
make run
```

### 2. Programmatic Control

Start/stop programmatically for tests:

```gleam
import dream_mock_server/server

// Start server
let assert Ok(handle) = server.start(3004)

// Use server...

// Stop server
server.stop(handle)
```

### 3. Integration Testing

Used by Dream's HTTP client tests:

```gleam
// In modules/http_client/test/integration_test.gleam
import dream_mock_server/server

pub fn concurrent_streams_test() {
  let assert Ok(mock) = server.start(3004)
  
  // Test HTTP client against localhost:3004
  // ...
  
  server.stop(mock)
}
```

## Implementation Details

### Streaming Technique

Streaming endpoints use Dream's `response.stream_response()`:

```gleam
import dream/http/response.{stream_response}
import dream/http/status
import gleam/yielder
import gleam/erlang/process

pub fn stream_fast(...) -> Response {
  let stream =
    yielder.range(1, 10)
    |> yielder.map(fn(n) {
      process.sleep(100)
      let line = "Chunk " <> int.to_string(n) <> "\n"
      bit_array.from_string(line)
    })

  stream_response(status.ok, stream, "text/plain")
}
```

### Non-Streaming Technique

Non-streaming endpoints use standard `json_response()` and `text_response()`:

```gleam
import dream/http/response.{json_response}
import dream/http/status
import gleam/json

pub fn get(...) -> Response {
  let body =
    json.object([
      #("method", json.string("GET")),
      #("url", json.string(request.path)),
    ])
    |> json.to_string
  
  json_response(status.ok, body)
}
```

### Timing Control

Streaming endpoints use `process.sleep()` between chunks for deterministic timing:

- **Fast**: 100ms delays
- **Slow**: 2000ms delays
- **Burst**: Variable 100-500ms delays
- **Huge**: 10ms delays (optimized for throughput)

### Error Simulation

The `/stream/error` endpoint demonstrates mid-stream errors by returning a 500 status with partial content. This tests client error handling during streaming.

## Architecture

```
src/
├── main.gleam                    # Standalone entry point (port 3004)
├── dream_mock_server/
│   ├── server.gleam             # Programmatic start/stop functions
│   ├── router.gleam             # Route definitions
│   ├── controllers/
│   │   ├── api_controller.gleam      # Non-streaming endpoints
│   │   └── stream_controller.gleam   # Streaming endpoints
│   └── views/
│       └── index_view.gleam          # Info page HTML
```

## Dependencies

- **Dream** - Web framework
- **gleam_erlang** - Process control (sleep)
- **gleam_json** - JSON encoding
- **gleam_yielder** - Stream generation

## See Also

- [Dream Streaming Guide](../../docs/guides/streaming.md)
- [HTTP Client Module](../../modules/http_client/)
- [Streaming Capabilities Example](../streaming_capabilities/)