Exemple #1
0
 /// <summary>
 /// Return the RAW request header.
 /// </summary>
 public static void RegisterRAWRequestHandler(this HTTPServer HTTPServer,
                                              HTTPHostname Hostname,
                                              String URITemplate,
                                              HTTPMethod HTTPMethod = null)
 {
     HTTPServer.AddMethodCallback(Hostname,
                                  HTTPMethod:    HTTPMethod ?? HTTPMethod.GET,
                                  URITemplate:   URITemplate,
                                  HTTPDelegate:  async Request => {
         return(new HTTPResponseBuilder(Request)
         {
             HTTPStatusCode = HTTPStatusCode.OK,
             Server = HTTPServer.DefaultServerName,
             Date = DateTime.Now,
             CacheControl = "no-cache",
             Connection = "close",
             ContentType = HTTPContentType.TEXT_UTF8,
             Content = ("Incoming http connection from '" + Request.RemoteSocket + "'" +
                        Environment.NewLine + Environment.NewLine +
                        Request.RawHTTPHeader +
                        Environment.NewLine + Environment.NewLine +
                        "Method => " + Request.HTTPMethod + Environment.NewLine +
                        "URL => " + Request.URI + Environment.NewLine +
                        "QueryString => " + Request.QueryString + Environment.NewLine +
                        "Protocol => " + Request.ProtocolName + Environment.NewLine +
                        "Version => " + Request.ProtocolVersion + Environment.NewLine).ToUTF8Bytes()
         });
     });
 }
Exemple #2
0
 /// <summary>
 /// Register a MovedTemporarily handler.
 /// </summary>
 public static void RegisterMovedTemporarilyHandler(this HTTPServer HTTPServer,
                                                    HTTPHostname Hostname,
                                                    String URITemplate,
                                                    String URITarget)
 {
     HTTPServer.AddMethodCallback(Hostname,
                                  HTTPMethod.GET,
                                  URITemplate,
                                  HTTPDelegate: async Request => HTTPTools.MovedTemporarily(Request, URITarget));
 }
Exemple #3
0
        /// <summary>
        /// Creates a new hostname node.
        /// </summary>
        /// <param name="Hostname">The hostname(s) for this (virtual) http service.</param>
        /// <param name="RequestHandler">The default delegate to call for any request to this hostname.</param>
        /// <param name="HostAuthentication">This and all subordinated nodes demand an explicit host authentication.</param>
        /// <param name="DefaultErrorHandler">The default error handling delegate.</param>
        internal HostnameNode(HTTPHostname Hostname,
                              HTTPAuthentication HostAuthentication = null,
                              HTTPDelegate RequestHandler           = null,
                              HTTPDelegate DefaultErrorHandler      = null)

        {
            #region Check Hostname

            if (Hostname == null)
            {
                throw new ArgumentNullException("Hostname", "The given HTTP hostname must not be null!");
            }

            var HostHeader = Hostname.ToString().Split(new Char[1] {
                ':'
            }, StringSplitOptions.None).Select(v => v.Trim()).ToArray();
            UInt16 HostPort = 80;

            // 1.2.3.4          => 1.2.3.4:80
            // 1.2.3.4:80       => ok
            // 1.2.3.4 : 80     => ok
            // 1.2.3.4:*        => ok
            // 1.2.3.4:a        => invalid
            // 1.2.3.4:80:      => ok
            // 1.2.3.4:80:0     => invalid

            // rfc 2616 - 3.2.2
            // If the port is empty or not given, port 80 is assumed.
            if (HostHeader.Length == 1)
            {
                this._Hostname = HTTPHostname.Parse(Hostname + ":" + HostPort);
            }

            else if ((HostHeader.Length == 2 && (!UInt16.TryParse(HostHeader[1], out HostPort) && HostHeader[1] != "*")) ||
                     HostHeader.Length > 2)
            {
                throw new ArgumentException("Invalid Hostname!", "Hostname");
            }

            else
            {
                this._Hostname = HTTPHostname.Parse(HostHeader[0] + ":" + HostHeader[1]);
            }

            #endregion

            this._HostAuthentication  = (HostAuthentication != null) ? HostAuthentication : _ => true;
            this._RequestHandler      = RequestHandler;
            this._DefaultErrorHandler = DefaultErrorHandler;
            this._URINodes            = new Dictionary <String, URINode>();
            this._ErrorHandlers       = new Dictionary <HTTPStatusCode, HTTPDelegate>();
        }
Exemple #4
0
        /// <summary>
        /// Register a EventStream handler.
        /// </summary>
        public static void RegisterEventStreamHandler(this HTTPServer HTTPServer,
                                                      HTTPHostname Hostname,
                                                      String URITemplate,
                                                      String EventSource)
        {
            HTTPServer.AddMethodCallback(Hostname,
                                         HTTPMethod.GET,
                                         URITemplate,
                                         HTTPDelegate: async Request => {
                var _LastEventId        = 0UL;
                var _Client_LastEventId = 0UL;
                var _EventSource        = HTTPServer.GetEventSource(EventSource);

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

                //_LastEventId = 0;

                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);
                }

                _ResourceContent += Environment.NewLine + "retry: " + _EventSource.RetryIntervall.TotalMilliseconds + Environment.NewLine + Environment.NewLine;

                return(new HTTPResponseBuilder(Request)
                {
                    HTTPStatusCode = HTTPStatusCode.OK,
                    Server = HTTPServer.DefaultServerName,
                    Date = DateTime.Now,
                    ContentType = HTTPContentType.EVENTSTREAM,
                    CacheControl = "no-cache",
                    Connection = "keep-alive",
                    Content = _ResourceContent.ToUTF8Bytes()
                });
            });
        }
Exemple #5
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;
        }
Exemple #6
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;
        }
Exemple #7
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;
        }
Exemple #8
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);
        }
Exemple #9
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;
        }
Exemple #10
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);
            }
        }
Exemple #11
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);
            }
        }
Exemple #12
0
        /// <summary>
        /// Return the best matching method handler for the given parameters.
        /// </summary>
        internal HTTPDelegate GetHandler(HTTPHostname Host,
                                         String URI,
                                         HTTPMethod HTTPMethod = null,
                                         Func <HTTPContentType[], HTTPContentType> HTTPContentTypeSelector = null,
                                         Action <IEnumerable <String> > ParsedURIParametersDelegate        = null)
        {
            Host       = Host ?? HTTPHostname.Any;
            URI        = URI.IsNullOrEmpty()      ? "/" : URI;
            HTTPMethod = HTTPMethod ?? HTTPMethod.GET;
            HTTPContentTypeSelector = HTTPContentTypeSelector ?? (v => HTTPContentType.HTML_UTF8);

            lock (Lock)
            {
                #region Get HostNode or "*" or fail

                HostnameNode _HostNode = null;
                if (!_HostnameNodes.TryGetValue(Host, out _HostNode))
                {
                    if (!_HostnameNodes.TryGetValue(HTTPHostname.Any, out _HostNode))
                    {
                        return(null);
                    }
                }
                //return GetErrorHandler(Host, URL, HTTPMethod, HTTPContentType, HTTPStatusCode.BadRequest);

                #endregion

                #region Try to find the best matching URLNode...

                var _RegexList = from __URLNode
                                 in     _HostNode.URINodes.Values
                                 select new {
                    URLNode = __URLNode,
                    Regex   = __URLNode.URIRegex
                };

                var _AllTemplates = from _RegexTupel
                                    in     _RegexList
                                    select new {
                    URLNode = _RegexTupel.URLNode,
                    Match   = _RegexTupel.Regex.Match(URI)
                };

                var _Matches = from _Match
                               in      _AllTemplates
                               where   _Match.Match.Success
                               orderby 100 * _Match.URLNode.SortLength +
                               _Match.URLNode.ParameterCount
                               descending
                               select  new {
                    URLNode = _Match.URLNode,
                    Match   = _Match.Match
                };

                #endregion

                #region ...or return HostNode

                if (!_Matches.Any())
                {
                    //if (_HostNode.RequestHandler != null)
                    //    return _HostNode.RequestHandler;

                    return(null);
                }

                #endregion


                HTTPMethodNode  _HTTPMethodNode      = null;
                ContentTypeNode _HTTPContentTypeNode = null;

                // Caused e.g. by the naming of the variables within the
                // URI templates, there could be multiple matches!
                //foreach (var _Match in _Matches)
                //{

                // Use best matching URL Handler!
                var _Match2 = _Matches.First();

                #region Copy MethodHandler Parameters

                var _Parameters = new List <String>();
                for (var i = 1; i < _Match2.Match.Groups.Count; i++)
                {
                    //_Parameters.Add(_Match2.Match.Groups[i].Value.RemoveLastSlash());
                    _Parameters.Add(_Match2.Match.Groups[i].Value);
                }

                var ParsedURIParametersDelegateLocal = ParsedURIParametersDelegate;
                if (ParsedURIParametersDelegateLocal != null)
                {
                    ParsedURIParametersDelegate(_Parameters);
                }

                #endregion

                // If HTTPMethod was found...
                if (_Match2.URLNode.HTTPMethods.TryGetValue(HTTPMethod, out _HTTPMethodNode))
                {
                    var BestMatchingContentType = HTTPContentTypeSelector(_HTTPMethodNode.HTTPContentTypes.Keys.ToArray());

                    // Get HTTPContentTypeNode
                    if (!_HTTPMethodNode.HTTPContentTypes.TryGetValue(BestMatchingContentType, out _HTTPContentTypeNode))
                    {
                        return(_HTTPMethodNode.RequestHandler);
                    }

                    return(_HTTPContentTypeNode.RequestHandler);
                }

                //}

                // No HTTPMethod was found => return best matching URL Handler
                return(_Match2.URLNode.RequestHandler);

                //return GetErrorHandler(Host, URL, HTTPMethod, HTTPContentType, HTTPStatusCode.BadRequest);
            }
        }