View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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.net.CookieStore;
22  import java.net.HttpCookie;
23  import java.net.URI;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.eclipse.jetty.client.api.Authentication;
28  import org.eclipse.jetty.client.api.Connection;
29  import org.eclipse.jetty.client.api.ContentProvider;
30  import org.eclipse.jetty.client.api.Request;
31  import org.eclipse.jetty.client.api.Response;
32  import org.eclipse.jetty.http.HttpField;
33  import org.eclipse.jetty.http.HttpFields;
34  import org.eclipse.jetty.http.HttpHeader;
35  import org.eclipse.jetty.http.HttpHeaderValue;
36  import org.eclipse.jetty.http.HttpMethod;
37  import org.eclipse.jetty.http.HttpVersion;
38  
39  public abstract class HttpConnection implements Connection
40  {
41      private static final HttpField CHUNKED_FIELD = new HttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED);
42  
43      private final HttpDestination destination;
44  
45      protected HttpConnection(HttpDestination destination)
46      {
47          this.destination = destination;
48      }
49  
50      public HttpClient getHttpClient()
51      {
52          return destination.getHttpClient();
53      }
54  
55      public HttpDestination getHttpDestination()
56      {
57          return destination;
58      }
59  
60      @Override
61      public void send(Request request, Response.CompleteListener listener)
62      {
63          ArrayList<Response.ResponseListener> listeners = new ArrayList<>(2);
64          if (request.getTimeout() > 0)
65          {
66              TimeoutCompleteListener timeoutListener = new TimeoutCompleteListener(request);
67              timeoutListener.schedule(getHttpClient().getScheduler());
68              listeners.add(timeoutListener);
69          }
70          if (listener != null)
71              listeners.add(listener);
72  
73          HttpExchange exchange = new HttpExchange(getHttpDestination(), (HttpRequest)request, listeners);
74  
75          send(exchange);
76      }
77  
78      protected abstract void send(HttpExchange exchange);
79  
80      protected void normalizeRequest(Request request)
81      {
82          String method = request.getMethod();
83          HttpVersion version = request.getVersion();
84          HttpFields headers = request.getHeaders();
85          ContentProvider content = request.getContent();
86          ProxyConfiguration.Proxy proxy = destination.getProxy();
87  
88          // Make sure the path is there
89          String path = request.getPath();
90          if (path.trim().length() == 0)
91          {
92              path = "/";
93              request.path(path);
94          }
95          if (proxy != null && !HttpMethod.CONNECT.is(method))
96          {
97              path = request.getURI().toString();
98              request.path(path);
99          }
100 
101         // If we are HTTP 1.1, add the Host header
102         if (version.getVersion() > 10)
103         {
104             if (!headers.containsKey(HttpHeader.HOST.asString()))
105                 headers.put(getHttpDestination().getHostField());
106         }
107 
108         // Add content headers
109         if (content != null)
110         {
111             if (content instanceof ContentProvider.Typed)
112             {
113                 if (!headers.containsKey(HttpHeader.CONTENT_TYPE.asString()))
114                 {
115                     String contentType = ((ContentProvider.Typed)content).getContentType();
116                     if (contentType != null)
117                         headers.put(HttpHeader.CONTENT_TYPE, contentType);
118                 }
119             }
120             long contentLength = content.getLength();
121             if (contentLength >= 0)
122             {
123                 if (!headers.containsKey(HttpHeader.CONTENT_LENGTH.asString()))
124                     headers.put(HttpHeader.CONTENT_LENGTH, String.valueOf(contentLength));
125             }
126             else
127             {
128                 if (!headers.containsKey(HttpHeader.TRANSFER_ENCODING.asString()))
129                     headers.put(CHUNKED_FIELD);
130             }
131         }
132 
133         // Cookies
134         CookieStore cookieStore = getHttpClient().getCookieStore();
135         if (cookieStore != null)
136         {
137             URI uri = request.getURI();
138             StringBuilder cookies = null;
139             if (uri != null)
140                 cookies = convertCookies(cookieStore.get(uri), null);
141             cookies = convertCookies(request.getCookies(), cookies);
142             if (cookies != null)
143                 request.header(HttpHeader.COOKIE.asString(), cookies.toString());
144         }
145 
146         // Authorization
147         URI authenticationURI = proxy != null ? proxy.getURI() : request.getURI();
148         if (authenticationURI != null)
149         {
150             Authentication.Result authnResult = getHttpClient().getAuthenticationStore().findAuthenticationResult(authenticationURI);
151             if (authnResult != null)
152                 authnResult.apply(request);
153         }
154     }
155 
156     private StringBuilder convertCookies(List<HttpCookie> cookies, StringBuilder builder)
157     {
158         for (int i = 0; i < cookies.size(); ++i)
159         {
160             if (builder == null)
161                 builder = new StringBuilder();
162             if (builder.length() > 0)
163                 builder.append("; ");
164             HttpCookie cookie = cookies.get(i);
165             builder.append(cookie.getName()).append("=").append(cookie.getValue());
166         }
167         return builder;
168     }
169 
170     @Override
171     public String toString()
172     {
173         return String.format("%s@%h", getClass().getSimpleName(), this);
174     }
175 }