1 20 package org.apache.mina.example.httpserver.codec; 21 22 import java.io.BufferedReader ; 23 import java.io.IOException ; 24 import java.io.Reader ; 25 import java.io.StringReader ; 26 import java.nio.charset.CharacterCodingException ; 27 import java.nio.charset.CharsetDecoder ; 28 import java.nio.charset.Charset ; 29 import java.util.HashMap ; 30 import java.util.Map ; 31 32 import org.apache.mina.common.ByteBuffer; 33 import org.apache.mina.common.IoSession; 34 import org.apache.mina.filter.codec.ProtocolDecoderOutput; 35 import org.apache.mina.filter.codec.demux.MessageDecoderAdapter; 36 import org.apache.mina.filter.codec.demux.MessageDecoderResult; 37 38 44 public class HttpRequestDecoder extends MessageDecoderAdapter { 45 private static final byte[] CONTENT_LENGTH = new String ("Content-Length:") 46 .getBytes(); 47 48 private CharsetDecoder decoder = Charset.defaultCharset().newDecoder(); 49 50 private HttpRequestMessage request = null; 51 52 public HttpRequestDecoder() { 53 } 54 55 public MessageDecoderResult decodable(IoSession session, ByteBuffer in) { 56 try { 58 return messageComplete(in) ? MessageDecoderResult.OK 59 : MessageDecoderResult.NEED_DATA; 60 } catch (Exception ex) { 61 ex.printStackTrace(); 62 } 63 64 return MessageDecoderResult.NOT_OK; 65 } 66 67 public MessageDecoderResult decode(IoSession session, ByteBuffer in, 68 ProtocolDecoderOutput out) throws Exception { 69 HttpRequestMessage m = decodeBody(in); 71 72 if (m == null) 74 return MessageDecoderResult.NEED_DATA; 75 76 out.write(m); 77 78 return MessageDecoderResult.OK; 79 } 80 81 private boolean messageComplete(ByteBuffer in) throws Exception { 82 int last = in.remaining() - 1; 83 if (in.remaining() < 4) 84 return false; 85 86 if (in.get(0) == (byte) 'G' && in.get(1) == (byte) 'E' 88 && in.get(2) == (byte) 'T') { 89 return (in.get(last) == (byte) 0x0A 91 && in.get(last - 1) == (byte) 0x0D 92 && in.get(last - 2) == (byte) 0x0A && in.get(last - 3) == (byte) 0x0D); 93 } else if (in.get(0) == (byte) 'P' && in.get(1) == (byte) 'O' 94 && in.get(2) == (byte) 'S' && in.get(3) == (byte) 'T') { 95 int eoh = -1; 98 for (int i = last; i > 2; i--) { 99 if (in.get(i) == (byte) 0x0A && in.get(i - 1) == (byte) 0x0D 100 && in.get(i - 2) == (byte) 0x0A 101 && in.get(i - 3) == (byte) 0x0D) { 102 eoh = i + 1; 103 break; 104 } 105 } 106 if (eoh == -1) 107 return false; 108 for (int i = 0; i < last; i++) { 109 boolean found = false; 110 for (int j = 0; j < CONTENT_LENGTH.length; j++) { 111 if (in.get(i + j) != CONTENT_LENGTH[j]) { 112 found = false; 113 break; 114 } 115 found = true; 116 } 117 if (found) { 118 StringBuilder contentLength = new StringBuilder (); 120 for (int j = i + CONTENT_LENGTH.length; j < last; j++) { 121 if (in.get(j) == 0x0D) 122 break; 123 contentLength.append(new String ( 124 new byte[] { in.get(j) })); 125 } 126 return (Integer.parseInt(contentLength.toString().trim()) 128 + eoh == in.remaining()); 129 } 130 } 131 } 132 133 return false; 135 } 136 137 private HttpRequestMessage decodeBody(ByteBuffer in) { 138 request = new HttpRequestMessage(); 139 try { 140 request.setHeaders(parseRequest(new StringReader (in 141 .getString(decoder)))); 142 return request; 143 } catch (CharacterCodingException ex) { 144 ex.printStackTrace(); 145 } 146 147 return null; 148 } 149 150 private Map parseRequest(Reader is) { 151 Map <String , String []> map = new HashMap <String , String []>(); 152 BufferedReader rdr = new BufferedReader (is); 153 154 try { 155 String line = rdr.readLine(); 157 String [] url = line.split(" "); 158 if (url.length < 3) 159 return map; 160 161 map.put("URI", new String [] { line }); 162 map.put("Method", new String [] { url[0].toUpperCase() }); 163 map.put("Context", new String [] { url[1].substring(1) }); 164 map.put("Protocol", new String [] { url[2] }); 165 while ((line = rdr.readLine()) != null && line.length() > 0) { 167 String [] tokens = line.split(": "); 168 map.put(tokens[0], new String [] { tokens[1] }); 169 } 170 171 if (url[0].equalsIgnoreCase("POST")) { 173 int len = Integer.parseInt(map.get("Content-Length")[0]); 174 char[] buf = new char[len]; 175 if (rdr.read(buf) == len) { 176 line = String.copyValueOf(buf); 177 } 178 } else if (url[0].equalsIgnoreCase("GET")) { 179 int idx = url[1].indexOf('?'); 180 if (idx != -1) { 181 map.put("Context", 182 new String [] { url[1].substring(1, idx) }); 183 line = url[1].substring(idx + 1); 184 } else { 185 line = null; 186 } 187 } 188 if (line != null) { 189 String [] match = line.split("\\&"); 190 for (int i = 0; i < match.length; i++) { 191 String [] params = new String [1]; 192 String [] tokens = match[i].split("="); 193 switch (tokens.length) { 194 case 0: 195 map.put("@".concat(match[i]), new String [] {}); 196 break; 197 case 1: 198 map.put("@".concat(tokens[0]), new String [] {}); 199 break; 200 default: 201 String name = "@".concat(tokens[0]); 202 if (map.containsKey(name)) { 203 params = map.get(name); 204 String [] tmp = new String [params.length + 1]; 205 for (int j = 0; j < params.length; j++) 206 tmp[j] = params[j]; 207 params = null; 208 params = tmp; 209 } 210 params[params.length - 1] = tokens[1].trim(); 211 map.put(name, params); 212 } 213 } 214 } 215 } catch (IOException ex) { 216 ex.printStackTrace(); 217 } 218 219 return map; 220 } 221 } 222 | Popular Tags |