Java 实现Http代理的关键是将接收到的http请求转发到被代理的主机,然后将主机的返回数据再转发到客户机
关键点:
1. HTTP协议
2. java 阻塞IO
3. 使用java阻塞IO实现转发HTTP请求的一个关键点就是转发器必须能够正确分析收到的HTTP请求内容,并根据请求内容正确的转发。
下面是一段请求内容:-----------------------------------------------------之间的是真正的请求内容,以/r/n为行结束符
-----------------------------------------------------
GET /test/test.jsp HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: localhost:7272
Connection: Keep-Alive
-----------------------------------------------------
当java的io读取到请求尾的时候,由于阻塞IO,导致读取等待,这个时候,转发器,必须能够解析上面的内容,根据Content-Length决定读取到什么地方结束,如果没有Content-Length,那么Content-Length为0,也就是不读取。
为了更便于对该请求进行操作,我们封装出来一个简单的HttpRequest对象:
/*
* $RCSfile: HttpRequest.java,v $$
* $Revision: 1.1 $
* $Date: 2007-4-15 $
*
* Copyright (C) 2008 Skin, Inc. All rights reserved.
*
* This software is the proprietary information of Skin, Inc.
* Use is subject to license terms.
*/
package com.skin.taurus.http;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* <p>Title: HttpRequest</p>
* <p>Description: </p>
* @author xuesong.net
* @version 1.0
*/
public class HttpRequest
{
private String method;
private String requestURI;
private String requestURL;
private String queryString;
private String httpProtocol;
private String localAddr;
private int serverPort = -1;
private String remoteAddr;
private String remoteHost;
private int remotePort = -1;
private String characterEncoding;
private HttpHeader httpHeader;
private InputStream inputStream;
private OutputStream outputStream;
public HttpRequest()
{
this.httpHeader = new HttpHeader();
}
public String getContextPath()
{
return "/";
}
/**
* @param encoding
*/
public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException
{
this.characterEncoding = encoding;
}
/**
* @return String
*/
public String getCharacterEncoding()
{
return this.characterEncoding;
}
/**
* @return HttpHeader
*/
public void setHttpHeader(HttpHeader httpHeader)
{
this.httpHeader = httpHeader;
}
/**
* @return HttpHeader
*/
public HttpHeader getHttpHeader()
{
return this.httpHeader;
}
/**
* @param name
* @param value
*/
public void addHeader(String name, String value)
{
this.httpHeader.addHeader(name, value);
}
/**
* @param name
* @param value
*/
public void setHeader(String name, String value)
{
this.httpHeader.setHeader(name, value);
}
/**
* @param name
* @return - String
*/
public String getHeader(String name)
{
return this.httpHeader.getHeader(name);
}
/**
* @param name
* @return - String
*/
public String[] getHeaderValues(String name)
{
return this.httpHeader.getHeaderValues(name);
}
/**
* @return - String
*/
public String getHttpProtocol()
{
return httpProtocol;
}
/**
* @param httpProtocol
*/
public void setHttpProtocol(String httpProtocol)
{
this.httpProtocol = httpProtocol;
}
/**
*
* @return - String
*/
public String getMethod()
{
return method;
}
/**
* @param method
*/
public void setMethod(String method)
{
this.method = method;
}
/**
* @return - String
*/
public String getQueryString()
{
return queryString;
}
/**
*
* @param queryString
*/
public void setQueryString(String queryString)
{
this.queryString = queryString;
}
/**
*
* @return - String
*/
public String getRequestURI()
{
return requestURI;
}
/**
*
* @param requestURI
*/
public void setRequestURI(String requestURI)
{
this.requestURI = requestURI;
}
/**
*
* @return - String
*/
public String getRequestURL()
{
return requestURL;
}
/**
*
* @param requestURL
*/
public void setRequestURL(String requestURL)
{
this.requestURL = requestURL;
}
/**
*
* @return - String
*/
public String getContentType()
{
return (String)(this.getHeader("Content-Type"));
}
/**
*
* @return - int
*/
public int getContentLength()
{
String value = (String)(this.getHeader("Content-Length"));
int contentLength = -1;
if(value == null)
{
return contentLength;
}
try
{
contentLength = Integer.parseInt(value);
}
catch(NumberFormatException e)
{
}
return contentLength;
}
public String getLocalAddr()
{
return localAddr;
}
public void setLocalAddr(String localAddr)
{
this.localAddr = localAddr;
}
public int getServerPort()
{
return serverPort;
}
public void setServerPort(int serverPort)
{
this.serverPort = serverPort;
}
public String getRemoteAddr()
{
return remoteAddr;
}
public void setRemoteAddr(String remoteAddr)
{
this.remoteAddr = remoteAddr;
}
public String getRemoteHost()
{
return remoteHost;
}
public void setRemoteHost(String remoteHost)
{
this.remoteHost = remoteHost;
}
public int getRemotePort()
{
return remotePort;
}
public void setRemotePort(int remotePort)
{
this.remotePort = remotePort;
}
/**
* @return - InputStream
*/
public InputStream getInputStream()
{
return inputStream;
}
/**
* @param inputStream
*/
public void setInputStream(InputStream inputStream)
{
this.inputStream = inputStream;
}
/**
* @return - OutputStream
*/
public OutputStream getOutputStream()
{
return outputStream;
}
/**
* @param outputStream
*/
public void setOutputStream(OutputStream outputStream)
{
this.outputStream = outputStream;
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder buffer = new StringBuilder();
buffer.append(this.method).append(" ").append(this.getRequestURL()).append(" ").append(this.getHttpProtocol()).append("\r\n");
buffer.append(this.httpHeader.toString());
buffer.append("\r\n");
return buffer.toString();
}
}
详细尚学堂版本 地址
服务端Request 封装