http_with_url/header/
name.rs

1use HttpTryFrom;
2use byte_str::ByteStr;
3use bytes::{Bytes, BytesMut};
4
5use std::{fmt, mem};
6use std::borrow::Borrow;
7use std::hash::{Hash, Hasher};
8use std::str::FromStr;
9use std::error::Error;
10
11/// Represents an HTTP header field name
12///
13/// Header field names identify the header. Header sets may include multiple
14/// headers with the same name. The HTTP specification defines a number of
15/// standard headers, but HTTP messages may include non-standard header names as
16/// well as long as they adhere to the specification.
17///
18/// `HeaderName` is used as the [`HeaderMap`] key. Constants are available for
19/// all standard header names in the [`header`] module.
20///
21/// # Representation
22///
23/// `HeaderName` represents standard header names using an `enum`, as such they
24/// will not require an allocation for storage. All custom header names are
25/// lower cased upon conversion to a `HeaderName` value. This avoids the
26/// overhead of dynamically doing lower case conversion during the hash code
27/// computation and the comparison operation.
28///
29/// [`HeaderMap`]: struct.HeaderMap.html
30/// [`header`]: index.html
31#[derive(Clone, Eq, PartialEq, Hash)]
32pub struct HeaderName {
33    inner: Repr<Custom>,
34}
35
36// Almost a full `HeaderName`
37#[derive(Debug, Hash)]
38pub struct HdrName<'a> {
39    inner: Repr<MaybeLower<'a>>,
40}
41
42#[derive(Debug, Clone, Eq, PartialEq, Hash)]
43enum Repr<T> {
44    Standard(StandardHeader),
45    Custom(T),
46}
47
48// Used to hijack the Hash impl
49#[derive(Debug, Clone, Eq, PartialEq)]
50struct Custom(ByteStr);
51
52#[derive(Debug, Clone)]
53struct MaybeLower<'a> {
54    buf: &'a [u8],
55    lower: bool,
56}
57
58/// A possible error when converting a `HeaderName` from another type.
59#[derive(Debug)]
60pub struct InvalidHeaderName {
61    _priv: (),
62}
63
64/// A possible error when converting a `HeaderName` from another type.
65#[derive(Debug)]
66pub struct InvalidHeaderNameBytes(InvalidHeaderName) ;
67
68macro_rules! standard_headers {
69    (
70        $(
71            $(#[$docs:meta])*
72            ($konst:ident, $upcase:ident, $name:expr);
73        )+
74    ) => {
75        #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
76        enum StandardHeader {
77            $(
78                $konst,
79            )+
80        }
81
82        $(
83            $(#[$docs])*
84            pub const $upcase: HeaderName = HeaderName {
85                inner: Repr::Standard(StandardHeader::$konst),
86            };
87        )+
88
89        impl StandardHeader {
90            #[inline]
91            fn as_str(&self) -> &'static str {
92                match *self {
93                    $(
94                    StandardHeader::$konst => $name,
95                    )+
96                }
97            }
98        }
99
100        #[cfg(test)]
101        const TEST_HEADERS: &'static [(StandardHeader, &'static str)] = &[
102            $(
103            (StandardHeader::$konst, $name),
104            )+
105        ];
106
107        #[test]
108        fn test_parse_standard_headers() {
109            for &(std, name) in TEST_HEADERS {
110                // Test lower case
111                assert_eq!(HeaderName::from_bytes(name.as_bytes()).unwrap(), HeaderName::from(std));
112
113                // Test upper case
114                let upper = name.to_uppercase().to_string();
115                assert_eq!(HeaderName::from_bytes(upper.as_bytes()).unwrap(), HeaderName::from(std));
116            }
117        }
118
119        #[test]
120        fn test_standard_headers_into_bytes() {
121            for &(std, name) in TEST_HEADERS {
122                let std = HeaderName::from(std);
123                // Test lower case
124                let name_bytes = name.as_bytes();
125                let bytes: Bytes =
126                    HeaderName::from_bytes(name_bytes).unwrap().into();
127                assert_eq!(bytes, name_bytes);
128                assert_eq!(HeaderName::from_bytes(name_bytes).unwrap(), std);
129
130                // Test upper case
131                let upper = name.to_uppercase().to_string();
132                let bytes: Bytes =
133                    HeaderName::from_bytes(upper.as_bytes()).unwrap().into();
134                assert_eq!(bytes, name.as_bytes());
135                assert_eq!(HeaderName::from_bytes(upper.as_bytes()).unwrap(),
136                           std);
137
138
139            }
140
141        }
142    }
143}
144
145// Generate constants for all standard HTTP headers. This includes a static hash
146// code for the "fast hash" path. The hash code for static headers *do not* have
147// to match the text representation of those headers. This is because header
148// strings are always converted to the static values (when they match) before
149// being hashed. This means that it is impossible to compare the static hash
150// code of CONTENT_LENGTH with "content-length".
151standard_headers! {
152    /// Advertises which content types the client is able to understand.
153    ///
154    /// The Accept request HTTP header advertises which content types, expressed
155    /// as MIME types, the client is able to understand. Using content
156    /// negotiation, the server then selects one of the proposals, uses it and
157    /// informs the client of its choice with the Content-Type response header.
158    /// Browsers set adequate values for this header depending of the context
159    /// where the request is done: when fetching a CSS stylesheet a different
160    /// value is set for the request than when fetching an image, video or a
161    /// script.
162    (Accept, ACCEPT, "accept");
163
164    /// Advertises which character set the client is able to understand.
165    ///
166    /// The Accept-Charset request HTTP header advertises which character set
167    /// the client is able to understand. Using content negotiation, the server
168    /// then selects one of the proposals, uses it and informs the client of its
169    /// choice within the Content-Type response header. Browsers usually don't
170    /// set this header as the default value for each content type is usually
171    /// correct and transmitting it would allow easier fingerprinting.
172    ///
173    /// If the server cannot serve any matching character set, it can
174    /// theoretically send back a 406 (Not Acceptable) error code. But, for a
175    /// better user experience, this is rarely done and the more common way is
176    /// to ignore the Accept-Charset header in this case.
177    (AcceptCharset, ACCEPT_CHARSET, "accept-charset");
178
179    /// Advertises which content encoding the client is able to understand.
180    ///
181    /// The Accept-Encoding request HTTP header advertises which content
182    /// encoding, usually a compression algorithm, the client is able to
183    /// understand. Using content negotiation, the server selects one of the
184    /// proposals, uses it and informs the client of its choice with the
185    /// Content-Encoding response header.
186    ///
187    /// Even if both the client and the server supports the same compression
188    /// algorithms, the server may choose not to compress the body of a
189    /// response, if the identity value is also acceptable. Two common cases
190    /// lead to this:
191    ///
192    /// * The data to be sent is already compressed and a second compression
193    /// won't lead to smaller data to be transmitted. This may the case with
194    /// some image formats;
195    ///
196    /// * The server is overloaded and cannot afford the computational overhead
197    /// induced by the compression requirement. Typically, Microsoft recommends
198    /// not to compress if a server use more than 80 % of its computational
199    /// power.
200    ///
201    /// As long as the identity value, meaning no encryption, is not explicitly
202    /// forbidden, by an identity;q=0 or a *;q=0 without another explicitly set
203    /// value for identity, the server must never send back a 406 Not Acceptable
204    /// error.
205    (AcceptEncoding, ACCEPT_ENCODING, "accept-encoding");
206
207    /// Advertises which languages the client is able to understand.
208    ///
209    /// The Accept-Language request HTTP header advertises which languages the
210    /// client is able to understand, and which locale variant is preferred.
211    /// Using content negotiation, the server then selects one of the proposals,
212    /// uses it and informs the client of its choice with the Content-Language
213    /// response header. Browsers set adequate values for this header according
214    /// their user interface language and even if a user can change it, this
215    /// happens rarely (and is frown upon as it leads to fingerprinting).
216    ///
217    /// This header is a hint to be used when the server has no way of
218    /// determining the language via another way, like a specific URL, that is
219    /// controlled by an explicit user decision. It is recommended that the
220    /// server never overrides an explicit decision. The content of the
221    /// Accept-Language is often out of the control of the user (like when
222    /// traveling and using an Internet Cafe in a different country); the user
223    /// may also want to visit a page in another language than the locale of
224    /// their user interface.
225    ///
226    /// If the server cannot serve any matching language, it can theoretically
227    /// send back a 406 (Not Acceptable) error code. But, for a better user
228    /// experience, this is rarely done and more common way is to ignore the
229    /// Accept-Language header in this case.
230    (AcceptLanguage, ACCEPT_LANGUAGE, "accept-language");
231
232    /// Marker used by the server to advertise partial request support.
233    ///
234    /// The Accept-Ranges response HTTP header is a marker used by the server to
235    /// advertise its support of partial requests. The value of this field
236    /// indicates the unit that can be used to define a range.
237    ///
238    /// In presence of an Accept-Ranges header, the browser may try to resume an
239    /// interrupted download, rather than to start it from the start again.
240    (AcceptRanges, ACCEPT_RANGES, "accept-ranges");
241
242    /// Preflight response indicating if the response to the request can be
243    /// exposed to the page.
244    ///
245    /// The Access-Control-Allow-Credentials response header indicates whether
246    /// or not the response to the request can be exposed to the page. It can be
247    /// exposed when the true value is returned; it can't in other cases.
248    ///
249    /// Credentials are cookies, authorization headers or TLS client
250    /// certificates.
251    ///
252    /// When used as part of a response to a preflight request, this indicates
253    /// whether or not the actual request can be made using credentials. Note
254    /// that simple GET requests are not preflighted, and so if a request is
255    /// made for a resource with credentials, if this header is not returned
256    /// with the resource, the response is ignored by the browser and not
257    /// returned to web content.
258    ///
259    /// The Access-Control-Allow-Credentials header works in conjunction with
260    /// the XMLHttpRequest.withCredentials property or with the credentials
261    /// option in the Request() constructor of the Fetch API. Credentials must
262    /// be set on both sides (the Access-Control-Allow-Credentials header and in
263    /// the XHR or Fetch request) in order for the CORS request with credentials
264    /// to succeed.
265    (AccessControlAllowCredentials, ACCESS_CONTROL_ALLOW_CREDENTIALS, "access-control-allow-credentials");
266
267    /// Preflight response indicating permitted HTTP headers.
268    ///
269    /// The Access-Control-Allow-Headers response header is used in response to
270    /// a preflight request to indicate which HTTP headers will be available via
271    /// Access-Control-Expose-Headers when making the actual request.
272    ///
273    /// The simple headers, Accept, Accept-Language, Content-Language,
274    /// Content-Type (but only with a MIME type of its parsed value (ignoring
275    /// parameters) of either application/x-www-form-urlencoded,
276    /// multipart/form-data, or text/plain), are always available and don't need
277    /// to be listed by this header.
278    ///
279    /// This header is required if the request has an
280    /// Access-Control-Request-Headers header.
281    (AccessControlAllowHeaders, ACCESS_CONTROL_ALLOW_HEADERS, "access-control-allow-headers");
282
283    /// Preflight header response indicating permitted access methods.
284    ///
285    /// The Access-Control-Allow-Methods response header specifies the method or
286    /// methods allowed when accessing the resource in response to a preflight
287    /// request.
288    (AccessControlAllowMethods, ACCESS_CONTROL_ALLOW_METHODS, "access-control-allow-methods");
289
290    /// Indicates whether the response can be shared with resources with the
291    /// given origin.
292    (AccessControlAllowOrigin, ACCESS_CONTROL_ALLOW_ORIGIN, "access-control-allow-origin");
293
294    /// Indicates which headers can be exposed as part of the response by
295    /// listing their names.
296    (AccessControlExposeHeaders, ACCESS_CONTROL_EXPOSE_HEADERS, "access-control-expose-headers");
297
298    /// Indicates how long the results of a preflight request can be cached.
299    (AccessControlMaxAge, ACCESS_CONTROL_MAX_AGE, "access-control-max-age");
300
301    /// Informs the server which HTTP headers will be used when an actual
302    /// request is made.
303    (AccessControlRequestHeaders, ACCESS_CONTROL_REQUEST_HEADERS, "access-control-request-headers");
304
305    /// Informs the server know which HTTP method will be used when the actual
306    /// request is made.
307    (AccessControlRequestMethod, ACCESS_CONTROL_REQUEST_METHOD, "access-control-request-method");
308
309    /// Indicates the time in seconds the object has been in a proxy cache.
310    ///
311    /// The Age header is usually close to zero. If it is Age: 0, it was
312    /// probably just fetched from the origin server; otherwise It is usually
313    /// calculated as a difference between the proxy's current date and the Date
314    /// general header included in the HTTP response.
315    (Age, AGE, "age");
316
317    /// Lists the set of methods support by a resource.
318    ///
319    /// This header must be sent if the server responds with a 405 Method Not
320    /// Allowed status code to indicate which request methods can be used. An
321    /// empty Allow header indicates that the resource allows no request
322    /// methods, which might occur temporarily for a given resource, for
323    /// example.
324    (Allow, ALLOW, "allow");
325
326    /// Advertises the availability of alternate services to clients.
327    (AltSvc, ALT_SVC, "alt-svc");
328
329    /// Contains the credentials to authenticate a user agent with a server.
330    ///
331    /// Usually this header is included after the server has responded with a
332    /// 401 Unauthorized status and the WWW-Authenticate header.
333    (Authorization, AUTHORIZATION, "authorization");
334
335    /// Specifies directives for caching mechanisms in both requests and
336    /// responses.
337    ///
338    /// Caching directives are unidirectional, meaning that a given directive in
339    /// a request is not implying that the same directive is to be given in the
340    /// response.
341    (CacheControl, CACHE_CONTROL, "cache-control");
342
343    /// Controls whether or not the network connection stays open after the
344    /// current transaction finishes.
345    ///
346    /// If the value sent is keep-alive, the connection is persistent and not
347    /// closed, allowing for subsequent requests to the same server to be done.
348    ///
349    /// Except for the standard hop-by-hop headers (Keep-Alive,
350    /// Transfer-Encoding, TE, Connection, Trailer, Upgrade, Proxy-Authorization
351    /// and Proxy-Authenticate), any hop-by-hop headers used by the message must
352    /// be listed in the Connection header, so that the first proxy knows he has
353    /// to consume them and not to forward them further. Standard hop-by-hop
354    /// headers can be listed too (it is often the case of Keep-Alive, but this
355    /// is not mandatory.
356    (Connection, CONNECTION, "connection");
357
358    /// Indicates if the content is expected to be displayed inline.
359    ///
360    /// In a regular HTTP response, the Content-Disposition response header is a
361    /// header indicating if the content is expected to be displayed inline in
362    /// the browser, that is, as a Web page or as part of a Web page, or as an
363    /// attachment, that is downloaded and saved locally.
364    ///
365    /// In a multipart/form-data body, the HTTP Content-Disposition general
366    /// header is a header that can be used on the subpart of a multipart body
367    /// to give information about the field it applies to. The subpart is
368    /// delimited by the boundary defined in the Content-Type header. Used on
369    /// the body itself, Content-Disposition has no effect.
370    ///
371    /// The Content-Disposition header is defined in the larger context of MIME
372    /// messages for e-mail, but only a subset of the possible parameters apply
373    /// to HTTP forms and POST requests. Only the value form-data, as well as
374    /// the optional directive name and filename, can be used in the HTTP
375    /// context.
376    (ContentDisposition, CONTENT_DISPOSITION, "content-disposition");
377
378    /// Used to compress the media-type.
379    ///
380    /// When present, its value indicates what additional content encoding has
381    /// been applied to the entity-body. It lets the client know, how to decode
382    /// in order to obtain the media-type referenced by the Content-Type header.
383    ///
384    /// It is recommended to compress data as much as possible and therefore to
385    /// use this field, but some types of resources, like jpeg images, are
386    /// already compressed.  Sometimes using additional compression doesn't
387    /// reduce payload size and can even make the payload longer.
388    (ContentEncoding, CONTENT_ENCODING, "content-encoding");
389
390    /// Used to describe the languages intended for the audience.
391    ///
392    /// This header allows a user to differentiate according to the users' own
393    /// preferred language. For example, if "Content-Language: de-DE" is set, it
394    /// says that the document is intended for German language speakers
395    /// (however, it doesn't indicate the document is written in German. For
396    /// example, it might be written in English as part of a language course for
397    /// German speakers).
398    ///
399    /// If no Content-Language is specified, the default is that the content is
400    /// intended for all language audiences. Multiple language tags are also
401    /// possible, as well as applying the Content-Language header to various
402    /// media types and not only to textual documents.
403    (ContentLanguage, CONTENT_LANGUAGE, "content-language");
404
405    /// Indicates the size fo the entity-body.
406    ///
407    /// The header value must be a decimal indicating the number of octets sent
408    /// to the recipient.
409    (ContentLength, CONTENT_LENGTH, "content-length");
410
411    /// Indicates an alternate location for the returned data.
412    ///
413    /// The principal use case is to indicate the URL of the resource
414    /// transmitted as the result of content negotiation.
415    ///
416    /// Location and Content-Location are different: Location indicates the
417    /// target of a redirection (or the URL of a newly created document), while
418    /// Content-Location indicates the direct URL to use to access the resource,
419    /// without the need of further content negotiation. Location is a header
420    /// associated with the response, while Content-Location is associated with
421    /// the entity returned.
422    (ContentLocation, CONTENT_LOCATION, "content-location");
423
424    /// Indicates where in a full body message a partial message belongs.
425    (ContentRange, CONTENT_RANGE, "content-range");
426
427    /// Allows controlling resources the user agent is allowed to load for a
428    /// given page.
429    ///
430    /// With a few exceptions, policies mostly involve specifying server origins
431    /// and script endpoints. This helps guard against cross-site scripting
432    /// attacks (XSS).
433    (ContentSecurityPolicy, CONTENT_SECURITY_POLICY, "content-security-policy");
434
435    /// Allows experimenting with policies by monitoring their effects.
436    ///
437    /// The HTTP Content-Security-Policy-Report-Only response header allows web
438    /// developers to experiment with policies by monitoring (but not enforcing)
439    /// their effects. These violation reports consist of JSON documents sent
440    /// via an HTTP POST request to the specified URI.
441    (ContentSecurityPolicyReportOnly, CONTENT_SECURITY_POLICY_REPORT_ONLY, "content-security-policy-report-only");
442
443    /// Used to indicate the media type of the resource.
444    ///
445    /// In responses, a Content-Type header tells the client what the content
446    /// type of the returned content actually is. Browsers will do MIME sniffing
447    /// in some cases and will not necessarily follow the value of this header;
448    /// to prevent this behavior, the header X-Content-Type-Options can be set
449    /// to nosniff.
450    ///
451    /// In requests, (such as POST or PUT), the client tells the server what
452    /// type of data is actually sent.
453    (ContentType, CONTENT_TYPE, "content-type");
454
455    /// Contains stored HTTP cookies previously sent by the server with the
456    /// Set-Cookie header.
457    ///
458    /// The Cookie header might be omitted entirely, if the privacy setting of
459    /// the browser are set to block them, for example.
460    (Cookie, COOKIE, "cookie");
461
462    /// Indicates the client's tracking preference.
463    ///
464    /// This header lets users indicate whether they would prefer privacy rather
465    /// than personalized content.
466    (Dnt, DNT, "dnt");
467
468    /// Contains the date and time at which the message was originated.
469    (Date, DATE, "date");
470
471    /// Identifier for a specific version of a resource.
472    ///
473    /// This header allows caches to be more efficient, and saves bandwidth, as
474    /// a web server does not need to send a full response if the content has
475    /// not changed. On the other side, if the content has changed, etags are
476    /// useful to help prevent simultaneous updates of a resource from
477    /// overwriting each other ("mid-air collisions").
478    ///
479    /// If the resource at a given URL changes, a new Etag value must be
480    /// generated. Etags are therefore similar to fingerprints and might also be
481    /// used for tracking purposes by some servers. A comparison of them allows
482    /// to quickly determine whether two representations of a resource are the
483    /// same, but they might also be set to persist indefinitely by a tracking
484    /// server.
485    (Etag, ETAG, "etag");
486
487    /// Indicates expectations that need to be fulfilled by the server in order
488    /// to properly handle the request.
489    ///
490    /// The only expectation defined in the specification is Expect:
491    /// 100-continue, to which the server shall respond with:
492    ///
493    /// * 100 if the information contained in the header is sufficient to cause
494    /// an immediate success,
495    ///
496    /// * 417 (Expectation Failed) if it cannot meet the expectation; or any
497    /// other 4xx status otherwise.
498    ///
499    /// For example, the server may reject a request if its Content-Length is
500    /// too large.
501    ///
502    /// No common browsers send the Expect header, but some other clients such
503    /// as cURL do so by default.
504    (Expect, EXPECT, "expect");
505
506    /// Contains the date/time after which the response is considered stale.
507    ///
508    /// Invalid dates, like the value 0, represent a date in the past and mean
509    /// that the resource is already expired.
510    ///
511    /// If there is a Cache-Control header with the "max-age" or "s-max-age"
512    /// directive in the response, the Expires header is ignored.
513    (Expires, EXPIRES, "expires");
514
515    /// Contains information from the client-facing side of proxy servers that
516    /// is altered or lost when a proxy is involved in the path of the request.
517    ///
518    /// The alternative and de-facto standard versions of this header are the
519    /// X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto headers.
520    ///
521    /// This header is used for debugging, statistics, and generating
522    /// location-dependent content and by design it exposes privacy sensitive
523    /// information, such as the IP address of the client. Therefore the user's
524    /// privacy must be kept in mind when deploying this header.
525    (Forwarded, FORWARDED, "forwarded");
526
527    /// Contains an Internet email address for a human user who controls the
528    /// requesting user agent.
529    ///
530    /// If you are running a robotic user agent (e.g. a crawler), the From
531    /// header should be sent, so you can be contacted if problems occur on
532    /// servers, such as if the robot is sending excessive, unwanted, or invalid
533    /// requests.
534    (From, FROM, "from");
535
536    /// Specifies the domain name of the server and (optionally) the TCP port
537    /// number on which the server is listening.
538    ///
539    /// If no port is given, the default port for the service requested (e.g.,
540    /// "80" for an HTTP URL) is implied.
541    ///
542    /// A Host header field must be sent in all HTTP/1.1 request messages. A 400
543    /// (Bad Request) status code will be sent to any HTTP/1.1 request message
544    /// that lacks a Host header field or contains more than one.
545    (Host, HOST, "host");
546
547    /// Makes a request conditional based on the E-Tag.
548    ///
549    /// For GET and HEAD methods, the server will send back the requested
550    /// resource only if it matches one of the listed ETags. For PUT and other
551    /// non-safe methods, it will only upload the resource in this case.
552    ///
553    /// The comparison with the stored ETag uses the strong comparison
554    /// algorithm, meaning two files are considered identical byte to byte only.
555    /// This is weakened when the  W/ prefix is used in front of the ETag.
556    ///
557    /// There are two common use cases:
558    ///
559    /// * For GET and HEAD methods, used in combination with an Range header, it
560    /// can guarantee that the new ranges requested comes from the same resource
561    /// than the previous one. If it doesn't match, then a 416 (Range Not
562    /// Satisfiable) response is returned.
563    ///
564    /// * For other methods, and in particular for PUT, If-Match can be used to
565    /// prevent the lost update problem. It can check if the modification of a
566    /// resource that the user wants to upload will not override another change
567    /// that has been done since the original resource was fetched. If the
568    /// request cannot be fulfilled, the 412 (Precondition Failed) response is
569    /// returned.
570    (IfMatch, IF_MATCH, "if-match");
571
572    /// Makes a request conditional based on the modification date.
573    ///
574    /// The If-Modified-Since request HTTP header makes the request conditional:
575    /// the server will send back the requested resource, with a 200 status,
576    /// only if it has been last modified after the given date. If the request
577    /// has not been modified since, the response will be a 304 without any
578    /// body; the Last-Modified header will contain the date of last
579    /// modification. Unlike If-Unmodified-Since, If-Modified-Since can only be
580    /// used with a GET or HEAD.
581    ///
582    /// When used in combination with If-None-Match, it is ignored, unless the
583    /// server doesn't support If-None-Match.
584    ///
585    /// The most common use case is to update a cached entity that has no
586    /// associated ETag.
587    (IfModifiedSince, IF_MODIFIED_SINCE, "if-modified-since");
588
589    /// Makes a request conditional based on the E-Tag.
590    ///
591    /// The If-None-Match HTTP request header makes the request conditional. For
592    /// GET and HEAD methods, the server will send back the requested resource,
593    /// with a 200 status, only if it doesn't have an ETag matching the given
594    /// ones. For other methods, the request will be processed only if the
595    /// eventually existing resource's ETag doesn't match any of the values
596    /// listed.
597    ///
598    /// When the condition fails for GET and HEAD methods, then the server must
599    /// return HTTP status code 304 (Not Modified). For methods that apply
600    /// server-side changes, the status code 412 (Precondition Failed) is used.
601    /// Note that the server generating a 304 response MUST generate any of the
602    /// following header fields that would have been sent in a 200 (OK) response
603    /// to the same request: Cache-Control, Content-Location, Date, ETag,
604    /// Expires, and Vary.
605    ///
606    /// The comparison with the stored ETag uses the weak comparison algorithm,
607    /// meaning two files are considered identical not only if they are
608    /// identical byte to byte, but if the content is equivalent. For example,
609    /// two pages that would differ only by the date of generation in the footer
610    /// would be considered as identical.
611    ///
612    /// When used in combination with If-Modified-Since, it has precedence (if
613    /// the server supports it).
614    ///
615    /// There are two common use cases:
616    ///
617    /// * For `GET` and `HEAD` methods, to update a cached entity that has an associated ETag.
618    /// * For other methods, and in particular for `PUT`, `If-None-Match` used with
619    /// the `*` value can be used to save a file not known to exist,
620    /// guaranteeing that another upload didn't happen before, losing the data
621    /// of the previous put; this problems is the variation of the lost update
622    /// problem.
623    (IfNoneMatch, IF_NONE_MATCH, "if-none-match");
624
625    /// Makes a request conditional based on range.
626    ///
627    /// The If-Range HTTP request header makes a range request conditional: if
628    /// the condition is fulfilled, the range request will be issued and the
629    /// server sends back a 206 Partial Content answer with the appropriate
630    /// body. If the condition is not fulfilled, the full resource is sent back,
631    /// with a 200 OK status.
632    ///
633    /// This header can be used either with a Last-Modified validator, or with
634    /// an ETag, but not with both.
635    ///
636    /// The most common use case is to resume a download, to guarantee that the
637    /// stored resource has not been modified since the last fragment has been
638    /// received.
639    (IfRange, IF_RANGE, "if-range");
640
641    /// Makes the request conditional based on the last modification date.
642    ///
643    /// The If-Unmodified-Since request HTTP header makes the request
644    /// conditional: the server will send back the requested resource, or accept
645    /// it in the case of a POST or another non-safe method, only if it has not
646    /// been last modified after the given date. If the request has been
647    /// modified after the given date, the response will be a 412 (Precondition
648    /// Failed) error.
649    ///
650    /// There are two common use cases:
651    ///
652    /// * In conjunction non-safe methods, like POST, it can be used to
653    /// implement an optimistic concurrency control, like done by some wikis:
654    /// editions are rejected if the stored document has been modified since the
655    /// original has been retrieved.
656    ///
657    /// * In conjunction with a range request with a If-Range header, it can be
658    /// used to ensure that the new fragment requested comes from an unmodified
659    /// document.
660    (IfUnmodifiedSince, IF_UNMODIFIED_SINCE, "if-unmodified-since");
661
662    /// Content-Types that are acceptable for the response.
663    (LastModified, LAST_MODIFIED, "last-modified");
664
665    /// Allows the server to point an interested client to another resource
666    /// containing metadata about the requested resource.
667    (Link, LINK, "link");
668
669    /// Indicates the URL to redirect a page to.
670    ///
671    /// The Location response header indicates the URL to redirect a page to. It
672    /// only provides a meaning when served with a 3xx status response.
673    ///
674    /// The HTTP method used to make the new request to fetch the page pointed
675    /// to by Location depends of the original method and of the kind of
676    /// redirection:
677    ///
678    /// * If 303 (See Also) responses always lead to the use of a GET method,
679    /// 307 (Temporary Redirect) and 308 (Permanent Redirect) don't change the
680    /// method used in the original request;
681    ///
682    /// * 301 (Permanent Redirect) and 302 (Found) doesn't change the method
683    /// most of the time, though older user-agents may (so you basically don't
684    /// know).
685    ///
686    /// All responses with one of these status codes send a Location header.
687    ///
688    /// Beside redirect response, messages with 201 (Created) status also
689    /// include the Location header. It indicates the URL to the newly created
690    /// resource.
691    ///
692    /// Location and Content-Location are different: Location indicates the
693    /// target of a redirection (or the URL of a newly created resource), while
694    /// Content-Location indicates the direct URL to use to access the resource
695    /// when content negotiation happened, without the need of further content
696    /// negotiation. Location is a header associated with the response, while
697    /// Content-Location is associated with the entity returned.
698    (Location, LOCATION, "location");
699
700    /// Indicates the max number of intermediaries the request should be sent
701    /// through.
702    (MaxForwards, MAX_FORWARDS, "max-forwards");
703
704    /// Indicates where a fetch originates from.
705    ///
706    /// It doesn't include any path information, but only the server name. It is
707    /// sent with CORS requests, as well as with POST requests. It is similar to
708    /// the Referer header, but, unlike this header, it doesn't disclose the
709    /// whole path.
710    (Origin, ORIGIN, "origin");
711
712    /// HTTP/1.0 header usually used for backwards compatibility.
713    ///
714    /// The Pragma HTTP/1.0 general header is an implementation-specific header
715    /// that may have various effects along the request-response chain. It is
716    /// used for backwards compatibility with HTTP/1.0 caches where the
717    /// Cache-Control HTTP/1.1 header is not yet present.
718    (Pragma, PRAGMA, "pragma");
719
720    /// Defines the authentication method that should be used to gain access to
721    /// a proxy.
722    ///
723    /// Unlike `www-authenticate`, the `proxy-authenticate` header field applies
724    /// only to the next outbound client on the response chain. This is because
725    /// only the client that chose a given proxy is likely to have the
726    /// credentials necessary for authentication. However, when multiple proxies
727    /// are used within the same administrative domain, such as office and
728    /// regional caching proxies within a large corporate network, it is common
729    /// for credentials to be generated by the user agent and passed through the
730    /// hierarchy until consumed. Hence, in such a configuration, it will appear
731    /// as if Proxy-Authenticate is being forwarded because each proxy will send
732    /// the same challenge set.
733    ///
734    /// The `proxy-authenticate` header is sent along with a `407 Proxy
735    /// Authentication Required`.
736    (ProxyAuthenticate, PROXY_AUTHENTICATE, "proxy-authenticate");
737
738    /// Contains the credentials to authenticate a user agent to a proxy server.
739    ///
740    /// This header is usually included after the server has responded with a
741    /// 407 Proxy Authentication Required status and the Proxy-Authenticate
742    /// header.
743    (ProxyAuthorization, PROXY_AUTHORIZATION, "proxy-authorization");
744
745    /// Associates a specific cryptographic public key with a certain server.
746    ///
747    /// This decreases the risk of MITM attacks with forged certificates. If one
748    /// or several keys are pinned and none of them are used by the server, the
749    /// browser will not accept the response as legitimate, and will not display
750    /// it.
751    (PublicKeyPins, PUBLIC_KEY_PINS, "public-key-pins");
752
753    /// Sends reports of pinning violation to the report-uri specified in the
754    /// header.
755    ///
756    /// Unlike `Public-Key-Pins`, this header still allows browsers to connect
757    /// to the server if the pinning is violated.
758    (PublicKeyPinsReportOnly, PUBLIC_KEY_PINS_REPORT_ONLY, "public-key-pins-report-only");
759
760    /// Indicates the part of a document that the server should return.
761    ///
762    /// Several parts can be requested with one Range header at once, and the
763    /// server may send back these ranges in a multipart document. If the server
764    /// sends back ranges, it uses the 206 Partial Content for the response. If
765    /// the ranges are invalid, the server returns the 416 Range Not Satisfiable
766    /// error. The server can also ignore the Range header and return the whole
767    /// document with a 200 status code.
768    (Range, RANGE, "range");
769
770    /// Contains the address of the previous web page from which a link to the
771    /// currently requested page was followed.
772    ///
773    /// The Referer header allows servers to identify where people are visiting
774    /// them from and may use that data for analytics, logging, or optimized
775    /// caching, for example.
776    (Referer, REFERER, "referer");
777
778    /// Governs which referrer information should be included with requests
779    /// made.
780    (ReferrerPolicy, REFERRER_POLICY, "referrer-policy");
781
782    /// Informs the web browser that the current page or frame should be
783    /// refreshed.
784    (Refresh, REFRESH, "refresh");
785
786    /// The Retry-After response HTTP header indicates how long the user agent
787    /// should wait before making a follow-up request. There are two main cases
788    /// this header is used:
789    ///
790    /// * When sent with a 503 (Service Unavailable) response, it indicates how
791    /// long the service is expected to be unavailable.
792    ///
793    /// * When sent with a redirect response, such as 301 (Moved Permanently),
794    /// it indicates the minimum time that the user agent is asked to wait
795    /// before issuing the redirected request.
796    (RetryAfter, RETRY_AFTER, "retry-after");
797
798    /// The |Sec-WebSocket-Accept| header field is used in the WebSocket
799    /// opening handshake. It is sent from the server to the client to
800    /// confirm that the server is willing to initiate the WebSocket
801    /// connection.
802    (SecWebSocketAccept, SEC_WEBSOCKET_ACCEPT, "sec-websocket-accept");
803
804    /// The |Sec-WebSocket-Extensions| header field is used in the WebSocket
805    /// opening handshake. It is initially sent from the client to the
806    /// server, and then subsequently sent from the server to the client, to
807    /// agree on a set of protocol-level extensions to use for the duration
808    /// of the connection.
809    (SecWebSocketExtensions, SEC_WEBSOCKET_EXTENSIONS, "sec-websocket-extensions");
810
811    /// The |Sec-WebSocket-Key| header field is used in the WebSocket opening
812    /// handshake. It is sent from the client to the server to provide part
813    /// of the information used by the server to prove that it received a
814    /// valid WebSocket opening handshake. This helps ensure that the server
815    /// does not accept connections from non-WebSocket clients (e.g., HTTP
816    /// clients) that are being abused to send data to unsuspecting WebSocket
817    /// servers.
818    (SecWebSocketKey, SEC_WEBSOCKET_KEY, "sec-websocket-key");
819
820    /// The |Sec-WebSocket-Protocol| header field is used in the WebSocket
821    /// opening handshake. It is sent from the client to the server and back
822    /// from the server to the client to confirm the subprotocol of the
823    /// connection.  This enables scripts to both select a subprotocol and be
824    /// sure that the server agreed to serve that subprotocol.
825    (SecWebSocketProtocol, SEC_WEBSOCKET_PROTOCOL, "sec-websocket-protocol");
826
827    /// The |Sec-WebSocket-Version| header field is used in the WebSocket
828    /// opening handshake.  It is sent from the client to the server to
829    /// indicate the protocol version of the connection.  This enables
830    /// servers to correctly interpret the opening handshake and subsequent
831    /// data being sent from the data, and close the connection if the server
832    /// cannot interpret that data in a safe manner.
833    (SecWebSocketVersion, SEC_WEBSOCKET_VERSION, "sec-websocket-version");
834
835    /// Contains information about the software used by the origin server to
836    /// handle the request.
837    ///
838    /// Overly long and detailed Server values should be avoided as they
839    /// potentially reveal internal implementation details that might make it
840    /// (slightly) easier for attackers to find and exploit known security
841    /// holes.
842    (Server, SERVER, "server");
843
844    /// Used to send cookies from the server to the user agent.
845    (SetCookie, SET_COOKIE, "set-cookie");
846
847    /// Tells the client to communicate with HTTPS instead of using HTTP.
848    (StrictTransportSecurity, STRICT_TRANSPORT_SECURITY, "strict-transport-security");
849
850    /// Informs the server of transfer encodings willing to be accepted as part
851    /// of the response.
852    ///
853    /// See also the Transfer-Encoding response header for more details on
854    /// transfer encodings. Note that chunked is always acceptable for HTTP/1.1
855    /// recipients and you that don't have to specify "chunked" using the TE
856    /// header. However, it is useful for setting if the client is accepting
857    /// trailer fields in a chunked transfer coding using the "trailers" value.
858    (Te, TE, "te");
859
860    /// Allows the sender to include additional fields at the end of chunked
861    /// messages.
862    (Trailer, TRAILER, "trailer");
863
864    /// Specifies the form of encoding used to safely transfer the entity to the
865    /// client.
866    ///
867    /// `transfer-encoding` is a hop-by-hop header, that is applying to a
868    /// message between two nodes, not to a resource itself. Each segment of a
869    /// multi-node connection can use different `transfer-encoding` values. If
870    /// you want to compress data over the whole connection, use the end-to-end
871    /// header `content-encoding` header instead.
872    ///
873    /// When present on a response to a `HEAD` request that has no body, it
874    /// indicates the value that would have applied to the corresponding `GET`
875    /// message.
876    (TransferEncoding, TRANSFER_ENCODING, "transfer-encoding");
877
878    /// Contains a string that allows identifying the requesting client's
879    /// software.
880    (UserAgent, USER_AGENT, "user-agent");
881
882    /// Used as part of the exchange to upgrade the protocol.
883    (Upgrade, UPGRADE, "upgrade");
884
885    /// Sends a signal to the server expressing the client’s preference for an
886    /// encrypted and authenticated response.
887    (UpgradeInsecureRequests, UPGRADE_INSECURE_REQUESTS, "upgrade-insecure-requests");
888
889    /// Determines how to match future requests with cached responses.
890    ///
891    /// The `vary` HTTP response header determines how to match future request
892    /// headers to decide whether a cached response can be used rather than
893    /// requesting a fresh one from the origin server. It is used by the server
894    /// to indicate which headers it used when selecting a representation of a
895    /// resource in a content negotiation algorithm.
896    ///
897    /// The `vary` header should be set on a 304 Not Modified response exactly
898    /// like it would have been set on an equivalent 200 OK response.
899    (Vary, VARY, "vary");
900
901    /// Added by proxies to track routing.
902    ///
903    /// The `via` general header is added by proxies, both forward and reverse
904    /// proxies, and can appear in the request headers and the response headers.
905    /// It is used for tracking message forwards, avoiding request loops, and
906    /// identifying the protocol capabilities of senders along the
907    /// request/response chain.
908    (Via, VIA, "via");
909
910    /// General HTTP header contains information about possible problems with
911    /// the status of the message.
912    ///
913    /// More than one `warning` header may appear in a response. Warning header
914    /// fields can in general be applied to any message, however some warn-codes
915    /// are specific to caches and can only be applied to response messages.
916    (Warning, WARNING, "warning");
917
918    /// Defines the authentication method that should be used to gain access to
919    /// a resource.
920    (WwwAuthenticate, WWW_AUTHENTICATE, "www-authenticate");
921
922    /// Marker used by the server to indicate that the MIME types advertised in
923    /// the `content-type` headers should not be changed and be followed.
924    ///
925    /// This allows to opt-out of MIME type sniffing, or, in other words, it is
926    /// a way to say that the webmasters knew what they were doing.
927    ///
928    /// This header was introduced by Microsoft in IE 8 as a way for webmasters
929    /// to block content sniffing that was happening and could transform
930    /// non-executable MIME types into executable MIME types. Since then, other
931    /// browsers have introduced it, even if their MIME sniffing algorithms were
932    /// less aggressive.
933    ///
934    /// Site security testers usually expect this header to be set.
935    (XContentTypeOptions, X_CONTENT_TYPE_OPTIONS, "x-content-type-options");
936
937    /// Controls DNS prefetching.
938    ///
939    /// The `x-dns-prefetch-control` HTTP response header controls DNS
940    /// prefetching, a feature by which browsers proactively perform domain name
941    /// resolution on both links that the user may choose to follow as well as
942    /// URLs for items referenced by the document, including images, CSS,
943    /// JavaScript, and so forth.
944    ///
945    /// This prefetching is performed in the background, so that the DNS is
946    /// likely to have been resolved by the time the referenced items are
947    /// needed. This reduces latency when the user clicks a link.
948    (XDnsPrefetchControl, X_DNS_PREFETCH_CONTROL, "x-dns-prefetch-control");
949
950    /// Indicates whether or not a browser should be allowed to render a page in
951    /// a frame.
952    ///
953    /// Sites can use this to avoid clickjacking attacks, by ensuring that their
954    /// content is not embedded into other sites.
955    ///
956    /// The added security is only provided if the user accessing the document
957    /// is using a browser supporting `x-frame-options`.
958    (XFrameOptions, X_FRAME_OPTIONS, "x-frame-options");
959
960    /// Stop pages from loading when an XSS attack is detected.
961    ///
962    /// The HTTP X-XSS-Protection response header is a feature of Internet
963    /// Explorer, Chrome and Safari that stops pages from loading when they
964    /// detect reflected cross-site scripting (XSS) attacks. Although these
965    /// protections are largely unnecessary in modern browsers when sites
966    /// implement a strong Content-Security-Policy that disables the use of
967    /// inline JavaScript ('unsafe-inline'), they can still provide protections
968    /// for users of older web browsers that don't yet support CSP.
969    (XXssProtection, X_XSS_PROTECTION, "x-xss-protection");
970}
971
972/// Valid header name characters
973///
974/// ```not_rust
975///       field-name     = token
976///       token          = 1*<any CHAR except CTLs or separators>
977///       separators     = "(" | ")" | "<" | ">" | "@"
978///                      | "," | ";" | ":" | "\" | <">
979///                      | "/" | "[" | "]" | "?" | "="
980///                      | "{" | "}" | SP | HT
981/// ```
982const HEADER_CHARS: [u8; 256] = [
983    //  0      1      2      3      4      5      6      7      8      9
984        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //   x
985        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  1x
986        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  2x
987        0,     0,     0,  b'!',  b'"',  b'#',  b'$',  b'%',  b'&', b'\'', //  3x
988        0,     0,  b'*',  b'+',     0,  b'-',  b'.',     0,  b'0',  b'1', //  4x
989     b'2',  b'3',  b'4',  b'5',  b'6',  b'7',  b'8',  b'9',     0,     0, //  5x
990        0,     0,     0,     0,     0,  b'a',  b'b',  b'c',  b'd',  b'e', //  6x
991     b'f',  b'g',  b'h',  b'i',  b'j',  b'k',  b'l',  b'm',  b'n',  b'o', //  7x
992     b'p',  b'q',  b'r',  b's',  b't',  b'u',  b'v',  b'w',  b'x',  b'y', //  8x
993     b'z',     0,     0,     0,     0,  b'_',     0,  b'a',  b'b',  b'c', //  9x
994     b'd',  b'e',  b'f',  b'g',  b'h',  b'i',  b'j',  b'k',  b'l',  b'm', // 10x
995     b'n',  b'o',  b'p',  b'q',  b'r',  b's',  b't',  b'u',  b'v',  b'w', // 11x
996     b'x',  b'y',  b'z',     0,  b'|',     0,  b'~',     0,     0,     0, // 12x
997        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 13x
998        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 14x
999        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 15x
1000        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 16x
1001        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 17x
1002        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 18x
1003        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 19x
1004        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 20x
1005        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 21x
1006        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 22x
1007        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 23x
1008        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 24x
1009        0,     0,     0,     0,     0,     0                              // 25x
1010];
1011
1012const HEADER_CHARS_H2: [u8; 256] = [
1013    //  0      1      2      3      4      5      6      7      8      9
1014        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //   x
1015        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  1x
1016        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  2x
1017        0,     0,     0,  b'!',  b'"',  b'#',  b'$',  b'%',  b'&', b'\'', //  3x
1018        0,     0,  b'*',  b'+',     0,  b'-',  b'.',     0,  b'0',  b'1', //  4x
1019     b'2',  b'3',  b'4',  b'5',  b'6',  b'7',  b'8',  b'9',     0,     0, //  5x
1020        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  6x
1021        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  7x
1022        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  8x
1023        0,     0,     0,     0,     0,  b'_',     0,  b'a',  b'b',  b'c', //  9x
1024     b'd',  b'e',  b'f',  b'g',  b'h',  b'i',  b'j',  b'k',  b'l',  b'm', // 10x
1025     b'n',  b'o',  b'p',  b'q',  b'r',  b's',  b't',  b'u',  b'v',  b'w', // 11x
1026     b'x',  b'y',  b'z',     0,  b'|',     0,  b'~',     0,     0,     0, // 12x
1027        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 13x
1028        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 14x
1029        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 15x
1030        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 16x
1031        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 17x
1032        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 18x
1033        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 19x
1034        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 20x
1035        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 21x
1036        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 22x
1037        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 23x
1038        0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 24x
1039        0,     0,     0,     0,     0,     0                              // 25x
1040];
1041
1042macro_rules! eq {
1043    ($v:ident[$n:expr] == $a:tt) => {
1044        $v[$n] == $a
1045    };
1046    ($v:ident[$n:expr] == $a:tt $($rest:tt)+) => {
1047        $v[$n] == $a && eq!($v[($n+1)] == $($rest)+)
1048    };
1049    ($v:ident == $a:tt $($rest:tt)*) => {
1050        $v[0] == $a && eq!($v[1] == $($rest)*)
1051    };
1052}
1053
1054fn parse_hdr<'a>(data: &'a [u8], b: &'a mut [u8; 64], table: &[u8; 256])
1055    -> Result<HdrName<'a>, InvalidHeaderName>
1056{
1057    use self::StandardHeader::*;
1058
1059    let len = data.len();
1060
1061    let validate = |buf: &'a [u8], len: usize| {
1062        let buf = &buf[..len];
1063        if buf.iter().any(|&b| b == 0) {
1064            Err(InvalidHeaderName::new())
1065        } else {
1066            Ok(HdrName::custom(buf, true))
1067        }
1068    };
1069
1070
1071    macro_rules! to_lower {
1072        ($d:ident, $src:ident, 1) => { $d[0] = table[$src[0] as usize]; };
1073        ($d:ident, $src:ident, 2) => { to_lower!($d, $src, 1); $d[1] = table[$src[1] as usize]; };
1074        ($d:ident, $src:ident, 3) => { to_lower!($d, $src, 2); $d[2] = table[$src[2] as usize]; };
1075        ($d:ident, $src:ident, 4) => { to_lower!($d, $src, 3); $d[3] = table[$src[3] as usize]; };
1076        ($d:ident, $src:ident, 5) => { to_lower!($d, $src, 4); $d[4] = table[$src[4] as usize]; };
1077        ($d:ident, $src:ident, 6) => { to_lower!($d, $src, 5); $d[5] = table[$src[5] as usize]; };
1078        ($d:ident, $src:ident, 7) => { to_lower!($d, $src, 6); $d[6] = table[$src[6] as usize]; };
1079        ($d:ident, $src:ident, 8) => { to_lower!($d, $src, 7); $d[7] = table[$src[7] as usize]; };
1080        ($d:ident, $src:ident, 9) => { to_lower!($d, $src, 8); $d[8] = table[$src[8] as usize]; };
1081        ($d:ident, $src:ident, 10) => { to_lower!($d, $src, 9); $d[9] = table[$src[9] as usize]; };
1082        ($d:ident, $src:ident, 11) => { to_lower!($d, $src, 10); $d[10] = table[$src[10] as usize]; };
1083        ($d:ident, $src:ident, 12) => { to_lower!($d, $src, 11); $d[11] = table[$src[11] as usize]; };
1084        ($d:ident, $src:ident, 13) => { to_lower!($d, $src, 12); $d[12] = table[$src[12] as usize]; };
1085        ($d:ident, $src:ident, 14) => { to_lower!($d, $src, 13); $d[13] = table[$src[13] as usize]; };
1086        ($d:ident, $src:ident, 15) => { to_lower!($d, $src, 14); $d[14] = table[$src[14] as usize]; };
1087        ($d:ident, $src:ident, 16) => { to_lower!($d, $src, 15); $d[15] = table[$src[15] as usize]; };
1088        ($d:ident, $src:ident, 17) => { to_lower!($d, $src, 16); $d[16] = table[$src[16] as usize]; };
1089        ($d:ident, $src:ident, 18) => { to_lower!($d, $src, 17); $d[17] = table[$src[17] as usize]; };
1090        ($d:ident, $src:ident, 19) => { to_lower!($d, $src, 18); $d[18] = table[$src[18] as usize]; };
1091        ($d:ident, $src:ident, 20) => { to_lower!($d, $src, 19); $d[19] = table[$src[19] as usize]; };
1092        ($d:ident, $src:ident, 21) => { to_lower!($d, $src, 20); $d[20] = table[$src[20] as usize]; };
1093        ($d:ident, $src:ident, 22) => { to_lower!($d, $src, 21); $d[21] = table[$src[21] as usize]; };
1094        ($d:ident, $src:ident, 23) => { to_lower!($d, $src, 22); $d[22] = table[$src[22] as usize]; };
1095        ($d:ident, $src:ident, 24) => { to_lower!($d, $src, 23); $d[23] = table[$src[23] as usize]; };
1096        ($d:ident, $src:ident, 25) => { to_lower!($d, $src, 24); $d[24] = table[$src[24] as usize]; };
1097        ($d:ident, $src:ident, 26) => { to_lower!($d, $src, 25); $d[25] = table[$src[25] as usize]; };
1098        ($d:ident, $src:ident, 27) => { to_lower!($d, $src, 26); $d[26] = table[$src[26] as usize]; };
1099        ($d:ident, $src:ident, 28) => { to_lower!($d, $src, 27); $d[27] = table[$src[27] as usize]; };
1100        ($d:ident, $src:ident, 29) => { to_lower!($d, $src, 28); $d[28] = table[$src[28] as usize]; };
1101        ($d:ident, $src:ident, 30) => { to_lower!($d, $src, 29); $d[29] = table[$src[29] as usize]; };
1102        ($d:ident, $src:ident, 31) => { to_lower!($d, $src, 30); $d[30] = table[$src[30] as usize]; };
1103        ($d:ident, $src:ident, 32) => { to_lower!($d, $src, 31); $d[31] = table[$src[31] as usize]; };
1104        ($d:ident, $src:ident, 33) => { to_lower!($d, $src, 32); $d[32] = table[$src[32] as usize]; };
1105        ($d:ident, $src:ident, 34) => { to_lower!($d, $src, 33); $d[33] = table[$src[33] as usize]; };
1106        ($d:ident, $src:ident, 35) => { to_lower!($d, $src, 34); $d[34] = table[$src[34] as usize]; };
1107    }
1108
1109    assert!(len < super::MAX_HEADER_NAME_LEN,
1110            "header name too long -- max length is {}",
1111            super::MAX_HEADER_NAME_LEN);
1112
1113    match len {
1114        0 => {
1115            Err(InvalidHeaderName::new())
1116        }
1117        2 => {
1118            to_lower!(b, data, 2);
1119
1120            if eq!(b == b't' b'e') {
1121                Ok(Te.into())
1122            } else {
1123                validate(b, len)
1124            }
1125        }
1126        3 => {
1127            to_lower!(b, data, 3);
1128
1129            if eq!(b == b'a' b'g' b'e') {
1130                Ok(Age.into())
1131            } else if eq!(b == b'v' b'i' b'a') {
1132                Ok(Via.into())
1133            } else if eq!(b == b'd' b'n' b't') {
1134                Ok(Dnt.into())
1135            } else {
1136                validate(b, len)
1137            }
1138        }
1139        4 => {
1140            to_lower!(b, data, 4);
1141
1142            if eq!(b == b'd' b'a' b't' b'e') {
1143                Ok(Date.into())
1144            } else if eq!(b == b'e' b't' b'a' b'g') {
1145                Ok(Etag.into())
1146            } else if eq!(b == b'f' b'r' b'o' b'm') {
1147                Ok(From.into())
1148            } else if eq!(b == b'h' b'o' b's' b't') {
1149                Ok(Host.into())
1150            } else if eq!(b == b'l' b'i' b'n' b'k') {
1151                Ok(Link.into())
1152            } else if eq!(b == b'v' b'a' b'r' b'y') {
1153                Ok(Vary.into())
1154            } else {
1155                validate(b, len)
1156            }
1157        }
1158        5 => {
1159            to_lower!(b, data, 5);
1160
1161            if eq!(b == b'a' b'l' b'l' b'o' b'w') {
1162                Ok(Allow.into())
1163            } else if eq!(b == b'r' b'a' b'n' b'g' b'e') {
1164                Ok(Range.into())
1165            } else {
1166                validate(b, len)
1167            }
1168        }
1169        6 => {
1170            to_lower!(b, data, 6);
1171
1172            if eq!(b == b'a' b'c' b'c' b'e' b'p' b't') {
1173                return Ok(Accept.into())
1174            } else if eq!(b == b'c' b'o' b'o' b'k' b'i' b'e') {
1175                return Ok(Cookie.into())
1176            } else if eq!(b == b'e' b'x' b'p' b'e' b'c' b't') {
1177                return Ok(Expect.into())
1178            } else if eq!(b == b'o' b'r' b'i' b'g' b'i' b'n') {
1179                return Ok(Origin.into())
1180            } else if eq!(b == b'p' b'r' b'a' b'g' b'm' b'a') {
1181                return Ok(Pragma.into())
1182            } else if b[0] == b's' {
1183                if eq!(b[1] == b'e' b'r' b'v' b'e' b'r') {
1184                    return Ok(Server.into())
1185                }
1186            }
1187
1188            validate(b, len)
1189        }
1190        7 => {
1191            to_lower!(b, data, 7);
1192
1193            if eq!(b == b'a' b'l' b't' b'-' b's' b'v' b'c') {
1194                Ok(AltSvc.into())
1195            } else if eq!(b == b'e' b'x' b'p' b'i' b'r' b'e' b's') {
1196                Ok(Expires.into())
1197            } else if eq!(b == b'r' b'e' b'f' b'e' b'r' b'e' b'r') {
1198                Ok(Referer.into())
1199            } else if eq!(b == b'r' b'e' b'f' b'r' b'e' b's' b'h') {
1200                Ok(Refresh.into())
1201            } else if eq!(b == b't' b'r' b'a' b'i' b'l' b'e' b'r') {
1202                Ok(Trailer.into())
1203            } else if eq!(b == b'u' b'p' b'g' b'r' b'a' b'd' b'e') {
1204                Ok(Upgrade.into())
1205            } else if eq!(b == b'w' b'a' b'r' b'n' b'i' b'n' b'g') {
1206                Ok(Warning.into())
1207            } else {
1208                validate(b, len)
1209            }
1210        }
1211        8 => {
1212            to_lower!(b, data, 8);
1213
1214            if eq!(b == b'i' b'f' b'-') {
1215                if eq!(b[3] == b'm' b'a' b't' b'c' b'h') {
1216                    return Ok(IfMatch.into())
1217                } else if eq!(b[3] == b'r' b'a' b'n' b'g' b'e') {
1218                    return Ok(IfRange.into())
1219                }
1220            } else if eq!(b == b'l' b'o' b'c' b'a' b't' b'i' b'o' b'n') {
1221                return Ok(Location.into())
1222            }
1223
1224            validate(b, len)
1225        }
1226        9 => {
1227            to_lower!(b, data, 9);
1228
1229            if eq!(b == b'f' b'o' b'r' b'w' b'a' b'r' b'd' b'e' b'd') {
1230                Ok(Forwarded.into())
1231            } else {
1232                validate(b, len)
1233            }
1234        }
1235        10 => {
1236            to_lower!(b, data, 10);
1237
1238            if eq!(b == b'c' b'o' b'n' b'n' b'e' b'c' b't' b'i' b'o' b'n') {
1239                Ok(Connection.into())
1240            } else if eq!(b == b's' b'e' b't' b'-' b'c' b'o' b'o' b'k' b'i' b'e') {
1241                Ok(SetCookie.into())
1242            } else if eq!(b == b'u' b's' b'e' b'r' b'-' b'a' b'g' b'e' b'n' b't') {
1243                Ok(UserAgent.into())
1244            } else {
1245                validate(b, len)
1246            }
1247        }
1248        11 => {
1249            to_lower!(b, data, 11);
1250
1251            if eq!(b == b'r' b'e' b't' b'r' b'y' b'-' b'a' b'f' b't' b'e' b'r') {
1252                Ok(RetryAfter.into())
1253            } else {
1254                validate(b, len)
1255            }
1256        }
1257        12 => {
1258            to_lower!(b, data, 12);
1259
1260            if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b't' b'y' b'p' b'e') {
1261                Ok(ContentType.into())
1262            } else if eq!(b == b'm' b'a' b'x' b'-' b'f' b'o' b'r' b'w' b'a' b'r' b'd' b's') {
1263                Ok(MaxForwards.into())
1264            } else {
1265                validate(b, len)
1266            }
1267        }
1268        13 => {
1269            to_lower!(b, data, 13);
1270
1271            if b[0] == b'a' {
1272                if eq!(b[1] == b'c' b'c' b'e' b'p' b't' b'-' b'r' b'a' b'n' b'g' b'e' b's') {
1273                    return Ok(AcceptRanges.into())
1274                } else if eq!(b[1] == b'u' b't' b'h' b'o' b'r' b'i' b'z' b'a' b't' b'i' b'o' b'n') {
1275                    return Ok(Authorization.into())
1276                }
1277            } else if b[0] == b'c' {
1278                if eq!(b[1] == b'a' b'c' b'h' b'e' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l') {
1279                    return Ok(CacheControl.into())
1280                } else if eq!(b[1] == b'o' b'n' b't' b'e' b'n' b't' b'-' b'r' b'a' b'n' b'g' b'e' ) {
1281                    return Ok(ContentRange.into())
1282                }
1283            } else if eq!(b == b'i' b'f' b'-' b'n' b'o' b'n' b'e' b'-' b'm' b'a' b't' b'c' b'h') {
1284                return Ok(IfNoneMatch.into())
1285            } else if eq!(b == b'l' b'a' b's' b't' b'-' b'm' b'o' b'd' b'i' b'f' b'i' b'e' b'd') {
1286                return Ok(LastModified.into())
1287            }
1288
1289            validate(b, len)
1290        }
1291        14 => {
1292            to_lower!(b, data, 14);
1293
1294            if eq!(b == b'a' b'c' b'c' b'e' b'p' b't' b'-' b'c' b'h' b'a' b'r' b's' b'e' b't') {
1295                Ok(AcceptCharset.into())
1296            } else if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b'l' b'e' b'n' b'g' b't' b'h') {
1297                Ok(ContentLength.into())
1298            } else {
1299                validate(b, len)
1300            }
1301        }
1302        15 => {
1303            to_lower!(b, data, 15);
1304
1305            if eq!(b == b'a' b'c' b'c' b'e' b'p' b't' b'-') { // accept-
1306                if eq!(b[7] == b'e' b'n' b'c' b'o' b'd' b'i' b'n' b'g') {
1307                    return Ok(AcceptEncoding.into())
1308                } else if eq!(b[7] == b'l' b'a' b'n' b'g' b'u' b'a' b'g' b'e') {
1309                    return Ok(AcceptLanguage.into())
1310                }
1311            } else if eq!(b == b'p' b'u' b'b' b'l' b'i' b'c' b'-' b'k' b'e' b'y' b'-' b'p' b'i' b'n' b's') {
1312                return Ok(PublicKeyPins.into())
1313            } else if eq!(b == b'x' b'-' b'f' b'r' b'a' b'm' b'e' b'-' b'o' b'p' b't' b'i' b'o' b'n' b's') {
1314                return Ok(XFrameOptions.into())
1315            }
1316            else if eq!(b == b'r' b'e' b'f' b'e' b'r' b'r' b'e' b'r' b'-' b'p' b'o' b'l' b'i' b'c' b'y') {
1317                return Ok(ReferrerPolicy.into())
1318            }
1319
1320            validate(b, len)
1321        }
1322        16 => {
1323            to_lower!(b, data, 16);
1324
1325            if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-') {
1326                if eq!(b[8] == b'l' b'a' b'n' b'g' b'u' b'a' b'g' b'e') {
1327                    return Ok(ContentLanguage.into())
1328                } else if eq!(b[8] == b'l' b'o' b'c' b'a' b't' b'i' b'o' b'n') {
1329                    return Ok(ContentLocation.into())
1330                } else if eq!(b[8] == b'e' b'n' b'c' b'o' b'd' b'i' b'n' b'g') {
1331                    return Ok(ContentEncoding.into())
1332                }
1333            } else if eq!(b == b'w' b'w' b'w' b'-' b'a' b'u' b't' b'h' b'e' b'n' b't' b'i' b'c' b'a' b't' b'e') {
1334                return Ok(WwwAuthenticate.into())
1335            } else if eq!(b == b'x' b'-' b'x' b's' b's' b'-' b'p' b'r' b'o' b't' b'e' b'c' b't' b'i' b'o' b'n') {
1336                return Ok(XXssProtection.into())
1337            }
1338
1339            validate(b, len)
1340        }
1341        17 => {
1342            to_lower!(b, data, 17);
1343
1344            if eq!(b == b't' b'r' b'a' b'n' b's' b'f' b'e' b'r' b'-' b'e' b'n' b'c' b'o' b'd' b'i' b'n' b'g') {
1345                Ok(TransferEncoding.into())
1346            } else if eq!(b == b'i' b'f' b'-' b'm' b'o' b'd' b'i' b'f' b'i' b'e' b'd' b'-' b's' b'i' b'n' b'c' b'e') {
1347                Ok(IfModifiedSince.into())
1348            } else if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'k' b'e' b'y') {
1349                Ok(SecWebSocketKey.into())
1350            } else {
1351                validate(b, len)
1352            }
1353        }
1354        18 => {
1355            to_lower!(b, data, 18);
1356
1357            if eq!(b == b'p' b'r' b'o' b'x' b'y' b'-' b'a' b'u' b't' b'h' b'e' b'n' b't' b'i' b'c' b'a' b't' b'e') {
1358                Ok(ProxyAuthenticate.into())
1359            } else {
1360                validate(b, len)
1361            }
1362        }
1363        19 => {
1364            to_lower!(b, data, 19);
1365
1366            if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b'd' b'i' b's' b'p' b'o' b's' b'i' b't' b'i' b'o' b'n') {
1367                Ok(ContentDisposition.into())
1368            } else if eq!(b == b'i' b'f' b'-' b'u' b'n' b'm' b'o' b'd' b'i' b'f' b'i' b'e' b'd' b'-' b's' b'i' b'n' b'c' b'e') {
1369                Ok(IfUnmodifiedSince.into())
1370            } else if eq!(b == b'p' b'r' b'o' b'x' b'y' b'-' b'a' b'u' b't' b'h' b'o' b'r' b'i' b'z' b'a' b't' b'i' b'o' b'n') {
1371                Ok(ProxyAuthorization.into())
1372            } else {
1373                validate(b, len)
1374            }
1375        }
1376        20 => {
1377            to_lower!(b, data, 20);
1378
1379            if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'a' b'c' b'c' b'e' b'p' b't') {
1380                Ok(SecWebSocketAccept.into())
1381            } else {
1382                validate(b, len)
1383            }
1384        }
1385        21 => {
1386            to_lower!(b, data, 21);
1387
1388            if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'v' b'e' b'r' b's' b'i' b'o' b'n') {
1389                Ok(SecWebSocketVersion.into())
1390            } else {
1391                validate(b, len)
1392            }
1393        }
1394        22 => {
1395            to_lower!(b, data, 22);
1396
1397            if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'm' b'a' b'x' b'-' b'a' b'g' b'e') {
1398                Ok(AccessControlMaxAge.into())
1399            } else if eq!(b == b'x' b'-' b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b't' b'y' b'p' b'e' b'-' b'o' b'p' b't' b'i' b'o' b'n' b's') {
1400                Ok(XContentTypeOptions.into())
1401            } else if eq!(b == b'x' b'-' b'd' b'n' b's' b'-' b'p' b'r' b'e' b'f' b'e' b't' b'c' b'h' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l') {
1402                Ok(XDnsPrefetchControl.into())
1403            } else if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'p' b'r' b'o' b't' b'o' b'c' b'o' b'l') {
1404                Ok(SecWebSocketProtocol.into())
1405            } else {
1406                validate(b, len)
1407            }
1408        }
1409        23 => {
1410            to_lower!(b, data, 23);
1411
1412            if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b's' b'e' b'c' b'u' b'r' b'i' b't' b'y' b'-' b'p' b'o' b'l' b'i' b'c' b'y') {
1413                Ok(ContentSecurityPolicy.into())
1414            } else {
1415                validate(b, len)
1416            }
1417        }
1418        24 => {
1419            to_lower!(b, data, 24);
1420
1421            if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'e' b'x' b't' b'e' b'n' b's' b'i' b'o' b'n' b's') {
1422                Ok(SecWebSocketExtensions.into())
1423            } else {
1424                validate(b, len)
1425            }
1426        }
1427        25 => {
1428            to_lower!(b, data, 25);
1429
1430            if eq!(b == b's' b't' b'r' b'i' b'c' b't' b'-' b't' b'r' b'a' b'n' b's' b'p' b'o' b'r' b't' b'-' b's' b'e' b'c' b'u' b'r' b'i' b't' b'y') {
1431                Ok(StrictTransportSecurity.into())
1432            } else if eq!(b == b'u' b'p' b'g' b'r' b'a' b'd' b'e' b'-' b'i' b'n' b's' b'e' b'c' b'u' b'r' b'e' b'-' b'r' b'e' b'q' b'u' b'e' b's' b't' b's') {
1433                Ok(UpgradeInsecureRequests.into())
1434            } else {
1435                validate(b, len)
1436            }
1437        }
1438        27 => {
1439            to_lower!(b, data, 27);
1440
1441            if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'a' b'l' b'l' b'o' b'w' b'-' b'o' b'r' b'i' b'g' b'i' b'n') {
1442                Ok(AccessControlAllowOrigin.into())
1443            } else if eq!(b == b'p' b'u' b'b' b'l' b'i' b'c' b'-' b'k' b'e' b'y' b'-' b'p' b'i' b'n' b's' b'-' b'r' b'e' b'p' b'o' b'r' b't' b'-' b'o' b'n' b'l' b'y') {
1444                Ok(PublicKeyPinsReportOnly.into())
1445            } else {
1446                validate(b, len)
1447            }
1448        }
1449        28 => {
1450            to_lower!(b, data, 28);
1451
1452            if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'a' b'l' b'l' b'o' b'w' b'-') {
1453                if eq!(b[21] == b'h' b'e' b'a' b'd' b'e' b'r' b's') {
1454                    return Ok(AccessControlAllowHeaders.into())
1455                } else if eq!(b[21] == b'm' b'e' b't' b'h' b'o' b'd' b's') {
1456                    return Ok(AccessControlAllowMethods.into())
1457                }
1458            }
1459
1460            validate(b, len)
1461        }
1462        29 => {
1463            to_lower!(b, data, 29);
1464
1465            if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-') {
1466                if eq!(b[15] == b'e' b'x' b'p' b'o' b's' b'e' b'-' b'h' b'e' b'a' b'd' b'e' b'r' b's') {
1467                    return Ok(AccessControlExposeHeaders.into())
1468                } else if eq!(b[15] == b'r' b'e' b'q' b'u' b'e' b's' b't' b'-' b'm' b'e' b't' b'h' b'o' b'd') {
1469                    return Ok(AccessControlRequestMethod.into())
1470                }
1471            }
1472
1473            validate(b, len)
1474        }
1475        30 => {
1476            to_lower!(b, data, 30);
1477
1478            if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'r' b'e' b'q' b'u' b'e' b's' b't' b'-' b'h' b'e' b'a' b'd' b'e' b'r' b's') {
1479                Ok(AccessControlRequestHeaders.into())
1480            } else {
1481                validate(b, len)
1482            }
1483        }
1484        32 => {
1485            to_lower!(b, data, 32);
1486
1487            if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'a' b'l' b'l' b'o' b'w' b'-' b'c' b'r' b'e' b'd' b'e' b'n' b't' b'i' b'a' b'l' b's') {
1488                Ok(AccessControlAllowCredentials.into())
1489            } else {
1490                validate(b, len)
1491            }
1492        }
1493        35 => {
1494            to_lower!(b, data, 35);
1495
1496            if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b's' b'e' b'c' b'u' b'r' b'i' b't' b'y' b'-' b'p' b'o' b'l' b'i' b'c' b'y' b'-' b'r' b'e' b'p' b'o' b'r' b't' b'-' b'o' b'n' b'l' b'y') {
1497                Ok(ContentSecurityPolicyReportOnly.into())
1498            } else {
1499                validate(b, len)
1500            }
1501        }
1502        _ => {
1503            if len < 64 {
1504                for i in 0..len {
1505                    b[i] = table[data[i] as usize];
1506                }
1507
1508                validate(b, len)
1509            } else {
1510                Ok(HdrName::custom(data, false))
1511            }
1512        }
1513    }
1514}
1515
1516impl<'a> From<StandardHeader> for HdrName<'a> {
1517    fn from(hdr: StandardHeader) -> HdrName<'a> {
1518        HdrName { inner: Repr::Standard(hdr) }
1519    }
1520}
1521
1522impl HeaderName {
1523    /// Converts a slice of bytes to an HTTP header name.
1524    ///
1525    /// This function normalizes the input.
1526    pub fn from_bytes(src: &[u8]) -> Result<HeaderName, InvalidHeaderName> {
1527        let mut buf = unsafe { mem::uninitialized() };
1528        match parse_hdr(src, &mut buf, &HEADER_CHARS)?.inner {
1529            Repr::Standard(std) => Ok(std.into()),
1530            Repr::Custom(MaybeLower { buf, lower: true }) => {
1531                let buf = Bytes::from(buf);
1532                let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
1533                Ok(Custom(val).into())
1534            }
1535            Repr::Custom(MaybeLower { buf, lower: false }) => {
1536                use bytes::{BufMut};
1537                let mut dst = BytesMut::with_capacity(buf.len());
1538
1539                for b in buf.iter() {
1540                    let b = HEADER_CHARS[*b as usize];
1541
1542                    if b == 0 {
1543                        return Err(InvalidHeaderName::new());
1544                    }
1545
1546                    dst.put(b);
1547                }
1548
1549                let val = unsafe { ByteStr::from_utf8_unchecked(dst.freeze()) };
1550
1551                Ok(Custom(val).into())
1552            }
1553        }
1554    }
1555
1556    /// Converts a slice of bytes to an HTTP header name.
1557    ///
1558    /// This function expects the input to only contain lowercase characters.
1559    /// This is useful when decoding HTTP/2.0 headers. The HTTP/2.0
1560    /// specification requires that all headers be represented in lower case.
1561    ///
1562    /// # Examples
1563    ///
1564    /// ```
1565    /// # use http::header::*;
1566    ///
1567    /// // Parsing a lower case header
1568    /// let hdr = HeaderName::from_lowercase(b"content-length").unwrap();
1569    /// assert_eq!(CONTENT_LENGTH, hdr);
1570    ///
1571    /// // Parsing a header that contains uppercase characters
1572    /// assert!(HeaderName::from_lowercase(b"Content-Length").is_err());
1573    /// ```
1574    pub fn from_lowercase(src: &[u8]) -> Result<HeaderName, InvalidHeaderName> {
1575        let mut buf = unsafe { mem::uninitialized() };
1576        match parse_hdr(src, &mut buf, &HEADER_CHARS_H2)?.inner {
1577            Repr::Standard(std) => Ok(std.into()),
1578            Repr::Custom(MaybeLower { buf, lower: true }) => {
1579                let buf = Bytes::from(buf);
1580                let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
1581                Ok(Custom(val).into())
1582            }
1583            Repr::Custom(MaybeLower { buf, lower: false }) => {
1584                for &b in buf.iter() {
1585                    if b != HEADER_CHARS[b as usize] {
1586                        return Err(InvalidHeaderName::new());
1587                    }
1588                }
1589
1590                let buf = Bytes::from(buf);
1591                let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
1592                Ok(Custom(val).into())
1593            }
1594        }
1595    }
1596
1597    /// Converts a static string to a HTTP header name.
1598    ///
1599    /// This function panics when the static string is a invalid header.
1600    /// 
1601    /// This function requires the static string to only contain lowercase 
1602    /// characters, numerals and symbols, as per the HTTP/2.0 specification 
1603    /// and header names internal representation within this library.
1604    /// 
1605    ///
1606    /// # Examples
1607    ///
1608    /// ```
1609    /// # use http::header::*;
1610    /// // Parsing a standard header
1611    /// let hdr = HeaderName::from_static("content-length");
1612    /// assert_eq!(CONTENT_LENGTH, hdr);
1613    /// 
1614    /// // Parsing a custom header
1615    /// let CUSTOM_HEADER: &'static str = "custom-header";
1616    /// 
1617    /// let a = HeaderName::from_lowercase(b"custom-header").unwrap();
1618    /// let b = HeaderName::from_static(CUSTOM_HEADER);
1619    /// assert_eq!(a, b);
1620    /// ```
1621    /// 
1622    /// ```should_panic
1623    /// # use http::header::*;
1624    /// #
1625    /// // Parsing a header that contains invalid symbols(s):
1626    /// HeaderName::from_static("content{}{}length"); // This line panics!
1627    /// 
1628    /// // Parsing a header that contains invalid uppercase characters.
1629    /// let a = HeaderName::from_static("foobar");
1630    /// let b = HeaderName::from_static("FOOBAR"); // This line panics!
1631    /// ```
1632    pub fn from_static(src: &'static str) -> HeaderName {
1633        let bytes = src.as_bytes();
1634        let mut buf = unsafe { mem::uninitialized() };
1635        match parse_hdr(bytes, &mut buf, &HEADER_CHARS_H2) {
1636            Ok(hdr_name) => match hdr_name.inner {
1637                Repr::Standard(std) => std.into(),
1638                Repr::Custom(MaybeLower { buf: _, lower: true }) => {
1639                    let val = ByteStr::from_static(src);
1640                    Custom(val).into()
1641                },
1642                Repr::Custom(MaybeLower { buf: _, lower: false }) => {
1643                    // With lower false, the string is left unchecked by
1644                    // parse_hdr and must be validated manually.
1645                    for &b in bytes.iter() {
1646                        if HEADER_CHARS_H2[b as usize] == 0 {
1647                            panic!("invalid header name")
1648                        }
1649                    }
1650
1651                    let val = ByteStr::from_static(src);
1652                    Custom(val).into()
1653                }
1654            },
1655
1656            Err(_) => panic!("invalid header name")
1657        }
1658    }
1659
1660    /// Returns a `str` representation of the header.
1661    ///
1662    /// The returned string will always be lower case.
1663    #[inline]
1664    pub fn as_str(&self) -> &str {
1665        match self.inner {
1666            Repr::Standard(v) => v.as_str(),
1667            Repr::Custom(ref v) => &*v.0,
1668        }
1669    }
1670}
1671
1672impl FromStr for HeaderName {
1673    type Err = InvalidHeaderName;
1674
1675    fn from_str(s: &str) -> Result<HeaderName, InvalidHeaderName> {
1676        HeaderName::from_bytes(s.as_bytes())
1677            .map_err(|_| InvalidHeaderName {
1678                _priv: (),
1679            })
1680    }
1681}
1682
1683impl AsRef<str> for HeaderName {
1684    fn as_ref(&self) -> &str {
1685        self.as_str()
1686    }
1687}
1688
1689impl AsRef<[u8]> for HeaderName {
1690    fn as_ref(&self) -> &[u8] {
1691        self.as_str().as_bytes()
1692    }
1693}
1694
1695impl Borrow<str> for HeaderName {
1696    fn borrow(&self) -> &str {
1697        self.as_str()
1698    }
1699}
1700
1701impl fmt::Debug for HeaderName {
1702    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1703        fmt::Debug::fmt(self.as_str(), fmt)
1704    }
1705}
1706
1707impl InvalidHeaderName {
1708    fn new() -> InvalidHeaderName {
1709        InvalidHeaderName { _priv: () }
1710    }
1711}
1712
1713impl<'a> From<&'a HeaderName> for HeaderName {
1714    fn from(src: &'a HeaderName) -> HeaderName {
1715        src.clone()
1716    }
1717}
1718
1719#[doc(hidden)]
1720impl<T> From<Repr<T>> for Bytes
1721where T: Into<Bytes> {
1722    fn from(repr: Repr<T>) -> Bytes {
1723        match repr {
1724            Repr::Standard(header) =>
1725                Bytes::from_static(header.as_str().as_bytes()),
1726            Repr::Custom(header) => header.into()
1727        }
1728    }
1729}
1730
1731impl From<Custom> for Bytes {
1732    #[inline]
1733    fn from(Custom(inner): Custom) -> Bytes {
1734        Bytes::from(inner)
1735    }
1736}
1737
1738impl From<HeaderName> for Bytes {
1739    #[inline]
1740    fn from(name: HeaderName) -> Bytes {
1741        name.inner.into()
1742    }
1743}
1744
1745impl<'a> HttpTryFrom<&'a str> for HeaderName {
1746    type Error = InvalidHeaderName;
1747    #[inline]
1748    fn try_from(s: &'a str) -> Result<Self, Self::Error> {
1749        Self::from_bytes(s.as_bytes())
1750    }
1751}
1752
1753impl<'a> HttpTryFrom<&'a [u8]> for HeaderName {
1754    type Error = InvalidHeaderName;
1755    #[inline]
1756    fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> {
1757        Self::from_bytes(s)
1758    }
1759}
1760
1761impl HttpTryFrom<Bytes> for HeaderName {
1762    type Error = InvalidHeaderNameBytes;
1763    #[inline]
1764    fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
1765        Self::from_bytes(bytes.as_ref()).map_err(InvalidHeaderNameBytes)
1766    }
1767}
1768
1769#[doc(hidden)]
1770impl From<StandardHeader> for HeaderName {
1771    fn from(src: StandardHeader) -> HeaderName {
1772        HeaderName {
1773            inner: Repr::Standard(src),
1774        }
1775    }
1776}
1777
1778#[doc(hidden)]
1779impl From<Custom> for HeaderName {
1780    fn from(src: Custom) -> HeaderName {
1781        HeaderName { inner: Repr::Custom(src) }
1782    }
1783}
1784
1785impl<'a> PartialEq<&'a HeaderName> for HeaderName {
1786    #[inline]
1787    fn eq(&self, other: &&'a HeaderName) -> bool {
1788        *self == **other
1789    }
1790}
1791
1792
1793impl<'a> PartialEq<HeaderName> for &'a HeaderName {
1794    #[inline]
1795    fn eq(&self, other: &HeaderName) -> bool {
1796        *other == *self
1797    }
1798}
1799
1800impl PartialEq<str> for HeaderName {
1801    /// Performs a case-insensitive comparison of the string against the header
1802    /// name
1803    ///
1804    /// # Examples
1805    ///
1806    /// ```
1807    /// use http::header::CONTENT_LENGTH;
1808    ///
1809    /// assert_eq!(CONTENT_LENGTH, "content-length");
1810    /// assert_eq!(CONTENT_LENGTH, "Content-Length");
1811    /// assert_ne!(CONTENT_LENGTH, "content length");
1812    /// ```
1813    #[inline]
1814    fn eq(&self, other: &str) -> bool {
1815        eq_ignore_ascii_case(self.as_ref(), other.as_bytes())
1816    }
1817}
1818
1819
1820impl PartialEq<HeaderName> for str {
1821    /// Performs a case-insensitive comparison of the string against the header
1822    /// name
1823    ///
1824    /// # Examples
1825    ///
1826    /// ```
1827    /// use http::header::CONTENT_LENGTH;
1828    ///
1829    /// assert_eq!(CONTENT_LENGTH, "content-length");
1830    /// assert_eq!(CONTENT_LENGTH, "Content-Length");
1831    /// assert_ne!(CONTENT_LENGTH, "content length");
1832    /// ```
1833    #[inline]
1834    fn eq(&self, other: &HeaderName) -> bool {
1835        *other == *self
1836    }
1837}
1838
1839impl<'a> PartialEq<&'a str> for HeaderName {
1840    /// Performs a case-insensitive comparison of the string against the header
1841    /// name
1842    #[inline]
1843    fn eq(&self, other: &&'a str) -> bool {
1844        *self == **other
1845    }
1846}
1847
1848
1849impl<'a> PartialEq<HeaderName> for &'a str {
1850    /// Performs a case-insensitive comparison of the string against the header
1851    /// name
1852    #[inline]
1853    fn eq(&self, other: &HeaderName) -> bool {
1854        *other == *self
1855    }
1856}
1857
1858impl fmt::Display for InvalidHeaderName {
1859    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1860        self.description().fmt(f)
1861    }
1862}
1863
1864impl Error for InvalidHeaderName {
1865    fn description(&self) -> &str {
1866        "invalid HTTP header name"
1867    }
1868}
1869
1870impl fmt::Display for InvalidHeaderNameBytes {
1871    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1872        self.0.fmt(f)
1873    }
1874}
1875
1876impl Error for InvalidHeaderNameBytes {
1877    fn description(&self) -> &str {
1878        self.0.description()
1879    }
1880}
1881
1882// ===== HdrName =====
1883
1884impl<'a> HdrName<'a> {
1885    fn custom(buf: &'a [u8], lower: bool) -> HdrName<'a> {
1886        HdrName {
1887            inner: Repr::Custom(MaybeLower {
1888                buf: buf,
1889                lower: lower,
1890            }),
1891        }
1892    }
1893
1894    pub fn from_bytes<F, U>(hdr: &[u8], f: F) -> Result<U, InvalidHeaderName>
1895        where F: FnOnce(HdrName) -> U,
1896    {
1897        let mut buf = unsafe { mem::uninitialized() };
1898        let hdr = parse_hdr(hdr, &mut buf, &HEADER_CHARS)?;
1899        Ok(f(hdr))
1900    }
1901
1902    pub fn from_static<F, U>(hdr: &'static str, f: F) -> U
1903        where F: FnOnce(HdrName) -> U,
1904    {
1905        let mut buf = unsafe { mem::uninitialized() };
1906        let hdr = parse_hdr(hdr.as_bytes(), &mut buf, &HEADER_CHARS)
1907            .expect("static str is invalid name");
1908        f(hdr)
1909    }
1910}
1911
1912#[doc(hidden)]
1913impl<'a> From<HdrName<'a>> for HeaderName {
1914    fn from(src: HdrName<'a>) -> HeaderName {
1915        match src.inner {
1916            Repr::Standard(s) => {
1917                HeaderName {
1918                    inner: Repr::Standard(s),
1919                }
1920            }
1921            Repr::Custom(maybe_lower) => {
1922                if maybe_lower.lower {
1923                    let buf = Bytes::from(&maybe_lower.buf[..]);
1924                    let byte_str = unsafe { ByteStr::from_utf8_unchecked(buf) };
1925
1926                    HeaderName {
1927                        inner: Repr::Custom(Custom(byte_str)),
1928                    }
1929                } else {
1930                    use bytes::{BufMut};
1931                    let mut dst = BytesMut::with_capacity(maybe_lower.buf.len());
1932
1933                    for b in maybe_lower.buf.iter() {
1934                        dst.put(HEADER_CHARS[*b as usize]);
1935                    }
1936
1937                    let buf = unsafe { ByteStr::from_utf8_unchecked(dst.freeze()) };
1938
1939                    HeaderName {
1940                        inner: Repr::Custom(Custom(buf)),
1941                    }
1942                }
1943            }
1944        }
1945    }
1946}
1947
1948#[doc(hidden)]
1949impl<'a> PartialEq<HdrName<'a>> for HeaderName {
1950    #[inline]
1951    fn eq(&self, other: &HdrName<'a>) -> bool {
1952        match self.inner {
1953            Repr::Standard(a) => {
1954                match other.inner {
1955                    Repr::Standard(b) => a == b,
1956                    _ => false,
1957                }
1958            }
1959            Repr::Custom(Custom(ref a)) => {
1960                match other.inner {
1961                    Repr::Custom(ref b) => {
1962                        if b.lower {
1963                            a.as_bytes() == b.buf
1964                        } else {
1965                            eq_ignore_ascii_case(a.as_bytes(), b.buf)
1966                        }
1967                    }
1968                    _ => false,
1969                }
1970            }
1971        }
1972    }
1973}
1974
1975// ===== Custom =====
1976
1977impl Hash for Custom {
1978    #[inline]
1979    fn hash<H: Hasher>(&self, hasher: &mut H) {
1980        hasher.write(self.0.as_bytes())
1981    }
1982}
1983
1984// ===== MaybeLower =====
1985
1986impl<'a> Hash for MaybeLower<'a> {
1987    #[inline]
1988    fn hash<H: Hasher>(&self, hasher: &mut H) {
1989        if self.lower {
1990            hasher.write(self.buf);
1991        } else {
1992            for &b in self.buf {
1993                hasher.write(&[HEADER_CHARS[b as usize]]);
1994            }
1995        }
1996    }
1997}
1998
1999// Assumes that the left hand side is already lower case
2000#[inline]
2001fn eq_ignore_ascii_case(lower: &[u8], s: &[u8]) -> bool {
2002    if lower.len() != s.len() {
2003        return false;
2004    }
2005
2006    lower.iter().zip(s).all(|(a, b)| {
2007        *a == HEADER_CHARS[*b as usize]
2008    })
2009}
2010
2011#[cfg(test)]
2012mod tests {
2013    use super::*;
2014    use self::StandardHeader::Vary;
2015
2016    #[test]
2017    fn test_bounds() {
2018        fn check_bounds<T: Sync + Send>() {}
2019        check_bounds::<HeaderName>();
2020    }
2021
2022    #[test]
2023    fn test_parse_invalid_headers() {
2024        for i in 0..128 {
2025            let hdr = vec![1u8; i];
2026            assert!(HeaderName::from_bytes(&hdr).is_err(), "{} invalid header chars did not fail", i);
2027        }
2028    }
2029
2030    #[test]
2031    fn test_from_hdr_name() {
2032        use self::StandardHeader::Vary;
2033
2034        let name = HeaderName::from(HdrName {
2035            inner: Repr::Standard(Vary),
2036        });
2037
2038        assert_eq!(name.inner, Repr::Standard(Vary));
2039
2040        let name = HeaderName::from(HdrName {
2041            inner: Repr::Custom(MaybeLower {
2042                buf: b"hello-world",
2043                lower: true,
2044            }),
2045        });
2046
2047        assert_eq!(name.inner, Repr::Custom(Custom(ByteStr::from_static("hello-world"))));
2048
2049        let name = HeaderName::from(HdrName {
2050            inner: Repr::Custom(MaybeLower {
2051                buf: b"Hello-World",
2052                lower: false,
2053            }),
2054        });
2055
2056        assert_eq!(name.inner, Repr::Custom(Custom(ByteStr::from_static("hello-world"))));
2057    }
2058
2059    #[test]
2060    fn test_eq_hdr_name() {
2061        use self::StandardHeader::Vary;
2062
2063        let a = HeaderName { inner: Repr::Standard(Vary) };
2064        let b = HdrName { inner: Repr::Standard(Vary) };
2065
2066        assert_eq!(a, b);
2067
2068        let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static("vaary"))) };
2069        assert_ne!(a, b);
2070
2071        let b = HdrName { inner: Repr::Custom(MaybeLower {
2072            buf: b"vaary",
2073            lower: true,
2074        })};
2075
2076        assert_eq!(a, b);
2077
2078        let b = HdrName { inner: Repr::Custom(MaybeLower {
2079            buf: b"vaary",
2080            lower: false,
2081        })};
2082
2083        assert_eq!(a, b);
2084
2085        let b = HdrName { inner: Repr::Custom(MaybeLower {
2086            buf: b"VAARY",
2087            lower: false,
2088        })};
2089
2090        assert_eq!(a, b);
2091
2092        let a = HeaderName { inner: Repr::Standard(Vary) };
2093        assert_ne!(a, b);
2094    }
2095
2096    #[test]
2097    fn test_from_static_std() {
2098        let a = HeaderName { inner: Repr::Standard(Vary) };
2099        
2100        let b = HeaderName::from_static("vary");
2101        assert_eq!(a, b);
2102
2103        let b = HeaderName::from_static("vaary");
2104        assert_ne!(a, b);
2105    }
2106
2107    #[test]
2108    #[should_panic]
2109    fn test_from_static_std_uppercase() {
2110        HeaderName::from_static("Vary");
2111    } 
2112
2113    #[test]
2114    #[should_panic]
2115    fn test_from_static_std_symbol() {
2116        HeaderName::from_static("vary{}");
2117    } 
2118
2119    // MaybeLower { lower: true }
2120    #[test]
2121    fn test_from_static_custom_short() {
2122        let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static("customheader"))) };
2123        let b = HeaderName::from_static("customheader");
2124        assert_eq!(a, b);
2125    }
2126
2127    #[test]
2128    #[should_panic]
2129    fn test_from_static_custom_short_uppercase() {
2130        HeaderName::from_static("custom header");
2131    }
2132
2133    #[test]
2134    #[should_panic]
2135    fn test_from_static_custom_short_symbol() {
2136        HeaderName::from_static("CustomHeader");
2137    }
2138
2139    // MaybeLower { lower: false }
2140    #[test]
2141    fn test_from_static_custom_long() {
2142        let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static(
2143            "longer-than-63--thisheaderislongerthansixtythreecharactersandthushandleddifferent"
2144        ))) };
2145        let b = HeaderName::from_static(
2146            "longer-than-63--thisheaderislongerthansixtythreecharactersandthushandleddifferent"
2147        );
2148        assert_eq!(a, b);
2149    }
2150
2151    #[test]
2152    #[should_panic]
2153    fn test_from_static_custom_long_uppercase() {
2154        HeaderName::from_static(
2155            "Longer-Than-63--ThisHeaderIsLongerThanSixtyThreeCharactersAndThusHandledDifferent"
2156        );
2157    }
2158
2159    #[test]
2160    #[should_panic]
2161    fn test_from_static_custom_long_symbol() {
2162        HeaderName::from_static(
2163            "longer-than-63--thisheader{}{}{}{}islongerthansixtythreecharactersandthushandleddifferent"
2164        );
2165    }
2166
2167    #[test]
2168    fn test_from_static_custom_single_char() {
2169        let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static("a"))) };
2170        let b = HeaderName::from_static("a");
2171        assert_eq!(a, b);
2172    }
2173
2174    #[test]
2175    #[should_panic]
2176    fn test_from_static_empty() {
2177        HeaderName::from_static("");
2178    }   
2179}