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 }