View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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.HttpExchange;
22  import org.eclipse.jetty.client.HttpReceiver;
23  import org.eclipse.jetty.client.HttpResponse;
24  import org.eclipse.jetty.http.HttpField;
25  import org.eclipse.jetty.http.HttpStatus;
26  import org.eclipse.jetty.http.HttpVersion;
27  import org.eclipse.jetty.spdy.api.DataInfo;
28  import org.eclipse.jetty.spdy.api.HeadersInfo;
29  import org.eclipse.jetty.spdy.api.PushInfo;
30  import org.eclipse.jetty.spdy.api.ReplyInfo;
31  import org.eclipse.jetty.spdy.api.RstInfo;
32  import org.eclipse.jetty.spdy.api.Stream;
33  import org.eclipse.jetty.spdy.api.StreamFrameListener;
34  import org.eclipse.jetty.spdy.api.StreamStatus;
35  import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
36  import org.eclipse.jetty.util.Callback;
37  import org.eclipse.jetty.util.Fields;
38  
39  public class HttpReceiverOverSPDY extends HttpReceiver implements StreamFrameListener
40  {
41      public HttpReceiverOverSPDY(HttpChannelOverSPDY channel)
42      {
43          super(channel);
44      }
45  
46      @Override
47      public HttpChannelOverSPDY getHttpChannel()
48      {
49          return (HttpChannelOverSPDY)super.getHttpChannel();
50      }
51  
52      @Override
53      public void onReply(Stream stream, ReplyInfo replyInfo)
54      {
55          HttpExchange exchange = getHttpExchange();
56          if (exchange == null)
57              return;
58  
59          try
60          {
61              HttpResponse response = exchange.getResponse();
62  
63              Fields fields = replyInfo.getHeaders();
64              short spdy = stream.getSession().getVersion();
65              HttpVersion version = HttpVersion.fromString(fields.get(HTTPSPDYHeader.VERSION.name(spdy)).getValue());
66              response.version(version);
67              String[] status = fields.get(HTTPSPDYHeader.STATUS.name(spdy)).getValue().split(" ", 2);
68  
69              Integer code = Integer.parseInt(status[0]);
70              response.status(code);
71              String reason = status.length < 2 ? HttpStatus.getMessage(code) : status[1];
72              response.reason(reason);
73  
74              if (responseBegin(exchange))
75              {
76                  for (Fields.Field field : fields)
77                  {
78                      String name = field.getName();
79                      if (HTTPSPDYHeader.from(spdy, name) != null)
80                          continue;
81                      // TODO: handle multiple values properly
82                      HttpField httpField = new HttpField(name, field.getValue());
83                      responseHeader(exchange, httpField);
84                  }
85  
86                  if (responseHeaders(exchange))
87                  {
88                      if (replyInfo.isClose())
89                      {
90                          responseSuccess(exchange);
91                      }
92                  }
93              }
94          }
95          catch (Exception x)
96          {
97              responseFailure(x);
98          }
99      }
100 
101     @Override
102     public StreamFrameListener onPush(Stream stream, PushInfo pushInfo)
103     {
104         // SPDY push not supported
105         getHttpChannel().getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new Callback.Adapter());
106         return null;
107     }
108 
109     @Override
110     public void onHeaders(Stream stream, HeadersInfo headersInfo)
111     {
112         // TODO: see above handling of headers
113     }
114 
115     @Override
116     public void onData(Stream stream, DataInfo dataInfo)
117     {
118         HttpExchange exchange = getHttpExchange();
119         if (exchange == null)
120             return;
121 
122         try
123         {
124             int length = dataInfo.length();
125             // TODO: avoid data copy here
126             boolean process = responseContent(exchange, dataInfo.asByteBuffer(false));
127             dataInfo.consume(length);
128 
129             if (process)
130             {
131                 if (dataInfo.isClose())
132                 {
133                     responseSuccess(exchange);
134                 }
135             }
136         }
137         catch (Exception x)
138         {
139             responseFailure(x);
140         }
141     }
142 
143     @Override
144     public void onFailure(Stream stream, Throwable x)
145     {
146         HttpExchange exchange = getHttpExchange();
147         if (exchange == null)
148             return;
149         exchange.getRequest().abort(x);
150     }
151 }