View Javadoc

1   /*
2    *  Copyright 2007 rafale.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *  under the License.
16   */
17  package org.apache.maven.archetype.proxy;
18  
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.io.PrintWriter;
24  import java.net.HttpURLConnection;
25  import java.net.InetSocketAddress;
26  import java.net.Socket;
27  import java.net.URL;
28  import java.net.URLConnection;
29  import java.util.Enumeration;
30  import java.util.HashSet;
31  import javax.servlet.ServletConfig;
32  import javax.servlet.ServletContext;
33  import javax.servlet.ServletException;
34  import javax.servlet.ServletRequest;
35  import javax.servlet.ServletResponse;
36  import javax.servlet.http.HttpServlet;
37  import javax.servlet.http.HttpServletRequest;
38  import javax.servlet.http.HttpServletResponse;
39  import org.mortbay.util.IO;
40  
41  /**
42   * Stolen code from Mortbay
43   *
44   * @author rafale
45   */
46  public class ProxyServlet
47      extends HttpServlet
48  {
49      protected HashSet _DontProxyHeaders = new HashSet();
50  
51      {
52          _DontProxyHeaders.add( "proxy-connection" );
53          _DontProxyHeaders.add( "connection" );
54          _DontProxyHeaders.add( "keep-alive" );
55          _DontProxyHeaders.add( "transfer-encoding" );
56          _DontProxyHeaders.add( "te" );
57          _DontProxyHeaders.add( "trailer" );
58          _DontProxyHeaders.add( "proxy-authorization" );
59          _DontProxyHeaders.add( "proxy-authenticate" );
60          _DontProxyHeaders.add( "upgrade" );
61      }
62  
63      private ServletConfig config;
64  
65      private ServletContext context;
66  
67      /* (non-Javadoc)
68       * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
69       */
70      public void init( ServletConfig config )
71          throws ServletException
72      {
73          this.config = config;
74          this.context = config.getServletContext();
75      }
76  
77      /* (non-Javadoc)
78       * @see javax.servlet.Servlet#getServletConfig()
79       */
80      public ServletConfig getServletConfig()
81      {
82          return config;
83      }
84  
85      /* (non-Javadoc)
86       * @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
87       */
88      public void service( ServletRequest req, ServletResponse res )
89          throws ServletException,
90                 IOException
91      {
92          HttpServletRequest request = (HttpServletRequest) req;
93          HttpServletResponse response = (HttpServletResponse) res;
94          if ( "CONNECT".equalsIgnoreCase( request.getMethod() ) )
95          {
96              handleConnect( request, response );
97          }
98          else
99          {
100             String uri = request.getRequestURI();
101             if ( request.getQueryString() != null )
102             {
103                 uri += "?" + request.getQueryString();
104             }
105             URL url =
106                 new URL( request.getScheme(), request.getServerName(),
107                 request.getServerPort(),
108                 uri );
109 
110             context.log( "\n\n\nURL=" + url );
111 
112             URLConnection connection = url.openConnection();
113             connection.setAllowUserInteraction( false );
114 
115             // Set method
116             HttpURLConnection http = null;
117             if ( connection instanceof HttpURLConnection )
118             {
119                 http = (HttpURLConnection) connection;
120                 http.setRequestMethod( request.getMethod() );
121                 http.setInstanceFollowRedirects( false );
122             }
123 
124             // check connection header
125             String connectionHdr = request.getHeader( "Connection" );
126             if ( connectionHdr != null )
127             {
128                 connectionHdr = connectionHdr.toLowerCase();
129                 if ( connectionHdr.equals( "keep-alive" ) || connectionHdr.equals( "close" ) )
130                 {
131                     connectionHdr = null;
132                 }
133             }
134 
135             // copy headers
136             boolean xForwardedFor = false;
137             boolean hasContent = false;
138             Enumeration enm = request.getHeaderNames();
139             while ( enm.hasMoreElements() )
140             {
141                 // TODO could be better than this!
142                 String hdr = (String) enm.nextElement();
143                 String lhdr = hdr.toLowerCase();
144 
145                 if ( _DontProxyHeaders.contains( lhdr ) )
146                 {
147                     continue;
148                 }
149                 if ( connectionHdr != null && connectionHdr.indexOf( lhdr ) >= 0 )
150                 {
151                     continue;
152                 }
153                 if ( "content-type".equals( lhdr ) )
154                 {
155                     hasContent = true;
156                 }
157                 Enumeration vals = request.getHeaders( hdr );
158                 while ( vals.hasMoreElements() )
159                 {
160                     String val = (String) vals.nextElement();
161                     if ( val != null )
162                     {
163                         connection.addRequestProperty( hdr, val );
164                         context.log( "req " + hdr + ": " + val );
165                         xForwardedFor |= "X-Forwarded-For".equalsIgnoreCase( hdr );
166                     }
167                 }
168             }
169 
170             // Proxy headers
171             connection.setRequestProperty( "Via", "1.1 (jetty)" );
172             if ( !xForwardedFor )
173             {
174                 connection.addRequestProperty( "X-Forwarded-For", request.getRemoteAddr() );
175             }
176             // a little bit of cache control
177             String cache_control = request.getHeader( "Cache-Control" );
178             if ( cache_control != null &&
179                 (cache_control.indexOf( "no-cache" ) >= 0 || cache_control.indexOf( "no-store" ) >= 0) )
180             {
181                 connection.setUseCaches( false );
182 
183             // customize Connection
184             }
185             try
186             {
187                 connection.setDoInput( true );
188 
189                 // do input thang!
190                 InputStream in = request.getInputStream();
191                 if ( hasContent )
192                 {
193                     connection.setDoOutput( true );
194                     IO.copy( in, connection.getOutputStream() );
195                 }
196 
197                 // Connect
198                 connection.connect();
199             }
200             catch ( Exception e )
201             {
202                 context.log( "proxy", e );
203             }
204 
205             InputStream proxy_in = null;
206 
207             // handler status codes etc.
208             int code = 500;
209             if ( http != null )
210             {
211                 proxy_in = http.getErrorStream();
212 
213                 code = http.getResponseCode();
214                 response.setStatus( code, http.getResponseMessage() );
215                 context.log( "response = " + http.getResponseCode() );
216             }
217 
218             if ( proxy_in == null )
219             {
220                 try
221                 {
222                     proxy_in = connection.getInputStream();
223                 }
224                 catch ( Exception e )
225                 {
226                     context.log( "stream", e );
227                     proxy_in = http.getErrorStream();
228                 }
229             }
230 
231             // clear response defaults.
232             response.setHeader( "Date", null );
233             response.setHeader( "Server", null );
234 
235             // set response headers
236             int h = 0;
237             String hdr = connection.getHeaderFieldKey( h );
238             String val = connection.getHeaderField( h );
239             while ( hdr != null || val != null )
240             {
241                 String lhdr = hdr != null ? hdr.toLowerCase() : null;
242                 if ( hdr != null && val != null && !_DontProxyHeaders.contains( lhdr ) )
243                 {
244                     response.addHeader( hdr, val );
245                 }
246                 context.log( "res " + hdr + ": " + val );
247 
248                 h++;
249                 hdr = connection.getHeaderFieldKey( h );
250                 val = connection.getHeaderField( h );
251             }
252             response.addHeader( "Via", "1.1 (jetty)" );
253 
254             // Handle
255             if ( proxy_in != null )
256             {
257                 IO.copy( proxy_in, response.getOutputStream() );
258             }
259         }
260     }
261 
262     /* ------------------------------------------------------------ */
263     public void handleConnect( HttpServletRequest request,
264         HttpServletResponse response )
265         throws IOException
266     {
267         String uri = request.getRequestURI();
268 
269         context.log( "CONNECT: " + uri );
270 
271         String port = "";
272         String host = "";
273 
274         int c = uri.indexOf( ':' );
275         if ( c >= 0 )
276         {
277             port = uri.substring( c + 1 );
278             host = uri.substring( 0, c );
279             if ( host.indexOf( '/' ) > 0 )
280             {
281                 host = host.substring( host.indexOf( '/' ) + 1 );
282             }
283         }
284 
285         InetSocketAddress inetAddress =
286             new InetSocketAddress( host, Integer.parseInt( port ) );
287 
288         InputStream in = request.getInputStream();
289         OutputStream out = response.getOutputStream();
290 
291         Socket socket = new Socket( inetAddress.getAddress(), inetAddress.getPort() );
292         context.log( "Socket: " + socket );
293 
294         response.setStatus( 200 );
295         response.setHeader( "Connection", "close" );
296         response.flushBuffer();
297 
298 
299 
300         context.log( "out<-in" );
301         IO.copyThread( socket.getInputStream(), out );
302         context.log( "in->out" );
303         IO.copy( in, socket.getOutputStream() );
304     }
305 
306     /* (non-Javadoc)
307      * @see javax.servlet.Servlet#getServletInfo()
308      */
309     public String getServletInfo()
310     {
311         return "Proxy Servlet";
312     }
313 
314     /* (non-Javadoc)
315      * @see javax.servlet.Servlet#destroy()
316      */
317     public void destroy()
318     {
319     }
320 
321     /**
322      * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
323      * @param request servlet request
324      * @param response servlet response
325      */
326     protected void processRequest( HttpServletRequest request,
327         HttpServletResponse response )
328         throws ServletException, IOException
329     {
330         response.setContentType( "text/html;charset=UTF-8" );
331         PrintWriter out = response.getWriter();
332         try
333         {
334         /* TODO output your page here
335         out.println("<html>");
336         out.println("<head>");
337         out.println("<title>Servlet ProxyServlet</title>");
338         out.println("</head>");
339         out.println("<body>");
340         out.println("<h1>Servlet ProxyServlet at " + request.getContextPath () + "</h1>");
341         out.println("</body>");
342         out.println("</html>");
343          */
344         }
345         finally
346         {
347             out.close();
348         }
349     }
350 
351 //    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
352 //    /**
353 //     * Handles the HTTP <code>GET</code> method.
354 //     * @param request servlet request
355 //     * @param response servlet response
356 //     */
357 //    protected void doGet( HttpServletRequest request,
358 //        HttpServletResponse response ) throws ServletException, IOException
359 //    {
360 //        processRequest( request, response );
361 //    }
362 //
363 //    /**
364 //     * Handles the HTTP <code>POST</code> method.
365 //     * @param request servlet request
366 //     * @param response servlet response
367 //     */
368 //    protected void doPost( HttpServletRequest request,
369 //        HttpServletResponse response ) throws ServletException, IOException
370 //    {
371 //        processRequest( request, response );
372 //    }
373 //
374 //    /**
375 //     * Returns a short description of the servlet.
376 //     */
377 //    public String getServletInfo( )
378 //    {
379 //        return "Short description";
380 //    }
381 //    // </editor-fold>
382 }