1 module hunt.http.HttpHeader; 2 3 import hunt.logging; 4 import hunt.util.ObjectUtils; 5 6 import std.algorithm; 7 import std.conv; 8 import std.string; 9 10 bool contains(HttpHeader[] items, ref HttpHeader item) { 11 return items.canFind(item); 12 } 13 14 /** 15 */ 16 struct HttpHeader { 17 enum HttpHeader Null = HttpHeader("Null"); 18 19 /** 20 * General Fields. 21 */ 22 enum HttpHeader CONNECTION = HttpHeader("Connection"); 23 enum HttpHeader CACHE_CONTROL = HttpHeader("Cache-Control"); 24 enum HttpHeader DATE = HttpHeader("Date"); 25 enum HttpHeader PRAGMA = HttpHeader("Pragma"); 26 enum HttpHeader PROXY_CONNECTION = HttpHeader("Proxy-Connection"); 27 enum HttpHeader TRAILER = HttpHeader("Trailer"); 28 enum HttpHeader TRANSFER_ENCODING = HttpHeader("Transfer-Encoding"); 29 enum HttpHeader UPGRADE = HttpHeader("Upgrade"); 30 enum HttpHeader VIA = HttpHeader("Via"); 31 enum HttpHeader WARNING = HttpHeader("Warning"); 32 enum HttpHeader NEGOTIATE = HttpHeader("Negotiate"); 33 34 /** 35 * Entity Fields. 36 */ 37 enum HttpHeader ALLOW = HttpHeader("Allow"); 38 enum HttpHeader CONTENT_DISPOSITION = HttpHeader("Content-Disposition"); 39 enum HttpHeader CONTENT_ENCODING = HttpHeader("Content-Encoding"); 40 enum HttpHeader CONTENT_LANGUAGE = HttpHeader("Content-Language"); 41 enum HttpHeader CONTENT_LENGTH = HttpHeader("Content-Length"); 42 enum HttpHeader CONTENT_LOCATION = HttpHeader("Content-Location"); 43 enum HttpHeader CONTENT_MD5 = HttpHeader("Content-MD5"); 44 enum HttpHeader CONTENT_RANGE = HttpHeader("Content-Range"); 45 enum HttpHeader CONTENT_TYPE = HttpHeader("Content-Type"); 46 enum HttpHeader EXPIRES = HttpHeader("Expires"); 47 enum HttpHeader LAST_MODIFIED = HttpHeader("Last-Modified"); 48 49 /** 50 * Request Fields. 51 */ 52 enum HttpHeader ACCEPT = HttpHeader("Accept"); 53 enum HttpHeader ACCEPT_CHARSET = HttpHeader("Accept-Charset"); 54 enum HttpHeader ACCEPT_ENCODING = HttpHeader("Accept-Encoding"); 55 enum HttpHeader ACCEPT_LANGUAGE = HttpHeader("Accept-Language"); 56 enum HttpHeader AUTHORIZATION = HttpHeader("Authorization"); 57 enum HttpHeader EXPECT = HttpHeader("Expect"); 58 enum HttpHeader FORWARDED = HttpHeader("Forwarded"); 59 enum HttpHeader FROM = HttpHeader("From"); 60 enum HttpHeader HOST = HttpHeader("Host"); 61 enum HttpHeader IF_MATCH = HttpHeader("If-Match"); 62 enum HttpHeader IF_MODIFIED_SINCE = HttpHeader("If-Modified-Since"); 63 enum HttpHeader IF_NONE_MATCH = HttpHeader("If-None-Match"); 64 enum HttpHeader IF_RANGE = HttpHeader("If-Range"); 65 enum HttpHeader IF_UNMODIFIED_SINCE = HttpHeader("If-Unmodified-Since"); 66 enum HttpHeader KEEP_ALIVE = HttpHeader("Keep-Alive"); 67 enum HttpHeader MAX_FORWARDS = HttpHeader("Max-Forwards"); 68 enum HttpHeader PROXY_AUTHORIZATION = HttpHeader("Proxy-Authorization"); 69 enum HttpHeader RANGE = HttpHeader("Range"); 70 enum HttpHeader REQUEST_RANGE = HttpHeader("Request-Range"); 71 enum HttpHeader REFERER = HttpHeader("Referer"); 72 enum HttpHeader TE = HttpHeader("TE"); 73 enum HttpHeader USER_AGENT = HttpHeader("User-Agent"); 74 enum HttpHeader X_FORWARDED_FOR = HttpHeader("X-Forwarded-For"); 75 enum HttpHeader X_FORWARDED_PROTO = HttpHeader("X-Forwarded-Proto"); 76 enum HttpHeader X_FORWARDED_SERVER = HttpHeader("X-Forwarded-Server"); 77 enum HttpHeader X_FORWARDED_HOST = HttpHeader("X-Forwarded-Host"); 78 79 /** 80 * Response Fields. 81 */ 82 enum HttpHeader ACCEPT_RANGES = HttpHeader("Accept-Ranges"); 83 enum HttpHeader AGE = HttpHeader("Age"); 84 enum HttpHeader ETAG = HttpHeader("ETag"); 85 enum HttpHeader LOCATION = HttpHeader("Location"); 86 enum HttpHeader PROXY_AUTHENTICATE = HttpHeader("Proxy-Authenticate"); 87 enum HttpHeader RETRY_AFTER = HttpHeader("Retry-After"); 88 enum HttpHeader SERVER = HttpHeader("Server"); 89 enum HttpHeader SERVLET_ENGINE = HttpHeader("Servlet-Engine"); 90 enum HttpHeader VARY = HttpHeader("Vary"); 91 enum HttpHeader WWW_AUTHENTICATE = HttpHeader("WWW-Authenticate"); 92 93 /** 94 * WebSocket Fields. 95 */ 96 enum HttpHeader ORIGIN = HttpHeader("Origin"); 97 enum HttpHeader SEC_WEBSOCKET_KEY = HttpHeader("Sec-WebSocket-Key"); 98 enum HttpHeader SEC_WEBSOCKET_VERSION = HttpHeader("Sec-WebSocket-Version"); 99 enum HttpHeader SEC_WEBSOCKET_EXTENSIONS = HttpHeader("Sec-WebSocket-Extensions"); 100 enum HttpHeader SEC_WEBSOCKET_SUBPROTOCOL = HttpHeader("Sec-WebSocket-Protocol"); 101 enum HttpHeader SEC_WEBSOCKET_ACCEPT = HttpHeader("Sec-WebSocket-Accept"); 102 103 /** 104 * Other Fields. 105 */ 106 enum HttpHeader COOKIE = HttpHeader("Cookie"); 107 enum HttpHeader SET_COOKIE = HttpHeader("Set-Cookie"); 108 enum HttpHeader SET_COOKIE2 = HttpHeader("Set-Cookie2"); 109 enum HttpHeader MIME_VERSION = HttpHeader("MIME-Version"); 110 enum HttpHeader IDENTITY = HttpHeader("identity"); 111 112 enum HttpHeader X_POWERED_BY = HttpHeader("X-Powered-By"); 113 enum HttpHeader HTTP2_SETTINGS = HttpHeader("HTTP2-Settings"); 114 115 enum HttpHeader STRICT_TRANSPORT_SECURITY = HttpHeader("Strict-Transport-Security"); 116 117 /** 118 * HTTP2 Fields. 119 */ 120 enum HttpHeader C_METHOD = HttpHeader(":method"); 121 enum HttpHeader C_SCHEME = HttpHeader(":scheme"); 122 enum HttpHeader C_AUTHORITY = HttpHeader(":authority"); 123 enum HttpHeader C_PATH = HttpHeader(":path"); 124 enum HttpHeader C_STATUS = HttpHeader(":status"); 125 126 enum HttpHeader UNKNOWN = HttpHeader("::UNKNOWN::"); 127 128 private __gshared HttpHeader[string] CACHE; 129 130 static bool exists(string name) { 131 return (name.toLower() in CACHE) !is null; 132 } 133 134 static HttpHeader get(string name) { 135 return CACHE.get(name.toLower(), HttpHeader.Null); 136 } 137 138 static int getCount() { 139 return cast(int) CACHE.length; 140 } 141 142 shared static this() { 143 int i = 0; 144 foreach (ref HttpHeader header; HttpHeader.values()) { 145 // header._ordinal = i++; 146 if (header != UNKNOWN) 147 CACHE[header.asString().toLower()] = header; 148 } 149 150 // trace(CACHE); 151 // foreach(ref HttpHeader header; HttpHeader.values()) 152 // { 153 // tracef("xx=%d", header._ordinal); 154 // } 155 } 156 157 mixin ValuesMemberTempate!(HttpHeader); 158 159 private int _ordinal; 160 private string _string; 161 private byte[] _bytes; 162 private byte[] _bytesColonSpace; 163 // private ByteBuffer _buffer; 164 165 this(string s) { 166 // tracef("<%s>", s); 167 _string = s; 168 _bytes = cast(byte[]) s.dup; // StringUtils.getBytes(s); 169 _bytesColonSpace = cast(byte[])(_string ~ ": ").dup; 170 _ordinal = cast(int) hashOf(s.toLower()); 171 // _buffer = BufferUtils.toBuffer(_bytes); 172 } 173 174 // ByteBuffer toBuffer() { 175 // return _buffer.asReadOnlyBuffer(); 176 // } 177 178 byte[] getBytes() { 179 return _bytes; 180 } 181 182 byte[] getBytesColonSpace() { 183 return _bytesColonSpace; 184 } 185 186 bool isSame(string s) const nothrow { 187 return std..string.icmp(_string, s) == 0; 188 } 189 190 string asString() const nothrow { 191 return _string; 192 } 193 194 string toString() { 195 return _string; 196 } 197 198 int ordinal() { 199 return _ordinal; 200 } 201 202 size_t toHash() @trusted nothrow { 203 return hashOf(_string); 204 } 205 206 bool opEquals(const HttpHeader h) nothrow { 207 return std..string.cmp(_string, h._string) == 0; 208 } 209 210 bool opEquals(ref const HttpHeader h) nothrow { 211 return std..string.cmp(_string, h._string) == 0; 212 } 213 214 // bool opEquals(const HttpHeader h) const nothrow{ 215 // return isSame(h.asString()); 216 // } 217 } 218 219 // import hunt.io.ByteBuffer; 220 // import java.nio.charset.StandardCharsets; 221 // import java.util.EnumSet; 222 223 // import hunt.http.utils.collection.ArrayTrie; 224 // import hunt.http.utils.collection.Trie; 225 226 /** 227 * 228 */ 229 struct HttpHeaderValue { 230 231 enum HttpHeaderValue CLOSE = HttpHeaderValue("close"); 232 enum HttpHeaderValue CHUNKED = HttpHeaderValue("chunked"); 233 enum HttpHeaderValue GZIP = HttpHeaderValue("gzip"); 234 enum HttpHeaderValue IDENTITY = HttpHeaderValue("identity"); 235 enum HttpHeaderValue KEEP_ALIVE = HttpHeaderValue("keep-alive"); 236 enum HttpHeaderValue CONTINUE = HttpHeaderValue("100-continue"); 237 enum HttpHeaderValue PROCESSING = HttpHeaderValue("102-processing"); 238 enum HttpHeaderValue TE = HttpHeaderValue("TE"); 239 enum HttpHeaderValue BYTES = HttpHeaderValue("bytes"); 240 enum HttpHeaderValue NO_CACHE = HttpHeaderValue("no-cache"); 241 enum HttpHeaderValue UPGRADE = HttpHeaderValue("Upgrade"); 242 enum HttpHeaderValue UNKNOWN = HttpHeaderValue("::UNKNOWN::"); 243 244 245 private enum HttpHeader[] __known = [ 246 HttpHeader.CONNECTION, 247 HttpHeader.TRANSFER_ENCODING, 248 HttpHeader.CONTENT_ENCODING 249 ]; 250 251 __gshared HttpHeaderValue[string] CACHE; 252 253 shared static this() { 254 foreach (ref HttpHeaderValue value ; HttpHeaderValue.values()) 255 { 256 if (value != UNKNOWN) 257 CACHE[value.toString()] = value; 258 } 259 } 260 261 mixin ValuesMemberTempate!(HttpHeaderValue); 262 263 private string _string; 264 // private ByteBuffer buffer; 265 266 private this(string s) { 267 _string = s; 268 // buffer = BufferUtils.toBuffer(s.getBytes(StandardCharsets.UTF_8)); 269 } 270 271 // ByteBuffer toBuffer() { 272 // return buffer.asReadOnlyBuffer(); 273 // } 274 275 bool isSame(string s) { 276 return s.length != 0 && std..string.icmp(_string, s) == 0; 277 } 278 279 string asString() { 280 return _string; 281 } 282 283 string toString() { 284 return _string; 285 } 286 287 static bool hasKnownValues(HttpHeader header) { 288 if (header == HttpHeader.Null) 289 return false; 290 return __known.canFind(header); 291 } 292 }