public Task HandshakeAsync(IChannel channel, IFullHttpRequest req, HttpHeaders responseHeaders)
        {
            var completion = new TaskCompletionSource();

            this.Handshake(channel, req, responseHeaders, completion);
            return(completion.Task);
        }
示例#2
0
 public virtual bool PrepareUpgradeResponse(IChannelHandlerContext ctx, IFullHttpRequest upgradeRequest, HttpHeaders headers)
 {
     try
     {
         // Decode the HTTP2-Settings header and set the settings on the handler to make
         // sure everything is fine with the request.
         var upgradeHeaders      = upgradeRequest.Headers.GetAll(Http2CodecUtil.HttpUpgradeSettingsHeader);
         var upgradeHeadersCount = upgradeHeaders.Count;
         if (upgradeHeadersCount <= 0 || upgradeHeadersCount > 1)
         {
             ThrowHelper.ThrowArgumentException_MustOnlyOne();
         }
         _settings = DecodeSettingsHeader(ctx, upgradeHeaders[0]);
         // Everything looks good.
         return(true);
     }
     catch (Exception cause)
     {
         if (Logger.InfoEnabled)
         {
             Logger.ErrorDuringUpgradeToHTTP2(cause);
         }
         return(false);
     }
 }
        IByteBuffer encodeFullHttpRequest(IChannelHandlerContext ctx, string appkey, IFullHttpRequest request)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(request.Method.ToString());
            sb.Append(" ");
            int pos = request.Uri.IndexOf("/" + appkey);
            var tmp = request.Uri.Substring(pos + appkey.Length + 1);

            sb.Append(tmp);
            sb.Append(" ");
            sb.Append(request.ProtocolVersion.ToString());
            sb.AppendLine(" ");
            sb.AppendLine(" ");
            var cl = HttpUtil.GetContentLength(request, -1L);

            if (cl == -1 && request.Content.ReadableBytes > 0)
            {
                request.Headers.Add(HttpHeaderNames.ContentLength, request.Content.ReadableBytes);
            }
            foreach (var obj in request.Headers)
            {
                sb.AppendLine(string.Format("{0}:{1}", obj.Key, obj.Value));
            }
            sb.AppendLine(" ");
            sb.AppendLine(" ");

            var bbs = ctx.Allocator.Buffer();

            bbs.WriteString(sb.ToString(), System.Text.Encoding.UTF8);
            bbs.WriteBytes(request.Content);

            return(bbs);
        }
示例#4
0
        public virtual void UpgradeTo(IChannelHandlerContext ctx, IFullHttpRequest upgradeRequest)
        {
            try
            {
                var pipeline = ctx.Pipeline;
                // Add the HTTP/2 connection handler to the pipeline immediately following the current handler.
                _ = pipeline.AddAfter(ctx.Name, _handlerName, _connectionHandler);

                // Add also all extra handlers as these may handle events / messages produced by the connectionHandler.
                // See https://github.com/netty/netty/issues/9314
                if (_handlers != null)
                {
                    var name = pipeline.Context(_connectionHandler).Name;
                    for (int i = _handlers.Length - 1; i >= 0; i--)
                    {
                        _ = pipeline.AddAfter(name, null, _handlers[i]);
                    }
                }
                _connectionHandler.OnHttpServerUpgrade(_settings);
            }
            catch (Http2Exception e)
            {
                _ = ctx.FireExceptionCaught(e);
                _ = ctx.CloseAsync();
            }
        }
示例#5
0
        /// <summary>
        /// 处理Body和Url参数
        /// </summary>
        /// <param name="request"></param>
        /// <param name="parameters"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        protected virtual object[] HandlerBodyAndUrlParams(IFullHttpRequest request, IReadOnlyList <ParameterInfo> parameters, ref IFullHttpResponse response)
        {
            string bodyParams = GetBodyParams(request);
            Dictionary <string, string> urlParams = GetUrlParams(request);

            if (parameters.Count <= 0)
            {
                return(null);
            }
            var @params = new object[parameters.Count];

            for (var i = 0; i < parameters.Count; i++)
            {
                if (!string.IsNullOrEmpty(bodyParams) && parameters[i].ParameterType.IsClass && parameters[i].ParameterType != typeof(string))
                {
                    @params[i] = bodyParams.JsonToObject(parameters[i].ParameterType);
                    continue;
                }
                if (urlParams.ContainsKey(parameters[i].Name ?? throw new MateralDotNettyException("参数为空")))
                {
                    @params[i] = urlParams[parameters[i].Name].ConvertTo(parameters[i].ParameterType);
                    continue;
                }
                if (@params[i] == null)
                {
                    ResultModel resultModel = ResultModel.Fail($"参数{parameters[i].Name}错误");
                    response = HttpResponseHelper.GetHttpResponse(HttpResponseStatus.BadRequest, resultModel.ToJson());
                    return(null);
                }
            }
            return(@params);
        }
示例#6
0
        /// <summary>
        /// 获得Response
        /// </summary>
        private async Task <IFullHttpResponse> GetResponseAsync(IFullHttpRequest request, BaseController baseController, MethodInfo action)
        {
            IFullHttpResponse           result     = null;
            string                      bodyParams = GetBodyParams(request);
            Dictionary <string, string> urlParams  = GetUrlParams(request);

            ParameterInfo[] parameters = action.GetParameters();
            object[]        @params    = null;
            if (parameters.Length > 0)
            {
                @params = new object[parameters.Length];
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (!string.IsNullOrEmpty(bodyParams) && parameters[i].ParameterType.IsClass && parameters[i].ParameterType != typeof(string))
                    {
                        @params[i] = bodyParams.JsonToT <object>(parameters[i].ParameterType);
                        continue;
                    }
                    if (urlParams.ContainsKey(parameters[i].Name))
                    {
                        @params[i] = urlParams[parameters[i].Name].ConvertTo(parameters[i].ParameterType);
                        continue;
                    }
                    if (@params[i] == null)
                    {
                        //ResultModel resultModel = ResultModel.Fail($"参数{parameters[i].Name}错误");
                        result = GetHttpResponse(HttpResponseStatus.BadRequest, $"参数{parameters[i].Name}错误)");
                        break;
                    }
                }
            }
            result = result ?? await GetResponseAsync(baseController, action, @params);

            return(result);
        }
示例#7
0
 /// <summary>
 /// 处理
 /// </summary>
 /// <param name="request"></param>
 /// <param name="response"></param>
 public void Handler(IFullHttpRequest request, IFullHttpResponse response)
 {
     if (!IsMatch(request.Method.Name))
     {
         response.SetStatus(HttpResponseStatus.BadRequest);
     }
 }
示例#8
0
        static string GetWebSocketLocation(IFullHttpRequest req)
        {
            bool   result   = req.Headers.TryGet(HttpHeaderNames.Host, out ICharSequence value);
            string location = value.ToString() + WebsocketPath;

            return("ws://" + location);
        }
示例#9
0
        /// <summary>
        /// 获取Url参数
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private Dictionary <string, string> GetUrlParams(IFullHttpRequest request)
        {
            var result = new Dictionary <string, string>();

            string[] tempString = request.Uri.Split('?');
            if (tempString.Length <= 1)
            {
                return(result);
            }
            string[] paramsString = tempString[1].Split('&');
            foreach (string param in paramsString)
            {
                if (string.IsNullOrEmpty(param))
                {
                    continue;
                }
                string[] values = param.Split('=');
                if (values.Length != 2 || result.ContainsKey(values[0]))
                {
                    continue;
                }
                result.Add(values[0], values[1]);
            }
            return(result);

            #endregion
        }
        /// <summary>
        /// Performs the opening handshake
        /// When call this method you <c>MUST NOT</c> retain the <see cref="IFullHttpRequest"/> which is passed in.
        /// </summary>
        /// <param name="channel">Channel</param>
        /// <param name="req">HTTP Request</param>
        /// <param name="responseHeaders">Extra headers to add to the handshake response or <code>null</code> if no extra headers should be added</param>
        /// <returns></returns>
        public Task HandshakeAsync(IChannel channel, IFullHttpRequest req, HttpHeaders responseHeaders)
        {
            var completion = channel.NewPromise();

            Handshake(channel, req, responseHeaders, completion);
            return(completion.Task);
        }
示例#11
0
        void HandleHttpRequest(IChannelHandlerContext ctx, IFullHttpRequest req)
        {
            // Handle a bad request.
            if (!req.Result.IsSuccess)
            {
                SendHttpResponse(ctx, req, new DefaultFullHttpResponse(Http11, BadRequest));
                return;
            }

            // Allow only GET methods.
            if (!Equals(req.Method, HttpMethod.Get))
            {
                SendHttpResponse(ctx, req, new DefaultFullHttpResponse(Http11, Forbidden));
                return;
            }

            // Handshake
            var wsFactory = new WebSocketServerHandshakerFactory(
                GetWebSocketLocation(req), null, true, 5 * 1024 * 1024);

            _handshaker = wsFactory.NewHandshaker(req);
            if (this._handshaker == null)
            {
                WebSocketServerHandshakerFactory.SendUnsupportedVersionResponse(ctx.Channel);
            }
            else
            {
                _logger.LogInformation($"New client to handshake:{ctx.Channel}");
                var appSession = new AppSession();
                appSession.Initialize(ctx.Channel, ctx.Channel.RemoteAddress);
                _appSessionContainer.Set(ctx.Channel.Id.ToString(), appSession);
                _handshaker.HandshakeAsync(ctx.Channel, req);
            }
        }
示例#12
0
        /// <summary>
        /// 获得Response
        /// </summary>
        /// <param name="request"></param>
        /// <param name="baseController"></param>
        /// <param name="action"></param>
        /// <param name="globalFilters"></param>
        /// <returns></returns>
        protected virtual async Task <IFullHttpResponse> GetResponseAsync(IFullHttpRequest request, BaseController baseController, ActionInfo action, IFilter[] globalFilters)
        {
            IFullHttpResponse response = action.HandlerMethod(request);

            if (response.Status.Code != HttpResponseStatus.OK.Code)
            {
                return(response);
            }
            response = await action.HandlerAuthorityFilterAsync(request, globalFilters);

            if (response.Status.Code != HttpResponseStatus.OK.Code)
            {
                return(response);
            }
            response = await action.HandlerActionBeforeFilterAsync(request, globalFilters);

            if (response.Status.Code != HttpResponseStatus.OK.Code)
            {
                return(response);
            }
            response = await HandlerParamsAsync(request, baseController, action);

            await action.HandlerActionAfterFilterAsync(request, response, globalFilters);

            return(response);
        }
        /// <summary>
        /// Performs the opening handshake
        /// When call this method you <c>MUST NOT</c> retain the <see cref="IFullHttpRequest"/> which is passed in.
        /// </summary>
        /// <param name="channel">Channel</param>
        /// <param name="req">HTTP Request</param>
        /// <param name="responseHeaders">Extra headers to add to the handshake response or <code>null</code> if no extra headers should be added</param>
        /// <param name="completion">the <see cref="IPromise"/> to be notified when the opening handshake is done</param>
        public void Handshake(IChannel channel, IFullHttpRequest req, HttpHeaders responseHeaders, IPromise completion)
        {
#if DEBUG
            if (Logger.DebugEnabled)
            {
                Logger.WebSocketVersionServerHandshake(channel, _version);
            }
#endif

            IFullHttpResponse response = NewHandshakeResponse(req, responseHeaders);
            IChannelPipeline  p        = channel.Pipeline;

            if (p.Get <HttpObjectAggregator>() is object)
            {
                _ = p.Remove <HttpObjectAggregator>();
            }
            if (p.Get <HttpContentCompressor>() is object)
            {
                _ = p.Remove <HttpContentCompressor>();
            }
            if (p.Get <CorsHandler>() is object)
            {
                _ = p.Remove <CorsHandler>();
            }
            if (p.Get <HttpServerExpectContinueHandler>() is object)
            {
                _ = p.Remove <HttpServerExpectContinueHandler>();
            }
            if (p.Get <HttpServerKeepAliveHandler>() is object)
            {
                _ = p.Remove <HttpServerKeepAliveHandler>();
            }

            IChannelHandlerContext ctx = p.Context <HttpRequestDecoder>();
            string encoderName;
            if (ctx is null)
            {
                // this means the user use an HttpServerCodec
                ctx = p.Context <HttpServerCodec>();
                if (ctx is null)
                {
                    _ = completion.TrySetException(ThrowHelper.GetInvalidOperationException_NoHttpDecoderAndServerCodec());
                    return;
                }

                encoderName = ctx.Name;
                _           = p.AddBefore(encoderName, "wsencoder", NewWebSocketEncoder());
                _           = p.AddBefore(encoderName, "wsdecoder", NewWebsocketDecoder());
            }
            else
            {
                _ = p.Replace(ctx.Name, "wsdecoder", NewWebsocketDecoder());

                encoderName = p.Context <HttpResponseEncoder>().Name;
                _           = p.AddBefore(encoderName, "wsencoder", NewWebSocketEncoder());
            }

            _ = channel.WriteAndFlushAsync(response).ContinueWith(RemoveHandlerAfterWriteAction, (completion, p, encoderName), TaskContinuationOptions.ExecuteSynchronously);
        }
示例#14
0
        /// <summary>
        /// 处理HttpMethodAttribute
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public IFullHttpResponse HandlerMethod(IFullHttpRequest request)
        {
            IFullHttpResponse response = HttpResponseHelper.GetHttpResponse(HttpResponseStatus.OK);
            var attribute = Action.GetCustomAttribute <HttpMethodAttribute>();

            attribute?.Handler(request, response);
            return(response);
        }
示例#15
0
 protected override void ChannelRead0(IChannelHandlerContext ctx, IFullHttpRequest request)
 {
     if (HttpUtil.Is100ContinueExpected(request))
     {
         ctx.WriteAsync(new DefaultFullHttpResponse(HttpVersion.Http11, HttpResponseStatus.Continue, Unpooled.Empty));
     }
     base.ChannelRead0(ctx, request);
 }
示例#16
0
        public void Handshake(IChannel channel, IFullHttpRequest req, HttpHeaders responseHeaders, TaskCompletionSource completion)
        {
            if (Logger.DebugEnabled)
            {
                Logger.Debug("{} WebSocket version {} server handshake", channel, this.version);
            }

            IFullHttpResponse response = this.NewHandshakeResponse(req, responseHeaders);
            IChannelPipeline  p        = channel.Pipeline;

            if (p.Get <HttpObjectAggregator>() != null)
            {
                p.Remove <HttpObjectAggregator>();
            }

            if (p.Get <HttpContentCompressor>() != null)
            {
                p.Remove <HttpContentCompressor>();
            }

            IChannelHandlerContext ctx = p.Context <HttpRequestDecoder>();
            string encoderName;

            if (ctx == null)
            {
                // this means the user use a HttpServerCodec
                ctx = p.Context <HttpServerCodec>();
                if (ctx == null)
                {
                    completion.TrySetException(new InvalidOperationException("No HttpDecoder and no HttpServerCodec in the pipeline"));
                    return;
                }

                p.AddBefore(ctx.Name, "wsdecoder", this.NewWebsocketDecoder());
                p.AddBefore(ctx.Name, "wsencoder", this.NewWebSocketEncoder());
                encoderName = ctx.Name;
            }
            else
            {
                p.Replace(ctx.Name, "wsdecoder", this.NewWebsocketDecoder());

                encoderName = p.Context <HttpResponseEncoder>().Name;
                p.AddBefore(encoderName, "wsencoder", this.NewWebSocketEncoder());
            }

            channel.WriteAndFlushAsync(response).ContinueWith(t =>
            {
                if (t.Status == TaskStatus.RanToCompletion)
                {
                    p.Remove(encoderName);
                    completion.TryComplete();
                }
                else
                {
                    completion.TrySetException(t.Exception);
                }
            });
        }
示例#17
0
        private bool IsNotWebSocketPath(IFullHttpRequest req)
        {
            string websocketPath = _serverConfig.WebsocketPath;

            return(_serverConfig.CheckStartsWith
                ? !req.Uri.StartsWith(websocketPath, StringComparison.Ordinal)
                : !string.Equals(req.Uri, websocketPath
#if NETCOREAPP_3_0_GREATER || NETSTANDARD_2_0_GREATER
                                 ));
示例#18
0
        /// <summary>
        /// 获得文件返回
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        protected virtual async Task <IFullHttpResponse> GetFileResponseAsync(IFullHttpRequest request)
        {
            string url = HttpUtility.UrlDecode(request.Uri, System.Text.Encoding.UTF8);

            url = string.IsNullOrEmpty(Path.GetExtension(url)) ? Path.Combine(url ?? throw new DotNettyException("Url为空"), "Index.html") : url;
            ICharSequence IfModifiedSince = request.Headers.Get(HttpHeaderNames.IfModifiedSince, null);

            return(await GetFileResponseAsync(url, IfModifiedSince));
        }
示例#19
0
 /// <summary>
 /// 处理Options
 /// </summary>
 /// <param name="ctx"></param>
 /// <param name="request"></param>
 /// <param name="action"></param>
 /// <param name="response"></param>
 /// <returns></returns>
 protected virtual bool HandlerOptions(IChannelHandlerContext ctx, IFullHttpRequest request, ActionInfo action, ref IFullHttpResponse response)
 {
     if (request.Method.Name != HttpMethod.Options.Name)
     {
         return(false);
     }
     response = GetOptionsResponse(action.GetMethodName());
     return(true);
 }
            public void UpgradeTo(IChannelHandlerContext ctx, IFullHttpRequest upgradeRequest)
            {
                // Ensure that the HttpServerUpgradeHandler is still installed when this is called
                Assert.Equal(ctx.Channel.Pipeline.Context <HttpServerUpgradeHandler>(), ctx);
                Assert.NotNull(ctx.Channel.Pipeline.Get <HttpServerUpgradeHandler>());

                // Add a marker handler to signal that the upgrade has happened
                ctx.Channel.Pipeline.AddAfter(ctx.Name, "marker", new ChannelHandlerAdapter());
            }
示例#21
0
 public async Task <IFullHttpResponse> GetHttpResponse(IFullHttpRequest request)
 {
     if (!request.Result.IsSuccess)
     {
         return(GetHttpResponse(HttpResponseStatus.BadRequest));
     }
     //return GetHttpResponse(HttpResponseStatus.OK, "Hello World!");
     return(await GetFileResponseAsync(request));
 }
示例#22
0
 internal static StringBuilder AppendFullRequest(StringBuilder buf, IFullHttpRequest req)
 {
     AppendFullCommon(buf, req);
     AppendInitialLine(buf, req);
     AppendHeaders(buf, req.Headers);
     AppendHeaders(buf, req.TrailingHeaders);
     RemoveLastNewLine(buf);
     return(buf);
 }
示例#23
0
        void HandleHttpRequest(IChannelHandlerContext ctx, IFullHttpRequest req)
        {
            // Handle a bad request.
            if (!req.Result.IsSuccess)
            {
                SendHttpResponse(ctx, req, new DefaultFullHttpResponse(Http11, BadRequest));
                return;
            }

            // Allow only GET methods.
            if (!Equals(req.Method, HttpMethod.Get))
            {
                SendHttpResponse(ctx, req, new DefaultFullHttpResponse(Http11, Forbidden));
                return;
            }

            // Send the demo page and favicon.ico
            if ("/".Equals(req.Uri))
            {
                IByteBuffer content = Unpooled.WrappedBuffer(Encoding.ASCII.GetBytes(
                                                                 "<html><head><title>XMPP WebSocket Proxy</title></head>" + Environment.NewLine +
                                                                 "<body>" + Environment.NewLine +
                                                                 "<h1>XMPP WebSocket server</h1>" + Environment.NewLine +
                                                                 "<p>running at: " + GetWebSocketLocation(req) + "</p>" + Environment.NewLine +
                                                                 "</body>" + Environment.NewLine +
                                                                 "</html>"));

                var res = new DefaultFullHttpResponse(Http11, OK, content);

                res.Headers.Set(HttpHeaderNames.ContentType, "text/html; charset=UTF-8");
                HttpUtil.SetContentLength(res, content.ReadableBytes);

                SendHttpResponse(ctx, req, res);
                return;
            }
            if ("/favicon.ico".Equals(req.Uri))
            {
                var res = new DefaultFullHttpResponse(Http11, NotFound);
                SendHttpResponse(ctx, req, res);
                return;
            }

            // Handshake
            var wsFactory = new WebSocketServerHandshakerFactory(
                GetWebSocketLocation(req), "xmpp", true, 5 * 1024 * 1024);

            this.handshaker = wsFactory.NewHandshaker(req);
            if (this.handshaker == null)
            {
                WebSocketServerHandshakerFactory.SendUnsupportedVersionResponse(ctx.Channel);
            }
            else
            {
                this.handshaker.HandshakeAsync(ctx.Channel, req);
            }
        }
示例#24
0
        /// <summary>
        /// 发送Http返回
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="req"></param>
        /// <param name="res"></param>
        private void SendHttpResponse(IChannelHandlerContext ctx, IFullHttpRequest req, IFullHttpResponse res)
        {
            Task task = ctx.Channel.WriteAndFlushAsync(res);

            if (!HttpUtil.IsKeepAlive(req) || res.Status.Code != 200)
            {
                task.ContinueWith((t, c) => ((IChannelHandlerContext)c).CloseAsync(),
                                  ctx, TaskContinuationOptions.ExecuteSynchronously);
            }
        }
示例#25
0
 /// <summary>
 /// Method验证
 /// </summary>
 /// <param name="request"></param>
 /// <param name="action"></param>
 /// <returns></returns>
 private bool CanMethodSuccess(IFullHttpRequest request, MethodInfo action)
 {
     Attribute[] attribute = action.GetCustomAttributes().ToArray();
     if (request.Method.Name == "GET" && attribute.Any(m => m is HttpGetAttribute) ||
         request.Method.Name == "POST" && attribute.Any(m => m is HttpPostAttribute))
     {
         return(true);
     }
     return(false);
 }
示例#26
0
        /// <summary>
        /// 执行请求
        /// <para/>
        /// 需手动调用 <see cref="IFullHttpResponse"/> 的Release方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task <IFullHttpResponse> ExecuteAsync(IFullHttpRequest request, CancellationToken token)
        {
            CheckDisposed();

            Interlocked.Exchange(ref _lastTicks, DateTime.UtcNow.Ticks);

            _requestSetupFunc?.Invoke(request);

            var channel = await GetChannelAsync().ConfigureAwait(false);

            var completionSource = new TaskCompletionSource <IFullHttpResponse>();

            if (token.CanBeCanceled)
            {
                token.Register(() =>
                {
                    _ = CloseChannelAsync().ContinueWith(_ =>
                    {
                        completionSource.TrySetException(new OperationCanceledException());
                    }, TaskScheduler.Default);
                });
            }

            _responseHandler.SetCallback((ctx, innerResponse) =>
            {
                try
                {
                    innerResponse.Retain();
                    completionSource.TrySetResult(innerResponse);
                }
#pragma warning disable CA1031 // 不捕获常规异常类型
                catch (Exception ex)
#pragma warning restore CA1031 // 不捕获常规异常类型
                {
                    completionSource.TrySetException(ex);
                }
            });

            var sendTask = channel.WriteAndFlushAsync(request);

            try
            {
                var response = await completionSource.Task.ConfigureAwait(false);

                return(response);
            }
            finally
            {
                if (!sendTask.IsCompleted)
                {
                    await CloseChannelAsync().ConfigureAwait(false);
                }
            }
        }
示例#27
0
        private string GetWebSocketLocation(IFullHttpRequest req)
        {
            req.Headers.TryGet(HttpHeaderNames.Host, out ICharSequence value);
            string location = value.ToString() + WebsocketPath;

            if (_webSocketConfig.IsSsl)
            {
                return("wss://" + location);
            }
            return("ws://" + location);
        }
示例#28
0
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        protected virtual async Task HandlerRequestAsync(IChannelHandlerContext ctx, IFullHttpRequest request)
        {
            IFullHttpResponse response = await GetFileResponseAsync(request);

            if (!CanNext || response.Status.Code == HttpResponseStatus.OK.Code)
            {
                await SendHttpResponseAsync(ctx, request, response);

                StopHandler();
            }
        }
示例#29
0
        public void ForbiddenShouldReleaseRequest()
        {
            CorsConfig       config  = CorsConfigBuilder.ForOrigin((AsciiString)"https://localhost").ShortCircuit().Build();
            var              channel = new EmbeddedChannel(new CorsHandler(config), new EchoHandler());
            IFullHttpRequest request = CreateHttpRequest(HttpMethod.Get);

            request.Headers.Set(HttpHeaderNames.Origin, "http://localhost:8888");
            Assert.False(channel.WriteInbound(request));
            Assert.Equal(0, request.ReferenceCount);
            Assert.True(ReferenceCountUtil.Release(channel.ReadOutbound()));
            Assert.False(channel.Finish());
        }
        /// <summary>
        /// Handle the web socket handshake for the web socket specification <a href=
        /// "http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07">HyBi version 7</a>.
        ///
        /// <para>
        /// Browser request to the server:
        /// </para>
        ///
        /// <![CDATA[
        /// GET /chat HTTP/1.1
        /// Host: server.example.com
        /// Upgrade: websocket
        /// Connection: Upgrade
        /// Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
        /// Sec-WebSocket-Origin: http://example.com
        /// Sec-WebSocket-Protocol: chat, superchat
        /// Sec-WebSocket-Version: 7
        /// ]]>
        ///
        /// <para>
        /// Server response:
        /// </para>
        ///
        /// <![CDATA[
        /// HTTP/1.1 101 Switching Protocols
        /// Upgrade: websocket
        /// Connection: Upgrade
        /// Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        /// Sec-WebSocket-Protocol: chat
        /// ]]>
        /// </summary>
        protected internal override IFullHttpResponse NewHandshakeResponse(IFullHttpRequest req, HttpHeaders headers)
        {
            if (!req.Headers.TryGet(HttpHeaderNames.SecWebsocketKey, out ICharSequence key) ||
                key is null)
            {
                ThrowHelper.ThrowWebSocketHandshakeException_MissingKey();
            }

            var res = new DefaultFullHttpResponse(HttpVersion.Http11, HttpResponseStatus.SwitchingProtocols,
                                                  req.Content.Allocator.Buffer(0));

            if (headers is object)
            {
                _ = res.Headers.Add(headers);
            }

            string acceptSeed = key + Websocket07AcceptGuid;

            byte[] sha1   = WebSocketUtil.Sha1(Encoding.ASCII.GetBytes(acceptSeed));
            string accept = WebSocketUtil.Base64String(sha1);

#if DEBUG
            if (Logger.DebugEnabled)
            {
                Logger.WebSocketVersion07ServerHandshakeKey(key, accept);
            }
#endif

            _ = res.Headers.Set(HttpHeaderNames.Upgrade, HttpHeaderValues.Websocket)
                .Set(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade)
                .Set(HttpHeaderNames.SecWebsocketAccept, accept);


            if (req.Headers.TryGet(HttpHeaderNames.SecWebsocketProtocol, out ICharSequence subprotocols) &&
                subprotocols is object)
            {
                string selectedSubprotocol = this.SelectSubprotocol(subprotocols.ToString());
                if (selectedSubprotocol is null)
                {
#if DEBUG
                    if (Logger.DebugEnabled)
                    {
                        Logger.RequestedSubprotocolNotSupported(subprotocols);
                    }
#endif
                }
                else
                {
                    _ = res.Headers.Add(HttpHeaderNames.SecWebsocketProtocol, selectedSubprotocol);
                }
            }
            return(res);
        }