View Javadoc

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