java mina http_基于Mina的Http Server以及简单的Http请求客户端

package com.ajita.httpserver;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.StringReader;

import java.nio.charset.CharacterCodingException;

import java.nio.charset.Charset;

import java.nio.charset.CharsetDecoder;

import java.util.HashMap;

import java.util.Map;

import org.apache.mina.core.buffer.IoBuffer;

import org.apache.mina.core.session.IoSession;

import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import org.apache.mina.filter.codec.demux.MessageDecoderAdapter;

import org.apache.mina.filter.codec.demux.MessageDecoderResult;

public class HttpRequestDecoder extends MessageDecoderAdapter {

private static final byte[] CONTENT_LENGTH = new String("Content-Length:")

.getBytes();

static String defaultEncoding;

private CharsetDecoder decoder;

public CharsetDecoder getDecoder() {

return decoder;

}

public void setEncoder(CharsetDecoder decoder) {

this.decoder = decoder;

}

private HttpRequestMessage request = null;

public HttpRequestDecoder() {

decoder = Charset.forName(defaultEncoding).newDecoder();

}

public MessageDecoderResult decodable(IoSession session, IoBuffer in) {

try {

return messageComplete(in) ? MessageDecoderResult.OK

: MessageDecoderResult.NEED_DATA;

} catch (Exception ex) {

ex.printStackTrace();

}

return MessageDecoderResult.NOT_OK;

}

public MessageDecoderResult decode(IoSession session, IoBuffer in,

ProtocolDecoderOutput out) throws Exception {

HttpRequestMessage m = decodeBody(in);

// Return NEED_DATA if the body is not fully read.

if (m == null) {

return MessageDecoderResult.NEED_DATA;

}

out.write(m);

return MessageDecoderResult.OK;

}

/*

* 判断HTTP请求是否完整,若格式有错误直接抛出异常

*/

private boolean messageComplete(IoBuffer in) {

int last = in.remaining() - 1;

if (in.remaining() 

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 

boolean found = false;

for (int j = 0; 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 = new StringBuilder();

for (int j = i + CONTENT_LENGTH.length; j 

if (in.get(j) == 0x0D) {

break;

}

contentLength.append(new String(

new byte[] { in.get(j) }));

}

// if content-length worth of data has been received then

// the message is complete

return Integer.parseInt(contentLength.toString().trim())

+ eoh == in.remaining();

}

}

}

// the message is not complete and we need more data

return false;

}

private HttpRequestMessage decodeBody(IoBuffer in) {

request = new HttpRequestMessage();

try {

request.setHeaders(parseRequest(new StringReader(in

.getString(decoder))));

return request;

} catch (CharacterCodingException ex) {

ex.printStackTrace();

}

return null;

}

private Map parseRequest(StringReader is) {

Map map = new HashMap();

BufferedReader rdr = new BufferedReader(is);

try {

// Get request URL.

String line = rdr.readLine();

String[] url = line.split(" ");

if (url.length 

return map;

}

map.put("URI", new String[] { 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), new String[] {});

break;

case 1:

map.put("@".concat(tokens[0]), new String[] {});

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 

tmp[j] = params[j];

}

params = null;

params = tmp;

}

params[params.length - 1] = tokens[1].trim();

map.put(name, params);

}

}

}

} catch (IOException ex) {

ex.printStackTrace();

}

return map;

}

}

package com.ajita.httpserver;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

import org.apache.mina.core.buffer.IoBuffer;

public class HttpResponseMessage {

/** 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;

public HttpResponseMessage() {

// 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", new SimpleDateFormat(

"EEE, dd MMM yyyy HH:mm:ss zzz").format(new Date()));

headers.put("Last-Modified", new SimpleDateFormat(

"EEE, dd MMM yyyy HH:mm:ss zzz").format(new Date()));

}

public Map getHeaders() {

return headers;

}

public void setContentType(String contentType) {

headers.put("Content-Type", contentType);

}

public void setResponseCode(int responseCode) {

this.responseCode = responseCode;

}

public int getResponseCode() {

return this.responseCode;

}

public void appendBody(byte[] b) {

try {

body.write(b);

} catch (IOException ex) {

ex.printStackTrace();

}

}

public void appendBody(String s) {

try {

body.write(s.getBytes());

} catch (IOException ex) {

ex.printStackTrace();

}

}

public IoBuffer getBody() {

return IoBuffer.wrap(body.toByteArray());

}

public int getBodyLength() {

return body.size();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值