一、HTTP代理服务器
HTTP代理服务器是一个中间服务器,它负责接收客户端的HTTP请求,然后将请求转发给目标服务器,并将目标服务器返回的响应返回给客户端。代理服务器可以处理各种HTTP请求,如GET、POST、PUT、DELETE等,并可以处理HTTPS请求。在开发Web应用程序时,使用代理服务器可以隐藏后端服务器的真实IP地址,增强安全性。
二、Java Socket
Java Socket是Java网络编程中的重要部分,它提供了一种使用TCP协议进行网络通信的方式。使用Java Socket,我们可以创建一个套接字,连接到远程主机,并通过套接字发送和接收数据。
三、思路
创建SocketServer监听端口,根据http请求头信息建立代理服务器与目标服务器的连接,然后通过httpclient转发请求数据,然后将目标服务器的响应消息通过socket连接返回给客户端。
四、示例代码
创建socket监听
/**
* @author Charles
* @module socket
* @since 2023/8/3 12:03
*/
public class InitProxyServer {
public void startServer(int port) {
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
//The server socket
Socket socket = serverSocket.accept();
new ProxyServer(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
请求转发处理
@Override
public void run() {
try {
StringBuffer res = new StringBuffer();
String content = "";
res.append("HTTP/1.1 200 ok \r\n");
res.append("Content-Type:application/json;charset=utf-8; \r\n");
// 解析请求地址 http(s)://serviceName/路径?userName=xxx&passWord=xxx&other=xxx
RequestData read = Request.read(this.input);
if(read == null){
res.append("Content-Length:" + content.getBytes().length + "\r\n");
res.append("\r\n");
res.append(content);
out.write(res.toString().getBytes());
out.flush();
return;
}
// 用户鉴权
Authenticator authenticator = new Authenticator();
authenticator.authenticateByMemory(read.getServiceName(), read.getUserName(), read.getPassword());
// 服务路由 根据服务名获取实际的服务地址和端口,这里处理的是http请求
ServiceRegistration serviceRegistration = new ServiceRegistration();
String target = serviceRegistration.getTarget(read.getServiceName());
// 使用jdk的http客户端发起真实的请求
String body = "";
if(read.getMethodType().contains(GET)){
body = HttpUtil.createGet(target + read.getRequestPath()).body(read.getParamBody()).execute().body();
}
if(read.getMethodType().contains(POST)){
body = HttpUtil.createPost(target + read.getRequestPath()).body(read.getParamBody()).execute().body();
}
// 响应目标服务器消息
content = body;
res.append("Content-Length:" + content.getBytes().length + "\r\n");
res.append("\r\n");
res.append(content);
out.write(res.toString().getBytes());
out.flush();
}catch (Exception e){
System.out.println("服务器代理异常!");
e.printStackTrace();
}finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
其他辅助类
/**
* 用户鉴权判断
*
* @param serviceName 代理的服务名称
* @param userName 用户名
* @param password 密码
*/
public void authenticateByMemory(String serviceName, String userName, String password){
Map<String, String> service = memoryUser.get(serviceName);
if(Objects.isNull(service)){
throw new RuntimeException("服务不存在");
}
String user = service.get(userName);
if(Objects.isNull(user)){
throw new RuntimeException("用户不存在");
}else if(!user.equals(password)){
throw new RuntimeException("密码错误");
}
}
/**
* 解析请求头
*
* @param input
* @return
*/
public static RequestData read(InputStream input) {
StringBuilder stringBuilder = new StringBuilder();
try {
byte[] bytes = new byte[1024];
while (input.available() != 0) {
input.read(bytes);
String str = new String(bytes, Charset.forName("utf-8"));
stringBuilder.append(str);
}
} catch (Exception e) {
e.printStackTrace();
}
String accept = stringBuilder.toString();
if("".equals(accept)){
return null;
}
String[] split = accept.split("\\r\\n");
if(!split[0].contains(HTTP)){
throw new RuntimeException("错误的请求");
}else if(!split[0].contains(GET) && !split[0].contains(POST)){
throw new RuntimeException("错误的请求方式");
}
String[] data = split[0].split(" ");
if(!data[1].contains("?")){
throw new RuntimeException("未携带用户参数");
}
RequestData requestData = new RequestData();
requestData.setMethodType(data[0].replace("/", ""));
requestData.setRequestPath(data[1].substring(data[1].indexOf("/", 1), data[1].indexOf("?")));
requestData.setServiceName(data[1].substring(1, data[1].indexOf("/", 1)));
String auth = data[1].substring(data[1].indexOf("?") + 1);
requestData.setParamBody(auth);
if(Objects.isNull(auth) || !auth.contains(USERNAME) || !auth.contains(PASSWORD)){
throw new RuntimeException("未携带用户消息");
}
String[] keyValue = auth.split("&");
for (int i = 0; i < keyValue.length; i++) {
if(keyValue[i].contains(USERNAME)){
requestData.setUserName(keyValue[i].replace(USERNAME, "").replace("=", ""));
}
if(keyValue[i].contains(PASSWORD)){
requestData.setPassword(keyValue[i].replace(PASSWORD, "").replace("=", ""));
}
}
return requestData;
}
五、测试效果
通过postman请求本地服务代理到远程目标服务上。
文章来源:https://www.toymoban.com/news/detail-779139.html
文章来源地址https://www.toymoban.com/news/detail-779139.html
到了这里,关于JAVA写HTTP代理服务器-socket实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!