1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.example.http.snoop;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.buffer.ChannelBuffers;
20 import org.jboss.netty.channel.ChannelFuture;
21 import org.jboss.netty.channel.ChannelFutureListener;
22 import org.jboss.netty.channel.ChannelHandlerContext;
23 import org.jboss.netty.channel.ExceptionEvent;
24 import org.jboss.netty.channel.MessageEvent;
25 import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
26 import org.jboss.netty.handler.codec.http.Cookie;
27 import org.jboss.netty.handler.codec.http.CookieDecoder;
28 import org.jboss.netty.handler.codec.http.CookieEncoder;
29 import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
30 import org.jboss.netty.handler.codec.http.HttpChunk;
31 import org.jboss.netty.handler.codec.http.HttpChunkTrailer;
32 import org.jboss.netty.handler.codec.http.HttpHeaders;
33 import org.jboss.netty.handler.codec.http.HttpRequest;
34 import org.jboss.netty.handler.codec.http.HttpResponse;
35 import org.jboss.netty.handler.codec.http.QueryStringDecoder;
36 import org.jboss.netty.util.CharsetUtil;
37
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Map.Entry;
41 import java.util.Set;
42
43 import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
44 import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
45 import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
46 import static org.jboss.netty.handler.codec.http.HttpVersion.*;
47
48 public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
49
50 private HttpRequest request;
51 private boolean readingChunks;
52
53 private final StringBuilder buf = new StringBuilder();
54
55 @Override
56 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
57 if (!readingChunks) {
58 HttpRequest request = this.request = (HttpRequest) e.getMessage();
59
60 if (is100ContinueExpected(request)) {
61 send100Continue(e);
62 }
63
64 buf.setLength(0);
65 buf.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
66 buf.append("===================================\r\n");
67
68 buf.append("VERSION: " + request.getProtocolVersion() + "\r\n");
69 buf.append("HOSTNAME: " + getHost(request, "unknown") + "\r\n");
70 buf.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n");
71
72 for (Map.Entry<String, String> h: request.headers()) {
73 buf.append("HEADER: " + h.getKey() + " = " + h.getValue() + "\r\n");
74 }
75 buf.append("\r\n");
76
77 QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
78 Map<String, List<String>> params = queryStringDecoder.getParameters();
79 if (!params.isEmpty()) {
80 for (Entry<String, List<String>> p: params.entrySet()) {
81 String key = p.getKey();
82 List<String> vals = p.getValue();
83 for (String val : vals) {
84 buf.append("PARAM: " + key + " = " + val + "\r\n");
85 }
86 }
87 buf.append("\r\n");
88 }
89
90 if (request.isChunked()) {
91 readingChunks = true;
92 } else {
93 ChannelBuffer content = request.getContent();
94 if (content.readable()) {
95 buf.append("CONTENT: " + content.toString(CharsetUtil.UTF_8) + "\r\n");
96 }
97 writeResponse(e);
98 }
99 } else {
100 HttpChunk chunk = (HttpChunk) e.getMessage();
101 if (chunk.isLast()) {
102 readingChunks = false;
103 buf.append("END OF CONTENT\r\n");
104
105 HttpChunkTrailer trailer = (HttpChunkTrailer) chunk;
106 if (!trailer.trailingHeaders().names().isEmpty()) {
107 buf.append("\r\n");
108 for (String name: trailer.trailingHeaders().names()) {
109 for (String value: trailer.trailingHeaders().getAll(name)) {
110 buf.append("TRAILING HEADER: " + name + " = " + value + "\r\n");
111 }
112 }
113 buf.append("\r\n");
114 }
115
116 writeResponse(e);
117 } else {
118 buf.append("CHUNK: " + chunk.getContent().toString(CharsetUtil.UTF_8) + "\r\n");
119 }
120 }
121 }
122
123 private void writeResponse(MessageEvent e) {
124
125 boolean keepAlive = isKeepAlive(request);
126
127
128 HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
129 response.setContent(ChannelBuffers.copiedBuffer(buf.toString(), CharsetUtil.UTF_8));
130 response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
131
132 if (keepAlive) {
133
134 response.headers().set(CONTENT_LENGTH, response.getContent().readableBytes());
135
136
137 response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
138 }
139
140
141 String cookieString = request.headers().get(COOKIE);
142 if (cookieString != null) {
143 CookieDecoder cookieDecoder = new CookieDecoder();
144 Set<Cookie> cookies = cookieDecoder.decode(cookieString);
145 if (!cookies.isEmpty()) {
146
147 CookieEncoder cookieEncoder = new CookieEncoder(true);
148 for (Cookie cookie : cookies) {
149 cookieEncoder.addCookie(cookie);
150 response.headers().add(SET_COOKIE, cookieEncoder.encode());
151 }
152 }
153 } else {
154
155 CookieEncoder cookieEncoder = new CookieEncoder(true);
156 cookieEncoder.addCookie("key1", "value1");
157 response.headers().add(SET_COOKIE, cookieEncoder.encode());
158 cookieEncoder.addCookie("key2", "value2");
159 response.headers().add(SET_COOKIE, cookieEncoder.encode());
160 }
161
162
163 ChannelFuture future = e.getChannel().write(response);
164
165
166 if (!keepAlive) {
167 future.addListener(ChannelFutureListener.CLOSE);
168 }
169 }
170
171 private static void send100Continue(MessageEvent e) {
172 HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
173 e.getChannel().write(response);
174 }
175
176 @Override
177 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
178 e.getCause().printStackTrace();
179 e.getChannel().close();
180 }
181 }