View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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.concurrent.CopyOnWriteArrayList;
24  
25  import org.eclipse.jetty.http.HttpScheme;
26  import org.eclipse.jetty.util.Jetty;
27  import org.eclipse.jetty.util.annotation.ManagedAttribute;
28  import org.eclipse.jetty.util.annotation.ManagedObject;
29  
30  
31  /* ------------------------------------------------------------ */
32  /** HTTP Configuration.
33   * <p>This class is a holder of HTTP configuration for use by the 
34   * {@link HttpChannel} class.  Typically a HTTPConfiguration instance
35   * is instantiated and passed to a {@link ConnectionFactory} that can 
36   * create HTTP channels (e.g. HTTP, AJP or FCGI).</p>
37   * <p>The configuration held by this class is not for the wire protocol,
38   * but for the interpretation and handling of HTTP requests that could
39   * be transported by a variety of protocols.
40   * </p>
41   */
42  @ManagedObject("HTTP Configuration")
43  public class HttpConfiguration
44  {
45      public static final String SERVER_VERSION = "Jetty(" + Jetty.VERSION + ")";
46  
47      private List<Customizer> _customizers=new CopyOnWriteArrayList<>();
48      private int _outputBufferSize=32*1024;
49      private int _outputAggregationSize=_outputBufferSize/4;
50      private int _requestHeaderSize=8*1024;
51      private int _responseHeaderSize=8*1024;
52      private int _headerCacheSize=512;
53      private int _securePort;
54      private String _secureScheme = HttpScheme.HTTPS.asString();
55      private boolean _sendServerVersion = true;
56      private boolean _sendXPoweredBy = false;
57      private boolean _sendDateHeader = true;
58      private boolean _delayDispatchUntilContent = true;
59      private boolean _persistentConnectionsEnabled = true;
60  
61      /* ------------------------------------------------------------ */
62      /** 
63       * <p>An interface that allows a request object to be customized 
64       * for a particular HTTP connector configuration.  Unlike Filters, customizer are
65       * applied before the request is submitted for processing and can be specific to the 
66       * connector on which the request was received.
67       * 
68       * <p>Typically Customizers perform tasks such as: <ul>
69       *  <li>process header fields that may be injected by a proxy or load balancer.
70       *  <li>setup attributes that may come from the connection/connector such as SSL Session IDs
71       *  <li>Allow a request to be marked as secure or authenticated if those have been offloaded
72       *  and communicated by header, cookie or other out-of-band mechanism
73       *  <li>Set request attributes/fields that are determined by the connector on which the
74       *  request was received
75       *  </ul>
76       */
77      public interface Customizer
78      {
79          public void customize(Connector connector, HttpConfiguration channelConfig, Request request);
80      }
81      
82      public interface ConnectionFactory
83      {
84          HttpConfiguration getHttpConfiguration();
85      }
86      
87      public HttpConfiguration()
88      {
89      }
90      
91      /* ------------------------------------------------------------ */
92      /** Create a configuration from another.
93       * @param config The configuration to copy.
94       */
95      public HttpConfiguration(HttpConfiguration config)
96      {
97          _customizers.addAll(config._customizers);
98          _outputBufferSize=config._outputBufferSize;
99          _outputAggregationSize=config._outputAggregationSize;
100         _requestHeaderSize=config._requestHeaderSize;
101         _responseHeaderSize=config._responseHeaderSize;
102         _securePort=config._securePort;
103         _secureScheme=config._secureScheme;
104         _sendDateHeader=config._sendDateHeader;
105         _sendServerVersion=config._sendServerVersion;
106         _headerCacheSize=config._headerCacheSize;
107     }
108     
109     /* ------------------------------------------------------------ */
110     /** 
111      * <p>Add a {@link Customizer} that is invoked for every 
112      * request received.</p>
113      * <p>Customiser are often used to interpret optional headers (eg {@link ForwardedRequestCustomizer}) or 
114      * optional protocol semantics (eg {@link SecureRequestCustomizer}). 
115      * @param customizer A request customizer
116      */
117     public void addCustomizer(Customizer customizer)
118     {
119         _customizers.add(customizer);
120     }
121     
122     /* ------------------------------------------------------------ */
123     public List<Customizer> getCustomizers()
124     {
125         return _customizers;
126     }
127 
128     /* ------------------------------------------------------------ */
129     public <T> T getCustomizer(Class<T> type)
130     {
131         for (Customizer c : _customizers)
132             if (type.isAssignableFrom(c.getClass()))
133                 return (T)c;
134         return null;
135     }
136 
137     /* ------------------------------------------------------------ */
138     @ManagedAttribute("The size in bytes of the output buffer used to aggregate HTTP output")
139     public int getOutputBufferSize()
140     {
141         return _outputBufferSize;
142     }
143 
144     /* ------------------------------------------------------------ */
145     @ManagedAttribute("The maximum size in bytes for HTTP output to be aggregated")
146     public int getOutputAggregationSize()
147     {
148         return _outputAggregationSize;
149     }
150 
151     /* ------------------------------------------------------------ */
152     @ManagedAttribute("The maximum allowed size in bytes for a HTTP request header")
153     public int getRequestHeaderSize()
154     {
155         return _requestHeaderSize;
156     }
157 
158     /* ------------------------------------------------------------ */
159     @ManagedAttribute("The maximum allowed size in bytes for a HTTP response header")
160     public int getResponseHeaderSize()
161     {
162         return _responseHeaderSize;
163     }
164 
165     /* ------------------------------------------------------------ */
166     @ManagedAttribute("The maximum allowed size in bytes for a HTTP header field cache")
167     public int getHeaderCacheSize()
168     {
169         return _headerCacheSize;
170     }
171 
172     /* ------------------------------------------------------------ */
173     @ManagedAttribute("The port to which Integral or Confidential security constraints are redirected")
174     public int getSecurePort()
175     {
176         return _securePort;
177     }
178 
179     /* ------------------------------------------------------------ */
180     @ManagedAttribute("The scheme with which Integral or Confidential security constraints are redirected")
181     public String getSecureScheme()
182     {
183         return _secureScheme;
184     }
185 
186     /* ------------------------------------------------------------ */
187     @ManagedAttribute("True if HTTP/1 persistent connection are enabled")
188     public boolean isPersistentConnectionsEnabled()
189     {
190         return _persistentConnectionsEnabled;
191     }
192 
193     /* ------------------------------------------------------------ */
194     public void setPersistentConnectionsEnabled(boolean persistentConnectionsEnabled)
195     {
196         _persistentConnectionsEnabled = persistentConnectionsEnabled;
197     }
198 
199     /* ------------------------------------------------------------ */
200     public void setSendServerVersion (boolean sendServerVersion)
201     {
202         _sendServerVersion = sendServerVersion;
203     }
204 
205     /* ------------------------------------------------------------ */
206     @ManagedAttribute("if true, send the Server header in responses")
207     public boolean getSendServerVersion()
208     {
209         return _sendServerVersion;
210     }
211 
212     /* ------------------------------------------------------------ */
213     public void writePoweredBy(Appendable out,String preamble,String postamble) throws IOException
214     {
215         if (getSendServerVersion())
216         {
217             if (preamble!=null)
218                 out.append(preamble);
219             out.append(Jetty.POWERED_BY);
220             if (postamble!=null)
221                 out.append(postamble);
222         }
223     }
224     
225     /* ------------------------------------------------------------ */
226     public void setSendXPoweredBy (boolean sendXPoweredBy)
227     {
228         _sendXPoweredBy=sendXPoweredBy;
229     }
230 
231     /* ------------------------------------------------------------ */
232     @ManagedAttribute("if true, send the X-Powered-By header in responses")
233     public boolean getSendXPoweredBy()
234     {
235         return _sendXPoweredBy;
236     }
237 
238     /* ------------------------------------------------------------ */
239     public void setSendDateHeader(boolean sendDateHeader)
240     {
241         _sendDateHeader = sendDateHeader;
242     }
243 
244     /* ------------------------------------------------------------ */
245     @ManagedAttribute("if true, include the date in HTTP headers")
246     public boolean getSendDateHeader()
247     {
248         return _sendDateHeader;
249     }
250 
251     /* ------------------------------------------------------------ */
252     /**
253      * @param delay if true, delay the application dispatch until content is available (default false)
254      */
255     public void setDelayDispatchUntilContent(boolean delay)
256     {
257         _delayDispatchUntilContent = delay;
258     }
259 
260     /* ------------------------------------------------------------ */
261     @ManagedAttribute("if true, delay the application dispatch until content is available")
262     public boolean isDelayDispatchUntilContent()
263     {
264         return _delayDispatchUntilContent;
265     }
266 
267     /* ------------------------------------------------------------ */
268     /**
269      * <p>Set the {@link Customizer}s that are invoked for every 
270      * request received.</p>
271      * <p>Customizers are often used to interpret optional headers (eg {@link ForwardedRequestCustomizer}) or
272      * optional protocol semantics (eg {@link SecureRequestCustomizer}). 
273      * @param customizers the list of customizers
274      */
275     public void setCustomizers(List<Customizer> customizers)
276     {
277         _customizers.clear();
278         _customizers.addAll(customizers);
279     }
280 
281     /* ------------------------------------------------------------ */
282     /**
283      * Set the size of the buffer into which response content is aggregated
284      * before being sent to the client.  A larger buffer can improve performance by allowing
285      * a content producer to run without blocking, however larger buffers consume more memory and
286      * may induce some latency before a client starts processing the content.
287      * @param outputBufferSize buffer size in bytes.
288      */
289     public void setOutputBufferSize(int outputBufferSize)
290     {
291         _outputBufferSize = outputBufferSize;
292         setOutputAggregationSize(outputBufferSize / 4);
293     }
294     
295     /* ------------------------------------------------------------ */
296     /**
297      * Set the max size of the response content write that is copied into the aggregate buffer.
298      * Writes that are smaller of this size are copied into the aggregate buffer, while
299      * writes that are larger of this size will cause the aggregate buffer to be flushed
300      * and the write to be executed without being copied.
301      * @param outputAggregationSize the max write size that is aggregated
302      */
303     public void setOutputAggregationSize(int outputAggregationSize)
304     {
305         _outputAggregationSize = outputAggregationSize;
306     }
307 
308     /* ------------------------------------------------------------ */
309     /** Set the maximum size of a request header.
310      * <p>Larger headers will allow for more and/or larger cookies plus larger form content encoded 
311      * in a URL. However, larger headers consume more memory and can make a server more vulnerable to denial of service
312      * attacks.</p>
313      * @param requestHeaderSize Max header size in bytes
314      */
315     public void setRequestHeaderSize(int requestHeaderSize)
316     {
317         _requestHeaderSize = requestHeaderSize;
318     }
319 
320     /* ------------------------------------------------------------ */
321     /** Set the maximum size of a response header.
322      * 
323      * <p>Larger headers will allow for more and/or larger cookies and longer HTTP headers (eg for redirection). 
324      * However, larger headers will also consume more memory.</p>
325      * @param responseHeaderSize Response header size in bytes.
326      */
327     public void setResponseHeaderSize(int responseHeaderSize)
328     {
329         _responseHeaderSize = responseHeaderSize;
330     }
331 
332     /* ------------------------------------------------------------ */
333     /** Set the header field cache size.
334      * @param headerCacheSize The size in bytes of the header field cache.
335      */
336     public void setHeaderCacheSize(int headerCacheSize)
337     {
338         _headerCacheSize = headerCacheSize;
339     }
340 
341     /* ------------------------------------------------------------ */
342     /** Set the TCP/IP port used for CONFIDENTIAL and INTEGRAL redirections.
343      * @param securePort the secure port to redirect to.
344      */
345     public void setSecurePort(int securePort)
346     {
347         _securePort = securePort;
348     }
349 
350     /* ------------------------------------------------------------ */
351     /** Set the  URI scheme used for CONFIDENTIAL and INTEGRAL redirections.
352      * @param secureScheme A scheme string like "https"
353      */
354     public void setSecureScheme(String secureScheme)
355     {
356         _secureScheme = secureScheme;
357     }
358 
359     @Override
360     public String toString()
361     {
362         return String.format("%s@%x{%d/%d,%d/%d,%s://:%d,%s}",
363                 this.getClass().getSimpleName(),
364                 hashCode(),
365                 _outputBufferSize, _outputAggregationSize,
366                 _requestHeaderSize,_responseHeaderSize,
367                 _secureScheme,_securePort,
368                 _customizers);
369     }
370 }