packagecom.ajita.httpserver;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.StringReader;importjava.nio.charset.CharacterCodingException;importjava.nio.charset.Charset;importjava.nio.charset.CharsetDecoder;importjava.util.HashMap;importjava.util.Map;importorg.apache.mina.core.buffer.IoBuffer;importorg.apache.mina.core.session.IoSession;importorg.apache.mina.filter.codec.ProtocolDecoderOutput;importorg.apache.mina.filter.codec.demux.MessageDecoderAdapter;importorg.apache.mina.filter.codec.demux.MessageDecoderResult;public class HttpRequestDecoder extendsMessageDecoderAdapter {private static final byte[] CONTENT_LENGTH = new String("Content-Length:")
.getBytes();staticString defaultEncoding;privateCharsetDecoder decoder;publicCharsetDecoder getDecoder() {returndecoder;
}public voidsetEncoder(CharsetDecoder decoder) {this.decoder =decoder;
}private HttpRequestMessage request = null;publicHttpRequestDecoder() {
decoder=Charset.forName(defaultEncoding).newDecoder();
}publicMessageDecoderResult decodable(IoSession session, IoBuffer in) {try{return messageComplete(in) ?MessageDecoderResult.OK
: MessageDecoderResult.NEED_DATA;
}catch(Exception ex) {
ex.printStackTrace();
}returnMessageDecoderResult.NOT_OK;
}publicMessageDecoderResult decode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out)throwsException {
HttpRequestMessage m=decodeBody(in);//Return NEED_DATA if the body is not fully read.
if (m == null) {returnMessageDecoderResult.NEED_DATA;
}
out.write(m);returnMessageDecoderResult.OK;
}/** 判断HTTP请求是否完整,若格式有错误直接抛出异常*/
private booleanmessageComplete(IoBuffer in) {int last = in.remaining() - 1;if (in.remaining() < 4) {return false;
}//to speed up things we check if the Http request is a GET or POST
if (in.get(0) == (byte) 'G' && in.get(1) == (byte) 'E'
&& in.get(2) == (byte) 'T') {//Http GET request therefore the last 4 bytes should be 0x0D 0x0A//0x0D 0x0A
return in.get(last) == (byte) 0x0A
&& in.get(last - 1) == (byte) 0x0D
&& in.get(last - 2) == (byte) 0x0A
&& in.get(last - 3) == (byte) 0x0D;
}else if (in.get(0) == (byte) 'P' && in.get(1) == (byte) 'O'
&& in.get(2) == (byte) 'S' && in.get(3) == (byte) 'T') {//Http POST request//first the position of the 0x0D 0x0A 0x0D 0x0A bytes
int eoh = -1;for (int i = last; i > 2; i--) {if (in.get(i) == (byte) 0x0A && in.get(i - 1) == (byte) 0x0D
&& in.get(i - 2) == (byte) 0x0A
&& in.get(i - 3) == (byte) 0x0D) {
eoh= i + 1;break;
}
}if (eoh == -1) {return false;
}for (int i = 0; i < last; i++) {boolean found = false;for (int j = 0; j < CONTENT_LENGTH.length; j++) {if (in.get(i + j) !=CONTENT_LENGTH[j]) {
found= false;break;
}
found= true;
}if(found) {//retrieve value from this position till next 0x0D 0x0A
StringBuilder contentLength = newStringBuilder();for (int j = i + CONTENT_LENGTH.length; j < last; j++) {if (in.get(j) == 0x0D) {break;
}
contentLength.append(newString(new byte[] { in.get(j) }));
}//if content-length worth of data has been received then//the message is complete
returnInteger.parseInt(contentLength.toString().trim())+ eoh ==in.remaining();
}
}
}//the message is not complete and we need more data
return false;
}privateHttpRequestMessage decodeBody(IoBuffer in) {
request= newHttpRequestMessage();try{
request.setHeaders(parseRequest(newStringReader(in
.getString(decoder))));returnrequest;
}catch(CharacterCodingException ex) {
ex.printStackTrace();
}return null;
}private MapparseRequest(StringReader is) {
Map map = new HashMap();
BufferedReader rdr= newBufferedReader(is);try{//Get request URL.
String line =rdr.readLine();
String[] url= line.split(" ");if (url.length < 3) {returnmap;
}
map.put("URI", newString[] { line });
map.put("Method", new String[] { url[0].toUpperCase() });
map.put("Context", new String[] { url[1].substring(1) });
map.put("Protocol", new String[] { url[2] });//Read header
while ((line = rdr.readLine()) != null && line.length() > 0) {
String[] tokens= line.split(": ");
map.put(tokens[0], new String[] { tokens[1] });
}//If method 'POST' then read Content-Length worth of data
if (url[0].equalsIgnoreCase("POST")) {int len = Integer.parseInt(map.get("Content-Length")[0]);char[] buf = new char[len];if (rdr.read(buf) ==len) {
line=String.copyValueOf(buf);
}
}else if (url[0].equalsIgnoreCase("GET")) {int idx = url[1].indexOf('?');if (idx != -1) {
map.put("Context",new String[] { url[1].substring(1, idx) });
line= url[1].substring(idx + 1);
}else{
line= null;
}
}if (line != null) {
String[] match= line.split("\\&");for(String element : match) {
String[] params= new String[1];
String[] tokens= element.split("=");switch(tokens.length) {case 0:
map.put("@".concat(element), newString[] {});break;case 1:
map.put("@".concat(tokens[0]), newString[] {});break;default:
String name= "@".concat(tokens[0]);if(map.containsKey(name)) {
params=map.get(name);
String[] tmp= new String[params.length + 1];for (int j = 0; j < params.length; j++) {
tmp[j]=params[j];
}
params= null;
params=tmp;
}
params[params.length- 1] = tokens[1].trim();
map.put(name, params);
}
}
}
}catch(IOException ex) {
ex.printStackTrace();
}returnmap;
}
}packagecom.ajita.httpserver;importjava.io.ByteArrayOutputStream;importjava.io.IOException;importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.HashMap;importjava.util.Map;importorg.apache.mina.core.buffer.IoBuffer;public classHttpResponseMessage {/**HTTP response codes*/
public static final int HTTP_STATUS_SUCCESS = 200;public static final int HTTP_STATUS_NOT_FOUND = 404;/**Map*/
private final Map headers = new HashMap();/**Storage for body of HTTP response.*/
private final ByteArrayOutputStream body = new ByteArrayOutputStream(1024);private int responseCode =HTTP_STATUS_SUCCESS;publicHttpResponseMessage() {//headers.put("Server", "HttpServer (" + Server.VERSION_STRING + ')');
headers.put("Server", "HttpServer (" + "Mina 2.0" + ')');
headers.put("Cache-Control", "private");
headers.put("Content-Type", "text/html; charset=iso-8859-1");
headers.put("Connection", "keep-alive");
headers.put("Keep-Alive", "200");
headers.put("Date", newSimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").format(newDate()));
headers.put("Last-Modified", newSimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").format(newDate()));
}public MapgetHeaders() {returnheaders;
}public voidsetContentType(String contentType) {
headers.put("Content-Type", contentType);
}public void setResponseCode(intresponseCode) {this.responseCode =responseCode;
}public intgetResponseCode() {return this.responseCode;
}public void appendBody(byte[] b) {try{
body.write(b);
}catch(IOException ex) {
ex.printStackTrace();
}
}public voidappendBody(String s) {try{
body.write(s.getBytes());
}catch(IOException ex) {
ex.printStackTrace();
}
}publicIoBuffer getBody() {returnIoBuffer.wrap(body.toByteArray());
}public intgetBodyLength() {returnbody.size();
}
}