View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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.spdy.client.http;
20  
21  import org.eclipse.jetty.client.HttpContent;
22  import org.eclipse.jetty.client.HttpExchange;
23  import org.eclipse.jetty.client.HttpSender;
24  import org.eclipse.jetty.client.api.Request;
25  import org.eclipse.jetty.http.HttpField;
26  import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
27  import org.eclipse.jetty.spdy.api.Stream;
28  import org.eclipse.jetty.spdy.api.SynInfo;
29  import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
30  import org.eclipse.jetty.util.Callback;
31  import org.eclipse.jetty.util.Fields;
32  import org.eclipse.jetty.util.Promise;
33  
34  public class HttpSenderOverSPDY extends HttpSender
35  {
36      private volatile Stream stream;
37  
38      public HttpSenderOverSPDY(HttpChannelOverSPDY channel)
39      {
40          super(channel);
41      }
42  
43      @Override
44      public HttpChannelOverSPDY getHttpChannel()
45      {
46          return (HttpChannelOverSPDY)super.getHttpChannel();
47      }
48  
49      @Override
50      protected void sendHeaders(HttpExchange exchange, final HttpContent content, final Callback callback)
51      {
52          final Request request = exchange.getRequest();
53          final long idleTimeout = request.getIdleTimeout();
54          short spdyVersion = getHttpChannel().getSession().getVersion();
55          Fields fields = new Fields();
56          HttpField hostHeader = null;
57          for (HttpField header : request.getHeaders())
58          {
59              String name = header.getName();
60              // The host header needs a special treatment
61              if (HTTPSPDYHeader.from(spdyVersion, name) != HTTPSPDYHeader.HOST)
62                  fields.add(name, header.getValue());
63              else
64                  hostHeader = header;
65          }
66  
67          // Add special SPDY headers
68          fields.put(HTTPSPDYHeader.METHOD.name(spdyVersion), request.getMethod());
69          String path = request.getPath();
70          String query = request.getQuery();
71          if (query != null)
72              path += "?" + query;
73          fields.put(HTTPSPDYHeader.URI.name(spdyVersion), path);
74          fields.put(HTTPSPDYHeader.VERSION.name(spdyVersion), request.getVersion().asString());
75          if (hostHeader != null)
76              fields.put(HTTPSPDYHeader.HOST.name(spdyVersion), hostHeader.getValue());
77  
78          SynInfo synInfo = new SynInfo(fields, !content.hasContent());
79          getHttpChannel().getSession().syn(synInfo, getHttpChannel().getHttpReceiver(), new Promise<Stream>()
80          {
81              @Override
82              public void succeeded(Stream stream)
83              {
84                  stream.setIdleTimeout(idleTimeout);
85                  if (content.hasContent())
86                      HttpSenderOverSPDY.this.stream = stream;
87                  callback.succeeded();
88              }
89  
90              @Override
91              public void failed(Throwable failure)
92              {
93                  callback.failed(failure);
94              }
95          });
96      }
97  
98      @Override
99      protected void sendContent(HttpExchange exchange, HttpContent content, Callback callback)
100     {
101         if (content.isConsumed())
102         {
103             callback.succeeded();
104         }
105         else
106         {
107             ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(content.getByteBuffer(), content.isLast());
108             stream.data(dataInfo, callback);
109         }
110     }
111 
112     @Override
113     protected void reset()
114     {
115         super.reset();
116         stream = null;
117     }
118 }