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
23 import org.eclipse.jetty.util.ArrayTrie;
24 import org.eclipse.jetty.util.StringUtil;
25 import org.eclipse.jetty.util.Trie;
26
27
28
29
30
31 public enum HttpMethod
32 {
33 GET,
34 POST,
35 HEAD,
36 PUT,
37 OPTIONS,
38 DELETE,
39 TRACE,
40 CONNECT,
41 MOVE,
42 PROXY,
43 PRI;
44
45
46
47
48
49
50
51
52
53 public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
54 {
55 int length=limit-position;
56 if (length<4)
57 return null;
58 switch(bytes[position])
59 {
60 case 'G':
61 if (bytes[position+1]=='E' && bytes[position+2]=='T' && bytes[position+3]==' ')
62 return GET;
63 break;
64 case 'P':
65 if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
66 return POST;
67 if (bytes[position+1]=='R' && bytes[position+2]=='O' && bytes[position+3]=='X' && length>=6 && bytes[position+4]=='Y' && bytes[position+5]==' ')
68 return PROXY;
69 if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
70 return PUT;
71 if (bytes[position+1]=='R' && bytes[position+2]=='I' && bytes[position+3]==' ')
72 return PRI;
73 break;
74 case 'H':
75 if (bytes[position+1]=='E' && bytes[position+2]=='A' && bytes[position+3]=='D' && length>=5 && bytes[position+4]==' ')
76 return HEAD;
77 break;
78 case 'O':
79 if (bytes[position+1]=='P' && bytes[position+2]=='T' && bytes[position+3]=='I' && length>=8 &&
80 bytes[position+4]=='O' && bytes[position+5]=='N' && bytes[position+6]=='S' && bytes[position+7]==' ' )
81 return OPTIONS;
82 break;
83 case 'D':
84 if (bytes[position+1]=='E' && bytes[position+2]=='L' && bytes[position+3]=='E' && length>=7 &&
85 bytes[position+4]=='T' && bytes[position+5]=='E' && bytes[position+6]==' ' )
86 return DELETE;
87 break;
88 case 'T':
89 if (bytes[position+1]=='R' && bytes[position+2]=='A' && bytes[position+3]=='C' && length>=6 &&
90 bytes[position+4]=='E' && bytes[position+5]==' ' )
91 return TRACE;
92 break;
93 case 'C':
94 if (bytes[position+1]=='O' && bytes[position+2]=='N' && bytes[position+3]=='N' && length>=8 &&
95 bytes[position+4]=='E' && bytes[position+5]=='C' && bytes[position+6]=='T' && bytes[position+7]==' ' )
96 return CONNECT;
97 break;
98 case 'M':
99 if (bytes[position+1]=='O' && bytes[position+2]=='V' && bytes[position+3]=='E' && length>=5 && bytes[position+4]==' ')
100 return MOVE;
101 break;
102
103 default:
104 break;
105 }
106 return null;
107 }
108
109
110
111
112
113
114
115 public static HttpMethod lookAheadGet(ByteBuffer buffer)
116 {
117 if (buffer.hasArray())
118 return lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position(),buffer.arrayOffset()+buffer.limit());
119
120 int l = buffer.remaining();
121 if (l>=4)
122 {
123 HttpMethod m = CACHE.getBest(buffer,0,l);
124 if (m!=null)
125 {
126 int ml = m.asString().length();
127 if (l>ml && buffer.get(buffer.position()+ml)==' ')
128 return m;
129 }
130 }
131 return null;
132 }
133
134
135 public final static Trie<HttpMethod> CACHE= new ArrayTrie<>();
136 static
137 {
138 for (HttpMethod method : HttpMethod.values())
139 CACHE.put(method.toString(),method);
140 }
141
142
143 private final ByteBuffer _buffer;
144 private final byte[] _bytes;
145
146
147 HttpMethod()
148 {
149 _bytes=StringUtil.getBytes(toString());
150 _buffer=ByteBuffer.wrap(_bytes);
151 }
152
153
154 public byte[] getBytes()
155 {
156 return _bytes;
157 }
158
159
160 public boolean is(String s)
161 {
162 return toString().equalsIgnoreCase(s);
163 }
164
165
166 public ByteBuffer asBuffer()
167 {
168 return _buffer.asReadOnlyBuffer();
169 }
170
171
172 public String asString()
173 {
174 return toString();
175 }
176
177
178
179
180
181
182
183 public static HttpMethod fromString(String method)
184 {
185 return CACHE.get(method);
186 }
187 }