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.http.annotation.*;
023import org.apache.juneau.internal.*;
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
104   //-----------------------------------------------------------------------------------------------------------------
105   // Static
106   //-----------------------------------------------------------------------------------------------------------------
107
108   private static final long serialVersionUID = 1L;
109   private static final String NAME = "Accept-Encoding";
110
111   private static final Cache<String,AcceptEncoding> CACHE = Cache.of(String.class, AcceptEncoding.class).build();
112
113   /**
114    * Static creator.
115    *
116    * @param value
117    *    The header value.
118    *    <br>Must be parsable by {@link StringRanges#of(String)}.
119    *    <br>Can be <jk>null</jk>.
120    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
121    */
122   public static AcceptEncoding of(String value) {
123      return value == null ? null : CACHE.get(value, ()->new AcceptEncoding(value));
124   }
125
126   /**
127    * Static creator.
128    *
129    * @param value
130    *    The header value.
131    *    <br>Can be <jk>null</jk>.
132    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
133    */
134   public static AcceptEncoding of(StringRanges value) {
135      return value == null ? null : new AcceptEncoding(value);
136   }
137
138   /**
139    * Static creator with delayed value.
140    *
141    * <p>
142    * Header value is re-evaluated on each call to {@link #getValue()}.
143    *
144    * @param value
145    *    The supplier of the header value.
146    *    <br>Can be <jk>null</jk>.
147    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
148    */
149   public static AcceptEncoding of(Supplier<StringRanges> value) {
150      return value == null ? null : new AcceptEncoding(value);
151   }
152
153   //-----------------------------------------------------------------------------------------------------------------
154   // Instance
155   //-----------------------------------------------------------------------------------------------------------------
156
157   /**
158    * Constructor.
159    *
160    * @param value
161    *    The header value.
162    *    <br>Must be parsable by {@link StringRanges#of(String)}.
163    *    <br>Can be <jk>null</jk>.
164    */
165   public AcceptEncoding(String value) {
166      super(NAME, value);
167   }
168
169   /**
170    * Constructor.
171    *
172    * @param value
173    *    The header value.
174    *    <br>Can be <jk>null</jk>.
175    */
176   public AcceptEncoding(StringRanges value) {
177      super(NAME, value);
178   }
179
180   /**
181    * Constructor with delayed value.
182    *
183    * <p>
184    * Header value is re-evaluated on each call to {@link #getValue()}.
185    *
186    * @param value
187    *    The supplier of the header value.
188    *    <br>Can be <jk>null</jk>.
189    */
190   public AcceptEncoding(Supplier<StringRanges> value) {
191      super(NAME, value);
192   }
193}