Files
WireMock.Net/copilot/WebSockets/v1/WEBSOCKET_VISUAL_OVERVIEW.md
Stef Heyenrath a3da39a9ec ws1
2026-02-08 10:30:59 +01:00

25 KiB

WebSocket Implementation - Visual Architecture Overview

System Architecture Diagram

┌─────────────────────────────────────────────────────────────────┐
│                    WireMock.Net Solution                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ Abstraction Layer (WireMock.Net.Abstractions)           │   │
│  ├──────────────────────────────────────────────────────────┤   │
│  │ • IRequestBuilder                                        │   │
│  │   ├─ WithPath(), WithHeader(), UsingGet(), ...          │   │
│  │   └─ WithWebSocketPath() [NEW]                          │   │
│  │   └─ WithWebSocketSubprotocol() [NEW]                   │   │
│  │                                                          │   │
│  │ • IResponseBuilder                                       │   │
│  │   ├─ WithStatusCode(), WithBody(), WithCallback()       │   │
│  │   └─ WithWebSocket() [NEW]                              │   │
│  │   └─ WithWebSocketCallback() [NEW]                      │   │
│  │                                                          │   │
│  │ • IWebSocketResponseBuilder [NEW]                       │   │
│  │   ├─ WithMessage(string)                                │   │
│  │   ├─ WithJsonMessage(object)                            │   │
│  │   ├─ WithBinaryMessage(byte[])                          │   │
│  │   └─ WithTransformer()                                  │   │
│  └──────────────────────────────────────────────────────────┘   │
│                          ▲                                       │
│                          │ implements                            │
│                          │                                       │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ Implementation Layer (WireMock.Net.Minimal)             │   │
│  ├──────────────────────────────────────────────────────────┤   │
│  │                                                          │   │
│  │ Request Building                                        │   │
│  │ ├─ Request.cs (core builder)                            │   │
│  │ ├─ Request.With*.cs (HTTP extensions)                   │   │
│  │ └─ Request.WithWebSocket.cs [NEW]                       │   │
│  │                                                          │   │
│  │ Response Building                                       │   │
│  │ ├─ Response.cs (core builder)                           │   │
│  │ ├─ Response.With*.cs (HTTP extensions)                  │   │
│  │ ├─ Response.WithWebSocket.cs [NEW]                      │   │
│  │ └─ WebSocketResponseBuilder.cs [NEW]                    │   │
│  │                                                          │   │
│  │ Domain Models                                           │   │
│  │ ├─ RequestMessage, ResponseMessage (existing)           │   │
│  │ ├─ WebSocketMessage [NEW]                               │   │
│  │ └─ WebSocketResponse [NEW]                              │   │
│  │                                                          │   │
│  │ Mapping Management                                      │   │
│  │ ├─ MappingBuilder.cs                                    │   │
│  │ ├─ RespondWithAProvider.cs                              │   │
│  │ └─ Mapping.cs                                           │   │
│  │                                                          │   │
│  │ Server Integration [NEW]                                │   │
│  │ ├─ WireMockServer.cs (update for WebSocket)             │   │
│  │ ├─ WireMockMiddleware.cs (upgrade handler)              │   │
│  │ ├─ MappingMatcher.cs (WebSocket routing)                │   │
│  │ └─ WebSocketConnectionManager [NEW]                     │   │
│  └──────────────────────────────────────────────────────────┘   │
│                          ▲                                       │
│                          │                                       │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ Integration Layers                                       │   │
│  ├──────────────────────────────────────────────────────────┤   │
│  │ • WireMock.Net (extends Minimal)                         │   │
│  │ • WireMock.Net.StandAlone (OWIN hosting)                │   │
│  │ • WireMock.Net.AspNetCore.Middleware (ASP.NET Core)    │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

Request Handling Flow (HTTP vs WebSocket)

HTTP Request Flow

Client                  Server
  │                       │
  ├──── HTTP Request ────>│
  │                       │ Request.Create()
  │                       │   .WithPath("/api")
  │                       │   .UsingPost()
  │                       │ Match request matchers
  │                       │
  │<─── HTTP Response ────┤ Response.Create()
  │                       │   .WithStatusCode(200)
  │                       │   .WithBody(...)
  │                       │
  └───── Connection closed

WebSocket Request Flow

Client                  Server
  │                       │
  ├─ WebSocket Upgrade ──>│
  │ (HTTP with headers)   │ Request.Create()
  │                       │   .WithWebSocketPath("/ws")
  │                       │ Match request matchers
  │                       │
  │<─ 101 Switching ──────┤ Upgrade to WebSocket
  │ Protocols             │
  │                       │
  │ ◄─────── Message 1 ───│ WebSocketResponse
  │                       │   .Messages[0]
  │ ◄─────── Message 2 ───│   .Messages[1]
  │                       │   (delayed 500ms)
  │ ◄─────── Message 3 ───│   .Messages[2]
  │                       │   (delayed 1000ms)
  │                       │
  │ ◄─── Close Frame ─────│ .WithClose(1000)
  │                       │
  └───── Connection closed

Data Model Diagram

HTTP Request/Response Models          WebSocket Models
═══════════════════════════════════   ═══════════════════════════

RequestMessage                        IWebSocketMessage
├─ Path                               ├─ DelayMs
├─ Method (GET, POST, etc.)           ├─ BodyAsString
├─ Headers                            ├─ BodyAsBytes
├─ Body                               ├─ IsText
├─ Query Params                       ├─ Id
└─ Cookies                            └─ CorrelationId

ResponseMessage                       IWebSocketResponse
├─ StatusCode                         ├─ Messages[]
├─ Headers                            │   └─ IWebSocketMessage
├─ Body                               ├─ UseTransformer
├─ BodyAsJson                         ├─ TransformerType
└─ ContentType                        ├─ CloseCode
                                      ├─ CloseMessage
                                      ├─ Subprotocol
                                      └─ AutoCloseDelayMs

                                      WebSocketResponse
                                      (implements IWebSocketResponse)

Builder Pattern Hierarchy

IRequestBuilder (interface)
    ▲
    │
    └── Request (class)
            │
            ├── Request.cs (core)
            ├── Request.WithPath.cs
            ├── Request.WithHeaders.cs
            ├── Request.UsingMethods.cs
            ├── Request.WithBody.cs
            ├── Request.WithParam.cs
            └── Request.WithWebSocket.cs [NEW]
                ├── WithWebSocketUpgrade()
                ├── WithWebSocketPath()
                ├── WithWebSocketSubprotocol()
                ├── WithWebSocketVersion()
                └── WithWebSocketOrigin()


IResponseBuilder (interface)
    ▲
    │
    └── Response (class)
            │
            ├── Response.cs (core)
            ├── Response.WithStatusCode.cs
            ├── Response.WithHeaders.cs
            ├── Response.WithBody.cs
            ├── Response.WithCallback.cs
            ├── Response.WithTransformer.cs
            ├── Response.WithProxy.cs
            ├── Response.WithFault.cs
            └── Response.WithWebSocket.cs [NEW]
                ├── WithWebSocket(builder)
                ├── WithWebSocketMessage()
                ├── WithWebSocketJsonMessage()
                ├── WithWebSocketBinaryMessage()
                ├── WithWebSocketCallback()
                ├── WithWebSocketTransformer()
                ├── WithWebSocketClose()
                ├── WithWebSocketSubprotocol()
                └── WithWebSocketAutoClose()


IWebSocketResponseBuilder (interface) [NEW]
    ▲
    │
    └── WebSocketResponseBuilder (class) [NEW]
            ├── WithMessage()
            ├── WithJsonMessage()
            ├── WithBinaryMessage()
            ├── WithTransformer()
            ├── WithClose()
            ├── WithSubprotocol()
            ├── WithAutoClose()
            └── Build() → IWebSocketResponse

Mapping Configuration Chain

server.Given(request)
    ↓
IRespondWithAProvider
    ├── AtPriority(int)          ✓ HTTP & WebSocket
    ├── WithTitle(string)         ✓ HTTP & WebSocket
    ├── WithDescription(string)   ✓ HTTP & WebSocket
    ├── WithPath(string)          ✓ HTTP & WebSocket
    ├── InScenario(string)        ✓ HTTP & WebSocket
    ├── WhenStateIs(string)       ✓ HTTP & WebSocket
    ├── WillSetStateTo(string)    ✓ HTTP & WebSocket
    ├── WithWebhook(...)          ✓ HTTP & WebSocket
    ├── WithTimeSettings(...)     ✓ HTTP & WebSocket
    ├── WithGuid(Guid)            ✓ HTTP & WebSocket
    ├── WithData(object)          ✓ HTTP & WebSocket
    └── RespondWith(provider)
         ↓
         IResponseProvider
         ├── Response (HTTP)
         │   ├── WithStatusCode()
         │   ├── WithBody()
         │   ├── WithCallback()
         │   └── ...
         └── Response (WebSocket) [NEW]
             ├── WithWebSocket()
             ├── WithWebSocketCallback()
             └── ...

Fluent API Method Chains

Simple Echo Server

Request.Create()
    .WithWebSocketPath("/echo")
        ↓
Response.Create()
    .WithWebSocketCallback(async request =>
        new[] { new WebSocketMessage { BodyAsString = request.Body } }
    )

Stream with Multiple Messages

Request.Create()
    .WithWebSocketPath("/stream")
        ↓
Response.Create()
    .WithWebSocket(ws => ws
        .WithMessage("Start", 0)
        .WithMessage("Middle", 500)
        .WithMessage("End", 1000)
        .WithClose(1000, "Complete")
    )

Dynamic with Templates

Request.Create()
    .WithWebSocketPath("/api")
    .WithWebSocketSubprotocol("v2")
        ↓
Response.Create()
    .WithWebSocketSubprotocol("v2")
    .WithWebSocket(ws => ws
        .WithJsonMessage(new { 
            user = "{{request.headers.X-User}}" 
        })
        .WithTransformer()
    )

Transformer Integration

WebSocket Response
    ├─ Raw Content
    │   └─ "Hello {{user}}, timestamp: {{now}}"
    │
    └─ WithTransformer() [Enable Handlebars/Scriban]
        ↓
        Transformer Engine (existing)
        ├─ Request context injection
        ├─ Helper methods (Math, String, etc.)
        └─ Custom helpers
            ↓
        Transformed Content
        └─ "Hello Alice, timestamp: 2024-01-15T10:30:00Z"

Message Delivery Timeline

Client connects → WebSocket Upgrade
                     ↓
              Message Queue Created
                     ↓
┌──────────────────────────────────────────────────────────┐
│ Message 1 (delayMs: 0)                                   │
│ ═════════════════════════════════════════════════════► │
│ Sent immediately                                         │
└──────────────────────────────────────────────────────────┘
            ↓ (wait 500ms)
┌──────────────────────────────────────────────────────────┐
│ Message 2 (delayMs: 500)                                 │
│                 ═════════════════════════════════════► │
│ Sent at T+500ms                                          │
└──────────────────────────────────────────────────────────┘
            ↓ (wait 1000ms from start)
┌──────────────────────────────────────────────────────────┐
│ Message 3 (delayMs: 1000)                                │
│                         ═════════════════════════════► │
│ Sent at T+1000ms                                         │
└──────────────────────────────────────────────────────────┘
            ↓ (Close connection)
            Close Frame (1000, "Complete")
                     ↓
              Connection Closed

File Organization

src/WireMock.Net.Abstractions/
│
├── Models/
│   ├── IWebSocketMessage.cs [NEW]
│   ├── IWebSocketResponse.cs [NEW]
│   └── ...existing models
│
├── Admin/Mappings/
│   ├── WebSocketModel.cs [NEW]
│   ├── ResponseModel.cs (extend for WebSocket)
│   ├── RequestModel.cs (extend for WebSocket)
│   └── ...existing models
│
├── BuilderExtensions/
│   ├── IWebSocketResponseBuilder.cs [NEW]
│   ├── WebSocketResponseModelBuilder.cs [NEW]
│   └── ...existing builders
│
└── ...rest of abstractions


src/WireMock.Net.Minimal/
│
├── Models/
│   ├── WebSocketMessage.cs [NEW]
│   ├── WebSocketResponse.cs [NEW]
│   └── ...existing models
│
├── RequestBuilders/
│   ├── Request.cs (update interfaces)
│   ├── Request.WithWebSocket.cs [NEW]
│   ├── Request.WithPath.cs
│   ├── Request.WithHeaders.cs
│   └── ...existing builders
│
├── ResponseBuilders/
│   ├── Response.cs (update interfaces)
│   ├── Response.WithWebSocket.cs [NEW]
│   ├── WebSocketResponseBuilder.cs [NEW]
│   ├── Response.WithStatusCode.cs
│   ├── Response.WithBody.cs
│   └── ...existing builders
│
├── Server/
│   ├── WireMockServer.cs (update for WebSocket)
│   ├── WireMockServer.Fluent.cs
│   ├── MappingBuilder.cs
│   ├── RespondWithAProvider.cs
│   └── ...existing server code
│
├── Owin/
│   ├── WireMockMiddleware.cs (add WebSocket upgrade)
│   ├── MappingMatcher.cs (add WebSocket routing)
│   └── ...existing OWIN code
│
└── ...rest of implementation

Dependency Graph

┌─────────────────────────────────────────┐
│ External Dependencies                   │
├─────────────────────────────────────────┤
│ • .NET Standard 2.0 / .NET Framework    │
│ • ASP.NET Core (WebSocket support)      │
│ • Newtonsoft.Json (serialization)       │
│ • Handlebars.Core (transformers)        │
│ • Scriban (transformers)                │
└──────────────────┬──────────────────────┘
                   ▲
                   │
┌──────────────────┴──────────────────────┐
│ WireMock.Net.Abstractions                │
├──────────────────────────────────────────┤
│ • Interfaces (IRequestBuilder, etc.)    │
│ • Models (RequestModel, ResponseModel)  │
│ • WebSocket abstractions [NEW]          │
└──────────────────┬──────────────────────┘
                   ▲
                   │
┌──────────────────┴──────────────────────┐
│ WireMock.Net.Minimal                     │
├──────────────────────────────────────────┤
│ • Request builders                      │
│ • Response builders                     │
│ • WebSocket builders [NEW]              │
│ • Server core                           │
│ • OWIN middleware                       │
└──────────────────┬──────────────────────┘
                   ▲
                   │
┌──────────────────┴──────────────────────┐
│ WireMock.Net (Full)                      │
│ WireMock.Net.StandAlone (OWIN)          │
│ Application Code                         │
└──────────────────────────────────────────┘

Test Coverage Areas

Unit Tests (Request/Response Builders)
├── WebSocketResponseBuilder tests
│   ├── Message ordering
│   ├── Delay handling
│   ├── Transformer support
│   └── Close frame handling
├── Request builder tests
│   ├── WebSocket path matching
│   ├── Subprotocol matching
│   └── Upgrade header validation
└── Integration tests
    ├── Client connection handling
    ├── Message delivery
    ├── Scenario state management
    ├── Concurrent connections
    ├── Connection timeout
    └── Error scenarios

Phase Implementation Timeline

Week 1: Phase 1-2 (Abstractions & Models)
├─ Mon-Tue: Abstractions (IWebSocketMessage, etc.)
├─ Wed: Domain Models (WebSocketMessage, etc.)
└─ Thu: Code review & refinement

Week 2: Phase 3 (Request Builder)
├─ Mon-Tue: Request.WithWebSocket.cs
├─ Wed: Request matching tests
└─ Thu: Integration with server

Week 3: Phase 4 (Response Builder)
├─ Mon-Wed: Response.WithWebSocket.cs
├─ Wed-Thu: WebSocketResponseBuilder
└─ Fri: Message delivery tests

Week 4: Phase 5 (Server Integration)
├─ Mon-Tue: WireMockMiddleware updates
├─ Wed: Connection lifecycle management
├─ Thu: Integration tests
└─ Fri: Documentation & release prep

Quick Reference: What's New vs What's Extended

┌─────────────────────┬─────────────────────┬──────────────────┐
│ Component           │ New [NEW]           │ Extended         │
├─────────────────────┼─────────────────────┼──────────────────┤
│ Request Builder     │ Request.            │ Request.cs       │
│                     │ WithWebSocket.cs    │ (interfaces)     │
├─────────────────────┼─────────────────────┼──────────────────┤
│ Response Builder    │ Response.           │ Response.cs      │
│                     │ WithWebSocket.cs    │ (interfaces)     │
│                     │ WebSocketResponse   │                  │
│                     │ Builder.cs          │                  │
├─────────────────────┼─────────────────────┼──────────────────┤
│ Domain Models       │ WebSocketMessage.cs │ None             │
│                     │ WebSocketResponse.  │                  │
│                     │ cs                  │                  │
├─────────────────────┼─────────────────────┼──────────────────┤
│ Admin API           │ WebSocketModel.cs   │ ResponseModel.cs │
│                     │                     │ RequestModel.cs  │
├─────────────────────┼─────────────────────┼──────────────────┤
│ Server              │ WebSocket           │ WireMock         │
│                     │ ConnectionManager   │ Server.cs        │
│                     │ [NEW]               │ WireMock         │
│                     │                     │ Middleware.cs    │
├─────────────────────┼─────────────────────┼──────────────────┤
│ Interfaces          │ IWebSocketMessage   │ IRequestBuilder  │
│                     │ IWebSocketResponse  │ IResponseBuilder │
│                     │ IWebSocketResponse  │                  │
│                     │ Builder             │                  │
└─────────────────────┴─────────────────────┴──────────────────┘

This visual guide helps understand the architecture, data flow, and implementation scope of the WebSocket support proposal.