View Javadoc

1   // ========================================================================
2   // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses.
12  // ========================================================================
13  
14  package org.eclipse.jetty.client;
15  
16  import java.io.IOException;
17  
18  import org.eclipse.jetty.http.HttpHeaders;
19  import org.eclipse.jetty.http.HttpSchemes;
20  import org.eclipse.jetty.http.HttpStatus;
21  import org.eclipse.jetty.io.Buffer;
22  
23  /**
24   * RedirectListener
25   *
26   * Detect and handle the redirect responses
27   */
28  public class RedirectListener extends HttpEventListenerWrapper
29  {
30      private final HttpExchange _exchange;
31      private HttpDestination _destination;
32      private String _location;
33      private int _attempts;
34      private boolean _requestComplete;
35      private boolean _responseComplete;
36      private boolean _redirected;
37  
38      public RedirectListener(HttpDestination destination, HttpExchange ex)
39      {
40          // Start of sending events through to the wrapped listener
41          // Next decision point is the onResponseStatus
42          super(ex.getEventListener(),true);
43  
44          _destination = destination;
45          _exchange = ex;
46      }
47  
48      @Override
49      public void onResponseStatus( Buffer version, int status, Buffer reason )
50          throws IOException
51      {
52          _redirected = ((status == HttpStatus.MOVED_PERMANENTLY_301 ||
53                          status == HttpStatus.MOVED_TEMPORARILY_302) &&
54                         _attempts < _destination.getHttpClient().maxRedirects());
55  
56          if (_redirected)
57          {
58              setDelegatingRequests(false);
59              setDelegatingResponses(false);
60          }
61  
62          super.onResponseStatus(version,status,reason);
63      }
64  
65  
66      @Override
67      public void onResponseHeader( Buffer name, Buffer value )
68          throws IOException
69      {
70          if (_redirected)
71          {
72              int header = HttpHeaders.CACHE.getOrdinal(name);
73              switch (header)
74              {
75                  case HttpHeaders.LOCATION_ORDINAL:
76                      _location = value.toString();
77                      break;
78              }
79          }
80          super.onResponseHeader(name,value);
81      }
82  
83      @Override
84      public void onRequestComplete() throws IOException
85      {
86          _requestComplete = true;
87  
88          if (checkExchangeComplete())
89          {
90              super.onRequestComplete();
91          }
92      }
93  
94      @Override
95      public void onResponseComplete() throws IOException
96      {
97          _responseComplete = true;
98  
99          if (checkExchangeComplete())
100         {
101             super.onResponseComplete();
102         }
103     }
104 
105     public boolean checkExchangeComplete()
106         throws IOException
107     {
108         if (_redirected && _requestComplete && _responseComplete)
109         {
110             if (_location != null)
111             {
112                 if (_location.indexOf("://")>0)
113                 {
114                     _exchange.setURL(_location);
115                 }
116                 else
117                 {
118                     _exchange.setRequestURI(_location);
119                 }
120 
121                 // destination may have changed
122                 boolean isHttps = HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme()));
123                 HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps);
124 
125                 if (_destination==destination)
126                 {
127                     _destination.resend(_exchange);
128                 }
129                 else
130                 {
131                     // unwrap to find ultimate listener.
132                     HttpEventListener listener=this;
133                     while(listener instanceof HttpEventListenerWrapper)
134                     {
135                         listener=((HttpEventListenerWrapper)listener).getEventListener();
136                     }
137                     
138                     //reset the listener
139                     _exchange.getEventListener().onRetry();
140                     _exchange.reset();
141                     _exchange.setEventListener(listener);
142 
143                     // Set the new Host header
144                     Address address = _exchange.getAddress();
145                     int port = address.getPort();
146                     StringBuilder hostHeader = new StringBuilder( 64 );
147                     hostHeader.append( address.getHost() );
148                     if( !( ( port == 80 && !isHttps ) || ( port == 443 && isHttps ) ) ) 
149                     {
150                         hostHeader.append( ':' );
151                         hostHeader.append( port );
152                     }
153                     
154                     _exchange.setRequestHeader( HttpHeaders.HOST, hostHeader.toString() );
155 
156                     destination.send(_exchange);
157                 }
158 
159                 return false;
160             }
161             else
162             {
163                 setDelegationResult(false);
164             }
165         }
166 
167         return true;
168     }
169 
170     public void onRetry()
171     {
172         _redirected=false;
173         _attempts++;
174 
175         setDelegatingRequests(true);
176         setDelegatingResponses(true);
177 
178         _requestComplete=false;
179         _responseComplete=false;
180 
181         super.onRetry();
182     }
183 
184     /**
185      * Delegate failed connection
186      */
187     @Override
188     public void onConnectionFailed( Throwable ex )
189     {
190         setDelegatingRequests(true);
191         setDelegatingResponses(true);
192 
193         super.onConnectionFailed( ex );
194     }
195 
196     /**
197      * Delegate onException
198      */
199     @Override
200     public void onException( Throwable ex )
201     {
202         setDelegatingRequests(true);
203         setDelegatingResponses(true);
204 
205         super.onException( ex );
206     }
207 }