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)); }
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); }
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); }
// 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); } }
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)); }
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; }
/// <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; }
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) }; }
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)); } }
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!"); } } }
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); }
/// <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>(); }
/// <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!"); } }
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)); }
/// <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; }
/// <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); }
/// <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; }
/// <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); }
/// <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); }
/// <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); } }
/// <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; }
/// <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; }
// 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); } }