Esempio n. 1
0
        /// <summary>
        /// Invoke event handlers.
        /// </summary>
        /// <param name="callbacks">Callbacks to invoke.</param>
        /// <param name="context">Http listener context.</param>
        /// <returns>True if we should continue handling this request, false if we need to stop handling it.</returns>
        private bool InvokeCallbacks(HandleRequestsCallback callbacks, ServeritoContext context)
        {
            // invoke callback
            try
            {
                callbacks?.Invoke(context);
            }
            // on break callbacks do nothing
            catch (BreakCallbacks)
            {
            }
            // on abort request call abort and return false.
            catch (AbortRequest)
            {
                context.Context.Response.Abort();
                return(false);
            }
            // on stop processing just return false.
            catch (StopProcessingRequest)
            {
                return(false);
            }

            // if we got here we return true to continue handling request.
            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Start listening to incoming requests.
        /// </summary>
        public void Start()
        {
            // start listener
            _listener.Start();

            // do an endless loop that listen to requests
            while (_listener.IsListening)
            {
                // hold the context we are currently processing
                ServeritoContext context = null;

                // handle incoming requests
                try
                {
                    // get context (block until a connection comes in)
                    context = new ServeritoContext()
                    {
                        Context = _listener.GetContext()
                    };

                    // set response default status code and if sending in chunks
                    context.Context.Response.StatusCode  = (int)HttpStatusCode.OK;
                    context.Context.Response.SendChunked = UseChunks;

                    // call new requests callbacks
                    if (!InvokeCallbacks(OnNewRawRequest, context))
                    {
                        continue;
                    }

                    // call the handler function using threads
                    if (UseThreads)
                    {
                        var thisContext = context;
                        ThreadPool.QueueUserWorkItem(o => HandleRequest(thisContext));
                    }
                    // call the handler function without using threads
                    else
                    {
                        HandleRequest(context);
                    }

                    // lose context pointer
                    context = null;
                }
                // Client disconnected or some other error
                catch (Exception e)
                {
                    HandleException(context, e);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Handle an exception while handling a request.
        /// </summary>
        /// <param name="context">Request context, or null if the error happened while trying to get context.</param>
        /// <param name="exp">Exception object.</param>
        private void HandleException(ServeritoContext context, Exception exp)
        {
            // set status code to error by default.
            // note: the try-catch is in case the context was disposed.
            try
            {
                context.Context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            } catch { }

            // call the errors handler callback
            try
            {
                OnException?.Invoke(context, exp);
            }
            catch (BreakCallbacks) { }

            // if need to close requests, try to close it
            if (CloseRequests)
            {
                Utils.TryCloseResponse(context.Context);
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Serve an HTML file as a webpage.
 /// Note: this works using the static files mechanism, eg you must set 'StaticFilesPath' path for it to work.
 /// </summary>
 /// <param name="context">Context containing the request to serve file for.</param>
 /// <param name="path">Path of file to serve, under 'StaticFilesPath'.</param>
 public void ServeHtmlPage(ServeritoContext context, string path)
 {
     ServeStaticFile(context, path, true);
 }
Esempio n. 5
0
        /// <summary>
        /// Serve a static file.
        /// Note: will close request even if 'CloseRequests' is set to false.
        /// </summary>
        /// <param name="context">Context containing the request to serve file for.</param>
        /// <param name="path">Path of file to serve, under 'StaticFilesPath'.</param>
        /// <param name="serveHtml">If true, instead of serving file as a file it will render it as an HTML page.</param>
        public void ServeStaticFile(ServeritoContext context, string path, bool serveHtml = false)
        {
            // static files path not defined? error
            if (StaticFilesPath == null)
            {
                throw new NullReferenceException("To serve static files you must set the 'StaticFilesPath' property.");
            }

            // get file full path
            path = System.IO.Path.Combine(StaticFilesPath, path);

            // file not found? return 404
            if (!System.IO.File.Exists(path))
            {
                // call missing file callback
                if (!InvokeCallbacks(OnMissingFile, context))
                {
                    return;
                }

                // set status code to not found and try closing request
                context.Context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                Utils.TryCloseResponse(context.Context);
                return;
            }

            // set default content type
            context.Context.Response.ContentType = serveHtml ? "text/html" : "application/octet-stream";

            // get filename
            var filename = System.IO.Path.GetFileName(path);

            // set and content disposition for serving html
            if (serveHtml)
            {
                context.Context.Response.Headers.Add("Content-Disposition", "inline;filename=\"" + filename + "\"");
            }
            // set and content disposition for file
            else
            {
                context.Context.Response.Headers.Add("Content-Disposition", "attachment;filename=\"" + filename + "\"");
            }

            // set content type based on known mime types
            if (!serveHtml && SetMimeContentType)
            {
                context.Context.Response.ContentType = Utils.ExtensionToMimeType(System.IO.Path.GetExtension(path)) ??
                                                       context.Context.Response.ContentType;
            }

            // set encoding type
            if (StaticFilesEncodingType != EncodingType.Default)
            {
                context.Context.Response.ContentType += _encodingToCharsetString[(int)StaticFilesEncodingType];
            }

            // read file into response
            var fileContent = StaticFilesReader(path);

            context.Context.Response.OutputStream.Write(fileContent, 0, fileContent.Length);

            // call serving files callback
            if (!InvokeCallbacks(OnServingFile, context))
            {
                return;
            }

            // close response
            Utils.TryCloseResponse(context.Context);
        }
Esempio n. 6
0
        /// <summary>
        /// Handle a single incoming request.
        /// Note: this function can run inside or outside a thread, depends on config.
        /// </summary>
        /// <param name="context"></param>
        public void HandleRequest(ServeritoContext context)
        {
            try
            {
                // handle static files
                if (IsStaticFileRequest(context.Context.Request))
                {
                    ServeStaticFile(context, context.Context.Request.RawUrl.Substring(StaticFilesRootUrl.Length));
                    return;
                }

                // call the before URL matching callback
                if (!InvokeCallbacks(OnUrlMatching, context))
                {
                    return;
                }

                // find view to handle this request
                bool missingUrl = true;
                foreach (var view in _views)
                {
                    // check if view match
                    if (view.UrlPattern.IsMatch(context.Context.Request.RawUrl, context.Context.Request.HttpMethod))
                    {
                        // do before-processing requests callbacks
                        if (!InvokeCallbacks(OnPassingRequestToView, context))
                        {
                            return;
                        }

                        // call view and set no longer missing url
                        view.ViewFunc(context);
                        missingUrl = false;
                    }
                }

                // didn't match any URL? set status code to 404 and call the missed URLs handler
                if (missingUrl)
                {
                    context.Context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    if (!InvokeCallbacks(OnUndefinedURL, context))
                    {
                        return;
                    }
                }
                // found and handled via view? invoke callbacks
                else
                {
                    // invoke end handling request callbacks
                    if (!InvokeCallbacks(OnFinishedProcessingView, context))
                    {
                        return;
                    }
                }

                // invoke end handling request callbacks
                if (!InvokeCallbacks(OnFinishHandlingRequest, context))
                {
                    return;
                }

                // if need to close requests, try to close it
                if (CloseRequests)
                {
                    Utils.TryCloseResponse(context.Context);
                }
            }
            // handle exceptions
            catch (Exception exp)
            {
                HandleException(context, exp);
            }
        }