1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http;
17
18 import java.util.Queue;
19
20 import org.jboss.netty.buffer.ChannelBuffer;
21 import org.jboss.netty.channel.Channel;
22 import org.jboss.netty.channel.ChannelDownstreamHandler;
23 import org.jboss.netty.channel.ChannelEvent;
24 import org.jboss.netty.channel.ChannelHandlerContext;
25 import org.jboss.netty.channel.ChannelUpstreamHandler;
26 import org.jboss.netty.util.internal.LinkedTransferQueue;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class HttpClientCodec implements ChannelUpstreamHandler,
47 ChannelDownstreamHandler {
48
49
50 final Queue<HttpMethod> queue = new LinkedTransferQueue<HttpMethod>();
51
52
53 volatile boolean done;
54
55 private final HttpRequestEncoder encoder = new Encoder();
56 private final HttpResponseDecoder decoder;
57
58
59
60
61
62
63 public HttpClientCodec() {
64 this(4096, 8192, 8192);
65 }
66
67
68
69
70 public HttpClientCodec(
71 int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
72 decoder = new Decoder(maxInitialLineLength, maxHeaderSize, maxChunkSize);
73 }
74
75 public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
76 throws Exception {
77 decoder.handleUpstream(ctx, e);
78 }
79
80 public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
81 throws Exception {
82 encoder.handleDownstream(ctx, e);
83 }
84
85 private final class Encoder extends HttpRequestEncoder {
86
87 Encoder() {
88 super();
89 }
90
91 @Override
92 protected Object encode(ChannelHandlerContext ctx, Channel channel,
93 Object msg) throws Exception {
94 if (msg instanceof HttpRequest && !done) {
95 queue.offer(((HttpRequest) msg).getMethod());
96 }
97 return super.encode(ctx, channel, msg);
98 }
99 }
100
101 private final class Decoder extends HttpResponseDecoder {
102
103 Decoder(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
104 super(maxInitialLineLength, maxHeaderSize, maxChunkSize);
105 }
106
107 @Override
108 protected Object decode(ChannelHandlerContext ctx, Channel channel,
109 ChannelBuffer buffer, State state) throws Exception {
110 if (done) {
111 return buffer.readBytes(actualReadableBytes());
112 } else {
113 return super.decode(ctx, channel, buffer, state);
114 }
115 }
116
117 @Override
118 protected boolean isContentAlwaysEmpty(HttpMessage msg) {
119 final int statusCode = ((HttpResponse) msg).getStatus().getCode();
120 if (statusCode == 100) {
121
122 return true;
123 }
124
125
126
127 HttpMethod method = queue.poll();
128
129 char firstChar = method.getName().charAt(0);
130 switch (firstChar) {
131 case 'H':
132
133
134
135
136 if (HttpMethod.HEAD.equals(method)) {
137 return true;
138
139
140
141
142
143
144
145
146
147
148
149
150
151 }
152 break;
153 case 'C':
154
155 if (statusCode == 200) {
156 if (HttpMethod.CONNECT.equals(method)) {
157
158 done = true;
159 queue.clear();
160 return true;
161 }
162 }
163 break;
164 }
165
166 return super.isContentAlwaysEmpty(msg);
167 }
168 }
169 }