1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http;
17
18 import io.netty.handler.codec.DefaultHeaders.NameValidator;
19 import io.netty.handler.codec.DefaultHeaders.ValueValidator;
20
21 import static io.netty.util.internal.ObjectUtil.checkNotNull;
22
23
24
25
26
27
28
29 public final class DefaultHttpHeadersFactory implements HttpHeadersFactory {
30 private static final NameValidator<CharSequence> DEFAULT_NAME_VALIDATOR = new NameValidator<CharSequence>() {
31 @Override
32 public void validateName(CharSequence name) {
33 if (name == null || name.length() == 0) {
34 throw new IllegalArgumentException("empty headers are not allowed [" + name + ']');
35 }
36 int index = HttpHeaderValidationUtil.validateToken(name);
37 if (index != -1) {
38 throw new IllegalArgumentException("a header name can only contain \"token\" characters, " +
39 "but found invalid character 0x" + Integer.toHexString(name.charAt(index)) +
40 " at index " + index + " of header '" + name + "'.");
41 }
42 }
43 };
44 private static final ValueValidator<CharSequence> DEFAULT_VALUE_VALIDATOR = new ValueValidator<CharSequence>() {
45 @Override
46 public void validate(CharSequence value) {
47 int index = HttpHeaderValidationUtil.validateValidHeaderValue(value);
48 if (index != -1) {
49 throw new IllegalArgumentException("a header value contains prohibited character 0x" +
50 Integer.toHexString(value.charAt(index)) + " at index " + index + '.');
51 }
52 }
53 };
54 private static final NameValidator<CharSequence> DEFAULT_TRAILER_NAME_VALIDATOR =
55 new NameValidator<CharSequence>() {
56 @Override
57 public void validateName(CharSequence name) {
58 DEFAULT_NAME_VALIDATOR.validateName(name);
59 if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(name)
60 || HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(name)
61 || HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(name)) {
62 throw new IllegalArgumentException("prohibited trailing header: " + name);
63 }
64 }
65 };
66
67 @SuppressWarnings("unchecked")
68 private static final NameValidator<CharSequence> NO_NAME_VALIDATOR = NameValidator.NOT_NULL;
69 @SuppressWarnings("unchecked")
70 private static final ValueValidator<CharSequence> NO_VALUE_VALIDATOR =
71 (ValueValidator<CharSequence>) ValueValidator.NO_VALIDATION;
72
73 private static final DefaultHttpHeadersFactory DEFAULT =
74 new DefaultHttpHeadersFactory(DEFAULT_NAME_VALIDATOR, DEFAULT_VALUE_VALIDATOR, false);
75 private static final DefaultHttpHeadersFactory DEFAULT_TRAILER =
76 new DefaultHttpHeadersFactory(DEFAULT_TRAILER_NAME_VALIDATOR, DEFAULT_VALUE_VALIDATOR, false);
77 private static final DefaultHttpHeadersFactory DEFAULT_COMBINING =
78 new DefaultHttpHeadersFactory(DEFAULT.nameValidator, DEFAULT.valueValidator, true);
79 private static final DefaultHttpHeadersFactory DEFAULT_NO_VALIDATION =
80 new DefaultHttpHeadersFactory(NO_NAME_VALIDATOR, NO_VALUE_VALIDATOR, false);
81
82 private final NameValidator<CharSequence> nameValidator;
83 private final ValueValidator<CharSequence> valueValidator;
84 private final boolean combiningHeaders;
85
86
87
88
89
90
91
92
93 private DefaultHttpHeadersFactory(
94 NameValidator<CharSequence> nameValidator,
95 ValueValidator<CharSequence> valueValidator,
96 boolean combiningHeaders) {
97 this.nameValidator = checkNotNull(nameValidator, "nameValidator");
98 this.valueValidator = checkNotNull(valueValidator, "valueValidator");
99 this.combiningHeaders = combiningHeaders;
100 }
101
102
103
104
105
106
107
108 public static DefaultHttpHeadersFactory headersFactory() {
109 return DEFAULT;
110 }
111
112
113
114
115
116
117
118 public static DefaultHttpHeadersFactory trailersFactory() {
119 return DEFAULT_TRAILER;
120 }
121
122 @Override
123 public HttpHeaders newHeaders() {
124 if (isCombiningHeaders()) {
125 return new CombinedHttpHeaders(getNameValidator(), getValueValidator());
126 }
127 return new DefaultHttpHeaders(getNameValidator(), getValueValidator());
128 }
129
130 @Override
131 public HttpHeaders newEmptyHeaders() {
132 if (isCombiningHeaders()) {
133 return new CombinedHttpHeaders(getNameValidator(), getValueValidator(), 2);
134 }
135 return new DefaultHttpHeaders(getNameValidator(), getValueValidator(), 2);
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public DefaultHttpHeadersFactory withNameValidation(boolean validation) {
154 return withNameValidator(validation ? DEFAULT_NAME_VALIDATOR : NO_NAME_VALIDATOR);
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public DefaultHttpHeadersFactory withNameValidator(NameValidator<CharSequence> validator) {
173 if (nameValidator == checkNotNull(validator, "validator")) {
174 return this;
175 }
176 if (validator == DEFAULT_NAME_VALIDATOR && valueValidator == DEFAULT_VALUE_VALIDATOR) {
177 return combiningHeaders ? DEFAULT_COMBINING : DEFAULT;
178 }
179 return new DefaultHttpHeadersFactory(validator, valueValidator, combiningHeaders);
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 public DefaultHttpHeadersFactory withValueValidation(boolean validation) {
198 return withValueValidator(validation ? DEFAULT_VALUE_VALIDATOR : NO_VALUE_VALIDATOR);
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 public DefaultHttpHeadersFactory withValueValidator(ValueValidator<CharSequence> validator) {
217 if (valueValidator == checkNotNull(validator, "validator")) {
218 return this;
219 }
220 if (nameValidator == DEFAULT_NAME_VALIDATOR && validator == DEFAULT_VALUE_VALIDATOR) {
221 return combiningHeaders ? DEFAULT_COMBINING : DEFAULT;
222 }
223 return new DefaultHttpHeadersFactory(nameValidator, validator, combiningHeaders);
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 public DefaultHttpHeadersFactory withValidation(boolean validation) {
242 if (this == DEFAULT && !validation) {
243 return DEFAULT_NO_VALIDATION;
244 }
245 if (this == DEFAULT_NO_VALIDATION && validation) {
246 return DEFAULT;
247 }
248 return withNameValidation(validation).withValueValidation(validation);
249 }
250
251
252
253
254
255
256
257
258 public DefaultHttpHeadersFactory withCombiningHeaders(boolean combiningHeaders) {
259 if (this.combiningHeaders == combiningHeaders) {
260 return this;
261 }
262 return new DefaultHttpHeadersFactory(nameValidator, valueValidator, combiningHeaders);
263 }
264
265
266
267
268
269
270
271
272 public NameValidator<CharSequence> getNameValidator() {
273 return nameValidator;
274 }
275
276
277
278
279
280
281
282
283 public ValueValidator<CharSequence> getValueValidator() {
284 return valueValidator;
285 }
286
287
288
289
290
291
292 public boolean isCombiningHeaders() {
293 return combiningHeaders;
294 }
295
296
297
298
299
300
301 public boolean isValidatingHeaderNames() {
302 return nameValidator != NO_NAME_VALIDATOR;
303 }
304
305
306
307
308
309
310 public boolean isValidatingHeaderValues() {
311 return valueValidator != NO_VALUE_VALIDATOR;
312 }
313 }