1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.eclipse.jetty.http2.hpack;
21
22
23 import org.eclipse.jetty.http.BadMessageException;
24 import org.eclipse.jetty.http.HostPortHttpField;
25 import org.eclipse.jetty.http.HttpField;
26 import org.eclipse.jetty.http.HttpFields;
27 import org.eclipse.jetty.http.HttpScheme;
28 import org.eclipse.jetty.http.HttpStatus;
29 import org.eclipse.jetty.http.HttpVersion;
30 import org.eclipse.jetty.http.MetaData;
31
32 public class MetaDataBuilder
33 {
34 private final int _maxSize;
35 private int _size;
36 private int _status;
37 private String _method;
38 private HttpScheme _scheme;
39 private HostPortHttpField _authority;
40 private String _path;
41 private long _contentLength=Long.MIN_VALUE;
42
43 private HttpFields _fields = new HttpFields(10);
44
45
46
47
48
49 MetaDataBuilder(int maxHeadersSize)
50 {
51 _maxSize=maxHeadersSize;
52 }
53
54
55
56
57 public int getMaxSize()
58 {
59 return _maxSize;
60 }
61
62
63
64
65 public int getSize()
66 {
67 return _size;
68 }
69
70 public void emit(HttpField field)
71 {
72 int field_size = field.getName().length()+field.getValue().length();
73 _size+=field_size;
74 if (_size>_maxSize)
75 throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_size+">"+_maxSize);
76
77 if (field instanceof StaticTableHttpField)
78 {
79 StaticTableHttpField value = (StaticTableHttpField)field;
80 switch(field.getHeader())
81 {
82 case C_STATUS:
83 _status=(Integer)value.getStaticValue();
84 break;
85
86 case C_METHOD:
87 _method=field.getValue();
88 break;
89
90 case C_SCHEME:
91 _scheme = (HttpScheme)value.getStaticValue();
92 break;
93
94 default:
95 throw new IllegalArgumentException(field.getName());
96 }
97 }
98 else if (field.getHeader()!=null)
99 {
100 switch(field.getHeader())
101 {
102 case C_STATUS:
103 _status=field.getIntValue();
104 break;
105
106 case C_METHOD:
107 _method=field.getValue();
108 break;
109
110 case C_SCHEME:
111 _scheme = HttpScheme.CACHE.get(field.getValue());
112 break;
113
114 case C_AUTHORITY:
115 _authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
116 break;
117
118 case HOST:
119
120 if (_authority==null)
121 _authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
122 _fields.add(field);
123 break;
124
125 case C_PATH:
126 _path = field.getValue();
127 break;
128
129 case CONTENT_LENGTH:
130 _contentLength = field.getLongValue();
131 _fields.add(field);
132 break;
133
134 default:
135 if (field.getName().charAt(0)!=':')
136 _fields.add(field);
137 }
138 }
139 else
140 {
141 if (field.getName().charAt(0)!=':')
142 _fields.add(field);
143 }
144 }
145
146 public MetaData build()
147 {
148 try
149 {
150 HttpFields fields = _fields;
151 _fields = new HttpFields(Math.max(10,fields.size()+5));
152
153 if (_method!=null)
154 return new MetaData.Request(_method,_scheme,_authority,_path,HttpVersion.HTTP_2,fields,_contentLength);
155 if (_status!=0)
156 return new MetaData.Response(HttpVersion.HTTP_2,_status,fields,_contentLength);
157 return new MetaData(HttpVersion.HTTP_2,fields,_contentLength);
158 }
159 finally
160 {
161 _status=0;
162 _method=null;
163 _scheme=null;
164 _authority=null;
165 _path=null;
166 _size=0;
167 _contentLength=Long.MIN_VALUE;
168 }
169 }
170
171
172
173
174
175
176 public void checkSize(int length, boolean huffman)
177 {
178
179 if (huffman)
180 length=(length*4)/3;
181 if ((_size+length)>_maxSize)
182 throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+(_size+length)+">"+_maxSize);
183 }
184 }