View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2012 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.util.List;
22  
23  import org.eclipse.jetty.client.api.Request;
24  import org.eclipse.jetty.client.api.Response;
25  import org.eclipse.jetty.client.api.Result;
26  import org.eclipse.jetty.client.util.BufferingResponseListener;
27  import org.eclipse.jetty.http.HttpHeader;
28  import org.eclipse.jetty.http.HttpHeaderValue;
29  
30  public class ContinueProtocolHandler implements ProtocolHandler
31  {
32      private static final String ATTRIBUTE = ContinueProtocolHandler.class.getName() + ".100continue";
33  
34      private final HttpClient client;
35      private final ResponseNotifier notifier;
36  
37      public ContinueProtocolHandler(HttpClient client)
38      {
39          this.client = client;
40          this.notifier = new ResponseNotifier(client);
41      }
42  
43      @Override
44      public boolean accept(Request request, Response response)
45      {
46          boolean expect100 = request.getHeaders().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
47          HttpConversation conversation = client.getConversation(request.getConversationID(), false);
48          boolean handled100 = conversation != null && conversation.getAttribute(ATTRIBUTE) != null;
49          return expect100 && !handled100;
50      }
51  
52      @Override
53      public Response.Listener getResponseListener()
54      {
55          // Return new instances every time to keep track of the response content
56          return new ContinueListener();
57      }
58  
59      private class ContinueListener extends BufferingResponseListener
60      {
61          @Override
62          public void onSuccess(Response response)
63          {
64              // Handling of success must be done here and not from onComplete(),
65              // since the onComplete() is not invoked because the request is not completed yet.
66  
67              HttpConversation conversation = client.getConversation(response.getConversationID(), false);
68              // Mark the 100 Continue response as handled
69              conversation.setAttribute(ATTRIBUTE, Boolean.TRUE);
70  
71              HttpExchange exchange = conversation.getExchanges().peekLast();
72              assert exchange.getResponse() == response;
73              List<Response.ResponseListener> listeners = exchange.getResponseListeners();
74              switch (response.getStatus())
75              {
76                  case 100:
77                  {
78                      // All good, continue
79                      exchange.resetResponse(true);
80                      conversation.setResponseListeners(listeners);
81                      exchange.proceed(true);
82                      break;
83                  }
84                  default:
85                  {
86                      // Server either does not support 100 Continue, or it does and wants to refuse the request content
87                      HttpContentResponse contentResponse = new HttpContentResponse(response, getContent(), getEncoding());
88                      notifier.forwardSuccess(listeners, contentResponse);
89                      conversation.setResponseListeners(listeners);
90                      exchange.proceed(false);
91                      break;
92                  }
93              }
94          }
95  
96          @Override
97          public void onFailure(Response response, Throwable failure)
98          {
99              HttpConversation conversation = client.getConversation(response.getConversationID(), false);
100             // Mark the 100 Continue response as handled
101             conversation.setAttribute(ATTRIBUTE, Boolean.TRUE);
102 
103             HttpExchange exchange = conversation.getExchanges().peekLast();
104             assert exchange.getResponse() == response;
105             List<Response.ResponseListener> listeners = exchange.getResponseListeners();
106             HttpContentResponse contentResponse = new HttpContentResponse(response, getContent(), getEncoding());
107             notifier.forwardFailureComplete(listeners, exchange.getRequest(), exchange.getRequestFailure(), contentResponse, failure);
108         }
109 
110         @Override
111         public void onComplete(Result result)
112         {
113         }
114     }
115 }