View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.http;
20  
21  import org.eclipse.jetty.client.HttpChannel;
22  import org.eclipse.jetty.client.HttpExchange;
23  import org.eclipse.jetty.client.HttpReceiver;
24  import org.eclipse.jetty.client.HttpSender;
25  import org.eclipse.jetty.client.api.Response;
26  import org.eclipse.jetty.client.api.Result;
27  import org.eclipse.jetty.http.HttpFields;
28  import org.eclipse.jetty.http.HttpHeader;
29  import org.eclipse.jetty.http.HttpHeaderValue;
30  import org.eclipse.jetty.http.HttpMethod;
31  import org.eclipse.jetty.http.HttpVersion;
32  
33  public class HttpChannelOverHTTP extends HttpChannel
34  {
35      private final HttpConnectionOverHTTP connection;
36      private final HttpSenderOverHTTP sender;
37      private final HttpReceiverOverHTTP receiver;
38  
39      public HttpChannelOverHTTP(HttpConnectionOverHTTP connection)
40      {
41          super(connection.getHttpDestination());
42          this.connection = connection;
43          this.sender = newHttpSender();
44          this.receiver = newHttpReceiver();
45      }
46  
47      protected HttpSenderOverHTTP newHttpSender()
48      {
49          return new HttpSenderOverHTTP(this);
50      }
51  
52      protected HttpReceiverOverHTTP newHttpReceiver()
53      {
54          return new HttpReceiverOverHTTP(this);
55      }
56  
57      @Override
58      protected HttpSender getHttpSender()
59      {
60          return sender;
61      }
62  
63      @Override
64      protected HttpReceiver getHttpReceiver()
65      {
66          return receiver;
67      }
68  
69      public HttpConnectionOverHTTP getHttpConnection()
70      {
71          return connection;
72      }
73  
74      @Override
75      public void send()
76      {
77          HttpExchange exchange = getHttpExchange();
78          if (exchange != null)
79              sender.send(exchange);
80      }
81  
82      @Override
83      public void release()
84      {
85          connection.release();
86      }
87  
88      public void receive()
89      {
90          receiver.receive();
91      }
92  
93      @Override
94      public void exchangeTerminated(HttpExchange exchange, Result result)
95      {
96          super.exchangeTerminated(exchange, result);
97  
98          Response response = result.getResponse();
99          HttpFields responseHeaders = response.getHeaders();
100 
101         String closeReason = null;
102         if (result.isFailed())
103             closeReason = "failure";
104         else if (receiver.isShutdown())
105             closeReason = "server close";
106 
107         if (closeReason == null)
108         {
109             if (response.getVersion().compareTo(HttpVersion.HTTP_1_1) < 0)
110             {
111                 // HTTP 1.0 must close the connection unless it has
112                 // an explicit keep alive or it's a CONNECT method.
113                 boolean keepAlive = responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString());
114                 boolean connect = HttpMethod.CONNECT.is(exchange.getRequest().getMethod());
115                 if (!keepAlive && !connect)
116                     closeReason = "http/1.0";
117             }
118             else
119             {
120                 // HTTP 1.1 or greater closes only if it has an explicit close.
121                 if (responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()))
122                     closeReason = "http/1.1";
123             }
124         }
125 
126         if (closeReason != null)
127         {
128             if (LOG.isDebugEnabled())
129                 LOG.debug("Closing, reason: {} - {}", closeReason, connection);
130             connection.close();
131         }
132         else
133         {
134             release();
135         }
136     }
137 
138     @Override
139     public String toString()
140     {
141         return String.format("%s[send=%s,recv=%s]",
142                 super.toString(),
143                 sender,
144                 receiver);
145     }
146 }