Beispiel #1
0
        internal async Task SendToOutputAsync(HTTPStreamResult httpStreamResult, HttpListenerContext context)
        {
            context.Response.ContentLength64 = httpStreamResult.Stream.Length;
            context.Response.ContentType     = httpStreamResult.ContentType;
            context.Response.ContentEncoding = Encoding.UTF8;
            //context.Response.AddHeader("Date", DateTime.Now.ToString("r"));
            //if (!String.IsNullOrEmpty(httpStreamResult?.FileToRead)) context.Response.AddHeader("Last-Modified", File.GetLastWriteTime(httpStreamResult.FileToRead).ToString("r"));

            context.Response.StatusCode = (int)HttpStatusCode.OK;
            await httpStreamResult.Stream.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false);
        }
Beispiel #2
0
        public override async Task <ProcessRuleResult> ProcessAsync(string callerIP, Scheme scheme, string host, int port, string path, string pathAndQuery, NameValueCollection query, NameValueCollection headers, StaticFileProcessor parent)
        {
            HTTPStreamResult httpStreamResult = await parent.ProcessRequestAsync(callerIP, path, this.AlternativeWWWDirectory).ConfigureAwait(false);

            if ((int)httpStreamResult.HttpStatusCode >= 200 && (int)httpStreamResult.HttpStatusCode < 300)
            {
                return(new ProcessRuleResult()
                {
                    IsSuccess = true, ActionType = ActionType.AlternativeWWWDirectory, HttpStreamResult = httpStreamResult, Message = "Served '" + httpStreamResult.FileToRead + "'"
                });
            }
            else
            {
                return(new ProcessRuleResult()
                {
                    IsSuccess = false,
                    ActionType = ActionType.AlternativeWWWDirectory,
                    SendErrorResponsePage_HttpStatusCode = httpStreamResult.HttpStatusCode,
                    LogLevel = LogLevel.Warning,
                    Message = httpStreamResult.ErrorMsg
                });
            }
        }
Beispiel #3
0
        private async void OnContext(IAsyncResult result)
        {
            if (!_listener.IsListening)
            {
                return;
            }
            HttpListenerContext context = null;

            try
            {
                context = _listener.EndGetContext(result);
                _listener.BeginGetContext(OnContext, null);

                string httpMethod = context.Request.HttpMethod;
                string callerIP   = context.Request.RemoteEndPoint.Address.ToString();
                string schemeStr  = context.Request.Url.Scheme;
                Scheme scheme; if (string.Equals(schemeStr, "https", StringComparison.OrdinalIgnoreCase))
                {
                    scheme = Scheme.https;
                }
                else
                {
                    scheme = Scheme.http;
                }
                string host         = context.Request.Url.Host;
                int    port         = context.Request.Url.Port;
                string pathAndQuery = context.Request.Url.PathAndQuery;
                string absolutePath = context.Request.Url.AbsolutePath;
                string absoluteURL  = context.Request.Url.AbsoluteUri;
                if (string.IsNullOrWhiteSpace(absolutePath))
                {
                    absolutePath = "/";
                }
                if (scheme == Scheme.http && this.Config.AllowLocalhostConnectionsOnlyForHttp)
                {
                    if (!context.Request.IsLocal)
                    {
                        string msg = callerIP + " requested '" + absoluteURL + "' > Blocked as caller is not local ('AllowLocalhostConnectionsOnlyForHttp' is set to 'true')";
                        this.OnWarningLog?.Invoke(msg);
                        await SendErrorResponsePage(context, msg, HttpStatusCode.Unauthorized).ConfigureAwait(false);

                        return;
                    }
                }

                //Process Rules
                if (this.Config.Rules != null)
                {
                    foreach (Rule rule in this.Config.Rules)
                    {
                        if (rule.IsMatch(scheme, host, port, absolutePath))
                        {
                            ProcessRuleResult processRuleResult = await rule.ResponseAction.ProcessAsync(callerIP, scheme, host, port, absolutePath, pathAndQuery, context.Request.QueryString, context.Request.Headers, this).ConfigureAwait(false);

                            switch (processRuleResult.ActionType)
                            {
                            case ActionType.AlternativeWWWDirectory:
                                if (processRuleResult.IsSuccess)
                                {
                                    await this.SendToOutputAsync(processRuleResult.HttpStreamResult, context).ConfigureAwait(false);
                                }
                                break;

                            case ActionType.Redirect:
                                context.Response.Redirect(processRuleResult.RedirectURL);
                                break;

                            case ActionType.Deny:
                                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                                //context.Response?.Close();
                                break;

                            case ActionType.ReverseProxy:
                                if (processRuleResult.IsSuccess)
                                {
                                    await this.SendToOutputAsync(processRuleResult.HttpStreamResult, context).ConfigureAwait(false);
                                }
                                break;
                            }

                            string msg = null; if (!string.IsNullOrWhiteSpace(processRuleResult.Message))
                            {
                                msg = processRuleResult.Message;
                            }
                            if (processRuleResult.LogLevel == LogLevel.Info)
                            {
                                this.OnInfoLog?.Invoke(callerIP + " requested '" + absoluteURL + "' > " + rule.Name + " > " + msg);
                            }
                            else if (processRuleResult.LogLevel == LogLevel.Warning)
                            {
                                this.OnWarningLog?.Invoke(callerIP + " requested '" + absoluteURL + "' > " + rule.Name + " > " + msg);
                            }
                            else if (processRuleResult.LogLevel == LogLevel.Error)
                            {
                                this.OnErrorLog?.Invoke(callerIP + " requested '" + absoluteURL + "' > " + rule.Name + " > " + msg);
                            }
                            if (!processRuleResult.IsSuccess)
                            {
                                await this.SendErrorResponsePage(context, processRuleResult.Message, processRuleResult.SendErrorResponsePage_HttpStatusCode).ConfigureAwait(false); return;
                            }
                            if (!processRuleResult.ContinueNextRule)
                            {
                                context.Response?.Close(); return;
                            }
                        }
                    }
                }

                //Process Embedded Web API Paths
                if (this.WebAPIs != null)
                {
                    foreach (WebAPIAction action in this.WebAPIs)
                    {
                        if ((httpMethod == null || string.Equals(action.HttpMethod, httpMethod, StringComparison.InvariantCultureIgnoreCase)) && string.Equals(action.Path, absolutePath, StringComparison.InvariantCultureIgnoreCase))
                        {
                            string body = null;
                            using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding)) body = await reader.ReadToEndAsync().ConfigureAwait(false);
                            string            query             = WebUtility.UrlDecode(context.Request.Url.Query);
                            WebAPIActionInput webAPIActionInput = new WebAPIActionInput(httpMethod, query, body, action, context, this.OnErrorLog);
                            var actionResult = action.Action?.Invoke(webAPIActionInput);
                            if (actionResult.Exception != null)
                            {
                                throw actionResult.Exception;
                            }
                            return;
                        }
                    }
                }


                //Process Static Files
                HTTPStreamResult httpStreamResult = await this.ProcessRequestAsync(callerIP, absolutePath, this.Config.WWWDirectoryParsed()).ConfigureAwait(false);

                if (httpStreamResult.HttpStatusCode == HttpStatusCode.OK)
                {
                    await this.SendToOutputAsync(httpStreamResult, context).ConfigureAwait(false);

                    this.OnInfoLog?.Invoke(callerIP + " requested '" + absoluteURL + "' > Served '" + httpStreamResult.FileToRead + "'");
                }
                else
                {
                    if (httpStreamResult.HttpStatusCode == HttpStatusCode.NotFound && !httpStreamResult.FaviconError)
                    {
                        this.OnWarningLog?.Invoke(callerIP + " requested '" + absoluteURL + "' > '" + httpStreamResult.FileToRead + "' does not exist. Returning NOT FOUND");
                    }
                    if (httpStreamResult.HttpStatusCode == HttpStatusCode.InternalServerError)
                    {
                        this.OnErrorLog?.Invoke(httpStreamResult.ErrorMsg);
                    }
                    await SendErrorResponsePage(context, httpStreamResult.ErrorMsg, httpStreamResult.HttpStatusCode).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                var exStr = ex.ToString();
                try
                {
                    if (context != null)
                    {
                        await SendErrorResponsePage(context, exStr, HttpStatusCode.InternalServerError).ConfigureAwait(false);
                    }
                }
                catch { }
                this.OnErrorLog?.Invoke(exStr);
            }
        }