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.http.annotation.*; 022 023/** 024 * Represents a parsed <l>If-None-Match</l> HTTP request header. 025 * 026 * <p> 027 * Allows a 304 Not Modified to be returned if content is unchanged. 028 * 029 * <h5 class='figure'>Example</h5> 030 * <p class='bcode'> 031 * If-None-Match: "737060cd8c284d8af7ad3082f209582d" 032 * </p> 033 * 034 * <h5 class='topic'>RFC2616 Specification</h5> 035 * 036 * The If-None-Match request-header field is used with a method to make it conditional. 037 * A client that has one or more entities previously obtained from the resource can verify that none of those entities 038 * is current by including a list of their associated entity tags in the If-None-Match header field. 039 * The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction 040 * overhead. 041 * It is also used to prevent a method (e.g. PUT) from inadvertently modifying an existing resource when the client 042 * believes that the resource does not exist. 043 * 044 * <p> 045 * As a special case, the value "*" matches any current entity of the resource. 046 * 047 * <p class='bcode'> 048 * If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag ) 049 * </p> 050 * 051 * <p> 052 * If any of the entity tags match the entity tag of the entity that would have been returned in the response to a 053 * similar GET request (without the If-None-Match header) on that resource, or if "*" is given 054 * and any current entity exists for that resource, then the server MUST NOT perform the requested method, unless 055 * required to do so because the resource's modification date fails to match that supplied in an If-Modified-Since 056 * header field in the request. 057 * Instead, if the request method was GET or HEAD, the server SHOULD respond with a 304 (Not Modified) response, 058 * including the cache- related header fields (particularly ETag) of one of the entities that matched. 059 * For all other request methods, the server MUST respond with a status of 412 (Precondition Failed). 060 * 061 * <p> 062 * See section 13.3.3 for rules on how to determine if two entities tags match. 063 * The weak comparison function can only be used with GET or HEAD requests. 064 * 065 * <p> 066 * If none of the entity tags match, then the server MAY perform the requested method as if the If-None-Match header 067 * field did not exist, but MUST also ignore any If-Modified-Since header field(s) in the request. 068 * That is, if no entity tags match, then the server MUST NOT return a 304 (Not Modified) response. 069 * 070 * <p> 071 * If the request would, without the If-None-Match header field, result in anything other than a 2xx or 304 status, 072 * then the If-None-Match header MUST be ignored. 073 * (See section 13.3.4 for a discussion of server behavior when both If-Modified-Since and If-None-Match appear in the 074 * same request.) 075 * 076 * <p> 077 * The meaning of "If-None-Match: *" is that the method MUST NOT be performed if the representation selected by the 078 * origin server (or by a cache, possibly using the Vary mechanism, see section 14.44) exists, and SHOULD be performed 079 * if the representation does not exist. 080 * This feature is intended to be useful in preventing races between PUT operations. 081 * 082 * <p> 083 * Examples: 084 * <p class='bcode'> 085 * If-None-Match: "xyzzy" 086 * If-None-Match: W/"xyzzy" 087 * If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" 088 * If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz" 089 * If-None-Match: * 090 * </p> 091 * 092 * <p> 093 * The result of a request having both an If-None-Match header field and either an If-Match or an If-Unmodified-Since 094 * header fields is undefined by this specification. 095 * 096 * <h5 class='section'>See Also:</h5><ul> 097 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a> 098 * <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a> 099 * </ul> 100 * 101 * @serial exclude 102 */ 103@Header("If-None-Match") 104public class IfNoneMatch extends BasicEntityTagsHeader { 105 106 //----------------------------------------------------------------------------------------------------------------- 107 // Static 108 //----------------------------------------------------------------------------------------------------------------- 109 110 private static final long serialVersionUID = 1L; 111 private static final String NAME = "If-None-Match"; 112 113 /** 114 * Static creator. 115 * 116 * @param value 117 * The header value. 118 * <br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>). 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 IfNoneMatch of(String value) { 123 return value == null ? null : new IfNoneMatch(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 IfNoneMatch of(EntityTags value) { 135 return value == null ? null : new IfNoneMatch(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 IfNoneMatch of(Supplier<EntityTags> value) { 150 return value == null ? null : new IfNoneMatch(value); 151 } 152 153 //----------------------------------------------------------------------------------------------------------------- 154 // Instance 155 //----------------------------------------------------------------------------------------------------------------- 156 157 /** 158 * Constructor. 159 * 160 * @param value 161 * The header value. 162 * <br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>). 163 * <br>Can be <jk>null</jk>. 164 */ 165 public IfNoneMatch(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 IfNoneMatch(EntityTags 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 IfNoneMatch(Supplier<EntityTags> value) { 191 super(NAME, value); 192 } 193}