@@ -19,6 +19,7 @@ public class WebSocketsProxyMiddlewareTests
19
19
20
20
private readonly Mock < HttpContext > _context ;
21
21
private readonly Mock < IOcelotLogger > _logger ;
22
+ private readonly Mock < IClientWebSocket > _client ;
22
23
23
24
public WebSocketsProxyMiddlewareTests ( )
24
25
{
@@ -27,48 +28,48 @@ public WebSocketsProxyMiddlewareTests()
27
28
_factory = new Mock < IWebSocketsFactory > ( ) ;
28
29
29
30
_context = new Mock < HttpContext > ( ) ;
31
+ _context . SetupGet ( x => x . WebSockets . IsWebSocketRequest ) . Returns ( true ) ;
32
+
30
33
_logger = new Mock < IOcelotLogger > ( ) ;
31
34
_loggerFactory . Setup ( x => x . CreateLogger < WebSocketsProxyMiddleware > ( ) )
32
35
. Returns ( _logger . Object ) ;
33
36
34
37
_middleware = new WebSocketsProxyMiddleware ( _loggerFactory . Object , _next . Object , _factory . Object ) ;
38
+
39
+ _client = new Mock < IClientWebSocket > ( ) ;
40
+ _factory . Setup ( x => x . CreateClient ( ) ) . Returns ( _client . Object ) ;
35
41
}
36
42
37
43
[ Fact ]
38
- public void ShouldIgnoreAllSslWarnings_WhenDangerousAcceptAnyServerCertificateValidatorIsTrue ( )
44
+ public void ShouldIgnoreAllSslWarningsWhenDangerousAcceptAnyServerCertificateValidatorIsTrue ( )
39
45
{
40
- this . Given ( x => x . GivenPropertyDangerousAcceptAnyServerCertificateValidator ( true ) )
46
+ List < object > actual = new ( ) ;
47
+ this . Given ( x => x . GivenPropertyDangerousAcceptAnyServerCertificateValidator ( true , actual ) )
41
48
. And ( x => x . AndDoNotSetupProtocolsAndHeaders ( ) )
42
- . And ( x => x . AndDoNotConnectReally ( ) )
49
+ . And ( x => x . AndDoNotConnectReally ( null ) )
43
50
. When ( x => x . WhenInvokeWithHttpContext ( ) )
44
- . Then ( x => x . ThenIgnoredAllSslWarnings ( ) )
51
+ . Then ( x => x . ThenIgnoredAllSslWarnings ( actual ) )
45
52
. BDDfy ( ) ;
46
53
}
47
54
48
- private void GivenPropertyDangerousAcceptAnyServerCertificateValidator ( bool enabled )
55
+ private void GivenPropertyDangerousAcceptAnyServerCertificateValidator ( bool enabled , List < object > actual )
49
56
{
50
- var request = new HttpRequestMessage ( HttpMethod . Get , "http ://localhost:80 ") ;
57
+ var request = new HttpRequestMessage ( HttpMethod . Get , $ " { Uri . UriSchemeWs } ://localhost:12345 ") ;
51
58
var downstream = new DownstreamRequest ( request ) ;
52
59
var route = new DownstreamRouteBuilder ( )
53
60
. WithDangerousAcceptAnyServerCertificateValidator ( enabled )
54
61
. Build ( ) ;
55
62
_context . SetupGet ( x => x . Items ) . Returns ( new Dictionary < object , object >
56
- {
57
- { "DownstreamRequest" , downstream } ,
58
- { "DownstreamRoute" , route } ,
59
- } ) ;
60
-
61
- _context . SetupGet ( x => x . WebSockets . IsWebSocketRequest ) . Returns ( true ) ;
62
-
63
- _client = new Mock < IClientWebSocket > ( ) ;
64
- _factory . Setup ( x => x . CreateClient ( ) ) . Returns ( _client . Object ) ;
63
+ {
64
+ { "DownstreamRequest" , downstream } ,
65
+ { "DownstreamRoute" , route } ,
66
+ } ) ;
65
67
66
68
_client . SetupSet ( x => x . Options . RemoteCertificateValidationCallback = It . IsAny < RemoteCertificateValidationCallback > ( ) )
67
- . Callback < RemoteCertificateValidationCallback > ( value => _callback = value ) ;
69
+ . Callback < RemoteCertificateValidationCallback > ( actual . Add ) ;
68
70
69
- _warning = string . Empty ;
70
71
_logger . Setup ( x => x . LogWarning ( It . IsAny < string > ( ) ) )
71
- . Callback < string > ( message => _warning = message ) ;
72
+ . Callback < string > ( actual . Add ) ;
72
73
}
73
74
74
75
private void AndDoNotSetupProtocolsAndHeaders ( )
@@ -77,9 +78,11 @@ private void AndDoNotSetupProtocolsAndHeaders()
77
78
_context . SetupGet ( x => x . Request . Headers ) . Returns ( new HeaderDictionary ( ) ) ;
78
79
}
79
80
80
- private void AndDoNotConnectReally ( )
81
+ private void AndDoNotConnectReally ( Action < Uri , CancellationToken > callbackConnectAsync )
81
82
{
82
- _client . Setup ( x => x . ConnectAsync ( It . IsAny < Uri > ( ) , It . IsAny < CancellationToken > ( ) ) ) . Verifiable ( ) ;
83
+ Action < Uri , CancellationToken > doNothing = ( u , t ) => { } ;
84
+ _client . Setup ( x => x . ConnectAsync ( It . IsAny < Uri > ( ) , It . IsAny < CancellationToken > ( ) ) )
85
+ . Callback ( callbackConnectAsync ?? doNothing ) ;
83
86
var clientSocket = new Mock < WebSocket > ( ) ;
84
87
var serverSocket = new Mock < WebSocket > ( ) ;
85
88
_client . Setup ( x => x . ToWebSocket ( ) ) . Returns ( clientSocket . Object ) ;
@@ -97,28 +100,77 @@ private void AndDoNotConnectReally()
97
100
serverSocket . SetupGet ( x => x . CloseStatus ) . Returns ( WebSocketCloseStatus . Empty ) ;
98
101
}
99
102
100
- private Mock < IClientWebSocket > _client ;
101
- private RemoteCertificateValidationCallback _callback ;
102
- private string _warning ;
103
-
104
103
private async Task WhenInvokeWithHttpContext ( )
105
104
{
106
105
await _middleware . Invoke ( _context . Object ) ;
107
106
}
108
107
109
- private void ThenIgnoredAllSslWarnings ( )
108
+ private void ThenIgnoredAllSslWarnings ( List < object > actual )
110
109
{
111
- _context . Object . Items . DownstreamRoute ( ) . DangerousAcceptAnyServerCertificateValidator
112
- . ShouldBeTrue ( ) ;
110
+ var route = _context . Object . Items . DownstreamRoute ( ) ;
111
+ var request = _context . Object . Items . DownstreamRequest ( ) ;
112
+ route . DangerousAcceptAnyServerCertificateValidator . ShouldBeTrue ( ) ;
113
113
114
114
_logger . Verify ( x => x . LogWarning ( It . IsAny < string > ( ) ) , Times . Once ( ) ) ;
115
- _warning . ShouldNotBeNullOrEmpty ( ) ;
115
+ var warning = actual . Last ( ) as string ;
116
+ warning . ShouldNotBeNullOrEmpty ( ) ;
117
+ var expectedWarning = string . Format ( WebSocketsProxyMiddleware . IgnoredSslWarningFormat , route . UpstreamPathTemplate , route . DownstreamPathTemplate ) ;
118
+ warning . ShouldBe ( expectedWarning ) ;
116
119
117
120
_client . VerifySet ( x => x . Options . RemoteCertificateValidationCallback = It . IsAny < RemoteCertificateValidationCallback > ( ) ,
118
121
Times . Once ( ) ) ;
119
122
120
- _callback . ShouldNotBeNull ( ) ;
121
- var validation = _callback . Invoke ( null , null , null , SslPolicyErrors . None ) ;
123
+ var callback = actual . First ( ) as RemoteCertificateValidationCallback ;
124
+ callback . ShouldNotBeNull ( ) ;
125
+ var validation = callback . Invoke ( null , null , null , SslPolicyErrors . None ) ;
122
126
validation . ShouldBeTrue ( ) ;
123
127
}
128
+
129
+ [ Theory ]
130
+ [ InlineData ( "http" , "ws" ) ]
131
+ [ InlineData ( "https" , "wss" ) ]
132
+ [ InlineData ( "ftp" , "ftp" ) ]
133
+ public void ShouldReplaceNonWsSchemes ( string scheme , string expectedScheme )
134
+ {
135
+ List < object > actual = new ( ) ;
136
+ this . Given ( x => x . GivenNonWebsocketScheme ( scheme , actual ) )
137
+ . And ( x => x . AndDoNotSetupProtocolsAndHeaders ( ) )
138
+ . And ( x => x . AndDoNotConnectReally ( ( uri , token ) => actual . Add ( uri ) ) )
139
+ . When ( x => x . WhenInvokeWithHttpContext ( ) )
140
+ . Then ( x => x . ThenNonWsSchemesAreReplaced ( scheme , expectedScheme , actual ) )
141
+ . BDDfy ( ) ;
142
+ }
143
+
144
+ private void GivenNonWebsocketScheme ( string scheme , List < object > actual )
145
+ {
146
+ var requestMessage = new HttpRequestMessage ( HttpMethod . Get , $ "{ scheme } ://localhost:12345") ;
147
+ var request = new DownstreamRequest ( requestMessage ) ;
148
+ var route = new DownstreamRouteBuilder ( ) . Build ( ) ;
149
+ var items = new Dictionary < object , object >
150
+ {
151
+ { "DownstreamRequest" , request } ,
152
+ { "DownstreamRoute" , route } ,
153
+ } ;
154
+ _context . SetupGet ( x => x . Items ) . Returns ( items ) ;
155
+
156
+ _logger . Setup ( x => x . LogWarning ( It . IsAny < string > ( ) ) )
157
+ . Callback < string > ( actual . Add ) ;
158
+ }
159
+
160
+ private void ThenNonWsSchemesAreReplaced ( string scheme , string expectedScheme , List < object > actual )
161
+ {
162
+ var route = _context . Object . Items . DownstreamRoute ( ) ;
163
+ var request = _context . Object . Items . DownstreamRequest ( ) ;
164
+ route . DangerousAcceptAnyServerCertificateValidator . ShouldBeFalse ( ) ;
165
+
166
+ _logger . Verify ( x => x . LogWarning ( It . IsAny < string > ( ) ) , Times . Once ( ) ) ;
167
+ var warning = actual . First ( ) as string ;
168
+ warning . ShouldNotBeNullOrEmpty ( ) ;
169
+ warning . ShouldContain ( $ "'{ scheme } '") ;
170
+ var expectedWarning = string . Format ( WebSocketsProxyMiddleware . InvalidSchemeWarningFormat , scheme , request . ToUri ( ) . Replace ( expectedScheme , scheme ) ) ;
171
+ warning . ShouldBe ( expectedWarning ) ;
172
+
173
+ request . Scheme . ShouldBe ( expectedScheme ) ;
174
+ ( ( Uri ) actual . Last ( ) ) . Scheme . ShouldBe ( expectedScheme ) ;
175
+ }
124
176
}
0 commit comments