001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.http.header;
018
019import java.util.function.*;
020
021import org.apache.juneau.*;
022import org.apache.juneau.commons.collections.*;
023import org.apache.juneau.http.annotation.*;
024
025/**
026 * Represents a parsed <l>Accept-Encoding</l> HTTP request header.
027 *
028 * <p>
029 * List of acceptable encodings.
030 *
031 * <h5 class='figure'>Example</h5>
032 * <p class='bcode'>
033 *    Accept-Encoding: gzip, deflate
034 * </p>
035 *
036 * <h5 class='topic'>RFC2616 Specification</h5>
037 *
038 * The Accept-Encoding request-header field is similar to Accept, but restricts the content-codings (section 3.5) that
039 * are acceptable in the response.
040 *
041 * <p class='bcode'>
042 *    Accept-Encoding  = "Accept-Encoding" ":"
043 *                       1#( codings [ ";" "q" "=" qvalue ] )
044 *    codings          = ( content-coding | "*" )
045 * </p>
046 *
047 * <p>
048 * Examples of its use are:
049 * <p class='bcode'>
050 *    Accept-Encoding: compress, gzip
051 *    Accept-Encoding:
052 *    Accept-Encoding: *
053 *    Accept-Encoding: compress;q=0.5, gzip;q=1.0
054 *    Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
055 * </p>
056 *
057 * <p>
058 * A server tests whether a content-coding is acceptable, according to an Accept-Encoding field, using these rules:
059 * <ol>
060 *    <li>If the content-coding is one of the content-codings listed in the Accept-Encoding field, then it is
061 *       acceptable, unless it is accompanied by a qvalue of 0.
062 *       (As defined in section 3.9, a qvalue of 0 means "not acceptable.")
063 *    <li>The special "*" symbol in an Accept-Encoding field matches any available content-coding not explicitly listed
064 *       in the header field.
065 *    <li>If multiple content-codings are acceptable, then the acceptable content-coding with the highest non-zero
066 *       qvalue is preferred.
067 *    <li>The "identity" content-coding is always acceptable, unless specifically refused because the Accept-Encoding
068 *       field includes "identity;q=0", or because the field includes "*;q=0" and does not explicitly include the
069 *       "identity" content-coding.
070 *       If the Accept-Encoding field-value is empty, then only the "identity" encoding is acceptable.
071 * </ol>
072 *
073 * <p>
074 * If an Accept-Encoding field is present in a request, and if the server cannot send a response which is acceptable
075 * according to the Accept-Encoding header, then the server SHOULD send an error response with the 406 (Not Acceptable)
076 * status code.
077 *
078 * <p>
079 * If no Accept-Encoding field is present in a request, the server MAY assume that the client will accept any content
080 * coding.
081 * In this case, if "identity" is one of the available content-codings, then the server SHOULD use the "identity"
082 * content-coding, unless it has additional information that a different content-coding is meaningful to the client.
083 *
084 * <p>
085 * Note: If the request does not include an Accept-Encoding field, and if the "identity" content-coding is unavailable,
086 * then content-codings commonly understood by HTTP/1.0 clients (i.e.,"gzip" and "compress") are preferred; some older
087 * clients improperly display messages sent with other content-codings.
088 * The server might also make this decision based on information about the particular user-agent or client.
089 *
090 * <p>
091 * Note: Most HTTP/1.0 applications do not recognize or obey qvalues associated with content-codings.
092 * This means that qvalues will not work and are not permitted with x-gzip or x-compress.
093 *
094 * <h5 class='section'>See Also:</h5><ul>
095 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
096 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
097 * </ul>
098 *
099 * @serial exclude
100 */
101@Header("Accept-Encoding")
102public class AcceptEncoding extends BasicStringRangesHeader {
103   private static final long serialVersionUID = 1L;
104   private static final String NAME = "Accept-Encoding";
105
106   private static final Cache<String,AcceptEncoding> CACHE = Cache.of(String.class, AcceptEncoding.class).build();
107
108   /**
109    * Static creator.
110    *
111    * @param value
112    *    The header value.
113    *    <br>Must be parsable by {@link StringRanges#of(String)}.
114    *    <br>Can be <jk>null</jk>.
115    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
116    */
117   public static AcceptEncoding of(String value) {
118      return value == null ? null : CACHE.get(value, () -> new AcceptEncoding(value));
119   }
120
121   /**
122    * Static creator.
123    *
124    * @param value
125    *    The header value.
126    *    <br>Can be <jk>null</jk>.
127    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
128    */
129   public static AcceptEncoding of(StringRanges value) {
130      return value == null ? null : new AcceptEncoding(value);
131   }
132
133   /**
134    * Static creator with delayed value.
135    *
136    * <p>
137    * Header value is re-evaluated on each call to {@link #getValue()}.
138    *
139    * @param value
140    *    The supplier of the header value.
141    *    <br>Can be <jk>null</jk>.
142    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
143    */
144   public static AcceptEncoding of(Supplier<StringRanges> value) {
145      return value == null ? null : new AcceptEncoding(value);
146   }
147
148   /**
149    * Constructor.
150    *
151    * @param value
152    *    The header value.
153    *    <br>Must be parsable by {@link StringRanges#of(String)}.
154    *    <br>Can be <jk>null</jk>.
155    */
156   public AcceptEncoding(String value) {
157      super(NAME, value);
158   }
159
160   /**
161    * Constructor.
162    *
163    * @param value
164    *    The header value.
165    *    <br>Can be <jk>null</jk>.
166    */
167   public AcceptEncoding(StringRanges value) {
168      super(NAME, value);
169   }
170
171   /**
172    * Constructor with delayed value.
173    *
174    * <p>
175    * Header value is re-evaluated on each call to {@link #getValue()}.
176    *
177    * @param value
178    *    The supplier of the header value.
179    *    <br>Can be <jk>null</jk>.
180    */
181   public AcceptEncoding(Supplier<StringRanges> value) {
182      super(NAME, value);
183   }
184}