View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.testing;
15  
16  import java.io.IOException;
17  import java.util.Enumeration;
18  
19  import javax.servlet.http.Cookie;
20  
21  import org.eclipse.jetty.http.HttpFields;
22  import org.eclipse.jetty.http.HttpGenerator;
23  import org.eclipse.jetty.http.HttpHeaders;
24  import org.eclipse.jetty.http.HttpParser;
25  import org.eclipse.jetty.http.HttpVersions;
26  import org.eclipse.jetty.http.MimeTypes;
27  import org.eclipse.jetty.io.Buffer;
28  import org.eclipse.jetty.io.ByteArrayBuffer;
29  import org.eclipse.jetty.io.SimpleBuffers;
30  import org.eclipse.jetty.io.View;
31  import org.eclipse.jetty.io.bio.StringEndPoint;
32  import org.eclipse.jetty.util.ByteArrayOutputStream2;
33  
34  /* ------------------------------------------------------------ */
35  /** Test support class.
36   * Assist with parsing and generating HTTP requests and responses.
37   * 
38   * <pre>
39   *      HttpTester tester = new HttpTester();
40   *      
41   *      tester.parse(
42   *          "GET /uri HTTP/1.1\r\n"+
43   *          "Host: fakehost\r\n"+
44   *          "Content-Length: 10\r\n" +
45   *          "\r\n");
46   *     
47   *      System.err.println(tester.getMethod());
48   *      System.err.println(tester.getURI());
49   *      System.err.println(tester.getVersion());
50   *      System.err.println(tester.getHeader("Host"));
51   *      System.err.println(tester.getContent());
52   * </pre>      
53   * 
54   * 
55   * @see org.eclipse.jetty.testing.ServletTester
56   */
57  public class HttpTester
58  {
59      protected HttpFields _fields=new HttpFields();
60      protected String _method;
61      protected String _uri;
62      protected String _version;
63      protected int _status;
64      protected String _reason;
65      protected ByteArrayOutputStream2 _parsedContent;
66      protected byte[] _genContent;
67      
68      private String _charset, _defaultCharset;
69      private Buffer _contentType;
70      
71      public HttpTester()
72      {
73          this("UTF-8");
74      }
75      
76      public HttpTester(String charset)
77      {
78          _defaultCharset = charset;
79      }
80      
81      public void reset()
82      {
83          _fields.clear();
84           _method=null;
85           _uri=null;
86           _version=null;
87           _status=0;
88           _reason=null;
89           _parsedContent=null;
90           _genContent=null;
91      }
92      
93      private String getString(Buffer buffer)
94      {
95          return getString(buffer.asArray());
96      }
97      
98      private String getString(byte[] b)
99      {
100         if(_charset==null)
101             return new String(b);
102         try
103         {
104             return new String(b, _charset);
105         }
106         catch(Exception e)
107         {
108             return new String(b);
109         }
110     }
111     
112     private byte[] getByteArray(String str)
113     {
114         if(_charset==null)
115             return str.getBytes();
116         try
117         {
118             return str.getBytes(_charset);
119         }
120         catch(Exception e)
121         {
122             return str.getBytes();
123         }
124     }
125 
126     /* ------------------------------------------------------------ */
127     /**
128      * Parse one HTTP request or response
129      * @param rawHTTP Raw HTTP to parse
130      * @return Any unparsed data in the rawHTTP (eg pipelined requests)
131      * @throws IOException
132      */
133     public String parse(String rawHTTP) throws IOException
134     {
135         _charset = _defaultCharset;
136         ByteArrayBuffer buf = new ByteArrayBuffer(getByteArray(rawHTTP));
137         View view = new View(buf);
138         HttpParser parser = new HttpParser(view,new PH());
139         parser.parse();
140         return getString(view.asArray());
141     }
142 
143     /* ------------------------------------------------------------ */
144     public String generate() throws IOException
145     {
146         _charset = _defaultCharset;
147         _contentType = _fields.get(HttpHeaders.CONTENT_TYPE_BUFFER);
148         if(_contentType!=null)
149         {
150             String charset = MimeTypes.getCharsetFromContentType(_contentType);
151             if(charset!=null)
152                 _charset = charset;
153         }
154         Buffer bb=new ByteArrayBuffer(32*1024 + (_genContent!=null?_genContent.length:0));
155         Buffer sb=new ByteArrayBuffer(4*1024);
156         StringEndPoint endp = new StringEndPoint(_charset);
157         HttpGenerator generator = new HttpGenerator(new SimpleBuffers(sb,bb),endp);
158         
159         if (_method!=null)
160         {
161             generator.setRequest(getMethod(),getURI());
162             if (_version==null)
163                 generator.setVersion(HttpVersions.HTTP_1_1_ORDINAL);
164             else
165                 generator.setVersion(HttpVersions.CACHE.getOrdinal(HttpVersions.CACHE.lookup(_version)));
166             generator.completeHeader(_fields,false);
167             if (_genContent!=null)
168                 generator.addContent(new View(new ByteArrayBuffer(_genContent)),false);
169             else if (_parsedContent!=null)
170                 generator.addContent(new ByteArrayBuffer(_parsedContent.toByteArray()),false);
171         }
172         
173         generator.complete();
174         generator.flushBuffer();
175         return endp.getOutput();
176     }
177     
178     /* ------------------------------------------------------------ */
179     /**
180      * @return the method
181      */
182     public String getMethod()
183     {
184         return _method;
185     }
186 
187     /* ------------------------------------------------------------ */
188     /**
189      * @param method the method to set
190      */
191     public void setMethod(String method)
192     {
193         _method=method;
194     }
195 
196     /* ------------------------------------------------------------ */
197     /**
198      * @return the reason
199      */
200     public String getReason()
201     {
202         return _reason;
203     }
204 
205     /* ------------------------------------------------------------ */
206     /**
207      * @param reason the reason to set
208      */
209     public void setReason(String reason)
210     {
211         _reason=reason;
212     }
213 
214     /* ------------------------------------------------------------ */
215     /**
216      * @return the status
217      */
218     public int getStatus()
219     {
220         return _status;
221     }
222 
223     /* ------------------------------------------------------------ */
224     /**
225      * @param status the status to set
226      */
227     public void setStatus(int status)
228     {
229         _status=status;
230     }
231 
232     /* ------------------------------------------------------------ */
233     /**
234      * @return the uri
235      */
236     public String getURI()
237     {
238         return _uri;
239     }
240 
241     /* ------------------------------------------------------------ */
242     /**
243      * @param uri the uri to set
244      */
245     public void setURI(String uri)
246     {
247         _uri=uri;
248     }
249 
250     /* ------------------------------------------------------------ */
251     /**
252      * @return the version
253      */
254     public String getVersion()
255     {
256         return _version;
257     }
258 
259     /* ------------------------------------------------------------ */
260     /**
261      * @param version the version to set
262      */
263     public void setVersion(String version)
264     {
265         _version=version;
266     }
267     
268     /* ------------------------------------------------------------ */
269     public String getContentType()
270     {
271         return getString(_contentType);
272     }
273     
274     /* ------------------------------------------------------------ */
275     public String getCharacterEncoding()
276     {
277         return _charset;
278     }
279 
280     /* ------------------------------------------------------------ */
281     /**
282      * @param name
283      * @param value
284      * @throws IllegalArgumentException
285      * @see org.eclipse.jetty.http.HttpFields#add(java.lang.String, java.lang.String)
286      */
287     public void addHeader(String name, String value) throws IllegalArgumentException
288     {
289         _fields.add(name,value);
290     }
291 
292     /* ------------------------------------------------------------ */
293     /**
294      * @param name
295      * @param date
296      * @see org.eclipse.jetty.http.HttpFields#addDateField(java.lang.String, long)
297      */
298     public void addDateHeader(String name, long date)
299     {
300         _fields.addDateField(name,date);
301     }
302 
303     /* ------------------------------------------------------------ */
304     /**
305      * @param name
306      * @param value
307      * @see org.eclipse.jetty.http.HttpFields#addLongField(java.lang.String, long)
308      */
309     public void addLongHeader(String name, long value)
310     {
311         _fields.addLongField(name,value);
312     }
313 
314     /* ------------------------------------------------------------ */
315     /**
316      * @param cookie
317      * @see org.eclipse.jetty.http.HttpFields#addSetCookie(org.eclipse.jetty.http.HttpCookie)
318      */
319     public void addSetCookie(Cookie cookie)
320     {
321         _fields.addSetCookie(
322                 cookie.getName(),
323                 cookie.getValue(),
324                 cookie.getDomain(),
325                 cookie.getPath(),
326                 cookie.getMaxAge(),
327                 cookie.getComment(),
328                 cookie.getSecure(),
329                 false,
330                 cookie.getVersion());
331     }
332 
333     /* ------------------------------------------------------------ */
334     /**
335      * @param name
336      * @return the header value as a date
337      * @see org.eclipse.jetty.http.HttpFields#getDateField(java.lang.String)
338      */
339     public long getDateHeader(String name)
340     {
341         return _fields.getDateField(name);
342     }
343 
344     /* ------------------------------------------------------------ */
345     /**
346      * @return the header value names
347      * @see org.eclipse.jetty.http.HttpFields#getFieldNames()
348      */
349     public Enumeration getHeaderNames()
350     {
351         return _fields.getFieldNames();
352     }
353 
354     /* ------------------------------------------------------------ */
355     /**
356      * @param name
357      * @return the header value as a long
358      * @throws NumberFormatException
359      * @see org.eclipse.jetty.http.HttpFields#getLongField(java.lang.String)
360      */
361     public long getLongHeader(String name) throws NumberFormatException
362     {
363         return _fields.getLongField(name);
364     }
365 
366     /* ------------------------------------------------------------ */
367     /**
368      * @param name
369      * @return the header value
370      * @see org.eclipse.jetty.http.HttpFields#getStringField(java.lang.String)
371      */
372     public String getHeader(String name)
373     {
374         return _fields.getStringField(name);
375     }
376 
377     /* ------------------------------------------------------------ */
378     /**
379      * @param name
380      * @return the header values
381      * @see org.eclipse.jetty.http.HttpFields#getValues(java.lang.String)
382      */
383     public Enumeration getHeaderValues(String name)
384     {
385         return _fields.getValues(name);
386     }
387 
388     /* ------------------------------------------------------------ */
389     /**
390      * @param name
391      * @param value
392      * @see org.eclipse.jetty.http.HttpFields#put(java.lang.String, java.lang.String)
393      */
394     public void setHeader(String name, String value)
395     {
396         _fields.put(name,value);
397     }
398 
399     /* ------------------------------------------------------------ */
400     /**
401      * @param name
402      * @param date
403      * @see org.eclipse.jetty.http.HttpFields#putDateField(java.lang.String, long)
404      */
405     public void setDateHeader(String name, long date)
406     {
407         _fields.putDateField(name,date);
408     }
409 
410     /* ------------------------------------------------------------ */
411     /**
412      * @param name
413      * @param value
414      * @see org.eclipse.jetty.http.HttpFields#putLongField(java.lang.String, long)
415      */
416     public void setLongHeader(String name, long value)
417     {
418         _fields.putLongField(name,value);
419     }
420 
421     /* ------------------------------------------------------------ */
422     /**
423      * @param name
424      * @see org.eclipse.jetty.http.HttpFields#remove(java.lang.String)
425      */
426     public void removeHeader(String name)
427     {
428         _fields.remove(name);
429     }
430     
431     /* ------------------------------------------------------------ */
432     public String getContent()
433     {
434         if (_parsedContent!=null)
435             return getString(_parsedContent.toByteArray());
436         if (_genContent!=null)
437             return getString(_genContent);
438         return null;
439     }
440     
441     /* ------------------------------------------------------------ */
442     public void setContent(String content)
443     {
444         _parsedContent=null;
445         if (content!=null)
446         {
447             _genContent=getByteArray(content);
448             setLongHeader(HttpHeaders.CONTENT_LENGTH,_genContent.length);
449         }
450         else
451         {
452             removeHeader(HttpHeaders.CONTENT_LENGTH);
453             _genContent=null;
454         }
455     }
456 
457     /* ------------------------------------------------------------ */
458     private class PH extends HttpParser.EventHandler
459     {
460         @Override
461         public void startRequest(Buffer method, Buffer url, Buffer version) throws IOException
462         {
463             reset();
464             _method=getString(method);
465             _uri=getString(url);
466             _version=getString(version);
467         }
468 
469         @Override
470         public void startResponse(Buffer version, int status, Buffer reason) throws IOException
471         {
472             reset();
473             _version=getString(version);
474             _status=status;
475             _reason=getString(reason);
476         }
477         
478         @Override
479         public void parsedHeader(Buffer name, Buffer value) throws IOException
480         {
481             _fields.add(name,value);
482         }
483 
484         @Override
485         public void headerComplete() throws IOException
486         {
487             _contentType = _fields.get(HttpHeaders.CONTENT_TYPE_BUFFER);
488             if(_contentType!=null)
489             {
490                 String charset = MimeTypes.getCharsetFromContentType(_contentType);
491                 if(charset!=null)
492                     _charset = charset;
493             }
494         }
495 
496         @Override
497         public void messageComplete(long contextLength) throws IOException
498         {
499         }
500         
501         @Override
502         public void content(Buffer ref) throws IOException
503         {
504             if (_parsedContent==null)
505                 _parsedContent=new ByteArrayOutputStream2();
506             _parsedContent.write(ref.asArray());
507         }
508     }
509 
510 }