1use http::header::*;
2use http::*;
3
4#[test]
5fn smoke() {
6 let mut headers = HeaderMap::new();
7
8 assert!(headers.get("hello").is_none());
9
10 let name: HeaderName = "hello".parse().unwrap();
11
12 match headers.entry(&name) {
13 Entry::Vacant(e) => {
14 e.insert("world".parse().unwrap());
15 }
16 _ => panic!(),
17 }
18
19 assert!(headers.get("hello").is_some());
20
21 match headers.entry(&name) {
22 Entry::Occupied(mut e) => {
23 assert_eq!(e.get(), &"world");
24
25 // Push another value
26 e.append("zomg".parse().unwrap());
27
28 let mut i = e.iter();
29
30 assert_eq!(*i.next().unwrap(), "world");
31 assert_eq!(*i.next().unwrap(), "zomg");
32 assert!(i.next().is_none());
33 }
34 _ => panic!(),
35 }
36}
37
38#[test]
39#[should_panic]
40fn reserve_over_capacity() {
41 // See https://github.com/hyperium/http/issues/352
42 let mut headers = HeaderMap::<u32>::with_capacity(32);
43 headers.reserve(50_000); // over MAX_SIZE
44}
45
46#[test]
47fn with_capacity_max() {
48 // The largest capacity such that (cap + cap / 3) < MAX_SIZE.
49 HeaderMap::<u32>::with_capacity(24_576);
50}
51
52#[test]
53#[should_panic]
54fn with_capacity_overflow() {
55 HeaderMap::<u32>::with_capacity(24_577);
56}
57
58#[test]
59#[should_panic]
60fn reserve_overflow() {
61 // See https://github.com/hyperium/http/issues/352
62 let mut headers = HeaderMap::<u32>::with_capacity(0);
63 headers.reserve(std::usize::MAX); // next_power_of_two overflows
64}
65
66#[test]
67fn drain() {
68 let mut headers = HeaderMap::new();
69
70 // Insert a single value
71 let name: HeaderName = "hello".parse().unwrap();
72 headers.insert(name, "world".parse().unwrap());
73
74 {
75 let mut iter = headers.drain();
76 let (name, value) = iter.next().unwrap();
77 assert_eq!(name.unwrap().as_str(), "hello");
78
79 assert_eq!(value, "world");
80
81 assert!(iter.next().is_none());
82 }
83
84 assert!(headers.is_empty());
85
86 // Insert two sequential values
87 headers.insert(
88 "hello".parse::<HeaderName>().unwrap(),
89 "world".parse().unwrap(),
90 );
91 headers.insert(
92 "zomg".parse::<HeaderName>().unwrap(),
93 "bar".parse().unwrap(),
94 );
95 headers.append(
96 "hello".parse::<HeaderName>().unwrap(),
97 "world2".parse().unwrap(),
98 );
99
100 // Drain...
101 {
102 let mut iter = headers.drain();
103
104 let (name, value) = iter.next().unwrap();
105 assert_eq!(name.unwrap().as_str(), "hello");
106 assert_eq!(value, "world");
107
108 let (name, value) = iter.next().unwrap();
109 assert_eq!(name, None);
110 assert_eq!(value, "world2");
111
112 let (name, value) = iter.next().unwrap();
113 assert_eq!(name.unwrap().as_str(), "zomg");
114 assert_eq!(value, "bar");
115
116 assert!(iter.next().is_none());
117 }
118}
119
120#[test]
121fn drain_drop_immediately() {
122 // test mem::forgetting does not double-free
123
124 let mut headers = HeaderMap::new();
125 headers.insert("hello", "world".parse().unwrap());
126 headers.insert("zomg", "bar".parse().unwrap());
127 headers.append("hello", "world2".parse().unwrap());
128
129 let iter = headers.drain();
130 assert_eq!(iter.size_hint(), (2, Some(3)));
131 // not consuming `iter`
132}
133
134#[test]
135fn drain_forget() {
136 // test mem::forgetting does not double-free
137
138 let mut headers = HeaderMap::<HeaderValue>::new();
139 headers.insert("hello", "world".parse().unwrap());
140 headers.insert("zomg", "bar".parse().unwrap());
141
142 assert_eq!(headers.len(), 2);
143
144 {
145 let mut iter = headers.drain();
146 assert_eq!(iter.size_hint(), (2, Some(2)));
147 let _ = iter.next().unwrap();
148 std::mem::forget(iter);
149 }
150
151 assert_eq!(headers.len(), 0);
152}
153
154#[test]
155fn drain_entry() {
156 let mut headers = HeaderMap::new();
157
158 headers.insert(
159 "hello".parse::<HeaderName>().unwrap(),
160 "world".parse().unwrap(),
161 );
162 headers.insert(
163 "zomg".parse::<HeaderName>().unwrap(),
164 "foo".parse().unwrap(),
165 );
166 headers.append(
167 "hello".parse::<HeaderName>().unwrap(),
168 "world2".parse().unwrap(),
169 );
170 headers.insert(
171 "more".parse::<HeaderName>().unwrap(),
172 "words".parse().unwrap(),
173 );
174 headers.append(
175 "more".parse::<HeaderName>().unwrap(),
176 "insertions".parse().unwrap(),
177 );
178 assert_eq!(5, headers.len());
179
180 // Using insert_mult
181 {
182 let mut e = match headers.entry("hello") {
183 Entry::Occupied(e) => e,
184 _ => panic!(),
185 };
186
187 let vals: Vec<_> = e.insert_mult("wat".parse().unwrap()).collect();
188 assert_eq!(2, vals.len());
189 assert_eq!(vals[0], "world");
190 assert_eq!(vals[1], "world2");
191 }
192
193 assert_eq!(5-2+1, headers.len());
194}
195
196#[test]
197fn eq() {
198 let mut a = HeaderMap::new();
199 let mut b = HeaderMap::new();
200
201 assert_eq!(a, b);
202
203 a.insert(
204 "hello".parse::<HeaderName>().unwrap(),
205 "world".parse().unwrap(),
206 );
207 assert_ne!(a, b);
208
209 b.insert(
210 "hello".parse::<HeaderName>().unwrap(),
211 "world".parse().unwrap(),
212 );
213 assert_eq!(a, b);
214
215 a.insert("foo".parse::<HeaderName>().unwrap(), "bar".parse().unwrap());
216 a.append("foo".parse::<HeaderName>().unwrap(), "baz".parse().unwrap());
217 assert_ne!(a, b);
218
219 b.insert("foo".parse::<HeaderName>().unwrap(), "bar".parse().unwrap());
220 assert_ne!(a, b);
221
222 b.append("foo".parse::<HeaderName>().unwrap(), "baz".parse().unwrap());
223 assert_eq!(a, b);
224
225 a.append("a".parse::<HeaderName>().unwrap(), "a".parse().unwrap());
226 a.append("a".parse::<HeaderName>().unwrap(), "b".parse().unwrap());
227 b.append("a".parse::<HeaderName>().unwrap(), "b".parse().unwrap());
228 b.append("a".parse::<HeaderName>().unwrap(), "a".parse().unwrap());
229
230 assert_ne!(a, b);
231}
232
233#[test]
234fn into_header_name() {
235 let mut m = HeaderMap::new();
236 m.insert(HOST, "localhost".parse().unwrap());
237 m.insert(&ACCEPT, "*/*".parse().unwrap());
238 m.insert("connection", "keep-alive".parse().unwrap());
239
240 m.append(LOCATION, "/".parse().unwrap());
241 m.append(&VIA, "bob".parse().unwrap());
242 m.append("transfer-encoding", "chunked".parse().unwrap());
243
244 assert_eq!(m.len(), 6);
245}
246
247#[test]
248fn as_header_name() {
249 let mut m = HeaderMap::new();
250 let v: HeaderValue = "localhost".parse().unwrap();
251 m.insert(HOST, v.clone());
252
253 let expected = Some(&v);
254
255 assert_eq!(m.get("host"), expected);
256 assert_eq!(m.get(&HOST), expected);
257
258 let s = String::from("host");
259 assert_eq!(m.get(&s), expected);
260 assert_eq!(m.get(s.as_str()), expected);
261}
262
263#[test]
264fn insert_all_std_headers() {
265 let mut m = HeaderMap::new();
266
267 for (i, hdr) in STD.iter().enumerate() {
268 m.insert(hdr.clone(), hdr.as_str().parse().unwrap());
269
270 for j in 0..(i + 1) {
271 assert_eq!(m[&STD[j]], STD[j].as_str());
272 }
273
274 if i != 0 {
275 for j in (i + 1)..STD.len() {
276 assert!(
277 m.get(&STD[j]).is_none(),
278 "contained {}; j={}",
279 STD[j].as_str(),
280 j
281 );
282 }
283 }
284 }
285}
286
287#[test]
288fn insert_79_custom_std_headers() {
289 let mut h = HeaderMap::new();
290 let hdrs = custom_std(79);
291
292 for (i, hdr) in hdrs.iter().enumerate() {
293 h.insert(hdr.clone(), hdr.as_str().parse().unwrap());
294
295 for j in 0..(i + 1) {
296 assert_eq!(h[&hdrs[j]], hdrs[j].as_str());
297 }
298
299 for j in (i + 1)..hdrs.len() {
300 assert!(h.get(&hdrs[j]).is_none());
301 }
302 }
303}
304
305#[test]
306fn append_multiple_values() {
307 let mut map = HeaderMap::new();
308
309 map.append(header::CONTENT_TYPE, "json".parse().unwrap());
310 map.append(header::CONTENT_TYPE, "html".parse().unwrap());
311 map.append(header::CONTENT_TYPE, "xml".parse().unwrap());
312
313 let vals = map
314 .get_all(&header::CONTENT_TYPE)
315 .iter()
316 .collect::<Vec<_>>();
317
318 assert_eq!(&vals, &[&"json", &"html", &"xml"]);
319}
320
321fn custom_std(n: usize) -> Vec<HeaderName> {
322 (0..n)
323 .map(|i| {
324 let s = format!("{}-{}", STD[i % STD.len()].as_str(), i);
325 s.parse().unwrap()
326 })
327 .collect()
328}
329
330const STD: &'static [HeaderName] = &[
331 ACCEPT,
332 ACCEPT_CHARSET,
333 ACCEPT_ENCODING,
334 ACCEPT_LANGUAGE,
335 ACCEPT_RANGES,
336 ACCESS_CONTROL_ALLOW_CREDENTIALS,
337 ACCESS_CONTROL_ALLOW_HEADERS,
338 ACCESS_CONTROL_ALLOW_METHODS,
339 ACCESS_CONTROL_ALLOW_ORIGIN,
340 ACCESS_CONTROL_EXPOSE_HEADERS,
341 ACCESS_CONTROL_MAX_AGE,
342 ACCESS_CONTROL_REQUEST_HEADERS,
343 ACCESS_CONTROL_REQUEST_METHOD,
344 AGE,
345 ALLOW,
346 ALT_SVC,
347 AUTHORIZATION,
348 CACHE_CONTROL,
349 CACHE_STATUS,
350 CDN_CACHE_CONTROL,
351 CONNECTION,
352 CONTENT_DISPOSITION,
353 CONTENT_ENCODING,
354 CONTENT_LANGUAGE,
355 CONTENT_LENGTH,
356 CONTENT_LOCATION,
357 CONTENT_RANGE,
358 CONTENT_SECURITY_POLICY,
359 CONTENT_SECURITY_POLICY_REPORT_ONLY,
360 CONTENT_TYPE,
361 COOKIE,
362 DNT,
363 DATE,
364 ETAG,
365 EXPECT,
366 EXPIRES,
367 FORWARDED,
368 FROM,
369 HOST,
370 IF_MATCH,
371 IF_MODIFIED_SINCE,
372 IF_NONE_MATCH,
373 IF_RANGE,
374 IF_UNMODIFIED_SINCE,
375 LAST_MODIFIED,
376 LINK,
377 LOCATION,
378 MAX_FORWARDS,
379 ORIGIN,
380 PRAGMA,
381 PROXY_AUTHENTICATE,
382 PROXY_AUTHORIZATION,
383 PUBLIC_KEY_PINS,
384 PUBLIC_KEY_PINS_REPORT_ONLY,
385 RANGE,
386 REFERER,
387 REFERRER_POLICY,
388 RETRY_AFTER,
389 SERVER,
390 SET_COOKIE,
391 STRICT_TRANSPORT_SECURITY,
392 TE,
393 TRAILER,
394 TRANSFER_ENCODING,
395 USER_AGENT,
396 UPGRADE,
397 UPGRADE_INSECURE_REQUESTS,
398 VARY,
399 VIA,
400 WARNING,
401 WWW_AUTHENTICATE,
402 X_CONTENT_TYPE_OPTIONS,
403 X_DNS_PREFETCH_CONTROL,
404 X_FRAME_OPTIONS,
405 X_XSS_PROTECTION,
406];
407
408#[test]
409fn get_invalid() {
410 let mut headers = HeaderMap::new();
411 headers.insert("foo", "bar".parse().unwrap());
412 assert!(headers.get("Evil\r\nKey").is_none());
413}
414
415#[test]
416#[should_panic]
417fn insert_invalid() {
418 let mut headers = HeaderMap::new();
419 headers.insert("evil\r\nfoo", "bar".parse().unwrap());
420}
421
422#[test]
423fn value_htab() {
424 // RFC 7230 Section 3.2:
425 // > field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
426 HeaderValue::from_static("hello\tworld");
427 HeaderValue::from_str("hello\tworld").unwrap();
428}
429
430
431#[test]
432fn remove_multiple_a() {
433 let mut headers = HeaderMap::new();
434 headers.insert(VIA, "1.1 example.com".parse().unwrap());
435 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
436 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
437 headers.append(VIA, "1.1 other.com".parse().unwrap());
438 headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
439 headers.insert(VARY, "*".parse().unwrap());
440
441 assert_eq!(headers.len(), 6);
442
443 let cookie = headers.remove(SET_COOKIE);
444 assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
445 assert_eq!(headers.len(), 3);
446
447 let via = headers.remove(VIA);
448 assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
449 assert_eq!(headers.len(), 1);
450
451 let vary = headers.remove(VARY);
452 assert_eq!(vary, Some("*".parse().unwrap()));
453 assert_eq!(headers.len(), 0);
454}
455
456#[test]
457fn remove_multiple_b() {
458 let mut headers = HeaderMap::new();
459 headers.insert(VIA, "1.1 example.com".parse().unwrap());
460 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
461 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
462 headers.append(VIA, "1.1 other.com".parse().unwrap());
463 headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
464 headers.insert(VARY, "*".parse().unwrap());
465
466 assert_eq!(headers.len(), 6);
467
468 let vary = headers.remove(VARY);
469 assert_eq!(vary, Some("*".parse().unwrap()));
470 assert_eq!(headers.len(), 5);
471
472 let via = headers.remove(VIA);
473 assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
474 assert_eq!(headers.len(), 3);
475
476 let cookie = headers.remove(SET_COOKIE);
477 assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
478 assert_eq!(headers.len(), 0);
479}
480
481#[test]
482fn remove_entry_multi_0() {
483 let mut headers = HeaderMap::new();
484 let cookies = remove_all_values(&mut headers, SET_COOKIE);
485 assert_eq!(cookies.len(), 0);
486 assert_eq!(headers.len(), 0);
487}
488
489#[test]
490fn remove_entry_multi_0_others() {
491 let mut headers = HeaderMap::new();
492 headers.insert(VIA, "1.1 example.com".parse().unwrap());
493 headers.append(VIA, "1.1 other.com".parse().unwrap());
494
495 let cookies = remove_all_values(&mut headers, SET_COOKIE);
496 assert_eq!(cookies.len(), 0);
497 assert_eq!(headers.len(), 2);
498}
499
500#[test]
501fn remove_entry_multi_1() {
502 let mut headers = HeaderMap::new();
503 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
504
505 let cookies = remove_all_values(&mut headers, SET_COOKIE);
506 assert_eq!(cookies.len(), 1);
507 assert_eq!(headers.len(), 0);
508}
509
510#[test]
511fn remove_entry_multi_1_other() {
512 let mut headers = HeaderMap::new();
513 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
514 headers.insert(VIA, "1.1 example.com".parse().unwrap());
515
516 let cookies = remove_all_values(&mut headers, SET_COOKIE);
517 assert_eq!(cookies.len(), 1);
518 assert_eq!(headers.len(), 1);
519
520 let vias = remove_all_values(&mut headers, VIA);
521 assert_eq!(vias.len(), 1);
522 assert_eq!(headers.len(), 0);
523}
524
525// For issue hyperimum/http#446
526#[test]
527fn remove_entry_multi_2() {
528 let mut headers = HeaderMap::new();
529 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
530 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
531
532 let cookies = remove_all_values(&mut headers, SET_COOKIE);
533 assert_eq!(cookies.len(), 2);
534 assert_eq!(headers.len(), 0);
535}
536
537#[test]
538fn remove_entry_multi_3() {
539 let mut headers = HeaderMap::new();
540 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
541 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
542 headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
543
544 let cookies = remove_all_values(&mut headers, SET_COOKIE);
545 assert_eq!(cookies.len(), 3);
546 assert_eq!(headers.len(), 0);
547}
548
549#[test]
550fn remove_entry_multi_3_others() {
551 let mut headers = HeaderMap::new();
552 headers.insert(VIA, "1.1 example.com".parse().unwrap());
553 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
554 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
555 headers.append(VIA, "1.1 other.com".parse().unwrap());
556 headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
557 headers.insert(VARY, "*".parse().unwrap());
558
559 let cookies = remove_all_values(&mut headers, SET_COOKIE);
560 assert_eq!(cookies.len(), 3);
561 assert_eq!(headers.len(), 3);
562
563 let vias = remove_all_values(&mut headers, VIA);
564 assert_eq!(vias.len(), 2);
565 assert_eq!(headers.len(), 1);
566
567 let varies = remove_all_values(&mut headers, VARY);
568 assert_eq!(varies.len(), 1);
569 assert_eq!(headers.len(), 0);
570}
571
572fn remove_all_values<K>(headers: &mut HeaderMap, key: K) -> Vec<HeaderValue>
573 where K: IntoHeaderName
574{
575 match headers.entry(key) {
576 Entry::Occupied(e) => e.remove_entry_mult().1.collect(),
577 Entry::Vacant(_) => vec![],
578 }
579}
580
581#[test]
582fn remove_entry_3_others_a() {
583 let mut headers = HeaderMap::new();
584 headers.insert(VIA, "1.1 example.com".parse().unwrap());
585 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
586 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
587 headers.append(VIA, "1.1 other.com".parse().unwrap());
588 headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
589 headers.insert(VARY, "*".parse().unwrap());
590
591 assert_eq!(headers.len(), 6);
592
593 let cookie = remove_values(&mut headers, SET_COOKIE);
594 assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
595 assert_eq!(headers.len(), 3);
596
597 let via = remove_values(&mut headers, VIA);
598 assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
599 assert_eq!(headers.len(), 1);
600
601 let vary = remove_values(&mut headers, VARY);
602 assert_eq!(vary, Some("*".parse().unwrap()));
603 assert_eq!(headers.len(), 0);
604}
605
606#[test]
607fn remove_entry_3_others_b() {
608 let mut headers = HeaderMap::new();
609 headers.insert(VIA, "1.1 example.com".parse().unwrap());
610 headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
611 headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
612 headers.append(VIA, "1.1 other.com".parse().unwrap());
613 headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
614 headers.insert(VARY, "*".parse().unwrap());
615
616 assert_eq!(headers.len(), 6);
617
618 let vary = remove_values(&mut headers, VARY);
619 assert_eq!(vary, Some("*".parse().unwrap()));
620 assert_eq!(headers.len(), 5);
621
622 let via = remove_values(&mut headers, VIA);
623 assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
624 assert_eq!(headers.len(), 3);
625
626 let cookie = remove_values(&mut headers, SET_COOKIE);
627 assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
628 assert_eq!(headers.len(), 0);
629}
630
631fn remove_values<K>(headers: &mut HeaderMap, key: K) -> Option<HeaderValue>
632 where K: IntoHeaderName
633{
634 match headers.entry(key) {
635 Entry::Occupied(e) => Some(e.remove_entry().1),
636 Entry::Vacant(_) => None,
637 }
638}
639