一、概述
个人是个实践型人员,所以打算看着jetty源码,从头开始组装Jetty。
首先从github.com里找到jetty-project项目,用git下载源码,本文以9.3.x为例。
首先Jetty作为一个web server,必然需要支持HTTP。
查看Jetty-http项目下http包下一共有下列几个类:
1接口: 2HttpContent 3HttpFieldPreEncoder 4HttpParser.HttpHandler 5HttpParser.RequestHandler 6HttpParser.ResponseHandler 7HttpTokens 8 9类: 10DateGenerator 11DateParser 12HttpPostHttpField 13Http1FieldPreEncoder 14HttpCookie 15HttpField 16HttpField.IntValueHttpField 17HttpField.LongValueHttpField 18HttpFields 19HttpGenerator 20HttpParser 21HttpStatus 22HttpURI 23MetaData 24MetaData.Request 25MetaData.Response 26MimeTypes 27PathMap 28PathMap.MappedEntry 29PathMap.PathSet 30PreEncodedHttpField 31ResourceHttpContent 32 33枚举类: 34HttpGenerator.Result 35HttpGenerator.State 36HttpHeader 37HttpHeaderValue 38HttpMethod 39HttpParser.State 40HttpScheme 41HttpStatus.Code 42HttpTokens.EndOfContent 43HttpVersion 44MimeTypes.Type 45 46异常类: 47BadMessageException
上述类里,需要关注的有下面几个基础类,分别进行解说。
Http协议由请求消息和响应消息组成,其中请求消息由请求行、首部行(消息报头)、实体主体组成;而响应消息由状态行、首部行、实体主体组成。围绕这些我们需要研究的类有HttpContent、HttpCookie、HttpField、HttpFields、HttpStatus等。
二、类分析
2.1 接口
1public interface HttpContent 2{ 3 HttpField getContentType(); 4 String getContentTypeValue(); 5 String getCharacterEncoding(); 6 Type getMimeType(); 7 8 HttpField getContentEncoding(); 9 String getContentEncodingValue(); 10 11 HttpField getContentLength(); 12 long getContentLengthValue(); 13 14 HttpField getLastModified(); 15 String getLastModifiedValue(); 16 17 HttpField getETag(); 18 String getETagValue(); 19 20 ByteBuffer getIndirectBuffer(); 21 ByteBuffer getDirectBuffer(); 22 Resource getResource(); 23 InputStream getInputStream() throws IOException; 24 ReadableByteChannel getReadableByteChannel() throws IOException; 25 void release(); 26 27 HttpContent getGzipContent(); 28 29 30 public interface Factory 31 { 32 HttpContent getContent(String path) throws IOException; 33 } 34}
HttpContent接口定义了一系列实体主体部分的操作。
并且本接口涉及到HttpField,查看HttpField源码。
1public class HttpField 2{ 3 private final static String __zeroquality="q=0"; 4 private final HttpHeader _header; 5 private final String _name; 6 private final String _value; 7 // cached hashcode for case insensitive name 8 private int hash = 0; 9 10 public HttpField(HttpHeader header, String name, String value) 11 { 12 _header = header; 13 _name = name; 14 _value = value; 15 } 16 17 public HttpField(HttpHeader header, String value) 18 { 19 this(header,header.asString(),value); 20 } 21 22 public HttpField(HttpHeader header, HttpHeaderValue value) 23 { 24 this(header,header.asString(),value.asString()); 25 } 26 27 public HttpField(String name, String value) 28 { 29 this(HttpHeader.CACHE.get(name),name,value); 30 } 31 //header、name的getter方法,value的int、long、String、String[]getter方法。 32 33 /* value是否包含search----------------------------- */ 34 /** Look for a value in a possible multi valued field 35 * @param search Values to search for 36 * @return True iff the value is contained in the field value entirely or 37 * as an element of a quoted comma separated list. List element parameters (eg qualities) are ignored, 38 * except if they are q=0, in which case the item itself is ignored. 39 */ 40 public boolean contains(String search){ 41 ... 42 } 43 44 @Override 45 public String toString() 46 { 47 String v=getValue(); 48 return getName() + ": " + (v==null?"":v); 49 } 50 //header是否和field同名 51 public boolean isSameName(HttpField field) 52 { 53 if (field==null) 54 return false; 55 if (field==this) 56 return true; 57 if (_header!=null && _header==field.getHeader()) 58 return true; 59 if (_name.equalsIgnoreCase(field.getName())) 60 return true; 61 return false; 62 } 63 64 private int nameHashCode() 65 { 66 int h = this.hash; 67 int len = _name.length(); 68 if (h == 0 && len > 0) 69 { 70 for (int i = 0; i < len; i++) 71 { 72 // simple case insensitive hash 73 char c = _name.charAt(i); 74 // assuming us-ascii (per last paragraph on http://tools.ietf.org/html/rfc7230#section-3.2.4) 75 if ((c >= 'a' && c <= 'z')) 76 c -= 0x20; 77 h = 31 * h + c; 78 } 79 this.hash = h; 80 } 81 return h; 82 } 83 84 @Override 85 public int hashCode() 86 { 87 if (_header==null) 88 return _value.hashCode() ^ nameHashCode(); 89 return _value.hashCode() ^ _header.hashCode(); 90 } 91 92 @Override 93 public boolean equals(Object o) 94 { 95 if (o==this) 96 return true; 97 if (!(o instanceof HttpField)) 98 return false; 99 HttpField field=(HttpField)o; 100 if (_header!=field.getHeader()) 101 return false; 102 if (!_name.equalsIgnoreCase(field.getName())) 103 return false; 104 if (_value==null && field.getValue()!=null) 105 return false; 106 return Objects.equals(_value,field.getValue()); 107 } 108 //内部类 109 public static class IntValueHttpField extends HttpField 110 { 111 private final int _int; 112 113 //构造方法和_int的getter 114 } 115 116 public static class LongValueHttpField extends HttpField 117 { 118 private final long _long; 119 120 //与IntValueHttpField相同 121 } 122}
HttpField包含header、name和value属性。可以看成一个有header的Map类。
HttpHeader是个枚举类,主要由General Fields、Entity Fields、Request Fields、Response Fields、Other Fields和HTTP2 Fields几块内容组成。我们在查看chrome的network里的Headers页签时能看到的内容可以查看到这General、Request和Response几块内容,而Other和HTTP2这里不讨论,剩下就是Entity部分其实也在Request里体现了。这就是一个文件头。
HttpFields是HttpField的集合类。
三、小结
Http协议请求消息由请求行(HttpURI)、首部行(HttpHeader)、实体主体(HttpContent)组成;而响应消息由状态行(HttpStatus)、首部行(HttpHeader)、实体主体(HttpContent)组成。