mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-25 10:52:52 +01:00
25 KiB
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.