View Javadoc
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.io.IOException;
22  import java.util.List;
23  import java.util.Set;
24  import java.util.concurrent.CopyOnWriteArrayList;
25  
26  import org.eclipse.jetty.http.HttpMethod;
27  import org.eclipse.jetty.http.HttpScheme;
28  import org.eclipse.jetty.util.Jetty;
29  import org.eclipse.jetty.util.TreeTrie;
30  import org.eclipse.jetty.util.Trie;
31  import org.eclipse.jetty.util.annotation.ManagedAttribute;
32  import org.eclipse.jetty.util.annotation.ManagedObject;
33  
34  
35  /* ------------------------------------------------------------ */
36  /** HTTP Configuration.
37   * <p>This class is a holder of HTTP configuration for use by the 
38   * {@link HttpChannel} class.  Typically a HTTPConfiguration instance
39   * is instantiated and passed to a {@link ConnectionFactory} that can 
40   * create HTTP channels (e.g. HTTP, AJP or FCGI).</p>
41   * <p>The configuration held by this class is not for the wire protocol,
42   * but for the interpretation and handling of HTTP requests that could
43   * be transported by a variety of protocols.
44   * </p>
45   */
46  @ManagedObject("HTTP Configuration")
47  public class HttpConfiguration
48  {
49      public static final String SERVER_VERSION = "Jetty(" + Jetty.VERSION + ")";
50  
51      private final List<Customizer> _customizers=new CopyOnWriteArrayList<>();
52      private final Trie<Boolean> _formEncodedMethods = new TreeTrie<>();
53      private int _outputBufferSize=32*1024;
54      private int _outputAggregationSize=_outputBufferSize/4;
55      private int _requestHeaderSize=8*1024;
56      private int _responseHeaderSize=8*1024;
57      private int _headerCacheSize=512;
58      private int _securePort;
59      private long _idleTimeout=-1;
60      private long _blockingTimeout=-1;
61      private String _secureScheme = HttpScheme.HTTPS.asString();
62      private boolean _sendServerVersion = true;
63      private boolean _sendXPoweredBy = false;
64      private boolean _sendDateHeader = true;
65      private boolean _delayDispatchUntilContent = true;
66      private boolean _persistentConnectionsEnabled = true;
67      private int _maxErrorDispatches = 10;
68      private long _minRequestDataRate;
69  
70      /* ------------------------------------------------------------ */
71      /** 
72       * <p>An interface that allows a request object to be customized 
73       * for a particular HTTP connector configuration.  Unlike Filters, customizer are
74       * applied before the request is submitted for processing and can be specific to the 
75       * connector on which the request was received.
76       * 
77       * <p>Typically Customizers perform tasks such as: <ul>
78       *  <li>process header fields that may be injected by a proxy or load balancer.
79       *  <li>setup attributes that may come from the connection/connector such as SSL Session IDs
80       *  <li>Allow a request to be marked as secure or authenticated if those have been offloaded
81       *  and communicated by header, cookie or other out-of-band mechanism
82       *  <li>Set request attributes/fields that are determined by the connector on which the
83       *  request was received
84       *  </ul>
85       */
86      public interface Customizer
87      {
88          public void customize(Connector connector, HttpConfiguration channelConfig, Request request);
89      }
90      
91      public interface ConnectionFactory
92      {
93          HttpConfiguration getHttpConfiguration();
94      }
95      
96      public HttpConfiguration()
97      {
98          _formEncodedMethods.put(HttpMethod.POST.asString(),Boolean.TRUE);
99          _formEncodedMethods.put(HttpMethod.PUT.asString(),Boolean.TRUE);
100     }
101     
102     /* ------------------------------------------------------------ */
103     /** Create a configuration from another.
104      * @param config The configuration to copy.
105      */
106     public HttpConfiguration(HttpConfiguration config)
107     {
108         _customizers.addAll(config._customizers);
109         for (String s:config._formEncodedMethods.keySet())
110             _formEncodedMethods.put(s,Boolean.TRUE);
111         _outputBufferSize=config._outputBufferSize;
112         _outputAggregationSize=config._outputAggregationSize;
113         _requestHeaderSize=config._requestHeaderSize;
114         _responseHeaderSize=config._responseHeaderSize;
115         _headerCacheSize=config._headerCacheSize;
116         _secureScheme=config._secureScheme;
117         _securePort=config._securePort;
118         _idleTimeout=config._idleTimeout;
119         _blockingTimeout=config._blockingTimeout;
120         _sendDateHeader=config._sendDateHeader;
121         _sendServerVersion=config._sendServerVersion;
122         _sendXPoweredBy=config._sendXPoweredBy;
123         _delayDispatchUntilContent=config._delayDispatchUntilContent;
124         _persistentConnectionsEnabled=config._persistentConnectionsEnabled;
125         _maxErrorDispatches=config._maxErrorDispatches;
126         _minRequestDataRate=config._minRequestDataRate;
127     }
128     
129     /* ------------------------------------------------------------ */
130     /** 
131      * <p>Add a {@link Customizer} that is invoked for every 
132      * request received.</p>
133      * <p>Customiser are often used to interpret optional headers (eg {@link ForwardedRequestCustomizer}) or 
134      * optional protocol semantics (eg {@link SecureRequestCustomizer}). 
135      * @param customizer A request customizer
136      */
137     public void addCustomizer(Customizer customizer)
138     {
139         _customizers.add(customizer);
140     }
141     
142     /* ------------------------------------------------------------ */
143     public List<Customizer> getCustomizers()
144     {
145         return _customizers;
146     }
147 
148     /* ------------------------------------------------------------ */
149     public <T> T getCustomizer(Class<T> type)
150     {
151         for (Customizer c : _customizers)
152             if (type.isAssignableFrom(c.getClass()))
153                 return (T)c;
154         return null;
155     }
156 
157     /* ------------------------------------------------------------ */
158     @ManagedAttribute("The size in bytes of the output buffer used to aggregate HTTP output")
159     public int getOutputBufferSize()
160     {
161         return _outputBufferSize;
162     }
163 
164     /* ------------------------------------------------------------ */
165     @ManagedAttribute("The maximum size in bytes for HTTP output to be aggregated")
166     public int getOutputAggregationSize()
167     {
168         return _outputAggregationSize;
169     }
170 
171     /* ------------------------------------------------------------ */
172     @ManagedAttribute("The maximum allowed size in bytes for a HTTP request header")
173     public int getRequestHeaderSize()
174     {
175         return _requestHeaderSize;
176     }
177 
178     /* ------------------------------------------------------------ */
179     @ManagedAttribute("The maximum allowed size in bytes for a HTTP response header")
180     public int getResponseHeaderSize()
181     {
182         return _responseHeaderSize;
183     }
184 
185     /* ------------------------------------------------------------ */
186     @ManagedAttribute("The maximum allowed size in bytes for a HTTP header field cache")
187     public int getHeaderCacheSize()
188     {
189         return _headerCacheSize;
190     }
191 
192     /* ------------------------------------------------------------ */
193     @ManagedAttribute("The port to which Integral or Confidential security constraints are redirected")
194     public int getSecurePort()
195     {
196         return _securePort;
197     }
198 
199     /* ------------------------------------------------------------ */
200     @ManagedAttribute("The scheme with which Integral or Confidential security constraints are redirected")
201     public String getSecureScheme()
202     {
203         return _secureScheme;
204     }
205 
206     /* ------------------------------------------------------------ */
207     @ManagedAttribute("Whether persistent connections are enabled")
208     public boolean isPersistentConnectionsEnabled()
209     {
210         return _persistentConnectionsEnabled;
211     }
212 
213     /* ------------------------------------------------------------ */
214     /** Get the max idle time in ms.
215      * <p>The max idle time is applied to a HTTP request for IO operations and
216      * delayed dispatch. 
217      * @return the max idle time in ms or if == 0 implies an infinite timeout, &lt;0 
218      * implies no HTTP channel timeout and the connection timeout is used instead.
219      */
220     @ManagedAttribute("The idle timeout in ms for I/O operations during the handling of a HTTP request")
221     public long getIdleTimeout()
222     {
223         return _idleTimeout;
224     }
225 
226     /* ------------------------------------------------------------ */
227     /** Set the max idle time in ms.
228      * <p>The max idle time is applied to a HTTP request for IO operations and
229      * delayed dispatch. 
230      * @param timeoutMs the max idle time in ms or if == 0 implies an infinite timeout, &lt;0 
231      * implies no HTTP channel timeout and the connection timeout is used instead.
232      */
233     public void setIdleTimeout(long timeoutMs)
234     {
235         _idleTimeout=timeoutMs;
236     }
237 
238     /* ------------------------------------------------------------ */
239     /** Get the timeout applied to blocking operations.
240      * <p>This timeout is in addition to the {@link Connector#getIdleTimeout()}, and applies
241      * to the total operation (as opposed to the idle timeout that applies to the time no 
242      * data is being sent).
243      * @return -1, for no blocking timeout (default), 0 for a blocking timeout equal to the 
244      * idle timeout; &gt;0 for a timeout in ms applied to the total blocking operation.
245      */
246     @ManagedAttribute("Total timeout in ms for blocking I/O operations.")
247     public long getBlockingTimeout()
248     {
249         return _blockingTimeout;
250     }
251 
252     /**
253      * Set the timeout applied to blocking operations.
254      * <p>This timeout is in addition to the {@link Connector#getIdleTimeout()}, and applies
255      * to the total operation (as opposed to the idle timeout that applies to the time no 
256      * data is being sent).
257      * @param blockingTimeout -1, for no blocking timeout (default), 0 for a blocking timeout equal to the 
258      * idle timeout; &gt;0 for a timeout in ms applied to the total blocking operation.
259      */
260     public void setBlockingTimeout(long blockingTimeout)
261     {
262         _blockingTimeout = blockingTimeout;
263     }
264 
265     /* ------------------------------------------------------------ */
266     public void setPersistentConnectionsEnabled(boolean persistentConnectionsEnabled)
267     {
268         _persistentConnectionsEnabled = persistentConnectionsEnabled;
269     }
270 
271     /* ------------------------------------------------------------ */
272     public void setSendServerVersion (boolean sendServerVersion)
273     {
274         _sendServerVersion = sendServerVersion;
275     }
276 
277     /* ------------------------------------------------------------ */
278     @ManagedAttribute("Whether to send the Server header in responses")
279     public boolean getSendServerVersion()
280     {
281         return _sendServerVersion;
282     }
283 
284     /* ------------------------------------------------------------ */
285     public void writePoweredBy(Appendable out,String preamble,String postamble) throws IOException
286     {
287         if (getSendServerVersion())
288         {
289             if (preamble!=null)
290                 out.append(preamble);
291             out.append(Jetty.POWERED_BY);
292             if (postamble!=null)
293                 out.append(postamble);
294         }
295     }
296     
297     /* ------------------------------------------------------------ */
298     public void setSendXPoweredBy (boolean sendXPoweredBy)
299     {
300         _sendXPoweredBy=sendXPoweredBy;
301     }
302 
303     /* ------------------------------------------------------------ */
304     @ManagedAttribute("Whether to send the X-Powered-By header in responses")
305     public boolean getSendXPoweredBy()
306     {
307         return _sendXPoweredBy;
308     }
309 
310     /* ------------------------------------------------------------ */
311     public void setSendDateHeader(boolean sendDateHeader)
312     {
313         _sendDateHeader = sendDateHeader;
314     }
315 
316     /* ------------------------------------------------------------ */
317     @ManagedAttribute("Whether to send the Date header in responses")
318     public boolean getSendDateHeader()
319     {
320         return _sendDateHeader;
321     }
322 
323     /* ------------------------------------------------------------ */
324     /**
325      * @param delay if true, delay the application dispatch until content is available (default false)
326      */
327     public void setDelayDispatchUntilContent(boolean delay)
328     {
329         _delayDispatchUntilContent = delay;
330     }
331 
332     /* ------------------------------------------------------------ */
333     @ManagedAttribute("Whether to delay the application dispatch until content is available")
334     public boolean isDelayDispatchUntilContent()
335     {
336         return _delayDispatchUntilContent;
337     }
338 
339     /* ------------------------------------------------------------ */
340     /**
341      * <p>Set the {@link Customizer}s that are invoked for every 
342      * request received.</p>
343      * <p>Customizers are often used to interpret optional headers (eg {@link ForwardedRequestCustomizer}) or
344      * optional protocol semantics (eg {@link SecureRequestCustomizer}). 
345      * @param customizers the list of customizers
346      */
347     public void setCustomizers(List<Customizer> customizers)
348     {
349         _customizers.clear();
350         _customizers.addAll(customizers);
351     }
352 
353     /* ------------------------------------------------------------ */
354     /**
355      * Set the size of the buffer into which response content is aggregated
356      * before being sent to the client.  A larger buffer can improve performance by allowing
357      * a content producer to run without blocking, however larger buffers consume more memory and
358      * may induce some latency before a client starts processing the content.
359      * @param outputBufferSize buffer size in bytes.
360      */
361     public void setOutputBufferSize(int outputBufferSize)
362     {
363         _outputBufferSize = outputBufferSize;
364         setOutputAggregationSize(outputBufferSize / 4);
365     }
366     
367     /* ------------------------------------------------------------ */
368     /**
369      * Set the max size of the response content write that is copied into the aggregate buffer.
370      * Writes that are smaller of this size are copied into the aggregate buffer, while
371      * writes that are larger of this size will cause the aggregate buffer to be flushed
372      * and the write to be executed without being copied.
373      * @param outputAggregationSize the max write size that is aggregated
374      */
375     public void setOutputAggregationSize(int outputAggregationSize)
376     {
377         _outputAggregationSize = outputAggregationSize;
378     }
379 
380     /* ------------------------------------------------------------ */
381     /** Set the maximum size of a request header.
382      * <p>Larger headers will allow for more and/or larger cookies plus larger form content encoded 
383      * in a URL. However, larger headers consume more memory and can make a server more vulnerable to denial of service
384      * attacks.</p>
385      * @param requestHeaderSize Max header size in bytes
386      */
387     public void setRequestHeaderSize(int requestHeaderSize)
388     {
389         _requestHeaderSize = requestHeaderSize;
390     }
391 
392     /* ------------------------------------------------------------ */
393     /** Set the maximum size of a response header.
394      * 
395      * <p>Larger headers will allow for more and/or larger cookies and longer HTTP headers (eg for redirection). 
396      * However, larger headers will also consume more memory.</p>
397      * @param responseHeaderSize Response header size in bytes.
398      */
399     public void setResponseHeaderSize(int responseHeaderSize)
400     {
401         _responseHeaderSize = responseHeaderSize;
402     }
403 
404     /* ------------------------------------------------------------ */
405     /** Set the header field cache size.
406      * @param headerCacheSize The size in bytes of the header field cache.
407      */
408     public void setHeaderCacheSize(int headerCacheSize)
409     {
410         _headerCacheSize = headerCacheSize;
411     }
412 
413     /* ------------------------------------------------------------ */
414     /** Set the TCP/IP port used for CONFIDENTIAL and INTEGRAL redirections.
415      * @param securePort the secure port to redirect to.
416      */
417     public void setSecurePort(int securePort)
418     {
419         _securePort = securePort;
420     }
421 
422     /* ------------------------------------------------------------ */
423     /** Set the  URI scheme used for CONFIDENTIAL and INTEGRAL redirections.
424      * @param secureScheme A scheme string like "https"
425      */
426     public void setSecureScheme(String secureScheme)
427     {
428         _secureScheme = secureScheme;
429     }
430 
431     /* ------------------------------------------------------------ */
432     @Override
433     public String toString()
434     {
435         return String.format("%s@%x{%d/%d,%d/%d,%s://:%d,%s}",
436                 this.getClass().getSimpleName(),
437                 hashCode(),
438                 _outputBufferSize, _outputAggregationSize,
439                 _requestHeaderSize,_responseHeaderSize,
440                 _secureScheme,_securePort,
441                 _customizers);
442     }
443 
444     /* ------------------------------------------------------------ */
445     /** Set the form encoded methods.
446      * @param methods HTTP Methods of requests that can be decoded as 
447      * x-www-form-urlencoded content to be made available via the 
448      * {@link Request#getParameter(String)} and associated APIs 
449      */
450     public void setFormEncodedMethods(String... methods)
451     {
452         _formEncodedMethods.clear();
453         for (String method:methods)
454             addFormEncodedMethod(method);
455     }
456     
457     /* ------------------------------------------------------------ */
458     /**
459      * @return Set of HTTP Methods of requests that can be decoded as 
460      * x-www-form-urlencoded content to be made available via the 
461      * {@link Request#getParameter(String)} and associated APIs
462      */
463     public Set<String> getFormEncodedMethods()
464     {
465         return _formEncodedMethods.keySet();
466     }
467 
468     /* ------------------------------------------------------------ */
469     /** Add a form encoded HTTP Method 
470      * @param method HTTP Method of requests that can be decoded as 
471      * x-www-form-urlencoded content to be made available via the 
472      * {@link Request#getParameter(String)} and associated APIs
473      */
474     public void addFormEncodedMethod(String method)
475     {
476         _formEncodedMethods.put(method,Boolean.TRUE);
477     }
478     
479     /* ------------------------------------------------------------ */
480     /**
481      * Test if the method type supports <code>x-www-form-urlencoded</code> content
482      * 
483      * @param method the method type
484      * @return True of the requests of this method type can be
485      * decoded as <code>x-www-form-urlencoded</code> content to be made available via the 
486      * {@link Request#getParameter(String)} and associated APIs
487      */
488     public boolean isFormEncodedMethod(String method)
489     {
490         return Boolean.TRUE.equals(_formEncodedMethods.get(method));
491     }
492 
493     /* ------------------------------------------------------------ */
494     /**
495      * @return The maximum error dispatches for a request to prevent looping on an error
496      */
497     @ManagedAttribute("The maximum ERROR dispatches for a request for loop prevention (default 10)")
498     public int getMaxErrorDispatches()
499     {
500         return _maxErrorDispatches;
501     }
502 
503     /* ------------------------------------------------------------ */
504     /**
505      * @param max The maximum error dispatches for a request to prevent looping on an error
506      */
507     public void setMaxErrorDispatches(int max)
508     {
509         _maxErrorDispatches=max;
510     }
511 
512     /* ------------------------------------------------------------ */
513     /**
514      * @return The minimum request data rate in bytes per second; or &lt;=0 for no limit
515      */
516     @ManagedAttribute("The minimum request content data rate in bytes per second")
517     public long getMinRequestDataRate()
518     {
519         return _minRequestDataRate;
520     }
521 
522     /* ------------------------------------------------------------ */
523     /**
524      * @param bytesPerSecond The minimum request data rate in bytes per second; or &lt;=0 for no limit
525      */
526     public void setMinRequestDataRate(long bytesPerSecond)
527     {
528         _minRequestDataRate=bytesPerSecond;
529     }
530 }