From f91f4738ea6694cf66cb92e70b2c9136f116a4f1 Mon Sep 17 00:00:00 2001 From: Andreas Katzig <akatzig@chimera-entertainment.de> Date: Mon, 13 Jun 2016 14:34:10 +0200 Subject: [PATCH 1/4] Use TryParse to read the PortNumber from the fast cgi request --- .../AppHosts/AspNet/AspNetNativeWebRequest.cs | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs index 96474d4..dfd85d2 100644 --- a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs +++ b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs @@ -84,14 +84,21 @@ static AspNetNativeWebRequest () private int input_data_offset; public int PortNumber { - get { - if (port < 0) - //FIXME: tryparse - port = int.Parse (GetParameter ( - "SERVER_PORT")); - - return port; - } + get + { + if (port < 0) + { + if (!int.TryParse(GetParameter("SERVER_PORT"), out port)) + { + Logger.Write(LogLevel.Error, "fastcgi_param 'SERVER_PORT' not set! Setting to default value '80'! " + + "Please add 'fastcgi_param SERVER_PORT $server_port;' to your webserver config!"); + port = 80; + } + + } + + return port; + } } public string Path { From 3e3987c42306e338f72b04d89c5778cd524bcb8f Mon Sep 17 00:00:00 2001 From: Andreas Katzig <akatzig@chimera-entertainment.de> Date: Mon, 13 Jun 2016 14:35:54 +0200 Subject: [PATCH 2/4] Using string.IsNullOrEmpty more often in AspNetNativeWebRequest --- .../AppHosts/AspNet/AspNetNativeWebRequest.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs index dfd85d2..e3565b6 100644 --- a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs +++ b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs @@ -317,7 +317,7 @@ public override string GetRawUrl () StringBuilder b = new StringBuilder (GetUriPath ()); string query = GetQueryString (); - if (query != null && query.Length > 0) { + if (!string.IsNullOrEmpty(query)) { b.Append ('?'); b.Append (query); } @@ -344,17 +344,17 @@ public override string GetHttpVersion () public override string GetLocalAddress () { string address = GetParameter ("SERVER_ADDR"); - if (address != null && address.Length > 0) + if (!string.IsNullOrEmpty(address)) return address; address = AddressFromHostName ( GetParameter ("HTTP_HOST")); - if (address != null && address.Length > 0) + if (!string.IsNullOrEmpty(address)) return address; address = AddressFromHostName ( GetParameter ("SERVER_NAME")); - if (address != null && address.Length > 0) + if (!string.IsNullOrEmpty(address)) return address; return base.GetLocalAddress (); @@ -385,7 +385,7 @@ public override byte [] GetQueryStringRawBytes () public override string GetRemoteAddress () { string addr = GetParameter ("REMOTE_ADDR"); - return addr != null && addr.Length > 0 ? + return !string.IsNullOrEmpty(addr) ? addr : base.GetRemoteAddress (); } @@ -406,7 +406,7 @@ public override string GetRemoteName () public override int GetRemotePort () { string port = GetParameter ("REMOTE_PORT"); - if (port == null || port.Length == 0) + if (string.IsNullOrEmpty(port)) return base.GetRemotePort (); try { @@ -423,7 +423,7 @@ public override string GetServerVariable (string name) if (value == null) value = Environment.GetEnvironmentVariable (name); - return value != null ? value : base.GetServerVariable (name); + return value ?? base.GetServerVariable (name); } public override string GetUriPath () @@ -577,7 +577,7 @@ private static string AddressFromHostName (string host) private static string HostNameFromString (string host) { - if (host == null || host.Length == 0) + if (string.IsNullOrEmpty(host)) return null; int colon_index = host.IndexOf (':'); From 49edfc0b039bf51614a18a7bf3d16d6cd5fcd539 Mon Sep 17 00:00:00 2001 From: Andreas Katzig <akatzig@chimera-entertainment.de> Date: Mon, 13 Jun 2016 14:51:52 +0200 Subject: [PATCH 3/4] Some minor refactorings for AspNetNativeWebRequest. Especially added logging to AddBodyPart --- .../AppHosts/AspNet/AspNetNativeWebRequest.cs | 54 ++++++++++++------- src/HyperFastCgi/Interfaces/IWebRequest.cs | 5 +- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs index e3565b6..ce8d239 100644 --- a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs +++ b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs @@ -88,8 +88,7 @@ public int PortNumber { { if (port < 0) { - if (!int.TryParse(GetParameter("SERVER_PORT"), out port)) - { + if (!int.TryParse(GetParameter("SERVER_PORT"), out port)) { Logger.Write(LogLevel.Error, "fastcgi_param 'SERVER_PORT' not set! Setting to default value '80'! " + "Please add 'fastcgi_param SERVER_PORT $server_port;' to your webserver config!"); port = 80; @@ -161,34 +160,48 @@ public void AddHeader (string header, string value) } } + /// <summary> + /// TODO errors can happen here, changing return value to bool and then evaluating the return value outside could help + /// </summary> + /// <param name="data"></param> public void AddBodyPart (byte[] data) { if (input_data == null) { - int len = 0; + int len; string slen = GetParameter ("CONTENT_LENGTH"); if (slen == null) { - //TODO: error, throw an exception + //Instead of throwing an Exception, write to error log and return + Logger.Write(LogLevel.Error, "fastcgi_param 'CONTENT_LENGTH' not set! " + + "Please add 'fastcgi_param SERVER_PORT $server_port;' to your webserver config!"); + + return; } + if (!int.TryParse (slen, NumberStyles.None, CultureInfo.InvariantCulture, out len)) { - //TODO: error, throw an exception + Logger.Write(LogLevel.Error, "Invalid CONTENT_LENGTH: {0}", slen); + + return; } input_data = new byte[len]; } if (input_data_offset + data.Length > input_data.Length) { - //TODO: throw an exception + //Instead of throwing an Exception, write to error log and return + Logger.Write(LogLevel.Error, "Buffer too small: input_data (size {0}) but should be at least {1}", input_data.Length, (input_data_offset + data.Length)); + + return; } - Buffer.BlockCopy (data, 0, input_data, input_data_offset, data.Length); + Buffer.BlockCopy (data, 0, input_data, input_data_offset, data.Length); input_data_offset += data.Length; } public string GetParameter (string parameter) { if (parameter_table != null && parameter_table.ContainsKey (parameter)) - return (string)parameter_table [parameter]; + return parameter_table [parameter]; return null; } @@ -275,8 +288,7 @@ public override void SendResponseFromMemory (byte[] data, int length) public override void SendStatus (int statusCode, string statusDescription) { - AppendHeaderLine ("Status: {0} {1}", - statusCode, statusDescription); + AppendHeaderLine ("Status: {0} {1}", statusCode, statusDescription); } public override void SendUnknownResponseHeader (string name, string value) @@ -301,7 +313,7 @@ public override bool IsEntireEntityBodyIsPreloaded () public override string GetPathInfo () { - return GetParameter ("PATH_INFO") ?? String.Empty; + return GetParameter ("PATH_INFO") ?? string.Empty; } public override string GetRawUrl () @@ -420,7 +432,7 @@ public override string GetServerVariable (string name) { string value = GetParameter (name); - if (value == null) + if (value == null && name != null) value = Environment.GetEnvironmentVariable (name); return value ?? base.GetServerVariable (name); @@ -560,7 +572,7 @@ private static string AddressFromHostName (string host) if (host == null || host.Length > 126) return null; - System.Net.IPAddress[] addresses = null; + IPAddress[] addresses = null; try { addresses = Dns.GetHostAddresses (host); } catch (System.Net.Sockets.SocketException) { @@ -599,15 +611,17 @@ private static void SetDefaultIndexFiles (string list) List<string> files = new List<string> (); string [] fs = list.Split (','); - foreach (string f in fs) { - string trimmed = f.Trim (); - if (trimmed == "") - continue; + for (int index = 0; index < fs.Length; index++) + { + string f = fs[index]; + string trimmed = f.Trim(); + if (trimmed == "") + continue; - files.Add (trimmed); - } + files.Add(trimmed); + } - indexFiles = files.ToArray (); + indexFiles = files.ToArray (); } #endregion diff --git a/src/HyperFastCgi/Interfaces/IWebRequest.cs b/src/HyperFastCgi/Interfaces/IWebRequest.cs index b219d52..e80ffec 100644 --- a/src/HyperFastCgi/Interfaces/IWebRequest.cs +++ b/src/HyperFastCgi/Interfaces/IWebRequest.cs @@ -41,11 +41,12 @@ public interface IWebRequest /// </summary> /// <param name="name">Header name.</param> /// <param name="value">Header value.</param> - /// <remarks>This method is called by transport when new header has come<remarks> + /// <remarks>This method is called by transport when new header has come</remarks> void AddHeader(string name, string value); /// <summary> /// Adds the content data + /// TODO: Change return value to "bool" to be able to report (buffer) errors? /// </summary> /// <param name="data">content data</param> /// <remarks>The method is called by transport to add the part of content (post) data. @@ -62,7 +63,7 @@ public interface IWebRequest /// Processes the request. /// </summary> /// <param name="response">Response</param> - /// <remarks>The method is called by transport to process Web Request<remarks> + /// <remarks>The method is called by transport to process Web Request</remarks> void Process (IWebResponse response); } } From b48ccfec489f3f221837d2a8612db37aa7de409d Mon Sep 17 00:00:00 2001 From: Andreas Katzig <akatzig@chimera-entertainment.de> Date: Mon, 13 Jun 2016 15:27:51 +0200 Subject: [PATCH 4/4] Some more smaller refactorings --- .../AppHosts/AspNet/AspNetNativeWebRequest.cs | 10 ++-- .../AppHosts/AspNet/MonoWorkerRequest.cs | 48 +++++++++---------- .../AppHosts/Raw/BaseRawRequest.cs | 8 ++-- src/HyperFastCgi/Interfaces/IWebResponse.cs | 4 +- 4 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs index ce8d239..761746b 100644 --- a/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs +++ b/src/HyperFastCgi/AppHosts/AspNet/AspNetNativeWebRequest.cs @@ -149,7 +149,7 @@ public AspNetNativeWebRequest (ulong requestId, int requestNumber, IApplicationH public void AddHeader (string header, string value) { - if (!String.IsNullOrEmpty (header)) { + if (!string.IsNullOrEmpty (header)) { int idx = HttpWorkerRequest.GetKnownRequestHeaderIndex (header); if (idx != -1) { @@ -634,16 +634,16 @@ public void Process (IWebResponse response) #endregion #region IWebResponse implementation - public void Send (int status, string description, IDictionary<string, string> headers) + public void Send (int status, string description, IDictionary<string, string> sendHeaders) { SendStatus (status, description); - foreach (KeyValuePair<string, string> pair in headers) { + foreach (KeyValuePair<string, string> pair in sendHeaders) { SendUnknownResponseHeader (pair.Key, pair.Value); } } - public void Send (int status, string description, IDictionary<string, string> headers, byte[] response) + public void Send (int status, string description, IDictionary<string, string> sendHeaders, byte[] response) { - Send (status, description, headers); + Send (status, description, sendHeaders); SendResponseFromMemory (response, response.Length); } public void Send (byte[] response) diff --git a/src/HyperFastCgi/AppHosts/AspNet/MonoWorkerRequest.cs b/src/HyperFastCgi/AppHosts/AspNet/MonoWorkerRequest.cs index 0f3f088..ce43c47 100644 --- a/src/HyperFastCgi/AppHosts/AspNet/MonoWorkerRequest.cs +++ b/src/HyperFastCgi/AppHosts/AspNet/MonoWorkerRequest.cs @@ -150,7 +150,7 @@ static MonoWorkerRequest () } public MonoWorkerRequest (HyperFastCgi.Interfaces.IApplicationHost appHost) - : base (String.Empty, String.Empty, null) + : base (string.Empty, string.Empty, null) { if (appHost == null) throw new ArgumentNullException ("appHost"); @@ -256,12 +256,11 @@ public override string MapPath (string path) if (eventResult != null) return eventResult; - string hostVPath = HostVPath; + string currentHostVPath = HostVPath; int hostVPathLen = HostVPath.Length; int pathLen = path != null ? path.Length : 0; - bool inThisApp; - inThisApp = path.StartsWith (hostVPath, StringComparison.Ordinal); + bool inThisApp = path.StartsWith (currentHostVPath, StringComparison.Ordinal); if (pathLen == 0 || (inThisApp && (pathLen == hostVPathLen || (pathLen == hostVPathLen + 1 && path [pathLen - 1] == '/')))) { if (needToReplacePathSeparator) @@ -314,18 +313,14 @@ public void ProcessRequest () error = ex.GetHtmlErrorMessage (); } catch (Exception ex) { inUnhandledException = true; - HttpException hex = new HttpException (400, "Bad request", ex); - if (hex != null) // just a precaution - error = hex.GetHtmlErrorMessage (); - else - error = String.Format (defaultExceptionHtml, ex.Message); + error = new HttpException(400, "Bad request", ex).GetHtmlErrorMessage(); } if (!inUnhandledException) return; - if (error.Length == 0) - error = String.Format (defaultExceptionHtml, "Unknown error"); + if (error != null && error.Length == 0) + error = string.Format (defaultExceptionHtml, "Unknown error"); try { SendStatus (400, "Bad request"); @@ -333,17 +328,20 @@ public void ProcessRequest () SendUnknownResponseHeader ("Date", DateTime.Now.ToUniversalTime ().ToString ("r")); Encoding enc = Encoding.UTF8; - if (enc == null) - enc = Encoding.ASCII; - byte[] bytes = enc.GetBytes (error); + SendUnknownResponseHeader("Content-Type", "text/html; charset=" + enc.WebName); + + if (error != null) + { + byte[] bytes = enc.GetBytes(error); + SendUnknownResponseHeader("Content-Length", bytes.Length.ToString()); + SendResponseFromMemory(bytes, bytes.Length); + } + + FlushResponse (true); - SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName); - SendUnknownResponseHeader ("Content-Length", bytes.Length.ToString ()); - SendResponseFromMemory (bytes, bytes.Length); - FlushResponse (true); } catch (Exception ex) { // should "never" happen - throw ex; + throw; // rethrow } } @@ -380,7 +378,7 @@ public override void SendKnownResponseHeader (int index, string value) public override string GetServerVariable (string name) { if (server_variables == null) - return String.Empty; + return string.Empty; if (IsSecure ()) { X509Certificate client = ClientCertificate; @@ -388,7 +386,7 @@ public override string GetServerVariable (string name) case "CERT_COOKIE": if (cert_cookie == null) { if (client == null) - cert_cookie = String.Empty; + cert_cookie = string.Empty; else cert_cookie = client.GetCertHashString (); } @@ -396,7 +394,7 @@ public override string GetServerVariable (string name) case "CERT_ISSUER": if (cert_issuer == null) { if (client == null) - cert_issuer = String.Empty; + cert_issuer = string.Empty; else cert_issuer = client.Issuer; } @@ -404,7 +402,7 @@ public override string GetServerVariable (string name) case "CERT_SERIALNUMBER": if (cert_serial == null) { if (client == null) - cert_serial = String.Empty; + cert_serial = string.Empty; else cert_serial = client.GetSerialNumberString (); } @@ -412,7 +410,7 @@ public override string GetServerVariable (string name) case "CERT_SUBJECT": if (cert_subject == null) { if (client == null) - cert_subject = String.Empty; + cert_subject = string.Empty; else cert_subject = client.Subject; } @@ -421,7 +419,7 @@ public override string GetServerVariable (string name) } string s = server_variables [name]; - return (s == null) ? String.Empty : s; + return s ?? string.Empty; } public void AddServerVariable (string name, string value) diff --git a/src/HyperFastCgi/AppHosts/Raw/BaseRawRequest.cs b/src/HyperFastCgi/AppHosts/Raw/BaseRawRequest.cs index b507646..05e7e10 100644 --- a/src/HyperFastCgi/AppHosts/Raw/BaseRawRequest.cs +++ b/src/HyperFastCgi/AppHosts/Raw/BaseRawRequest.cs @@ -114,16 +114,16 @@ public IDictionary<string, string> ServerVariables { #region IWebResponse implementation - public void Send (int status, string description, IDictionary<string, string> headers) + public void Send (int status, string description, IDictionary<string, string> sendHeaders) { Status = status; StatusDescription = description; - responseHeaders = (Dictionary<string,string>)headers; + responseHeaders = (Dictionary<string,string>)sendHeaders; } - public void Send (int status, string description, IDictionary<string, string> headers, byte[] response) + public void Send (int status, string description, IDictionary<string, string> sendHeaders, byte[] response) { - Send (status, description, headers); + Send (status, description, sendHeaders); Send (response); } diff --git a/src/HyperFastCgi/Interfaces/IWebResponse.cs b/src/HyperFastCgi/Interfaces/IWebResponse.cs index 48c2ed7..be81116 100644 --- a/src/HyperFastCgi/Interfaces/IWebResponse.cs +++ b/src/HyperFastCgi/Interfaces/IWebResponse.cs @@ -8,9 +8,9 @@ public interface IWebResponse { IWebRequest Request { get; } - void Send (int status, string description, IDictionary<string,string> headers); + void Send (int status, string description, IDictionary<string,string> sendHeaders); - void Send (int status, string description, IDictionary<string,string> headers, byte[] response); + void Send (int status, string description, IDictionary<string,string> sendHeaders, byte[] response); void Send (byte[] response);