001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.http.header; 014 015import java.util.function.*; 016 017import org.apache.juneau.*; 018import org.apache.juneau.http.annotation.*; 019import org.apache.juneau.internal.*; 020 021/** 022 * Represents a parsed <l>Accept</l> HTTP request header. 023 * 024 * <p> 025 * Content-Types that are acceptable for the response. 026 * 027 * <h5 class='figure'>Example</h5> 028 * <p class='bcode'> 029 * Accept: text/plain 030 * </p> 031 * 032 * <h5 class='topic'>RFC2616 Specification</h5> 033 * 034 * The Accept request-header field can be used to specify certain media types which are acceptable for the response. 035 * Accept headers can be used to indicate that the request is specifically limited to a small set of desired types, as 036 * in the case of a request for an in-line image. 037 * 038 * <p class='bcode'> 039 * Accept = "Accept" ": 040 * #( media-range [ accept-params ] ) 041 * 042 * media-range = ( "* /*" 043 * | ( type "/" "*" ) 044 * | ( type "/" subtype ) 045 * ) *( ";" parameter ) 046 * accept-params = ";" "q" "=" qvalue *( accept-extension ) 047 * accept-extension = ";" token [ "=" ( token | quoted-string ) ] 048 * </p> 049 * 050 * <p> 051 * The asterisk "*" character is used to group media types into ranges, with "* /*" indicating all media types and 052 * "type/*" indicating all subtypes of that type. 053 * The media-range MAY include media type parameters that are applicable to that range. 054 * 055 * <p> 056 * Each media-range MAY be followed by one or more accept-params, beginning with the "q" parameter for indicating a 057 * relative quality factor. 058 * The first "q" parameter (if any) separates the media-range parameter(s) from the accept-params. 059 * Quality factors allow the user or user agent to indicate the relative degree of preference for that media-range, 060 * using the qvalue scale from 0 to 1 (section 3.9). 061 * The default value is q=1. 062 * 063 * <p> 064 * Note: Use of the "q" parameter name to separate media type parameters from Accept extension parameters is due to 065 * historical practice. 066 * Although this prevents any media type parameter named "q" from being used with a media range, such an event is 067 * believed to be unlikely given the lack of any "q" parameters in the IANA 068 * media type registry and the rare usage of any media type parameters in Accept. 069 * Future media types are discouraged from registering any parameter named "q". 070 * 071 * <p> 072 * The example 073 * <p class='bcode'> 074 * Accept: audio/*; q=0.2, audio/basic 075 * </p> 076 * <p> 077 * SHOULD be interpreted as "I prefer audio/basic, but send me any audio type if it is the best available after an 80% 078 * mark-down in quality." 079 * 080 * <p> 081 * If no Accept header field is present, then it is assumed that the client accepts all media types. 082 * 083 * <p> 084 * If an Accept header field is present, and if the server cannot send a response which is acceptable according to the 085 * combined Accept field value, then the server SHOULD send a 406 (not acceptable) response. 086 * 087 * <p> 088 * A more elaborate example is 089 * <p class='bcode'> 090 * Accept: text/plain; q=0.5, text/html, 091 * text/x-dvi; q=0.8, text/x-c 092 * </p> 093 * 094 * <p> 095 * Verbally, this would be interpreted as "text/html and text/x-c are the preferred media types, but if they do not 096 * exist, then send the 097 * text/x-dvi entity, and if that does not exist, send the text/plain entity." 098 * 099 * <p> 100 * Media ranges can be overridden by more specific media ranges or specific media types. 101 * If more than one media range applies to a given type, the most specific reference has precedence. 102 * For example, 103 * <p class='bcode'> 104 * Accept: text/ *, text/html, text/html;level=1, * /* 105 * </p> 106 * <p> 107 * have the following precedence: 108 * <ol> 109 * <li>text/html;level=1 110 * <li>text/html 111 * <li>text/* 112 * <li>* /* 113 * </ol> 114 * 115 * <p> 116 * The media type quality factor associated with a given type is determined by finding the media range with the highest 117 * precedence which matches that type. 118 * For example, 119 * <p class='bcode'> 120 * Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, 121 * text/html;level=2;q=0.4, * /*;q=0.5 122 * </p> 123 * <p> 124 * would cause the following values to be associated: 125 * <p class='bcode'> 126 * text/html;level=1 = 1 127 * text/html = 0.7 128 * text/plain = 0.3 129 * image/jpeg = 0.5 130 * text/html;level=2 = 0.4 131 * text/html;level=3 = 0.7 132 * </p> 133 * 134 * <p> 135 * Note: A user agent might be provided with a default set of quality values for certain media ranges. 136 * However, unless the user agent is a closed system which cannot interact with other rendering agents, this default 137 * set ought to be configurable by the user. 138 * 139 * <h5 class='section'>See Also:</h5><ul> 140 * <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a> 141 * <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a> 142 * </ul> 143 * 144 * @serial exclude 145 */ 146@Header("Accept") 147public class Accept extends BasicMediaRangesHeader { 148 149 //----------------------------------------------------------------------------------------------------------------- 150 // Static 151 //----------------------------------------------------------------------------------------------------------------- 152 153 private static final long serialVersionUID = 1L; 154 private static final String NAME = "Accept"; 155 156 private static final Cache<String,Accept> CACHE = Cache.of(String.class, Accept.class).build(); 157 158 // Constants 159 @SuppressWarnings("javadoc") 160 public static final Accept 161 APPLICATION_ATOM_XML = of("application/atom+xml"), 162 APPLICATION_FORM_URLENCODED = of("application/x-www-form-urlencoded"), 163 APPLICATION_JSON = of("application/json"), 164 APPLICATION_OCTET_STREAM = of("application/octet-stream"), 165 APPLICATION_SOAP_XML = of("application/soap+xml"), 166 APPLICATION_SVG_XML = of("application/svg+xml"), 167 APPLICATION_XHTML_XML = of("application/xhtml+xml"), 168 APPLICATION_XML = of("application/xml"), 169 IMAGE_BMP = of("image/bmp"), 170 IMAGE_GIF = of("image/gif"), 171 IMAGE_JPEG = of("image/jpeg"), 172 IMAGE_PNG = of("image/png"), 173 IMAGE_SVG = of("image/svg+xml"), 174 IMAGE_TIFF = of("image/tiff"), 175 IMAGE_WEBP = of("image/webp"), 176 MULTIPART_FORM_DATA = of("multipart/form-data"), 177 TEXT_HTML = of("text/html"), 178 TEXT_PLAIN = of("text/plain"), 179 TEXT_XML = of("text/xml"), 180 WILDCARD = of("*/*"), 181 NULL = new Accept((String)null); 182 183 /** 184 * Static creator. 185 * 186 * @param value 187 * The header value. 188 * <br>Must be parsable by {@link MediaRanges#of(String)}. 189 * <br>Can be <jk>null</jk>. 190 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 191 */ 192 public static Accept of(String value) { 193 return value == null ? null : CACHE.get(value, ()->new Accept(value)); 194 } 195 196 /** 197 * Static creator. 198 * 199 * @param value 200 * The header value. 201 * <br>Can be <jk>null</jk>. 202 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 203 */ 204 public static Accept of(MediaRanges value) { 205 return value == null ? null : new Accept(value); 206 } 207 208 /** 209 * Static creator. 210 * 211 * @param value 212 * The header value. 213 * <br>Can be <jk>null</jk>. 214 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 215 */ 216 public static Accept of(MediaType value) { 217 return value == null ? null : new Accept(value.toString()); 218 } 219 220 /** 221 * Static creator with delayed value. 222 * 223 * <p> 224 * Header value is re-evaluated on each call to {@link #getValue()}. 225 * 226 * @param value 227 * The header value. 228 * <br>Can be <jk>null</jk>. 229 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 230 */ 231 public static Accept of(Supplier<MediaRanges> value) { 232 return value == null ? null : new Accept(value); 233 } 234 235 //----------------------------------------------------------------------------------------------------------------- 236 // Instance 237 //----------------------------------------------------------------------------------------------------------------- 238 239 /** 240 * Constructor. 241 * 242 * @param value 243 * The header value. 244 * <br>Must be parsable by {@link MediaRanges#of(String)}. 245 * <br>Can be <jk>null</jk>. 246 */ 247 public Accept(String value) { 248 super(NAME, value); 249 } 250 251 /** 252 * Constructor. 253 * 254 * @param value 255 * The header value. 256 * <br>Can be <jk>null</jk>. 257 */ 258 public Accept(MediaRanges value) { 259 super(NAME, value); 260 } 261 262 /** 263 * Constructor with delayed value. 264 * 265 * <p> 266 * Header value is re-evaluated on each call to {@link #getValue()}. 267 * 268 * @param value 269 * The supplier of the header value. 270 * <br>Can be <jk>null</jk>. 271 */ 272 public Accept(Supplier<MediaRanges> value) { 273 super(NAME, value); 274 } 275}