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.http2.client.http;
20  
21  import java.net.URI;
22  
23  import org.eclipse.jetty.client.HttpContent;
24  import org.eclipse.jetty.client.HttpExchange;
25  import org.eclipse.jetty.client.HttpSender;
26  import org.eclipse.jetty.client.api.Request;
27  import org.eclipse.jetty.http.HttpURI;
28  import org.eclipse.jetty.http.HttpVersion;
29  import org.eclipse.jetty.http.MetaData;
30  import org.eclipse.jetty.http2.api.Stream;
31  import org.eclipse.jetty.http2.frames.DataFrame;
32  import org.eclipse.jetty.http2.frames.HeadersFrame;
33  import org.eclipse.jetty.util.Callback;
34  import org.eclipse.jetty.util.Promise;
35  
36  public class HttpSenderOverHTTP2 extends HttpSender
37  {
38      public HttpSenderOverHTTP2(HttpChannelOverHTTP2 channel)
39      {
40          super(channel);
41      }
42  
43      @Override
44      protected HttpChannelOverHTTP2 getHttpChannel()
45      {
46          return (HttpChannelOverHTTP2)super.getHttpChannel();
47      }
48  
49      @Override
50      protected void sendHeaders(HttpExchange exchange, final HttpContent content, final Callback callback)
51      {
52          Request request = exchange.getRequest();
53          String path = relativize(request.getPath());
54          HttpURI uri = new HttpURI(request.getScheme(), request.getHost(), request.getPort(), path, null, request.getQuery(), null);
55          MetaData.Request metaData = new MetaData.Request(request.getMethod(), uri, HttpVersion.HTTP_2, request.getHeaders());
56          HeadersFrame headersFrame = new HeadersFrame(metaData, null, !content.hasContent());
57          HttpChannelOverHTTP2 channel = getHttpChannel();
58          Promise<Stream> promise = new Promise<Stream>()
59          {
60              @Override
61              public void succeeded(Stream stream)
62              {
63                  getHttpChannel().setStream(stream);
64                  stream.setIdleTimeout(request.getIdleTimeout());
65  
66                  if (content.hasContent() && !expects100Continue(request))
67                  {
68                      boolean advanced = content.advance();
69                      boolean lastContent = content.isLast();
70                      if (advanced || lastContent)
71                      {
72                          DataFrame dataFrame = new DataFrame(stream.getId(), content.getByteBuffer(), lastContent);
73                          stream.data(dataFrame, callback);
74                          return;
75                      }
76                  }
77                  callback.succeeded();
78              }
79  
80              @Override
81              public void failed(Throwable failure)
82              {
83                  callback.failed(failure);
84              }
85          };
86          // TODO optimize the send of HEADERS and DATA frames.
87          channel.getSession().newStream(headersFrame, promise, channel.getStreamListener());
88      }
89  
90      private String relativize(String path)
91      {
92          try
93          {
94              String result = path;
95              URI uri = URI.create(result);
96              if (uri.isAbsolute())
97                  result = uri.getPath();
98              return result.isEmpty() ? "/" : result;
99          }
100         catch (Throwable x)
101         {
102             if (LOG.isDebugEnabled())
103                 LOG.debug("Could not relativize " + path);
104             return path;
105         }
106     }
107 
108     @Override
109     protected void sendContent(HttpExchange exchange, HttpContent content, Callback callback)
110     {
111         if (content.isConsumed())
112         {
113             callback.succeeded();
114         }
115         else
116         {
117             Stream stream = getHttpChannel().getStream();
118             DataFrame frame = new DataFrame(stream.getId(), content.getByteBuffer(), content.isLast());
119             stream.data(frame, callback);
120         }
121     }
122 }