1 module hunt.http.codec.http.model.HttpHeader;
2 
3 import hunt.util.traits;
4 
5 import std.algorithm;
6 import std.conv;
7 import std.string;
8 
9 import hunt.logging;
10 
11 bool contains(HttpHeader[] items, ref HttpHeader item) {
12     return items.canFind(item);
13 }
14 
15 /**
16 */
17 struct HttpHeader {
18     enum HttpHeader Null = HttpHeader("Null");
19 
20     /**
21      * General Fields.
22      */
23     enum HttpHeader CONNECTION = HttpHeader("Connection");
24     enum HttpHeader CACHE_CONTROL = HttpHeader("Cache-Control");
25     enum HttpHeader DATE = HttpHeader("Date");
26     enum HttpHeader PRAGMA = HttpHeader("Pragma");
27     enum HttpHeader PROXY_CONNECTION = HttpHeader("Proxy-Connection");
28     enum HttpHeader TRAILER = HttpHeader("Trailer");
29     enum HttpHeader TRANSFER_ENCODING = HttpHeader("Transfer-Encoding");
30     enum HttpHeader UPGRADE = HttpHeader("Upgrade");
31     enum HttpHeader VIA = HttpHeader("Via");
32     enum HttpHeader WARNING = HttpHeader("Warning");
33     enum HttpHeader NEGOTIATE = HttpHeader("Negotiate");
34 
35     /**
36      * Entity Fields.
37      */
38     enum HttpHeader ALLOW = HttpHeader("Allow");
39     enum HttpHeader CONTENT_DISPOSITION = HttpHeader("Content-Disposition");
40     enum HttpHeader CONTENT_ENCODING = HttpHeader("Content-Encoding");
41     enum HttpHeader CONTENT_LANGUAGE = HttpHeader("Content-Language");
42     enum HttpHeader CONTENT_LENGTH = HttpHeader("Content-Length");
43     enum HttpHeader CONTENT_LOCATION = HttpHeader("Content-Location");
44     enum HttpHeader CONTENT_MD5 = HttpHeader("Content-MD5");
45     enum HttpHeader CONTENT_RANGE = HttpHeader("Content-Range");
46     enum HttpHeader CONTENT_TYPE = HttpHeader("Content-Type");
47     enum HttpHeader EXPIRES = HttpHeader("Expires");
48     enum HttpHeader LAST_MODIFIED = HttpHeader("Last-Modified");
49 
50     /**
51      * Request Fields.
52      */
53     enum HttpHeader ACCEPT = HttpHeader("Accept");
54     enum HttpHeader ACCEPT_CHARSET = HttpHeader("Accept-Charset");
55     enum HttpHeader ACCEPT_ENCODING = HttpHeader("Accept-Encoding");
56     enum HttpHeader ACCEPT_LANGUAGE = HttpHeader("Accept-Language");
57     enum HttpHeader AUTHORIZATION = HttpHeader("Authorization");
58     enum HttpHeader EXPECT = HttpHeader("Expect");
59     enum HttpHeader FORWARDED = HttpHeader("Forwarded");
60     enum HttpHeader FROM = HttpHeader("From");
61     enum HttpHeader HOST = HttpHeader("Host");
62     enum HttpHeader IF_MATCH = HttpHeader("If-Match");
63     enum HttpHeader IF_MODIFIED_SINCE = HttpHeader("If-Modified-Since");
64     enum HttpHeader IF_NONE_MATCH = HttpHeader("If-None-Match");
65     enum HttpHeader IF_RANGE = HttpHeader("If-Range");
66     enum HttpHeader IF_UNMODIFIED_SINCE = HttpHeader("If-Unmodified-Since");
67     enum HttpHeader KEEP_ALIVE = HttpHeader("Keep-Alive");
68     enum HttpHeader MAX_FORWARDS = HttpHeader("Max-Forwards");
69     enum HttpHeader PROXY_AUTHORIZATION = HttpHeader("Proxy-Authorization");
70     enum HttpHeader RANGE = HttpHeader("Range");
71     enum HttpHeader REQUEST_RANGE = HttpHeader("Request-Range");
72     enum HttpHeader REFERER = HttpHeader("Referer");
73     enum HttpHeader TE = HttpHeader("TE");
74     enum HttpHeader USER_AGENT = HttpHeader("User-Agent");
75     enum HttpHeader X_FORWARDED_FOR = HttpHeader("X-Forwarded-For");
76     enum HttpHeader X_FORWARDED_PROTO = HttpHeader("X-Forwarded-Proto");
77     enum HttpHeader X_FORWARDED_SERVER = HttpHeader("X-Forwarded-Server");
78     enum HttpHeader X_FORWARDED_HOST = HttpHeader("X-Forwarded-Host");
79 
80     /**
81      * Response Fields.
82      */
83     enum HttpHeader ACCEPT_RANGES = HttpHeader("Accept-Ranges");
84     enum HttpHeader AGE = HttpHeader("Age");
85     enum HttpHeader ETAG = HttpHeader("ETag");
86     enum HttpHeader LOCATION = HttpHeader("Location");
87     enum HttpHeader PROXY_AUTHENTICATE = HttpHeader("Proxy-Authenticate");
88     enum HttpHeader RETRY_AFTER = HttpHeader("Retry-After");
89     enum HttpHeader SERVER = HttpHeader("Server");
90     enum HttpHeader SERVLET_ENGINE = HttpHeader("Servlet-Engine");
91     enum HttpHeader VARY = HttpHeader("Vary");
92     enum HttpHeader WWW_AUTHENTICATE = HttpHeader("WWW-Authenticate");
93 
94     /**
95      * WebSocket Fields.
96      */
97     enum HttpHeader ORIGIN = HttpHeader("Origin");
98     enum HttpHeader SEC_WEBSOCKET_KEY = HttpHeader("Sec-WebSocket-Key");
99     enum HttpHeader SEC_WEBSOCKET_VERSION = HttpHeader("Sec-WebSocket-Version");
100     enum HttpHeader SEC_WEBSOCKET_EXTENSIONS = HttpHeader("Sec-WebSocket-Extensions");
101     enum HttpHeader SEC_WEBSOCKET_SUBPROTOCOL = HttpHeader("Sec-WebSocket-Protocol");
102     enum HttpHeader SEC_WEBSOCKET_ACCEPT = HttpHeader("Sec-WebSocket-Accept");
103 
104     /**
105      * Other Fields.
106      */
107     enum HttpHeader COOKIE = HttpHeader("Cookie");
108     enum HttpHeader SET_COOKIE = HttpHeader("Set-Cookie");
109     enum HttpHeader SET_COOKIE2 = HttpHeader("Set-Cookie2");
110     enum HttpHeader MIME_VERSION = HttpHeader("MIME-Version");
111     enum HttpHeader IDENTITY = HttpHeader("identity");
112 
113     enum HttpHeader X_POWERED_BY = HttpHeader("X-Powered-By");
114     enum HttpHeader HTTP2_SETTINGS = HttpHeader("HTTP2-Settings");
115 
116     enum HttpHeader STRICT_TRANSPORT_SECURITY = HttpHeader("Strict-Transport-Security");
117 
118     /**
119      * HTTP2 Fields.
120      */
121     enum HttpHeader C_METHOD = HttpHeader(":method");
122     enum HttpHeader C_SCHEME = HttpHeader(":scheme");
123     enum HttpHeader C_AUTHORITY = HttpHeader(":authority");
124     enum HttpHeader C_PATH = HttpHeader(":path");
125     enum HttpHeader C_STATUS = HttpHeader(":status");
126 
127     enum HttpHeader UNKNOWN = HttpHeader("::UNKNOWN::");
128 
129     private __gshared HttpHeader[string] CACHE;
130 
131     static bool exists(string name) {
132         return (name.toLower() in CACHE) !is null;
133     }
134 
135     static HttpHeader get(string name) {
136         return CACHE.get(name.toLower(), HttpHeader.Null);
137     }
138 
139     static int getCount() {
140         return cast(int) CACHE.length;
141     }
142 
143     shared static this() {
144         int i = 0;
145         foreach (ref HttpHeader header; HttpHeader.values()) {
146             // header._ordinal = i++;
147             if (header != UNKNOWN)
148                 CACHE[header.asString().toLower()] = header;
149         }
150 
151         // trace(CACHE);
152         // foreach(ref HttpHeader header; HttpHeader.values())
153         // {
154         //     tracef("xx=%d", header._ordinal);
155         // }
156     }
157 
158     mixin GetConstantValues!(HttpHeader);
159 
160     private int _ordinal;
161     private string _string;
162     private byte[] _bytes;
163     private byte[] _bytesColonSpace;
164     // private ByteBuffer _buffer;
165 
166     this(string s) {
167         _string = s;
168         _bytes = cast(byte[]) s.dup; // StringUtils.getBytes(s);
169         _bytesColonSpace = cast(byte[])(s ~ ": ").dup;
170         _ordinal = cast(int) hashOf(s.toLower());
171         // _buffer = ByteBuffer.wrap(_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 }