| // |
| // ======================================================================== |
| // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.server; |
| |
| import java.util.Set; |
| |
| import javax.servlet.http.Cookie; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpSession; |
| |
| |
| /** Build a request to be pushed. |
| * |
| * <p>A PushBuilder is obtained by calling {@link |
| * Request#getPushBuilder()} (<code>Eventually HttpServletRequest.getPushBuilder()</code>). |
| * Each call to this method will |
| * return a new instance of a PushBuilder based off the current {@code |
| * HttpServletRequest}. Any mutations to the returned PushBuilder are |
| * not reflected on future returns.</p> |
| * |
| * <p>The instance is initialized as follows:</p> |
| * |
| * <ul> |
| * |
| * <li>The method is initialized to "GET"</li> |
| * |
| * <li>The existing headers of the current {@link HttpServletRequest} |
| * are added to the builder, except for: |
| * |
| * <ul> |
| * <li>Conditional headers (eg. If-Modified-Since) |
| * <li>Range headers |
| * <li>Expect headers |
| * <li>Authorization headers |
| * <li>Referrer headers |
| * </ul> |
| * |
| * </li> |
| * |
| * <li>If the request was authenticated, an Authorization header will |
| * be set with a container generated token that will result in equivalent |
| * Authorization for the pushed request.</li> |
| * |
| * <li>The {@link HttpServletRequest#getRequestedSessionId()} value, |
| * unless at the time of the call {@link |
| * HttpServletRequest#getSession(boolean)} has previously been called to |
| * create a new {@link HttpSession}, in which case the new session ID |
| * will be used as the PushBuilder's requested session ID. The source of |
| * the requested session id will be the same as for the request</li> |
| * |
| * <li>The Referer(sic) header will be set to {@link |
| * HttpServletRequest#getRequestURL()} plus any {@link |
| * HttpServletRequest#getQueryString()} </li> |
| * |
| * <li>If {@link HttpServletResponse#addCookie(Cookie)} has been called |
| * on the associated response, then a corresponding Cookie header will be added |
| * to the PushBuilder, unless the {@link Cookie#getMaxAge()} is <=0, in which |
| * case the Cookie will be removed from the builder.</li> |
| * |
| * <li>If this request has has the conditional headers If-Modified-Since |
| * or If-None-Match, then the {@link #isConditional()} header is set to |
| * true.</li> |
| * |
| * </ul> |
| * |
| * <p>The {@link #path} method must be called on the {@code PushBuilder} |
| * instance before the call to {@link #push}. Failure to do so must |
| * cause an exception to be thrown from {@link |
| * #push}, as specified in that method.</p> |
| * |
| * <p>A PushBuilder can be customized by chained calls to mutator |
| * methods before the {@link #push()} method is called to initiate an |
| * asynchronous push request with the current state of the builder. |
| * After the call to {@link #push()}, the builder may be reused for |
| * another push, however the implementation must make it so the {@link |
| * #path(String)}, {@link #etag(String)} and {@link |
| * #lastModified(String)} values are cleared before returning from |
| * {@link #push}. All other values are retained over calls to {@link |
| * #push()}. |
| * |
| * @since 4.0 |
| */ |
| public interface PushBuilder |
| { |
| /** |
| * <p>Set the method to be used for the push.</p> |
| * |
| * <p>Any non-empty String may be used for the method.</p> |
| * |
| * @param method the method to be used for the push. |
| * @return this builder. |
| * @throws NullPointerException if the argument is {@code null} |
| * @throws IllegalArgumentException if the argument is the empty String |
| */ |
| public abstract PushBuilder method(String method); |
| |
| /** Set the query string to be used for the push. |
| * |
| * Will be appended to any query String included in a call to {@link |
| * #path(String)}. Any duplicate parameters must be preserved. This |
| * method should be used instead of a query in {@link #path(String)} |
| * when multiple {@link #push()} calls are to be made with the same |
| * query string. |
| * @param queryString the query string to be used for the push. |
| * @return this builder. |
| */ |
| public abstract PushBuilder queryString(String queryString); |
| |
| /** Set the SessionID to be used for the push. |
| * The session ID will be set in the same way it was on the associated request (ie |
| * as a cookie if the associated request used a cookie, or as a url parameter if |
| * the associated request used a url parameter). |
| * Defaults to the requested session ID or any newly assigned session id from |
| * a newly created session. |
| * @param sessionId the SessionID to be used for the push. |
| * @return this builder. |
| */ |
| public abstract PushBuilder sessionId(String sessionId); |
| |
| /** Set if the request is to be conditional. |
| * If the request is conditional, any available values from {@link #etag(String)} or |
| * {@link #lastModified(String)} will be set in the appropriate headers. If the request |
| * is not conditional, then etag and lastModified values are ignored. |
| * Defaults to true if the associated request was conditional. |
| * @param conditional true if the push request is conditional |
| * @return this builder. |
| */ |
| public abstract PushBuilder conditional(boolean conditional); |
| |
| /** |
| * <p>Set a header to be used for the push. If the builder has an |
| * existing header with the same name, its value is overwritten.</p> |
| * |
| * @param name The header name to set |
| * @param value The header value to set |
| * @return this builder. |
| */ |
| public abstract PushBuilder setHeader(String name, String value); |
| |
| |
| /** |
| * <p>Add a header to be used for the push.</p> |
| * @param name The header name to add |
| * @param value The header value to add |
| * @return this builder. |
| */ |
| public abstract PushBuilder addHeader(String name, String value); |
| |
| |
| /** |
| * <p>Remove the named header. If the header does not exist, take |
| * no action.</p> |
| * |
| * @param name The name of the header to remove |
| * @return this builder. |
| */ |
| public abstract PushBuilder removeHeader(String name); |
| |
| |
| |
| /** |
| * Set the URI path to be used for the push. The path may start |
| * with "/" in which case it is treated as an absolute path, |
| * otherwise it is relative to the context path of the associated |
| * request. There is no path default and {@link #path(String)} must |
| * be called before every call to {@link #push()}. If a query |
| * string is present in the argument {@code path}, its contents must |
| * be merged with the contents previously passed to {@link |
| * #queryString}, preserving duplicates. |
| * |
| * @param path the URI path to be used for the push, which may include a |
| * query string. |
| * @return this builder. |
| */ |
| public abstract PushBuilder path(String path); |
| |
| /** |
| * Set the etag to be used for conditional pushes. |
| * The etag will be used only if {@link #isConditional()} is true. |
| * Defaults to no etag. The value is nulled after every call to |
| * {@link #push()} |
| * @param etag the etag to be used for the push. |
| * @return this builder. |
| */ |
| public abstract PushBuilder etag(String etag); |
| |
| /** |
| * Set the last modified date to be used for conditional pushes. |
| * The last modified date will be used only if {@link |
| * #isConditional()} is true. Defaults to no date. The value is |
| * nulled after every call to {@link #push()} |
| * @param lastModified the last modified date to be used for the push. |
| * @return this builder. |
| */ |
| public abstract PushBuilder lastModified(String lastModified); |
| |
| |
| /** Push a resource given the current state of the builder, |
| * returning immediately without blocking. |
| * |
| * <p>Push a resource based on the current state of the PushBuilder. |
| * If {@link #isConditional()} is true and an etag or lastModified |
| * value is provided, then an appropriate conditional header will be |
| * generated. If both an etag and lastModified value are provided |
| * only an If-None-Match header will be generated. If the builder |
| * has a session ID, then the pushed request will include the |
| * session ID either as a Cookie or as a URI parameter as |
| * appropriate. The builders query string is merged with any passed |
| * query string.</p> |
| * |
| * <p>Before returning from this method, the builder has its path, |
| * etag and lastModified fields nulled. All other fields are left as |
| * is for possible reuse in another push.</p> |
| * |
| * @throws IllegalArgumentException if the method set expects a |
| * request body (eg POST) |
| * |
| * @throws IllegalStateException if there was no call to {@link |
| * #path} on this instance either between its instantiation or the |
| * last call to {@code push()} that did not throw an |
| * IllegalStateException. |
| */ |
| public abstract void push(); |
| |
| public abstract String getMethod(); |
| public abstract String getQueryString(); |
| public abstract String getSessionId(); |
| public abstract boolean isConditional(); |
| public abstract Set<String> getHeaderNames(); |
| public abstract String getHeader(String name); |
| public abstract String getPath(); |
| public abstract String getEtag(); |
| public abstract String getLastModified(); |
| } |