1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.server; 20 21 import java.util.Set; 22 23 import javax.servlet.http.Cookie; 24 import javax.servlet.http.HttpServletRequest; 25 import javax.servlet.http.HttpServletResponse; 26 import javax.servlet.http.HttpSession; 27 28 /** Build a request to be pushed. 29 * <p> 30 * A PushBuilder is obtained by calling {@link Request#getPushBuilder()} 31 * which creates an initializes the builder as follows: 32 * <ul> 33 * <li> Each call to getPushBuilder() will return a new instance of a 34 * PushBuilder based off the Request. Any mutations to the 35 * returned PushBuilder are not reflected on future returns.</li> 36 * <li>The method is initialized to "GET"</li> 37 * <li>The requests headers are added to the Builder, except for:<ul> 38 * <li>Conditional headers (eg. If-Modified-Since) 39 * <li>Range headers 40 * <li>Expect headers 41 * <li>Authorization headers 42 * <li>Referrer headers 43 * </ul></li> 44 * <li>If the request was Authenticated, an Authorization header will 45 * be set with a container generated token that will result in equivalent 46 * Authorization for the pushed request</li> 47 * <li>The query string from {@link HttpServletRequest#getQueryString()} 48 * <li>The {@link HttpServletRequest#getRequestedSessionId()} value, unless at the time 49 * of the call {@link HttpServletRequest#getSession(boolean)} 50 * has previously been called to create a new {@link HttpSession}, in 51 * which case the new session ID will be used as the PushBuilders 52 * requested session ID. The source of the requested session id will be the 53 * same as for the request</li> 54 * <li>The Referer header will be set to {@link HttpServletRequest#getRequestURL()} 55 * plus any {@link HttpServletRequest#getQueryString()} </li> 56 * <li>If {@link HttpServletResponse#addCookie(Cookie)} has been called 57 * on the associated response, then a corresponding Cookie header will be added 58 * to the PushBuilder, unless the {@link Cookie#getMaxAge()} is <=0, in which 59 * case the Cookie will be removed from the builder.</li> 60 * <li>If this request has has the conditional headers If-Modified-Since or 61 * If-None-Match then the {@link #isConditional()} header is set to true.</li> 62 * </ul> 63 * <p>A PushBuilder can be customized by chained calls to mutator methods before the 64 * {@link #push()} method is called to initiate a push request with the current state 65 * of the builder. After the call to {@link #push()}, the builder may be reused for 66 * another push, however the {@link #path(String)}, {@link #etag(String)} and 67 * {@link #lastModified(String)} values will have been nulled. All other 68 * values are retained over calls to {@link #push()}. 69 */ 70 public interface PushBuilder 71 { 72 /** Set the method to be used for the push. 73 * Defaults to GET. 74 * @param method the method to be used for the push. 75 * @return this builder. 76 */ 77 public abstract PushBuilder method(String method); 78 79 /** Set the query string to be used for the push. 80 * Defaults to the requests query string. 81 * Will be appended to any query String included in a call to {@link #path(String)}. This 82 * method should be used instead of a query in {@link #path(String)} when multiple 83 * {@link #push()} calls are to be made with the same query string, or to remove a 84 * query string obtained from the associated request. 85 * @param queryString the query string to be used for the push. 86 * @return this builder. 87 */ 88 public abstract PushBuilder queryString(String queryString); 89 90 /** Set the SessionID to be used for the push. 91 * The session ID will be set in the same way it was on the associated request (ie 92 * as a cookie if the associated request used a cookie, or as a url parameter if 93 * the associated request used a url parameter). 94 * Defaults to the requested session ID or any newly assigned session id from 95 * a newly created session. 96 * @param sessionId the SessionID to be used for the push. 97 * @return this builder. 98 */ 99 public abstract PushBuilder sessionId(String sessionId); 100 101 /** Set if the request is to be conditional. 102 * If the request is conditional, any available values from {@link #etag(String)} or 103 * {@link #lastModified(String)} will be set in the appropriate headers. If the request 104 * is not conditional, then etag and lastModified values are ignored. 105 * Defaults to true if the associated request was conditional. 106 * @param conditional true if the push request is conditional 107 * @return this builder. 108 */ 109 public abstract PushBuilder conditional(boolean conditional); 110 111 /** Set a header to be used for the push. 112 * @param name The header name to set 113 * @param value The header value to set 114 * @return this builder. 115 */ 116 public abstract PushBuilder setHeader(String name, String value); 117 118 /** Add a header to be used for the push. 119 * @param name The header name to add 120 * @param value The header value to add 121 * @return this builder. 122 */ 123 public abstract PushBuilder addHeader(String name, String value); 124 125 /** Set the URI path to be used for the push. 126 * The path may start with "/" in which case it is treated as an 127 * absolute path, otherwise it is relative to the context path of 128 * the associated request. 129 * There is no path default and {@link #path(String)} must be called 130 * before every call to {@link #push()} 131 * @param path the URI path to be used for the push, which may include a 132 * query string. 133 * @return this builder. 134 */ 135 public abstract PushBuilder path(String path); 136 137 /** Set the etag to be used for conditional pushes. 138 * The etag will be used only if {@link #isConditional()} is true. 139 * Defaults to no etag. The value is nulled after every call to 140 * {@link #push()} 141 * @param etag the etag to be used for the push. 142 * @return this builder. 143 */ 144 public abstract PushBuilder etag(String etag); 145 146 /** Set the last modified date to be used for conditional pushes. 147 * The last modified date will be used only if {@link #isConditional()} is true. 148 * Defaults to no date. The value is nulled after every call to 149 * {@link #push()} 150 * @param lastModified the last modified date to be used for the push. 151 * @return this builder. 152 * */ 153 public abstract PushBuilder lastModified(String lastModified); 154 155 156 /** Push a resource. 157 * Push a resource based on the current state of the PushBuilder. If {@link #isConditional()} 158 * is true and an etag or lastModified value is provided, then an appropriate conditional header 159 * will be generated. If both an etag and lastModified value are provided only an If-None-Match header 160 * will be generated. If the builder has a session ID, then the pushed request 161 * will include the session ID either as a Cookie or as a URI parameter as appropriate. The builders 162 * query string is merged with any passed query string. 163 * After initiating the push, the builder has its path, etag and lastModified fields nulled. All 164 * other fields are left as is for possible reuse in another push. 165 * @throws IllegalArgumentException if the method set expects a request body (eg POST) 166 */ 167 public abstract void push(); 168 169 170 171 172 173 public abstract String getMethod(); 174 public abstract String getQueryString(); 175 public abstract String getSessionId(); 176 public abstract boolean isConditional(); 177 public abstract Set<String> getHeaderNames(); 178 public abstract String getHeader(String name); 179 public abstract String getPath(); 180 public abstract String getEtag(); 181 public abstract String getLastModified(); 182 183 184 185 }