1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.message;
29
30 import java.nio.charset.StandardCharsets;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.LinkedHashSet;
35 import java.util.List;
36 import java.util.Set;
37
38 import org.apache.hc.core5.http.ContentType;
39 import org.apache.hc.core5.http.Header;
40 import org.apache.hc.core5.http.HeaderElement;
41 import org.apache.hc.core5.http.HttpEntity;
42 import org.apache.hc.core5.http.HttpHeaders;
43 import org.apache.hc.core5.http.HttpMessage;
44 import org.apache.hc.core5.http.HttpResponse;
45 import org.apache.hc.core5.http.HttpStatus;
46 import org.apache.hc.core5.http.NameValuePair;
47 import org.apache.hc.core5.http.io.entity.HttpEntities;
48 import org.apache.hc.core5.http.support.BasicResponseBuilder;
49 import org.apache.hc.core5.util.CharArrayBuffer;
50 import org.junit.jupiter.api.Assertions;
51 import org.junit.jupiter.api.Test;
52
53 class TestMessageSupport {
54
55 private static Set<String> makeSet(final String... tokens) {
56 if (tokens == null) {
57 return null;
58 }
59 final Set<String> set = new LinkedHashSet<>();
60 Collections.addAll(set, tokens);
61 return set;
62 }
63
64 @Test
65 void testTokenSetFormatting() {
66 final Header header = MessageSupport.header(HttpHeaders.TRAILER, makeSet("z", "b", "a"));
67 Assertions.assertNotNull(header);
68 Assertions.assertEquals("z, b, a", header.getValue());
69 }
70
71 @Test
72 void testTokenListFormatting() {
73 final Header header = MessageSupport.headerOfTokens(HttpHeaders.TRAILER, Arrays.asList("z", "b", "a", "a"));
74 Assertions.assertNotNull(header);
75 Assertions.assertEquals("z, b, a, a", header.getValue());
76 }
77
78 @Test
79 void testTokenSetFormattingSameName() {
80 final Header header = MessageSupport.header(HttpHeaders.TRAILER, makeSet("a", "a", "a"));
81 Assertions.assertNotNull(header);
82 Assertions.assertEquals("a", header.getValue());
83 }
84
85 @Test
86 void testTokenListFormattingSameName() {
87 final Header header = MessageSupport.header(HttpHeaders.TRAILER, "a", "a", "a");
88 Assertions.assertNotNull(header);
89 Assertions.assertEquals("a, a, a", header.getValue());
90 }
91
92 @Test
93 void testParseTokensWithConsumer() {
94 final String s = "a, b, c, c";
95 final ParserCursor cursor = new ParserCursor(0, s.length());
96 final List<String> tokens = new ArrayList<>();
97 MessageSupport.parseTokens(s, cursor, tokens::add);
98 Assertions.assertEquals(Arrays.asList("a", "b", "c", "c"), tokens);
99 }
100
101 @Test
102 void testParseTokenHeaderWithConsumer() {
103 final Header header = new BasicHeader(HttpHeaders.TRAILER, "a, b, c, c");
104 final List<String> tokens = new ArrayList<>();
105 MessageSupport.parseTokens(header, tokens::add);
106 Assertions.assertEquals(Arrays.asList("a", "b", "c", "c"), tokens);
107 }
108
109 @Test
110 void testParseTokenBufferWithConsumer() {
111 final CharArrayBuffer buf = new CharArrayBuffer(128);
112 buf.append("stuff: a, b, c, c");
113 final Header header = BufferedHeader.create(buf);
114 Assertions.assertEquals(makeSet("a", "b", "c", "c"), MessageSupport.parseTokens(header));
115 }
116
117 @Test
118 void testParseTokens() {
119 final String s = "a, b, c, c";
120 final ParserCursor cursor = new ParserCursor(0, s.length());
121 Assertions.assertEquals(makeSet("a", "b", "c"), MessageSupport.parseTokens(s, cursor));
122 }
123
124 @Test
125 void testParseTokenHeader() {
126 final Header header = new BasicHeader(HttpHeaders.TRAILER, "a, b, c, c");
127 Assertions.assertEquals(makeSet("a", "b", "c"), MessageSupport.parseTokens(header));
128 }
129
130 @Test
131 void testParseTokenBuffer() {
132 final CharArrayBuffer buf = new CharArrayBuffer(128);
133 buf.append("stuff: a, b, c, c");
134 final Header header = BufferedHeader.create(buf);
135 Assertions.assertEquals(makeSet("a", "b", "c"), MessageSupport.parseTokens(header));
136 }
137
138 @Test
139 void testElementListFormatting() {
140 final List<HeaderElement> elements = Arrays.asList(
141 new BasicHeaderElement("name1", "value1", new BasicNameValuePair("param", "regular_stuff")),
142 new BasicHeaderElement("name2", "value2", new BasicNameValuePair("param", "this\\that")),
143 new BasicHeaderElement("name3", "value3", new BasicNameValuePair("param", "this,that")),
144 new BasicHeaderElement("name4", "value4", new BasicNameValuePair("param", null)),
145 new BasicHeaderElement("name5", null));
146
147 final Header header = MessageSupport.headerOfElements("Some-header", elements);
148 Assertions.assertNotNull(header);
149 Assertions.assertEquals("name1=value1; param=regular_stuff, name2=value2; " +
150 "param=\"this\\\\that\", name3=value3; param=\"this,that\", " +
151 "name4=value4; param, name5", header.getValue());
152 }
153
154 @Test
155 void testElementArrayFormatting() {
156 final HeaderElement[] elements = {
157 new BasicHeaderElement("name1", "value1", new BasicNameValuePair("param", "regular_stuff")),
158 new BasicHeaderElement("name2", "value2", new BasicNameValuePair("param", "this\\that")),
159 new BasicHeaderElement("name3", "value3", new BasicNameValuePair("param", "this,that")),
160 new BasicHeaderElement("name4", "value4", new BasicNameValuePair("param", null)),
161 new BasicHeaderElement("name5", null)};
162
163 final Header header = MessageSupport.header("Some-Header", elements);
164 Assertions.assertNotNull(header);
165 Assertions.assertEquals("name1=value1; param=regular_stuff, name2=value2; " +
166 "param=\"this\\\\that\", name3=value3; param=\"this,that\", " +
167 "name4=value4; param, name5", header.getValue());
168 }
169
170 @Test
171 void testParseElementsBufferWithConsumer() {
172 final CharArrayBuffer buf = new CharArrayBuffer(64);
173 buf.append("name1 = value1; name2; name3=\"value3\" , name4=value4; " +
174 "name5=value5, name6= ; name7 = value7; name8 = \" value8\"");
175 final List<HeaderElement> elements = new ArrayList<>();
176 final ParserCursor cursor = new ParserCursor(0, buf.length());
177 MessageSupport.parseElements(buf, cursor, elements::add);
178
179 Assertions.assertEquals(3,elements.size());
180
181 Assertions.assertEquals("name1", elements.get(0).getName());
182 Assertions.assertEquals("value1", elements.get(0).getValue());
183
184 Assertions.assertEquals(2, elements.get(0).getParameters().length);
185 Assertions.assertEquals("name2", elements.get(0).getParameters()[0].getName());
186 Assertions.assertNull(elements.get(0).getParameters()[0].getValue());
187 Assertions.assertEquals("name3", elements.get(0).getParameters()[1].getName());
188 Assertions.assertEquals("value3", elements.get(0).getParameters()[1].getValue());
189
190 Assertions.assertEquals("name4", elements.get(1).getName());
191 Assertions.assertEquals("value4", elements.get(1).getValue());
192
193 Assertions.assertEquals(1, elements.get(1).getParameters().length);
194 Assertions.assertEquals("name5", elements.get(1).getParameters()[0].getName());
195 Assertions.assertEquals("value5", elements.get(1).getParameters()[0].getValue());
196
197 Assertions.assertEquals("name6", elements.get(2).getName());
198 Assertions.assertEquals("", elements.get(2).getValue());
199
200 Assertions.assertEquals(2, elements.get(2).getParameters().length);
201 Assertions.assertEquals("name7", elements.get(2).getParameters()[0].getName());
202 Assertions.assertEquals("value7", elements.get(2).getParameters()[0].getValue());
203 Assertions.assertEquals("name8", elements.get(2).getParameters()[1].getName());
204 Assertions.assertEquals(" value8", elements.get(2).getParameters()[1].getValue());
205 }
206
207 @Test
208 void testParseElementsHeaderWithConsumer() {
209 final Header header = new BasicHeader("Some-Header",
210 "name1 = value1; name2; name3=\"value3\" , name4=value4; " +
211 "name5=value5, name6= ; name7 = value7; name8 = \" value8\"");
212 final List<HeaderElement> elements = new ArrayList<>();
213 MessageSupport.parseElements(header, elements::add);
214
215 Assertions.assertEquals(3,elements.size());
216
217 Assertions.assertEquals("name1", elements.get(0).getName());
218 Assertions.assertEquals("value1", elements.get(0).getValue());
219
220 Assertions.assertEquals(2, elements.get(0).getParameters().length);
221 Assertions.assertEquals("name2", elements.get(0).getParameters()[0].getName());
222 Assertions.assertNull(elements.get(0).getParameters()[0].getValue());
223 Assertions.assertEquals("name3", elements.get(0).getParameters()[1].getName());
224 Assertions.assertEquals("value3", elements.get(0).getParameters()[1].getValue());
225
226 Assertions.assertEquals("name4", elements.get(1).getName());
227 Assertions.assertEquals("value4", elements.get(1).getValue());
228
229 Assertions.assertEquals(1, elements.get(1).getParameters().length);
230 Assertions.assertEquals("name5", elements.get(1).getParameters()[0].getName());
231 Assertions.assertEquals("value5", elements.get(1).getParameters()[0].getValue());
232
233 Assertions.assertEquals("name6", elements.get(2).getName());
234 Assertions.assertEquals("", elements.get(2).getValue());
235
236 Assertions.assertEquals(2, elements.get(2).getParameters().length);
237 Assertions.assertEquals("name7", elements.get(2).getParameters()[0].getName());
238 Assertions.assertEquals("value7", elements.get(2).getParameters()[0].getValue());
239 Assertions.assertEquals("name8", elements.get(2).getParameters()[1].getName());
240 Assertions.assertEquals(" value8", elements.get(2).getParameters()[1].getValue());
241 }
242
243 @Test
244 void testParseElementsHeader() {
245 final Header header = new BasicHeader("Some-Header",
246 "name1 = value1; name2; name3=\"value3\" , name4=value4; " +
247 "name5=value5, name6= ; name7 = value7; name8 = \" value8\"");
248 final List<HeaderElement> elements = MessageSupport.parseElements(header);
249
250 Assertions.assertEquals(3,elements.size());
251
252 Assertions.assertEquals("name1", elements.get(0).getName());
253 Assertions.assertEquals("value1", elements.get(0).getValue());
254
255 Assertions.assertEquals(2, elements.get(0).getParameters().length);
256 Assertions.assertEquals("name2", elements.get(0).getParameters()[0].getName());
257 Assertions.assertNull(elements.get(0).getParameters()[0].getValue());
258 Assertions.assertEquals("name3", elements.get(0).getParameters()[1].getName());
259 Assertions.assertEquals("value3", elements.get(0).getParameters()[1].getValue());
260
261 Assertions.assertEquals("name4", elements.get(1).getName());
262 Assertions.assertEquals("value4", elements.get(1).getValue());
263
264 Assertions.assertEquals(1, elements.get(1).getParameters().length);
265 Assertions.assertEquals("name5", elements.get(1).getParameters()[0].getName());
266 Assertions.assertEquals("value5", elements.get(1).getParameters()[0].getValue());
267
268 Assertions.assertEquals("name6", elements.get(2).getName());
269 Assertions.assertEquals("", elements.get(2).getValue());
270
271 Assertions.assertEquals(2, elements.get(2).getParameters().length);
272 Assertions.assertEquals("name7", elements.get(2).getParameters()[0].getName());
273 Assertions.assertEquals("value7", elements.get(2).getParameters()[0].getValue());
274 Assertions.assertEquals("name8", elements.get(2).getParameters()[1].getName());
275 Assertions.assertEquals(" value8", elements.get(2).getParameters()[1].getValue());
276 }
277
278 @Test
279 void testParamListFormatting() {
280 final CharArrayBuffer buf = new CharArrayBuffer(64);
281 MessageSupport.formatParameters(buf, Arrays.asList(
282 new BasicNameValuePair("param", "regular_stuff"),
283 new BasicNameValuePair("param", "this\\that"),
284 new BasicNameValuePair("param", "this,that")
285 ));
286 Assertions.assertEquals("param=regular_stuff; param=\"this\\\\that\"; param=\"this,that\"",
287 buf.toString());
288 }
289
290 @Test
291 void testParamArrayFormatting() {
292 final CharArrayBuffer buf = new CharArrayBuffer(64);
293 MessageSupport.formatParameters(buf,
294 new BasicNameValuePair("param", "regular_stuff"),
295 new BasicNameValuePair("param", "this\\that"),
296 new BasicNameValuePair("param", "this,that")
297 );
298 Assertions.assertEquals("param=regular_stuff; param=\"this\\\\that\"; param=\"this,that\"",
299 buf.toString());
300 }
301
302 @Test
303 void testParseParams() {
304 final String s =
305 "test; test1 = stuff ; test2 = \"stuff; stuff\"; test3=stuff,123";
306 final CharArrayBuffer buffer = new CharArrayBuffer(16);
307 buffer.append(s);
308 final ParserCursor cursor = new ParserCursor(0, s.length());
309
310 final List<NameValuePair> params = new ArrayList<>();
311 MessageSupport.parseParameters(buffer, cursor, params::add);
312 Assertions.assertEquals("test", params.get(0).getName());
313 Assertions.assertNull(params.get(0).getValue());
314 Assertions.assertEquals("test1", params.get(1).getName());
315 Assertions.assertEquals("stuff", params.get(1).getValue());
316 Assertions.assertEquals("test2", params.get(2).getName());
317 Assertions.assertEquals("stuff; stuff", params.get(2).getValue());
318 Assertions.assertEquals("test3", params.get(3).getName());
319 Assertions.assertEquals("stuff", params.get(3).getValue());
320 Assertions.assertEquals(s.length() - 4, cursor.getPos());
321 Assertions.assertFalse(cursor.atEnd());
322 }
323
324 @Test
325 void testAddContentHeaders() {
326 final HttpEntity entity = HttpEntities.create("some stuff with trailers", StandardCharsets.US_ASCII,
327 new BasicHeader("z", "this"), new BasicHeader("b", "that"), new BasicHeader("a", "this and that"));
328 final HttpMessage message = new BasicHttpResponse(200);
329 MessageSupport.addTrailerHeader(message, entity);
330 MessageSupport.addContentTypeHeader(message, entity);
331
332 final Header h1 = message.getFirstHeader(HttpHeaders.TRAILER);
333 final Header h2 = message.getFirstHeader(HttpHeaders.CONTENT_TYPE);
334
335 Assertions.assertNotNull(h1);
336 Assertions.assertEquals("z, b, a", h1.getValue());
337 Assertions.assertNotNull(h2);
338 Assertions.assertEquals("text/plain; charset=US-ASCII", h2.getValue());
339 }
340
341 @Test
342 void testContentHeadersAlreadyPresent() {
343 final HttpEntity entity = HttpEntities.create("some stuff with trailers", StandardCharsets.US_ASCII,
344 new BasicHeader("z", "this"), new BasicHeader("b", "that"), new BasicHeader("a", "this and that"));
345 final HttpMessage message = new BasicHttpResponse(200);
346 message.addHeader(HttpHeaders.TRAILER, "a, a, a");
347 message.addHeader(HttpHeaders.CONTENT_TYPE, "text/plain; charset=ascii");
348
349 MessageSupport.addTrailerHeader(message, entity);
350 MessageSupport.addContentTypeHeader(message, entity);
351
352 final Header h1 = message.getFirstHeader(HttpHeaders.TRAILER);
353 final Header h2 = message.getFirstHeader(HttpHeaders.CONTENT_TYPE);
354
355 Assertions.assertNotNull(h1);
356 Assertions.assertEquals("a, a, a", h1.getValue());
357 Assertions.assertNotNull(h2);
358 Assertions.assertEquals("text/plain; charset=ascii", h2.getValue());
359 }
360
361 @Test
362 void testHopByHopHeaders() {
363 Assertions.assertTrue(MessageSupport.isHopByHop("Connection"));
364 Assertions.assertTrue(MessageSupport.isHopByHop("connection"));
365 Assertions.assertTrue(MessageSupport.isHopByHop("coNNection"));
366 Assertions.assertFalse(MessageSupport.isHopByHop("Content-Type"));
367 Assertions.assertFalse(MessageSupport.isHopByHop("huh"));
368 }
369
370 @Test
371 void testHopByHopHeadersConnectionSpecific() {
372 final HttpResponse response = BasicResponseBuilder.create(HttpStatus.SC_OK)
373 .addHeader(HttpHeaders.CONNECTION, "blah, blah, this, that")
374 .addHeader(HttpHeaders.CONTENT_TYPE, ContentType.TEXT_PLAIN.toString())
375 .build();
376 final Set<String> hopByHopConnectionSpecific = MessageSupport.hopByHopConnectionSpecific(response);
377 Assertions.assertTrue(hopByHopConnectionSpecific.contains("Connection"));
378 Assertions.assertTrue(hopByHopConnectionSpecific.contains("connection"));
379 Assertions.assertTrue(hopByHopConnectionSpecific.contains("coNNection"));
380 Assertions.assertFalse(hopByHopConnectionSpecific.contains("Content-Type"));
381 Assertions.assertTrue(hopByHopConnectionSpecific.contains("blah"));
382 Assertions.assertTrue(hopByHopConnectionSpecific.contains("Blah"));
383 Assertions.assertTrue(hopByHopConnectionSpecific.contains("This"));
384 Assertions.assertTrue(hopByHopConnectionSpecific.contains("That"));
385 }
386
387 }