Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: a16c9960e6995f08845a77a789ee48b1d7f8448b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
//
//  ========================================================================
//  Copyright (c) 1995-2015 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 &lt;=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();
}

Back to the top