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.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.nio.ByteBuffer;
24 import java.nio.charset.Charset;
25 import java.nio.charset.StandardCharsets;
26
27 import org.eclipse.jetty.http.HttpGenerator.RequestInfo;
28 import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
29 import org.eclipse.jetty.util.BufferUtil;
30 import org.eclipse.jetty.util.StringUtil;
31
32 public class HttpTester
33 {
34 private HttpTester()
35 {
36 }
37
38 public static Request newRequest()
39 {
40 return new Request();
41 }
42
43 public static Request parseRequest(String request)
44 {
45 Request r=new Request();
46 HttpParser parser =new HttpParser(r);
47 parser.parseNext(BufferUtil.toBuffer(request));
48 return r;
49 }
50
51 public static Request parseRequest(ByteBuffer request)
52 {
53 Request r=new Request();
54 HttpParser parser =new HttpParser(r);
55 parser.parseNext(request);
56 return r;
57 }
58
59 public static Response parseResponse(String response)
60 {
61 Response r=new Response();
62 HttpParser parser =new HttpParser(r);
63 parser.parseNext(BufferUtil.toBuffer(response));
64 return r;
65 }
66
67 public static Response parseResponse(ByteBuffer response)
68 {
69 Response r=new Response();
70 HttpParser parser =new HttpParser(r);
71 parser.parseNext(response);
72 return r;
73 }
74
75
76 public abstract static class Message extends HttpFields implements HttpParser.HttpHandler<ByteBuffer>
77 {
78 ByteArrayOutputStream _content;
79 HttpVersion _version=HttpVersion.HTTP_1_0;
80
81 public HttpVersion getVersion()
82 {
83 return _version;
84 }
85
86 public void setVersion(String version)
87 {
88 setVersion(HttpVersion.CACHE.get(version));
89 }
90
91 public void setVersion(HttpVersion version)
92 {
93 _version=version;
94 }
95
96 public void setContent(byte[] bytes)
97 {
98 try
99 {
100 _content=new ByteArrayOutputStream();
101 _content.write(bytes);
102 }
103 catch (IOException e)
104 {
105 throw new RuntimeException(e);
106 }
107 }
108
109 public void setContent(String content)
110 {
111 try
112 {
113 _content=new ByteArrayOutputStream();
114 _content.write(StringUtil.getBytes(content));
115 }
116 catch (IOException e)
117 {
118 throw new RuntimeException(e);
119 }
120 }
121
122 public void setContent(ByteBuffer content)
123 {
124 try
125 {
126 _content=new ByteArrayOutputStream();
127 _content.write(BufferUtil.toArray(content));
128 }
129 catch (IOException e)
130 {
131 throw new RuntimeException(e);
132 }
133 }
134 @Override
135 public boolean parsedHeader(HttpField field)
136 {
137 put(field.getName(),field.getValue());
138 return false;
139 }
140
141 @Override
142 public boolean messageComplete()
143 {
144 return true;
145 }
146
147 @Override
148 public boolean headerComplete()
149 {
150 _content=new ByteArrayOutputStream();
151 return false;
152 }
153
154 @Override
155 public void earlyEOF()
156 {
157 }
158
159 @Override
160 public boolean content(ByteBuffer ref)
161 {
162 try
163 {
164 _content.write(BufferUtil.toArray(ref));
165 }
166 catch (IOException e)
167 {
168 throw new RuntimeException(e);
169 }
170 return false;
171 }
172
173 @Override
174 public void badMessage(int status, String reason)
175 {
176 throw new RuntimeException(reason);
177 }
178
179 public ByteBuffer generate()
180 {
181 try
182 {
183 HttpGenerator generator = new HttpGenerator();
184 HttpGenerator.Info info = getInfo();
185
186
187
188 ByteArrayOutputStream out = new ByteArrayOutputStream();
189 ByteBuffer header=null;
190 ByteBuffer chunk=null;
191 ByteBuffer content=_content==null?null:ByteBuffer.wrap(_content.toByteArray());
192
193
194 loop: while(!generator.isEnd())
195 {
196 HttpGenerator.Result result = info instanceof RequestInfo
197 ?generator.generateRequest((RequestInfo)info,header,chunk,content,true)
198 :generator.generateResponse((ResponseInfo)info,header,chunk,content,true);
199 switch(result)
200 {
201 case NEED_HEADER:
202 header=BufferUtil.allocate(8192);
203 continue;
204
205 case NEED_CHUNK:
206 chunk=BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
207 continue;
208
209 case NEED_INFO:
210 throw new IllegalStateException();
211
212 case FLUSH:
213 if (BufferUtil.hasContent(header))
214 {
215 out.write(BufferUtil.toArray(header));
216 BufferUtil.clear(header);
217 }
218 if (BufferUtil.hasContent(chunk))
219 {
220 out.write(BufferUtil.toArray(chunk));
221 BufferUtil.clear(chunk);
222 }
223 if (BufferUtil.hasContent(content))
224 {
225 out.write(BufferUtil.toArray(content));
226 BufferUtil.clear(content);
227 }
228 break;
229
230 case SHUTDOWN_OUT:
231 break loop;
232 }
233 }
234
235 return ByteBuffer.wrap(out.toByteArray());
236 }
237 catch (IOException e)
238 {
239 throw new RuntimeException(e);
240 }
241
242 }
243 abstract public HttpGenerator.Info getInfo();
244
245 @Override
246 public int getHeaderCacheSize()
247 {
248 return 0;
249 }
250
251 }
252
253 public static class Request extends Message implements HttpParser.RequestHandler<ByteBuffer>
254 {
255 private String _method;
256 private String _uri;
257
258 @Override
259 public boolean startRequest(HttpMethod method, String methodString, ByteBuffer uri, HttpVersion version)
260 {
261 _method=methodString;
262 _uri=BufferUtil.toUTF8String(uri);
263 _version=version;
264 return false;
265 }
266
267 public String getMethod()
268 {
269 return _method;
270 }
271
272 public String getUri()
273 {
274 return _uri;
275 }
276
277 public void setMethod(String method)
278 {
279 _method=method;
280 }
281
282 public void setURI(String uri)
283 {
284 _uri=uri;
285 }
286
287 @Override
288 public HttpGenerator.RequestInfo getInfo()
289 {
290 return new HttpGenerator.RequestInfo(_version,this,_content==null?0:_content.size(),_method,_uri);
291 }
292
293 @Override
294 public String toString()
295 {
296 return String.format("%s %s %s\n%s\n",_method,_uri,_version,super.toString());
297 }
298
299 public void setHeader(String name, String value)
300 {
301 put(name,value);
302 }
303
304 @Override
305 public boolean parsedHostHeader(String host,int port)
306 {
307 return false;
308 }
309 }
310
311 public static class Response extends Message implements HttpParser.ResponseHandler<ByteBuffer>
312 {
313 private int _status;
314 private String _reason;
315
316 @Override
317 public boolean startResponse(HttpVersion version, int status, String reason)
318 {
319 _version=version;
320 _status=status;
321 _reason=reason;
322 return false;
323 }
324
325 public int getStatus()
326 {
327 return _status;
328 }
329
330 public String getReason()
331 {
332 return _reason;
333 }
334
335 public byte[] getContentBytes()
336 {
337 if (_content==null)
338 return null;
339 return _content.toByteArray();
340 }
341
342 public String getContent()
343 {
344 if (_content==null)
345 return null;
346 byte[] bytes=_content.toByteArray();
347
348 String content_type=get(HttpHeader.CONTENT_TYPE);
349 String encoding=MimeTypes.getCharsetFromContentType(content_type);
350 Charset charset=encoding==null?StandardCharsets.UTF_8:Charset.forName(encoding);
351
352 return new String(bytes,charset);
353 }
354
355 @Override
356 public HttpGenerator.ResponseInfo getInfo()
357 {
358 return new HttpGenerator.ResponseInfo(_version,this,_content==null?-1:_content.size(),_status,_reason,false);
359 }
360
361 @Override
362 public String toString()
363 {
364 return String.format("%s %s %s\n%s\n",_version,_status,_reason,super.toString());
365 }
366 }
367 }