Beispiel #1
0
        public static HTTPResult <String> GetRequestBodyAsUTF8String(this HTTPRequest Request,
                                                                     HTTPContentType HTTPContentType,
                                                                     Boolean AllowEmptyHTTPBody = false)
        {
            if (Request.ContentType != HTTPContentType)
            {
                return(new HTTPResult <String>(Request, HTTPStatusCode.BadRequest));
            }

            if (!AllowEmptyHTTPBody)
            {
                if (Request.ContentLength == 0)
                {
                    return(new HTTPResult <String>(Request, HTTPStatusCode.BadRequest));
                }

                if (Request.TryReadHTTPBodyStream() == false)
                {
                    return(new HTTPResult <String>(Request, HTTPStatusCode.BadRequest));
                }

                if (Request.HTTPBody == null || Request.HTTPBody.Length == 0)
                {
                    return(new HTTPResult <String>(Request, HTTPStatusCode.BadRequest));
                }
            }

            var RequestBodyString = Request.HTTPBody.ToUTF8String().Trim();

            return(RequestBodyString.IsNullOrEmpty()
                ? AllowEmptyHTTPBody
                      ? new HTTPResult <String>(Result: "")
                      : new HTTPResult <String>(Request, HTTPStatusCode.BadRequest)
                : new HTTPResult <String>(Result: RequestBodyString));
        }
Beispiel #2
0
        public void AddHandler(HTTPDelegate HTTPDelegate,

                               HTTPMethod HTTPMethod           = null,
                               HTTPContentType HTTPContentType = null,

                               HTTPAuthentication HTTPMethodAuthentication  = null,
                               HTTPAuthentication ContentTypeAuthentication = null,

                               HTTPDelegate DefaultErrorHandler = null,
                               URIReplacement AllowReplacement  = URIReplacement.Fail)

        {
            HTTPMethodNode _HTTPMethodNode = null;

            if (!_HTTPMethods.TryGetValue(HTTPMethod, out _HTTPMethodNode))
            {
                _HTTPMethodNode = new HTTPMethodNode(HTTPMethod, HTTPMethodAuthentication, HTTPDelegate, DefaultErrorHandler);
                _HTTPMethods.Add(HTTPMethod, _HTTPMethodNode);
            }

            _HTTPMethodNode.AddHandler(HTTPDelegate,

                                       HTTPContentType,

                                       ContentTypeAuthentication,

                                       DefaultErrorHandler,
                                       AllowReplacement);
        }
Beispiel #3
0
        public void AddHandler(HTTPDelegate HTTPDelegate,

                               String URITemplate              = "/",
                               HTTPMethod HTTPMethod           = null,
                               HTTPContentType HTTPContentType = null,

                               HTTPAuthentication URIAuthentication         = null,
                               HTTPAuthentication HTTPMethodAuthentication  = null,
                               HTTPAuthentication ContentTypeAuthentication = null,

                               HTTPDelegate DefaultErrorHandler = null,
                               URIReplacement AllowReplacement  = URIReplacement.Fail)

        {
            URINode _URINode = null;

            if (!_URINodes.TryGetValue(URITemplate, out _URINode))
            {
                _URINode = new URINode(URITemplate, URIAuthentication, HTTPDelegate, DefaultErrorHandler);
                _URINodes.Add(URITemplate, _URINode);
            }

            _URINode.AddHandler(HTTPDelegate,

                                HTTPMethod,
                                HTTPContentType,

                                HTTPMethodAuthentication,
                                ContentTypeAuthentication,

                                DefaultErrorHandler,
                                AllowReplacement);
        }
Beispiel #4
0
        // Error Handling

        #region (internal) GetErrorHandler(Host, URL, HTTPMethod = null, HTTPContentType = null, HTTPStatusCode = null)

        /// <summary>
        /// Return the best matching error handler for the given parameters.
        /// </summary>
        internal Tuple <MethodInfo, IEnumerable <Object> > GetErrorHandler(String Host,
                                                                           String URL,
                                                                           HTTPMethod HTTPMethod           = null,
                                                                           HTTPContentType HTTPContentType = null,
                                                                           HTTPStatusCode HTTPStatusCode   = null)

        {
            lock (Lock)
            {
                return(null);
            }
        }
Beispiel #5
0
        public void Add(HTTPContentType HTTPContentType, Double Quality = 1)
        {
            #region Initial checks

            if (HTTPContentType == null)
            {
                throw new ArgumentNullException("The given HTTPContentType must not be null!");
            }

            #endregion

            List.Add(new AcceptType(HTTPContentType, Quality));
        }
Beispiel #6
0
        public AcceptType(String AcceptString, Double Quality)
        {
            #region Initial checks

            if (AcceptString.IsNullOrEmpty())
            {
                throw new ArgumentNullException("The given Accept string must not be null or empty!");
            }

            #endregion

            this.ContentType = HTTPContentType.ForMediaType(AcceptString, () => new HTTPContentType(AcceptString));
            this.Quality     = Quality;
        }
Beispiel #7
0
        /// <summary>
        /// Create a new HTTP accept header field.
        /// </summary>
        /// <param name="HTTPContentType">The accepted content type.</param>
        /// <param name="Quality">The preference of the content type.</param>
        public AcceptType(HTTPContentType HTTPContentType, Double Quality = 1.0)
        {
            #region Initial checks

            if (HTTPContentType == null)
            {
                throw new ArgumentNullException("The given HTTPContentType must not be null!");
            }

            #endregion

            this.ContentType = HTTPContentType;
            this.Quality     = Quality;
        }
Beispiel #8
0
        public AcceptTypes(HTTPContentType HTTPContentType)
        {
            #region Initial checks

            if (HTTPContentType == null)
            {
                throw new ArgumentNullException("The given HTTPContentType must not be null!");
            }

            #endregion

            this.List = new List <AcceptType>()
            {
                new AcceptType(HTTPContentType, 1)
            };
        }
Beispiel #9
0
        public AcceptTypes(HTTPContentType FirstHTTPContentType, params HTTPContentType[] MoreHTTPContentTypes)
        {
            #region Initial checks

            if (FirstHTTPContentType == null)
            {
                throw new ArgumentNullException("The given HTTPContentType must not be null!");
            }

            #endregion

            this.List = new List <AcceptType>()
            {
                new AcceptType(FirstHTTPContentType, 1)
            };

            if (MoreHTTPContentTypes != null && MoreHTTPContentTypes.Length > 0)
            {
                this.List.AddRange(from _HTTPContentType in MoreHTTPContentTypes select new AcceptType(_HTTPContentType, 1));
            }
        }
Beispiel #10
0
        public void AddHandler(HTTPDelegate HTTPDelegate,
                               HTTPContentType HTTPContentType = null,
                               HTTPAuthentication ContentTypeAuthentication = null,
                               HTTPDelegate DefaultErrorHandler             = null,
                               URIReplacement AllowReplacement = URIReplacement.Fail)

        {
            ContentTypeNode _ContentTypeNode = null;

            if (HTTPContentType == null)
            {
                //RequestHandler       = HTTPDelegate;
                //DefaultErrorHandler  = DefaultErrorHandler;
            }

            else if (!_HTTPContentTypes.TryGetValue(HTTPContentType, out _ContentTypeNode))
            {
                _ContentTypeNode = new ContentTypeNode(HTTPContentType, ContentTypeAuthentication, HTTPDelegate, DefaultErrorHandler, AllowReplacement);
                _HTTPContentTypes.Add(HTTPContentType, _ContentTypeNode);
            }

            else
            {
                if (_ContentTypeNode.AllowReplacement == URIReplacement.Allow)
                {
                    _ContentTypeNode = new ContentTypeNode(HTTPContentType, ContentTypeAuthentication, HTTPDelegate, DefaultErrorHandler, AllowReplacement);
                    _HTTPContentTypes[HTTPContentType] = _ContentTypeNode;
                }

                else if (_ContentTypeNode.AllowReplacement == URIReplacement.Ignore)
                {
                }

                else
                {
                    throw new ArgumentException("Duplicate HTTP API definition!");
                }
            }
        }
Beispiel #11
0
        public static Boolean TryParseUTF8StringRequestBody(this HTTPRequest Request,
                                                            HTTPContentType ContentType,
                                                            out String Text,
                                                            out HTTPResponse HTTPResponse,
                                                            Boolean AllowEmptyHTTPBody = false)
        {
            #region AllowEmptyHTTPBody

            Text         = null;
            HTTPResponse = null;

            if (Request.ContentLength == 0 && AllowEmptyHTTPBody)
            {
                HTTPResponse = new HTTPResponseBuilder(Request)
                {
                    HTTPStatusCode = HTTPStatusCode.OK,
                };

                return(false);
            }

            #endregion

            #region Get text body

            var RequestBodyString = Request.GetRequestBodyAsUTF8String(ContentType, AllowEmptyHTTPBody);
            if (RequestBodyString.HasErrors)
            {
                HTTPResponse = RequestBodyString.Error;
                return(false);
            }

            #endregion

            Text = RequestBodyString.Data;

            return(true);
        }
Beispiel #12
0
        /// <summary>
        /// Creates a new HTTP ContentTypeNode.
        /// </summary>
        /// <param name="HTTPContentType">The http content type for this service.</param>
        /// <param name="HTTPContentTypeAuthentication">This and all subordinated nodes demand an explicit HTTP content type authentication.</param>
        /// <param name="RequestHandler">The default delegate to call for any request to this URI template.</param>
        /// <param name="DefaultErrorHandler">The default error handling delegate.</param>
        /// <param name="AllowReplacement">How to handle duplicate URI handlers.</param>
        internal ContentTypeNode(HTTPContentType HTTPContentType,
                                 HTTPAuthentication HTTPContentTypeAuthentication = null,
                                 HTTPDelegate RequestHandler      = null,
                                 HTTPDelegate DefaultErrorHandler = null,
                                 URIReplacement AllowReplacement  = URIReplacement.Fail)
        {
            #region Initial checks

            if (HTTPContentType == null)
            {
                throw new ArgumentNullException(nameof(HTTPContentType), "The given HTTP content type must not be null!");
            }

            #endregion

            this.HTTPContentType = HTTPContentType;
            this.HTTPContentTypeAuthentication = HTTPContentTypeAuthentication;
            this.RequestHandler      = RequestHandler;
            this.DefaultErrorHandler = DefaultErrorHandler;
            this.AllowReplacement    = AllowReplacement;

            this.ErrorHandlers = new Dictionary <HTTPStatusCode, HTTPDelegate>();
        }
Beispiel #13
0
        /// <summary>
        /// Parse the string representation of a HTTP accept header field.
        /// </summary>
        /// <param name="AcceptString"></param>
        public AcceptType(String AcceptString)
        {
            this.Quality = 1;

            var SplittedAcceptString = AcceptString.Split(new Char[1] {
                ';'
            }, StringSplitOptions.RemoveEmptyEntries);

            switch (SplittedAcceptString.Length)
            {
            case 1:
                ContentType = HTTPContentType.ForMediaType(AcceptString, () => new HTTPContentType(AcceptString));
                Quality     = 1.0;
                break;

            case 2:
                this.ContentType = HTTPContentType.ForMediaType(AcceptString, () => new HTTPContentType(SplittedAcceptString[0]));
                this.Quality     = Double.Parse(SplittedAcceptString[1].Substring(2));
                break;

            default: throw new ArgumentException("Could not parse the given AcceptString!");
            }
        }
Beispiel #14
0
        public static HTTPResult <XDocument> ParseXMLRequestBody(this HTTPRequest Request,
                                                                 HTTPContentType ContentType = null)
        {
            var RequestBodyString = Request.GetRequestBodyAsUTF8String(ContentType != null ? ContentType : HTTPContentType.XMLTEXT_UTF8);

            if (RequestBodyString.HasErrors)
            {
                return(new HTTPResult <XDocument>(RequestBodyString.Error));
            }

            XDocument RequestBodyXML;

            try
            {
                RequestBodyXML = XDocument.Parse(RequestBodyString.Data);
            }
            catch (Exception e)
            {
                Log.WriteLine(e.Message);
                return(new HTTPResult <XDocument>(Request, HTTPStatusCode.BadRequest));
            }

            return(new HTTPResult <XDocument>(RequestBodyXML));
        }
Beispiel #15
0
        /// <summary>
        /// Returns a resource from the given file system location.
        /// </summary>
        /// <param name="HTTPServer">A HTTP server.</param>
        /// <param name="Hostname">The HTTP hostname.</param>
        /// <param name="URITemplate">An URI template.</param>
        /// <param name="ResourceFilenameBuilder">The path to the file within the assembly.</param>
        /// <param name="DefaultFile">If an error occures, return this file.</param>
        /// <param name="ResponseContentType">Set the HTTP MIME content-type of the file. If null try to autodetect the content type based on the filename extention.</param>
        /// <param name="CacheControl">Set the HTTP cache control response header.</param>
        public static void RegisterFilesystemFile(this IHTTPServer HTTPServer,
                                                  HTTPHostname Hostname,
                                                  String URITemplate,
                                                  Func <String[], String> ResourceFilenameBuilder,
                                                  String DefaultFile = null,
                                                  HTTPContentType ResponseContentType = null,
                                                  String CacheControl = "no-cache")
        {
            #region Get the appropriate content type based on the suffix returned by the ResourceFilenameBuilder

            // NumberOfTemplateParameters
            var _ResourceFilename = ResourceFilenameBuilder(Enumerable.Repeat("", URITemplate.Count(c => c == '{')).ToArray());

            if (ResponseContentType == null)
            {
                switch (_ResourceFilename.Remove(0, _ResourceFilename.LastIndexOf(".") + 1))
                {
                case "htm":  ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                case "html": ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                case "css":  ResponseContentType = HTTPContentType.CSS_UTF8;        break;

                case "gif":  ResponseContentType = HTTPContentType.GIF;             break;

                case "jpg":  ResponseContentType = HTTPContentType.JPEG;            break;

                case "jpeg": ResponseContentType = HTTPContentType.JPEG;            break;

                case "svg":  ResponseContentType = HTTPContentType.SVG;             break;

                case "png":  ResponseContentType = HTTPContentType.PNG;             break;

                case "ico":  ResponseContentType = HTTPContentType.ICO;             break;

                case "swf":  ResponseContentType = HTTPContentType.SWF;             break;

                case "js":   ResponseContentType = HTTPContentType.JAVASCRIPT_UTF8; break;

                case "txt":  ResponseContentType = HTTPContentType.TEXT_UTF8;       break;

                default:     ResponseContentType = HTTPContentType.OCTETSTREAM;     break;
                }
            }

            #endregion

            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate,
                                         HTTPContentType: ResponseContentType,
                                         HTTPDelegate: async Request => {
                var ResourceFilename = ResourceFilenameBuilder(Request.ParsedURIParameters);

                if (!File.Exists(ResourceFilename) && DefaultFile != null)
                {
                    ResourceFilename = DefaultFile;
                }

                if (File.Exists(ResourceFilename))
                {
                    var FileStream = File.OpenRead(ResourceFilename);
                    if (FileStream != null)
                    {
                        return(new HTTPResponseBuilder(Request)
                        {
                            HTTPStatusCode = HTTPStatusCode.OK,
                            Server = HTTPServer.DefaultServerName,
                            Date = DateTime.Now,
                            ContentType = ResponseContentType,
                            ContentStream = FileStream,
                            CacheControl = CacheControl,
                            Connection = "close",
                        });
                    }
                }

                return(new HTTPResponseBuilder(Request)
                {
                    HTTPStatusCode = HTTPStatusCode.NotFound,
                    Server = HTTPServer.DefaultServerName,
                    Date = DateTime.Now,
                    CacheControl = "no-cache",
                    Connection = "close",
                });
            }, AllowReplacement: URIReplacement.Fail);

            return;
        }
Beispiel #16
0
        /// <summary>
        /// Returns internal resources embedded within the given assembly.
        /// </summary>
        /// <param name="HTTPServer">A HTTP server.</param>
        /// <param name="Hostname">The HTTP hostname.</param>
        /// <param name="URITemplate">An URI template.</param>
        /// <param name="ResourcePath">The path to the file within the assembly.</param>
        /// <param name="ResourceAssembly">Optionally the assembly where the resources are located (default: the calling assembly).</param>
        /// <param name="DefaultFilename">The default file to load.</param>
        /// <param name="HTTPRealm">An optional realm for HTTP basic authentication.</param>
        /// <param name="HTTPLogin">An optional login for HTTP basic authentication.</param>
        /// <param name="HTTPPassword">An optional password for HTTP basic authentication.</param>
        public static void RegisterResourcesFolder(this IHTTPServer HTTPServer,
                                                   HTTPHostname Hostname,
                                                   String URITemplate,
                                                   String ResourcePath,
                                                   Assembly ResourceAssembly = null,
                                                   String DefaultFilename    = "index.html",
                                                   String HTTPRealm          = null,
                                                   String HTTPLogin          = null,
                                                   String HTTPPassword       = null)
        {
            if (ResourceAssembly == null)
            {
                ResourceAssembly = Assembly.GetCallingAssembly();
            }


            HTTPDelegate GetEmbeddedResources = async Request => {
                #region Check HTTP Basic Authentication

                if (HTTPLogin.IsNotNullOrEmpty() && HTTPPassword.IsNotNullOrEmpty())
                {
                    if (Request.Authorization == null ||
                        Request.Authorization.Username != HTTPLogin ||
                        Request.Authorization.Password != HTTPPassword)
                    {
                        return new HTTPResponseBuilder(Request)
                               {
                                   HTTPStatusCode  = HTTPStatusCode.Unauthorized,
                                   Server          = HTTPServer.DefaultServerName,
                                   Date            = DateTime.Now,
                                   WWWAuthenticate = @"Basic realm=""" + HTTPRealm + @"""",
                                   ContentType     = HTTPContentType.TEXT_UTF8,
                                   Content         = "Unauthorized Access!".ToUTF8Bytes(),
                                   Connection      = "close"
                               }
                    }
                    ;
                }

                #endregion


                HTTPContentType ResponseContentType = null;

                var FilePath = (Request.ParsedURIParameters != null && Request.ParsedURIParameters.Length > 0)
                                      ? Request.ParsedURIParameters.Last().Replace("/", ".")
                                      : DefaultFilename.Replace("/", ".");

                var FileStream = ResourceAssembly.GetManifestResourceStream(ResourcePath + "." + FilePath);

                if (FileStream != null)
                {
                    #region Choose HTTP Content Type based on the file name extention...

                    var FileName = FilePath.Substring(FilePath.LastIndexOf("/") + 1);

                    // Get the appropriate content type based on the suffix of the requested resource
                    switch (FileName.Remove(0, FileName.LastIndexOf(".") + 1))
                    {
                    case "htm": ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                    case "html": ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                    case "css": ResponseContentType = HTTPContentType.CSS_UTF8;        break;

                    case "gif": ResponseContentType = HTTPContentType.GIF;             break;

                    case "jpg": ResponseContentType = HTTPContentType.JPEG;            break;

                    case "jpeg": ResponseContentType = HTTPContentType.JPEG;            break;

                    case "svg": ResponseContentType = HTTPContentType.SVG;             break;

                    case "png": ResponseContentType = HTTPContentType.PNG;             break;

                    case "ico": ResponseContentType = HTTPContentType.ICO;             break;

                    case "swf": ResponseContentType = HTTPContentType.SWF;             break;

                    case "js": ResponseContentType = HTTPContentType.JAVASCRIPT_UTF8; break;

                    case "txt": ResponseContentType = HTTPContentType.TEXT_UTF8;       break;

                    case "xml":  ResponseContentType = HTTPContentType.XML_UTF8;        break;

                    default:     ResponseContentType = HTTPContentType.OCTETSTREAM;     break;
                    }

                    #endregion

                    #region Create HTTP Response

                    return(new HTTPResponseBuilder(Request)
                    {
                        HTTPStatusCode = HTTPStatusCode.OK,
                        Server = HTTPServer.DefaultServerName,
                        Date = DateTime.Now,
                        ContentType = ResponseContentType,
                        ContentStream = FileStream,
                        CacheControl = "public, max-age=300",
                        //Expires          = "Mon, 25 Jun 2015 21:31:12 GMT",
                        KeepAlive = new KeepAliveType(TimeSpan.FromMinutes(5), 500),
                        Connection = "Keep-Alive",
                    });

                    #endregion
                }

                else
                {
                    #region Try to find a appropriate customized errorpage...

                    Stream ErrorStream = null;

                    Request.BestMatchingAcceptType = Request.Accept.BestMatchingContentType(new HTTPContentType[] { HTTPContentType.HTML_UTF8, HTTPContentType.TEXT_UTF8 });

                    if (Request.BestMatchingAcceptType == HTTPContentType.HTML_UTF8)
                    {
                        ResponseContentType = HTTPContentType.HTML_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourcePath.Substring(0, ResourcePath.LastIndexOf(".")) + ".ErrorPages." + "404.html");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.TEXT_UTF8)
                    {
                        ResponseContentType = HTTPContentType.TEXT_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourcePath.Substring(0, ResourcePath.LastIndexOf(".")) + ".ErrorPages." + "404.txt");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.JSON_UTF8)
                    {
                        ResponseContentType = HTTPContentType.JSON_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourcePath.Substring(0, ResourcePath.LastIndexOf(".")) + ".ErrorPages." + "404.js");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.XML_UTF8)
                    {
                        ResponseContentType = HTTPContentType.XML_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourcePath.Substring(0, ResourcePath.LastIndexOf(".")) + ".ErrorPages." + "404.xml");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.ALL)
                    {
                        ResponseContentType = HTTPContentType.HTML_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourcePath.Substring(0, ResourcePath.LastIndexOf(".")) + ".ErrorPages." + "404.html");
                    }

                    if (ErrorStream != null)
                    {
                        return new HTTPResponseBuilder(Request)
                               {
                                   HTTPStatusCode = HTTPStatusCode.NotFound,
                                   Server         = HTTPServer.DefaultServerName,
                                   Date           = DateTime.Now,
                                   ContentType    = ResponseContentType,
                                   ContentStream  = ErrorStream,
                                   CacheControl   = "no-cache",
                                   Connection     = "close",
                               }
                    }
                    ;

                    #endregion

                    #region ...or send a default error page!

                    else
                    {
                        return new HTTPResponseBuilder(Request)
                               {
                                   HTTPStatusCode = HTTPStatusCode.NotFound,
                                   Server         = HTTPServer.DefaultServerName,
                                   Date           = DateTime.Now,
                                   CacheControl   = "no-cache",
                                   Connection     = "close",
                               }
                    };

                    #endregion
                }
            };


            // ~/map
            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate.EndsWith("/", StringComparison.InvariantCulture) ? URITemplate.Substring(0, URITemplate.Length) : URITemplate,
                                         HTTPDelegate: GetEmbeddedResources);

            // ~/map/
            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate + (URITemplate.EndsWith("/", StringComparison.InvariantCulture) ? "" : "/"),
                                         HTTPDelegate: GetEmbeddedResources);

            // ~/map/file.name
            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate + (URITemplate.EndsWith("/", StringComparison.InvariantCulture) ? "{ResourceName}" : "/{ResourceName}"),
                                         HTTPDelegate: GetEmbeddedResources);
        }
Beispiel #17
0
        /// <summary>
        /// Returns internal resources embedded within the given assembly.
        /// </summary>
        /// <param name="HTTPServer">A HTTP server.</param>
        /// <param name="Hostname">The HTTP hostname.</param>
        /// <param name="URITemplate">An URI template.</param>
        /// <param name="ResourceAssembly">The assembly where the resources are located.</param>
        /// <param name="ResourceFilename">The path to the file within the assembly.</param>
        /// <param name="ResponseContentType">Set the HTTP MIME content-type of the file. If null try to autodetect the content type based on the filename extention.</param>
        /// <param name="CacheControl">Set the HTTP cache control response header.</param>
        public static void RegisterResourcesFile(this IHTTPServer HTTPServer,
                                                 HTTPHostname Hostname,
                                                 String URITemplate,
                                                 Assembly ResourceAssembly,
                                                 String ResourceFilename,
                                                 HTTPContentType ResponseContentType = null,
                                                 String CacheControl = "no-cache")
        {
            #region Get the appropriate content type based on the suffix of the requested resource

            if (ResponseContentType == null)
            {
                switch (ResourceFilename.Remove(0, ResourceFilename.LastIndexOf(".") + 1))
                {
                case "htm":  ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                case "html": ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                case "css":  ResponseContentType = HTTPContentType.CSS_UTF8;        break;

                case "gif":  ResponseContentType = HTTPContentType.GIF;             break;

                case "jpg":  ResponseContentType = HTTPContentType.JPEG;            break;

                case "jpeg": ResponseContentType = HTTPContentType.JPEG;            break;

                case "svg":  ResponseContentType = HTTPContentType.SVG;             break;

                case "png":  ResponseContentType = HTTPContentType.PNG;             break;

                case "ico":  ResponseContentType = HTTPContentType.ICO;             break;

                case "swf":  ResponseContentType = HTTPContentType.SWF;             break;

                case "js":   ResponseContentType = HTTPContentType.JAVASCRIPT_UTF8; break;

                case "txt":  ResponseContentType = HTTPContentType.TEXT_UTF8;       break;

                case "xml":  ResponseContentType = HTTPContentType.XML_UTF8;        break;

                default:     ResponseContentType = HTTPContentType.OCTETSTREAM;     break;
                }
            }

            #endregion

            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate,
                                         HTTPContentType: ResponseContentType,
                                         HTTPDelegate: async Request => {
                var FileStream = ResourceAssembly.GetManifestResourceStream(ResourceFilename);

                if (FileStream != null)
                {
                    return new HTTPResponseBuilder(Request)
                    {
                        HTTPStatusCode = HTTPStatusCode.OK,
                        Server         = HTTPServer.DefaultServerName,
                        Date           = DateTime.Now,
                        ContentType    = ResponseContentType,
                        ContentStream  = FileStream,
                        CacheControl   = CacheControl,
                        Connection     = "close",
                    }
                }
                ;

                else
                {
                    #region Try to find a appropriate customized errorpage...

                    Stream ErrorStream = null;

                    Request.BestMatchingAcceptType = Request.Accept.BestMatchingContentType(new HTTPContentType[] { HTTPContentType.HTML_UTF8, HTTPContentType.TEXT_UTF8 });

                    if (Request.BestMatchingAcceptType == HTTPContentType.HTML_UTF8)
                    {
                        ResponseContentType = HTTPContentType.HTML_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourceFilename.Substring(0, ResourceFilename.LastIndexOf(".")) + ".ErrorPages." + "404.html");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.TEXT_UTF8)
                    {
                        ResponseContentType = HTTPContentType.TEXT_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourceFilename.Substring(0, ResourceFilename.LastIndexOf(".")) + ".ErrorPages." + "404.txt");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.JSON_UTF8)
                    {
                        ResponseContentType = HTTPContentType.JSON_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourceFilename.Substring(0, ResourceFilename.LastIndexOf(".")) + ".ErrorPages." + "404.js");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.XML_UTF8)
                    {
                        ResponseContentType = HTTPContentType.XML_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourceFilename.Substring(0, ResourceFilename.LastIndexOf(".")) + ".ErrorPages." + "404.xml");
                    }

                    else if (Request.BestMatchingAcceptType == HTTPContentType.ALL)
                    {
                        ResponseContentType = HTTPContentType.HTML_UTF8;
                        ErrorStream         = ResourceAssembly.GetManifestResourceStream(ResourceFilename.Substring(0, ResourceFilename.LastIndexOf(".")) + ".ErrorPages." + "404.html");
                    }

                    if (ErrorStream != null)
                    {
                        return new HTTPResponseBuilder(Request)
                        {
                            HTTPStatusCode = HTTPStatusCode.NotFound,
                            ContentType    = ResponseContentType,
                            ContentStream  = ErrorStream,
                            CacheControl   = "no-cache",
                            Connection     = "close",
                        }
                    }
                    ;

                    #endregion

                    #region ...or send a default error page!

                    else
                    {
                        return new HTTPResponseBuilder(Request)
                        {
                            HTTPStatusCode = HTTPStatusCode.NotFound,
                            Server         = HTTPServer.DefaultServerName,
                            Date           = DateTime.Now,
                            CacheControl   = "no-cache",
                            Connection     = "close",
                        }
                    };

                    #endregion
                }
            }, AllowReplacement: URIReplacement.Fail);

            return;
        }
Beispiel #18
0
 /// <summary>
 /// Add a HTTPContentType and its quality to the Accept header field.
 /// </summary>
 /// <param name="HTTPContentType">A HTTPContentType.</param>
 /// <param name="Quality">The quality of the HTTPContentType.</param>
 public HTTPRequestBuilder AddAccept(HTTPContentType HTTPContentType, Double Quality = 1)
 {
     this.Accept.Add(HTTPContentType, Quality);
     return(this);
 }
Beispiel #19
0
 /// <summary>
 /// Set the HTTP Content-Type header field.
 /// </summary>
 /// <param name="ContentType">The type of the HTTP content/body.</param>
 public HTTPRequestBuilder SetContentType(HTTPContentType ContentType)
 {
     this.ContentType = ContentType;
     return(this);
 }
Beispiel #20
0
        /// <summary>
        /// Add a method call back for the given URI template and
        /// add a HTTP Sever Sent Events source.
        /// </summary>
        /// <param name="EventIdentification">The unique identification of the event source.</param>
        /// <param name="URITemplate">The URI template.</param>
        ///
        /// <param name="MaxNumberOfCachedEvents">Maximum number of cached events.</param>
        /// <param name="RetryIntervall">The retry intervall.</param>
        /// <param name="LogfileName">A delegate to create a filename for storing and reloading events.</param>
        ///
        /// <param name="Hostname">The HTTP host.</param>
        /// <param name="HTTPMethod">The HTTP method.</param>
        /// <param name="HTTPContentType">The HTTP content type.</param>
        ///
        /// <param name="HostAuthentication">Whether this method needs explicit host authentication or not.</param>
        /// <param name="URIAuthentication">Whether this method needs explicit uri authentication or not.</param>
        /// <param name="HTTPMethodAuthentication">Whether this method needs explicit HTTP method authentication or not.</param>
        ///
        /// <param name="DefaultErrorHandler">The default error handler.</param>
        internal HTTPEventSource AddEventSource(String EventIdentification,
                                                String URITemplate,

                                                UInt32 MaxNumberOfCachedEvents = 500,
                                                TimeSpan?RetryIntervall        = null,
                                                Func <String, DateTime, String> LogfileName = null,

                                                HTTPHostname Hostname           = null,
                                                HTTPMethod HTTPMethod           = null,
                                                HTTPContentType HTTPContentType = null,

                                                HTTPAuthentication HostAuthentication       = null,
                                                HTTPAuthentication URIAuthentication        = null,
                                                HTTPAuthentication HTTPMethodAuthentication = null,

                                                HTTPDelegate DefaultErrorHandler = null)

        {
            lock (Lock)
            {
                #region Get or Create Event Source

                HTTPEventSource _HTTPEventSource;

                if (!_EventSources.TryGetValue(EventIdentification, out _HTTPEventSource))
                {
                    _HTTPEventSource = _EventSources.AddAndReturnValue(EventIdentification,
                                                                       new HTTPEventSource(EventIdentification,
                                                                                           MaxNumberOfCachedEvents,
                                                                                           RetryIntervall,
                                                                                           LogfileName));
                }

                #endregion

                #region Define HTTP Delegate

                HTTPDelegate _HTTPDelegate = Request => {
                    var _LastEventId        = 0UL;
                    var _Client_LastEventId = 0UL;
                    var _EventSource        = GetEventSource(EventIdentification);

                    if (Request.TryGet <UInt64>("Last-Event-ID", out _Client_LastEventId))
                    {
                        _LastEventId = _Client_LastEventId;
                    }

                    var _HTTPEvents = (from _HTTPEvent
                                       in     _EventSource.GetAllEventsGreater(_LastEventId)
                                       where  _HTTPEvent != null
                                       select _HTTPEvent.ToString())
                                      .ToArray();      // For thread safety!

                    // Transform HTTP events into an UTF8 string
                    var _ResourceContent = String.Empty;

                    if (_HTTPEvents.Length > 0)
                    {
                        _ResourceContent = Environment.NewLine + _HTTPEvents.Aggregate((a, b) => a + Environment.NewLine + b) + Environment.NewLine;
                    }

                    else
                    {
                        _ResourceContent += Environment.NewLine + "retry: " + ((UInt32)_EventSource.RetryIntervall.TotalMilliseconds) + Environment.NewLine + Environment.NewLine;
                    }


                    return(Task.FromResult <HTTPResponse>(
                               new HTTPResponseBuilder(Request)
                    {
                        HTTPStatusCode = HTTPStatusCode.OK,
                        ContentType = HTTPContentType.EVENTSTREAM,
                        CacheControl = "no-cache",
                        Connection = "keep-alive",
                        KeepAlive = new KeepAliveType(TimeSpan.FromSeconds(2 * _EventSource.RetryIntervall.TotalSeconds)),
                        Content = _ResourceContent.ToUTF8Bytes()
                    }));
                };

                #endregion

                AddHandler(_HTTPDelegate,
                           Hostname,
                           URITemplate,
                           HTTPMethod ?? HTTPMethod.GET,
                           HTTPContentType.EVENTSTREAM,

                           HostAuthentication,
                           URIAuthentication,
                           HTTPMethodAuthentication,
                           null,

                           DefaultErrorHandler);

                return(_HTTPEventSource);
            }
        }
Beispiel #21
0
        /// <summary>
        /// Returns resources from the given file system location.
        /// </summary>
        /// <param name="HTTPServer">A HTTP server.</param>
        /// <param name="Hostname">The HTTP hostname.</param>
        /// <param name="URITemplate">An URI template.</param>
        /// <param name="ResourcePath">The path to the file within the assembly.</param>
        /// <param name="DefaultFilename">The default file to load.</param>
        public static void RegisterFilesystemFolder(this IHTTPServer HTTPServer,
                                                    HTTPHostname Hostname,
                                                    String URITemplate,
                                                    Func <String[], String> ResourcePath,
                                                    String DefaultFilename = "index.html")
        {
            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate + (URITemplate.EndsWith("/", StringComparison.InvariantCulture) ? "{ResourceName}" : "/{ResourceName}"),
                                         HTTPContentType: HTTPContentType.PNG,
                                         HTTPDelegate: async Request => {
                HTTPContentType ResponseContentType = null;

                var NumberOfTemplateParameters = URITemplate.Count(c => c == '{');

                var FilePath = (Request.ParsedURIParameters != null && Request.ParsedURIParameters.Length > NumberOfTemplateParameters)
                                                                ? Request.ParsedURIParameters.Last().Replace('/', Path.DirectorySeparatorChar)
                                                                : DefaultFilename.Replace('/', Path.DirectorySeparatorChar);

                var FileStream = File.OpenRead(ResourcePath(Request.ParsedURIParameters) + Path.DirectorySeparatorChar + FilePath);

                if (FileStream != null)
                {
                    #region Choose HTTP Content Type based on the file name extention...

                    var FileName = FilePath.Substring(FilePath.LastIndexOf("/") + 1);

                    // Get the appropriate content type based on the suffix of the requested resource
                    switch (FileName.Remove(0, FileName.LastIndexOf(".") + 1))
                    {
                    case "htm":  ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                    case "html": ResponseContentType = HTTPContentType.HTML_UTF8;       break;

                    case "css":  ResponseContentType = HTTPContentType.CSS_UTF8;        break;

                    case "gif":  ResponseContentType = HTTPContentType.GIF;             break;

                    case "jpg":  ResponseContentType = HTTPContentType.JPEG;            break;

                    case "jpeg": ResponseContentType = HTTPContentType.JPEG;            break;

                    case "svg":  ResponseContentType = HTTPContentType.SVG;             break;

                    case "png":  ResponseContentType = HTTPContentType.PNG;             break;

                    case "ico":  ResponseContentType = HTTPContentType.ICO;             break;

                    case "swf":  ResponseContentType = HTTPContentType.SWF;             break;

                    case "js":   ResponseContentType = HTTPContentType.JAVASCRIPT_UTF8; break;

                    case "txt":  ResponseContentType = HTTPContentType.TEXT_UTF8;       break;

                    default:     ResponseContentType = HTTPContentType.OCTETSTREAM;     break;
                    }

                    #endregion

                    #region Create HTTP Response

                    return(new HTTPResponseBuilder(Request)
                    {
                        HTTPStatusCode = HTTPStatusCode.OK,
                        Server = HTTPServer.DefaultServerName,
                        Date = DateTime.Now,
                        ContentType = ResponseContentType,
                        ContentStream = FileStream,
                        CacheControl = "public, max-age=300",
                        //Expires         = "Mon, 25 Jun 2015 21:31:12 GMT",
                        KeepAlive = new KeepAliveType(TimeSpan.FromMinutes(5), 500),
                        Connection = "Keep-Alive",
                    });

                    #endregion
                }

                else
                {
                    return new HTTPResponseBuilder(Request)
                    {
                        HTTPStatusCode = HTTPStatusCode.NotFound,
                        Server         = HTTPServer.DefaultServerName,
                        Date           = DateTime.Now,
                        CacheControl   = "no-cache",
                        Connection     = "close",
                    }
                };
            }, AllowReplacement: URIReplacement.Fail);

            return;
        }
Beispiel #22
0
        /// <summary>
        /// Returns resources from the given file system location.
        /// </summary>
        /// <param name="HTTPServer">A HTTP server.</param>
        /// <param name="URITemplate">An URI template.</param>
        /// <param name="DefaultFilename">The default file to load.</param>
        public static void RegisterWatchedFileSystemFolder(this IHTTPServer HTTPServer,
                                                           HTTPHostname Hostname,
                                                           String URITemplate,
                                                           String FileSystemLocation,
                                                           String HTTPSSE_EventIdentification,
                                                           String HTTPSSE_URITemplate,
                                                           //          Func<String[], String>  ResourcePath,
                                                           String DefaultFilename = "index.html")
        {
            #region Setup file system watcher

            var watcher = new FileSystemWatcher()
            {
                Path         = FileSystemLocation,
                NotifyFilter = NotifyFilters.FileName |
                               NotifyFilters.DirectoryName |
                               NotifyFilters.LastWrite,
                //Filter                 = "*.html",//|*.css|*.js|*.json",
                IncludeSubdirectories = true,
                InternalBufferSize    = 4 * 4096
            };

            watcher.Created += (s, e) => FileWasChanged(HTTPServer, HTTPSSE_EventIdentification, e.ChangeType.ToString(), e.FullPath.Remove(0, FileSystemLocation.Length).Replace(Path.DirectorySeparatorChar, '/'));
            watcher.Changed += (s, e) => FileWasChanged(HTTPServer, HTTPSSE_EventIdentification, e.ChangeType.ToString(), e.FullPath.Remove(0, FileSystemLocation.Length).Replace(Path.DirectorySeparatorChar, '/'));
            watcher.Renamed += FileWasRenamed;
            watcher.Deleted += (s, e) => FileWasChanged(HTTPServer, HTTPSSE_EventIdentification, e.ChangeType.ToString(), e.FullPath.Remove(0, FileSystemLocation.Length).Replace(Path.DirectorySeparatorChar, '/'));
            watcher.Error   += FileWatcherError;

            #endregion

            HTTPServer.AddEventSource(HTTPSSE_EventIdentification, URITemplate: HTTPSSE_URITemplate);

            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate + (URITemplate.EndsWith("/", StringComparison.InvariantCulture) ? "{ResourceName}" : "/{ResourceName}"),
                                         HTTPContentType.PNG,
                                         HTTPDelegate: async Request => {
                HTTPContentType ResponseContentType = null;

                var NumberOfTemplateParameters = URITemplate.Count(c => c == '{');

                var FilePath = (Request.ParsedURIParameters != null && Request.ParsedURIParameters.Length > NumberOfTemplateParameters)
                                                                   ? Request.ParsedURIParameters.Last().Replace('/', Path.DirectorySeparatorChar)
                                                                   : DefaultFilename.Replace('/', Path.DirectorySeparatorChar);

                try
                {
                    var FileStream = File.OpenRead(FileSystemLocation + Path.DirectorySeparatorChar + FilePath);

                    if (FileStream != null)
                    {
                        #region Choose HTTP Content Type based on the file name extention...

                        ResponseContentType = HTTPContentType.ForFileExtention(FilePath.Remove(0, FilePath.LastIndexOf(".", StringComparison.InvariantCulture) + 1),
                                                                               () => HTTPContentType.OCTETSTREAM).FirstOrDefault();

                        #endregion

                        #region Create HTTP Response

                        return(new HTTPResponseBuilder(Request)
                        {
                            HTTPStatusCode = HTTPStatusCode.OK,
                            Server = HTTPServer.DefaultServerName,
                            Date = DateTime.Now,
                            ContentType = ResponseContentType,
                            ContentStream = FileStream,
                            CacheControl = "public, max-age=300",
                            //Expires         = "Mon, 25 Jun 2015 21:31:12 GMT",
                            KeepAlive = new KeepAliveType(TimeSpan.FromMinutes(5), 500),
                            Connection = "Keep-Alive"
                        });

                        #endregion
                    }
                }
                catch (FileNotFoundException e)
                {
                }

                return(new HTTPResponseBuilder(Request)
                {
                    HTTPStatusCode = HTTPStatusCode.NotFound,
                    Server = HTTPServer.DefaultServerName,
                    Date = DateTime.Now,
                    ContentType = HTTPContentType.TEXT_UTF8,
                    Content = "Error 404 - Not found!".ToUTF8Bytes(),
                    CacheControl = "no-cache",
                    Connection = "close",
                });
            }, AllowReplacement: URIReplacement.Fail);


            // And now my watch begins...
            watcher.EnableRaisingEvents = true;
        }
Beispiel #23
0
        // Method Callbacks

        #region (internal) AddHandler(HTTPDelegate, Hostname = "*", URITemplate = "/", HTTPMethod = null, HTTPContentType = null, HostAuthentication = null, URIAuthentication = null, HTTPMethodAuthentication = null, ContentTypeAuthentication = null, DefaultErrorHandler = null)

        /// <summary>
        /// Add a method callback for the given URI template.
        /// </summary>
        /// <param name="HTTPDelegate">A delegate called for each incoming HTTP request.</param>
        /// <param name="Hostname">The HTTP hostname.</param>
        /// <param name="URITemplate">The URI template.</param>
        /// <param name="HTTPMethod">The HTTP method.</param>
        /// <param name="HTTPContentType">The HTTP content type.</param>
        /// <param name="HostAuthentication">Whether this method needs explicit host authentication or not.</param>
        /// <param name="URIAuthentication">Whether this method needs explicit uri authentication or not.</param>
        /// <param name="HTTPMethodAuthentication">Whether this method needs explicit HTTP method authentication or not.</param>
        /// <param name="ContentTypeAuthentication">Whether this method needs explicit HTTP content type authentication or not.</param>
        /// <param name="DefaultErrorHandler">The default error handler.</param>
        internal void AddHandler(HTTPDelegate HTTPDelegate,

                                 HTTPHostname Hostname           = null,
                                 String URITemplate              = "/",
                                 HTTPMethod HTTPMethod           = null,
                                 HTTPContentType HTTPContentType = null,

                                 HTTPAuthentication HostAuthentication        = null,
                                 HTTPAuthentication URIAuthentication         = null,
                                 HTTPAuthentication HTTPMethodAuthentication  = null,
                                 HTTPAuthentication ContentTypeAuthentication = null,

                                 HTTPDelegate DefaultErrorHandler = null,
                                 URIReplacement AllowReplacement  = URIReplacement.Fail)

        {
            lock (Lock)
            {
                #region Initial Checks

                if (HTTPDelegate == null)
                {
                    throw new ArgumentNullException("HTTPDelegate", "The given parameter must not be null!");
                }

                if (Hostname == null)
                {
                    Hostname = HTTPHostname.Any;
                }

                if (URITemplate.IsNullOrEmpty())
                {
                    URITemplate = "/";
                }

                if (HTTPMethod == null && HTTPContentType != null)
                {
                    throw new ArgumentNullException("If HTTPMethod is null the HTTPContentType must also be null!");
                }

                #endregion

                #region AddOrUpdate HostNode

                HostnameNode _HostnameNode = null;
                if (!_HostnameNodes.TryGetValue(Hostname, out _HostnameNode))
                {
                    _HostnameNode = new HostnameNode(Hostname, HostAuthentication, HTTPDelegate, DefaultErrorHandler);
                    _HostnameNodes.Add(Hostname, _HostnameNode);
                }

                #endregion

                _HostnameNode.AddHandler(HTTPDelegate,

                                         URITemplate,
                                         HTTPMethod,
                                         HTTPContentType,

                                         URIAuthentication,
                                         HTTPMethodAuthentication,
                                         ContentTypeAuthentication,

                                         DefaultErrorHandler,
                                         AllowReplacement);
            }
        }