public void Decode100ContinueHttp2HeadersAsFullHttpResponse() { EmbeddedChannel ch = new EmbeddedChannel(new Http2StreamFrameToHttpObjectCodec(false)); IHttp2Headers headers = new DefaultHttp2Headers(); headers.Scheme = HttpScheme.Http.Name; headers.Status = HttpResponseStatus.Continue.CodeAsText; Assert.True(ch.WriteInbound(new DefaultHttp2HeadersFrame(headers, false))); IFullHttpResponse response = ch.ReadInbound <IFullHttpResponse>(); try { Assert.Equal(HttpResponseStatus.Continue, response.Status); Assert.Equal(HttpVersion.Http11, response.ProtocolVersion); } finally { response.Release(); } Assert.Null(ch.ReadInbound <object>()); Assert.False(ch.Finish()); }
public void SubsequentHttpRequestsAfterUpgradeShouldReturn403() { EmbeddedChannel ch = this.CreateChannel(); WriteUpgradeRequest(ch); IFullHttpResponse response = this.responses.Dequeue(); Assert.Equal(SwitchingProtocols, response.Status); response.Release(); ch.WriteInbound(new DefaultFullHttpRequest(Http11, HttpMethod.Get, "/test")); response = this.responses.Dequeue(); Assert.Equal(Forbidden, response.Status); response.Release(); }
public void TestDuplicateHandshakeResponseHeaders() { WebSocketServerHandshaker serverHandshaker = NewHandshaker("ws://example.com/chat", "chat", WebSocketDecoderConfig.Default); IFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.Http11, HttpMethod.Get, "/chat"); request.Headers .Set(HttpHeaderNames.Host, "example.com") .Set(HttpHeaderNames.Origin, "example.com") .Set(HttpHeaderNames.Upgrade, HttpHeaderValues.Websocket) .Set(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade) .Set(HttpHeaderNames.SecWebsocketKey, "dGhlIHNhbXBsZSBub25jZQ==") .Set(HttpHeaderNames.SecWebsocketOrigin, "http://example.com") .Set(HttpHeaderNames.SecWebsocketProtocol, "chat, superchat") .Set(HttpHeaderNames.SecWebsocketVersion, WebSocketVersion().ToHttpHeaderValue()); HttpHeaders customResponseHeaders = new DefaultHttpHeaders(); // set duplicate required headers and one custom customResponseHeaders .Set(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade) .Set(HttpHeaderNames.Upgrade, HttpHeaderValues.Websocket) .Set(AsciiString.Of("custom"), AsciiString.Of("header")); if (WebSocketVersion() != Http.WebSockets.WebSocketVersion.V00) { customResponseHeaders.Set(HttpHeaderNames.SecWebsocketAccept, "12345"); } IFullHttpResponse response = null; try { response = serverHandshaker.NewHandshakeResponse(request, customResponseHeaders); HttpHeaders responseHeaders = response.Headers; Assert.Equal(1, responseHeaders.GetAll(HttpHeaderNames.Connection).Count); Assert.Equal(1, responseHeaders.GetAll(HttpHeaderNames.Upgrade).Count); Assert.True(responseHeaders.ContainsValue(AsciiString.Of("custom"), AsciiString.Of("header"), true)); if (WebSocketVersion() != Http.WebSockets.WebSocketVersion.V00) { Assert.False(responseHeaders.ContainsValue(HttpHeaderNames.SecWebsocketAccept, AsciiString.Of("12345"), false)); } } finally { request.Release(); if (response != null) { response.Release(); } } }
public void HttpUpgradeRequest() { EmbeddedChannel ch = this.CreateChannel(new MockOutboundHandler(this)); IChannelHandlerContext handshakerCtx = ch.Pipeline.Context <WebSocketServerProtocolHandshakeHandler>(); WriteUpgradeRequest(ch); IFullHttpResponse response = this.responses.Dequeue(); Assert.Equal(SwitchingProtocols, response.Status); response.Release(); Assert.NotNull(WebSocketServerProtocolHandler.GetHandshaker(handshakerCtx.Channel)); }
public void WebSocketServerProtocolHandshakeHandlerReplacedBeforeHandshake() { EmbeddedChannel ch = CreateChannel(new MockOutboundHandler(this)); IChannelHandlerContext handshakerCtx = ch.Pipeline.Context <WebSocketServerProtocolHandshakeHandler>(); ch.Pipeline.AddLast(new ReplacedBeforeHandshakeHandler()); WriteUpgradeRequest(ch); IFullHttpResponse response = _responses.Dequeue(); Assert.Equal(SwitchingProtocols, response.Status); response.Release(); Assert.NotNull(WebSocketServerProtocolHandler.GetHandshaker(handshakerCtx.Channel)); Assert.False(ch.Finish()); }
public void HttpUpgradeRequestInvalidUpgradeHeader() { EmbeddedChannel ch = this.CreateChannel(); IFullHttpRequest httpRequestWithEntity = new WebSocketRequestBuilder() .HttpVersion(Http11) .Method(HttpMethod.Get) .Uri("/test") .Connection("Upgrade") .Version00() .Upgrade("BogusSocket") .Build(); ch.WriteInbound(httpRequestWithEntity); IFullHttpResponse response = this.responses.Dequeue(); Assert.Equal(BadRequest, response.Status); Assert.Equal("not a WebSocket handshake request: missing upgrade", GetResponseMessage(response)); response.Release(); }
public void HttpUpgradeRequestMissingWsKeyHeader() { EmbeddedChannel ch = this.CreateChannel(); IHttpRequest httpRequest = new WebSocketRequestBuilder() .HttpVersion(Http11) .Method(HttpMethod.Get) .Uri("/test") .Key(null) .Connection("Upgrade") .Upgrade(HttpHeaderValues.Websocket) .Version13() .Build(); ch.WriteInbound(httpRequest); IFullHttpResponse response = this.responses.Dequeue(); Assert.Equal(BadRequest, response.Status); Assert.Equal("not a WebSocket request: missing key", GetResponseMessage(response)); response.Release(); }
private void TestDecodeFullResponseHeaders0(bool withStreamId) { EmbeddedChannel ch = new EmbeddedChannel(new Http2StreamFrameToHttpObjectCodec(false)); IHttp2Headers headers = new DefaultHttp2Headers(); headers.Scheme = HttpScheme.Http.Name; headers.Status = HttpResponseStatus.OK.CodeAsText; IHttp2HeadersFrame frame = new DefaultHttp2HeadersFrame(headers, true); if (withStreamId) { frame.Stream = new TestHttp2FrameStream(); } Assert.True(ch.WriteInbound(frame)); IFullHttpResponse response = ch.ReadInbound <IFullHttpResponse>(); try { Assert.Equal(HttpResponseStatus.OK, response.Status); Assert.Equal(HttpVersion.Http11, response.ProtocolVersion); Assert.Equal(0, response.Content.ReadableBytes); Assert.True(response.TrailingHeaders.IsEmpty); Assert.False(HttpUtil.IsTransferEncodingChunked(response)); if (withStreamId) { Assert.Equal(1, response.Headers.GetInt(HttpConversionUtil.ExtensionHeaderNames.StreamId, 0)); } } finally { response.Release(); } Assert.Null(ch.ReadInbound <object>()); Assert.False(ch.Finish()); }
public void DoNotCreateUTF8Validator() { var config = WebSocketServerProtocolConfig.NewBuilder() .WebsocketPath("/test") .WithUTF8Validator(false) .Build(); EmbeddedChannel ch = new EmbeddedChannel( new WebSocketServerProtocolHandler(config), new HttpRequestDecoder(), new HttpResponseEncoder(), new MockOutboundHandler(this)); WriteUpgradeRequest(ch); IFullHttpResponse response = _responses.Dequeue(); Assert.Equal(HttpResponseStatus.SwitchingProtocols, response.Status); response.Release(); Assert.Null(ch.Pipeline.Get <Utf8FrameValidator>()); }
public void HandleTextFrame() { var customTextFrameHandler = new CustomTextFrameHandler(); EmbeddedChannel ch = CreateChannel(customTextFrameHandler); WriteUpgradeRequest(ch); IFullHttpResponse response = _responses.Dequeue(); Assert.Equal(HttpResponseStatus.SwitchingProtocols, response.Status); response.Release(); if (ch.Pipeline.Context <HttpRequestDecoder>() != null) { // Removing the HttpRequestDecoder because we are writing a TextWebSocketFrame and thus // decoding is not necessary. ch.Pipeline.Remove <HttpRequestDecoder>(); } ch.WriteInbound(new TextWebSocketFrame("payload")); Assert.Equal("processed: payload", customTextFrameHandler.Content); Assert.False(ch.Finish()); }
protected internal override void Decode(IChannelHandlerContext context, IHttpObject message, List <object> output) { IFullHttpResponse response = null; try { if (!this.upgradeRequested) { throw new InvalidOperationException("Read HTTP response without requesting protocol switch"); } if (message is IHttpResponse rep) { if (!HttpResponseStatus.SwitchingProtocols.Equals(rep.Status)) { // The server does not support the requested protocol, just remove this handler // and continue processing HTTP. // NOTE: not releasing the response since we're letting it propagate to the // next handler. context.FireUserEventTriggered(UpgradeEvent.UpgradeRejected); RemoveThisHandler(context); context.FireChannelRead(rep); return; } } if (message is IFullHttpResponse fullRep) { response = fullRep; // Need to retain since the base class will release after returning from this method. response.Retain(); output.Add(response); } else { // Call the base class to handle the aggregation of the full request. base.Decode(context, message, output); if (output.Count == 0) { // The full request hasn't been created yet, still awaiting more data. return; } Debug.Assert(output.Count == 1); response = (IFullHttpResponse)output[0]; } if (response.Headers.TryGet(HttpHeaderNames.Upgrade, out ICharSequence upgradeHeader) && !AsciiString.ContentEqualsIgnoreCase(this.upgradeCodec.Protocol, upgradeHeader)) { throw new InvalidOperationException($"Switching Protocols response with unexpected UPGRADE protocol: {upgradeHeader}"); } // Upgrade to the new protocol. this.sourceCodec.PrepareUpgradeFrom(context); this.upgradeCodec.UpgradeTo(context, response); // Notify that the upgrade to the new protocol completed successfully. context.FireUserEventTriggered(UpgradeEvent.UpgradeSuccessful); // We guarantee UPGRADE_SUCCESSFUL event will be arrived at the next handler // before http2 setting frame and http response. this.sourceCodec.UpgradeFrom(context); // We switched protocols, so we're done with the upgrade response. // Release it and clear it from the output. response.Release(); output.Clear(); RemoveThisHandler(context); } catch (Exception exception) { ReferenceCountUtil.Release(response); context.FireExceptionCaught(exception); RemoveThisHandler(context); } }