1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
61 if (HTTPSPDYHeader.from(spdyVersion, name) != HTTPSPDYHeader.HOST)
62 fields.add(name, header.getValue());
63 else
64 hostHeader = header;
65 }
66
67
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 }