using System; using System.IO; using System.Net; using System.Threading.Tasks; using System.Collections.Generic; using System.Threading; using System.Text; namespace Tesses.Http { public static class Extensions { private static Lazy> _statusCodeMap = new Lazy>(() => new Dictionary() { [202] = "Accepted", [502] = "Bad Gateway", [400] = "Bad Request", [409] = "Conflict", [100] = "Continue", [201] = "Created", [417] = "Expectation Failed", [403] = "Forbidden", [302] = "Found", [504] = "Gateway Timeout", [410] = "Gone", [505] = "HTTP Version Not Supported", [500] = "Internal Server Error", [411] = "Length Required", [405] = "Method Not Allowed", [301] = "Moved Permanently", [300] = "Multiple Choices", [204] = "No Content", [203] = "Non Authoritative Information", [406] = "Not Acceptable", [404] = "Not Found", [501] = "Not Implemented", [304] = "Not Modified", [200] = "OK", [206] = "Partial Content", [402] = "Payment Required", [412] = "Precondition Failed", [407] = "Proxy Authentication Required", [302] = "Redirect", [307] = "Redirect Keep Verb", [303] = "Redirect Method", [416] = "Requested Range Not Satisfiable", [413] = "Request Entry Too Large", [408] = "Request Timeout", [414] = "Request Uri Too Long", [205] = "Reset Content", [503] = "Service Unavailable", [101] = "Switching Protocols", [307] = "Temporary Redirect", [401] = "Unauthorized", [415] = "Unsupported Media Type", [306] = "Unused", [426] = "Upgrade Required", [305] = "Use Proxy", [429] = "Too Many Requests" }); public static byte[] AsArray(this Stream strm,bool begin=true) { if(strm.Position != 0 && begin) strm.Position=0; byte[] data=new byte[strm.Length-strm.Position]; strm.Read(data,0,data.Length); return data; } public static string AsString(this byte[] data) { return Encoding.UTF8.GetString(data); } public static string GetReasonPhrase(this StatusLine line) { string res; if(_statusCodeMap.Value.TryGetValue(line.StatusCode,out res)) { return res; } return ""; } /// /// StringBuilder ends with /// /// string builder /// text to check /// comparison type /// true if sb ends with test, false if it does not internal static bool EndsWith(this StringBuilder sb, string test, StringComparison comparison) { if (sb.Length < test.Length) return false; string end = sb.ToString(sb.Length - test.Length, test.Length); return end.Equals(test, comparison); } internal static string ReadHttpHeaders(this Stream strm) { StringBuilder s = new StringBuilder(); var decoder = Encoding.UTF8.GetDecoder(); var nextChar = new char[1]; while (!s.EndsWith("\r\n\r\n",StringComparison.Ordinal)) { int data = strm.ReadByte(); if(data == -1) { break; } int charCount=decoder.GetChars(new byte[] { (byte)data }, 0, 1, nextChar, 0); if (charCount == 0) continue; s.Append(nextChar); } return s.ToString(); } public static void Add(this Dictionary> headers,T1 key,T2 value) { if(!headers.ContainsKey(key)) { headers.Add(key,new List()); } headers[key].Add(value); } public static bool TryGetFirst(this Dictionary> headers,T1 key,out T2 value) { value=default(T2); if(headers ==null) return false; if(headers.ContainsKey(key) && headers[key] !=null && headers[key].Count > 0) { value=headers[key][0]; return true; } return false; } public static bool TryGetFirst(this Dictionary> headers,T key,out long value) { value=0; string v; return (headers.TryGetFirst(key,out v) && long.TryParse(v,out value)); } } }