1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http;
20
21 import java.nio.ByteBuffer;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import org.eclipse.jetty.util.StringMap;
26 import org.eclipse.jetty.util.StringUtil;
27
28
29 public enum HttpHeader
30 {
31
32
33
34 CONNECTION("Connection"),
35 CACHE_CONTROL("Cache-Control"),
36 DATE("Date"),
37 PRAGMA("Pragma"),
38 PROXY_CONNECTION ("Proxy-Connection"),
39 TRAILER("Trailer"),
40 TRANSFER_ENCODING("Transfer-Encoding"),
41 UPGRADE("Upgrade"),
42 VIA("Via"),
43 WARNING("Warning"),
44 NEGOTIATE("Negotiate"),
45
46
47
48
49 ALLOW("Allow"),
50 CONTENT_ENCODING("Content-Encoding"),
51 CONTENT_LANGUAGE("Content-Language"),
52 CONTENT_LENGTH("Content-Length"),
53 CONTENT_LOCATION("Content-Location"),
54 CONTENT_MD5("Content-MD5"),
55 CONTENT_RANGE("Content-Range"),
56 CONTENT_TYPE("Content-Type"),
57 EXPIRES("Expires"),
58 LAST_MODIFIED("Last-Modified"),
59
60
61
62
63 ACCEPT("Accept"),
64 ACCEPT_CHARSET("Accept-Charset"),
65 ACCEPT_ENCODING("Accept-Encoding"),
66 ACCEPT_LANGUAGE("Accept-Language"),
67 AUTHORIZATION("Authorization"),
68 EXPECT("Expect"),
69 FORWARDED("Forwarded"),
70 FROM("From"),
71 HOST("Host"),
72 IF_MATCH("If-Match"),
73 IF_MODIFIED_SINCE("If-Modified-Since"),
74 IF_NONE_MATCH("If-None-Match"),
75 IF_RANGE("If-Range"),
76 IF_UNMODIFIED_SINCE("If-Unmodified-Since"),
77 KEEP_ALIVE("Keep-Alive"),
78 MAX_FORWARDS("Max-Forwards"),
79 PROXY_AUTHORIZATION("Proxy-Authorization"),
80 RANGE("Range"),
81 REQUEST_RANGE("Request-Range"),
82 REFERER("Referer"),
83 TE("TE"),
84 USER_AGENT("User-Agent"),
85 X_FORWARDED_FOR("X-Forwarded-For"),
86 X_FORWARDED_PROTO("X-Forwarded-Proto"),
87 X_FORWARDED_SERVER("X-Forwarded-Server"),
88 X_FORWARDED_HOST("X-Forwarded-Host"),
89
90
91
92
93 ACCEPT_RANGES("Accept-Ranges"),
94 AGE("Age"),
95 ETAG("ETag"),
96 LOCATION("Location"),
97 PROXY_AUTHENTICATE("Proxy-Authenticate"),
98 RETRY_AFTER("Retry-After"),
99 SERVER("Server"),
100 SERVLET_ENGINE("Servlet-Engine"),
101 VARY("Vary"),
102 WWW_AUTHENTICATE("WWW-Authenticate"),
103
104
105
106
107 COOKIE("Cookie"),
108 SET_COOKIE("Set-Cookie"),
109 SET_COOKIE2("Set-Cookie2"),
110 MIME_VERSION("MIME-Version"),
111 IDENTITY("identity"),
112
113 UNKNOWN("::UNKNOWN::");
114
115
116
117 public final static StringMap<HttpHeader> CACHE= new StringMap<HttpHeader>(true);
118 static
119 {
120 for (HttpHeader header : HttpHeader.values())
121 if (header!=UNKNOWN)
122 CACHE.put(header.toString(),header);
123 }
124
125
126 private final static HttpHeader[] __hashed= new HttpHeader[4096];
127 private final static int __maxHashed;
128 static
129 {
130
131
132 int max=0;
133 Map<Integer,HttpHeader> hashes=new HashMap<>();
134 for (HttpHeader header : HttpHeader.values())
135 {
136 String s=header.asString();
137 max=Math.max(max,s.length());
138 int h=0;
139 for (char c:s.toCharArray())
140 h = 31*h + ((c>='a')?(c-'a'+'A'):c);
141 int hash=h%__hashed.length;
142 if (hash<0)hash=-hash;
143 if (hashes.containsKey(hash))
144 {
145
146 System.err.println("Duplicate hash "+header+" "+hashes.get(hash));
147 System.exit(1);
148 }
149 hashes.put(hash,header);
150 __hashed[hash]=header;
151 }
152 __maxHashed=max;
153 }
154
155 public static HttpHeader lookAheadGet(byte[] bytes, int position, int limit)
156 {
157 int h=0;
158 byte b=0;
159 limit=Math.min(position+__maxHashed,limit);
160 for (int i=position;i<limit;i++)
161 {
162 b=bytes[i];
163 if (b==':'||b==' ')
164 break;
165 h= 31*h+ ((b>='a')?(b-'a'+'A'):b);
166 }
167 if (b!=':'&&b!=' ')
168 return null;
169
170 int hash=h%__hashed.length;
171 if (hash<0)hash=-hash;
172 HttpHeader header=__hashed[hash];
173
174 if (header!=null)
175 {
176 String s=header.asString();
177 for (int i=s.length();i-->0;)
178 {
179 b=bytes[position+i];
180 char c=s.charAt(i);
181 if (c!=b && Character.toUpperCase(c)!=(b>='a'?(b-'a'+'A'):b))
182 return null;
183 }
184 }
185
186 return header;
187 }
188
189
190 private final String _string;
191 private final byte[] _bytes;
192 private final byte[] _bytesColonSpace;
193 private final ByteBuffer _buffer;
194
195
196 HttpHeader(String s)
197 {
198 _string=s;
199 _bytes=StringUtil.getBytes(s);
200 _bytesColonSpace=StringUtil.getBytes(s+": ");
201 _buffer=ByteBuffer.wrap(_bytes);
202 }
203
204
205 public ByteBuffer toBuffer()
206 {
207 return _buffer.asReadOnlyBuffer();
208 }
209
210
211 public byte[] getBytes()
212 {
213 return _bytes;
214 }
215
216
217 public byte[] getBytesColonSpace()
218 {
219 return _bytesColonSpace;
220 }
221
222
223 public boolean is(String s)
224 {
225 return _string.equalsIgnoreCase(s);
226 }
227
228
229 public String asString()
230 {
231 return _string;
232 }
233
234
235 @Override
236 public String toString()
237 {
238 return _string;
239 }
240
241 }
242