手写HTTP代理服务器,使用灵活
手写HTTP代理转发工具
- 本文地址:
- 手写通过系统设置的代理:
背景
代理工具实际上有很多,最常用的就是ngnix了,能代理非常多的场景,但是在生产开发验证的时候,遇到了一个问题,某些平台的回调地址必须使用域名才能访问,当回调地址使用公网IP又无权限设置域名解析的时候,只有使用ngnix做代理转发,在ngnix中设置proxy路径的代理,配置为:
location /proxy/ {
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://公网IP:8888/test/;
}
但是访问代理后的路径又出现一个了问题,访问地址出现如下图所示的限制:
于是自己手写代理绕过这个限制,
原理
如需要访问的Tomcat的路径为:http://公网IP:8888/test/,原始Get请求资源路径为:http://公网IP:8888/test/index.html?name=hello,其中公网IP可能是阿里云、腾讯云等,域名访问会被要求备案
1.设置代理
经过url编码后作为参数传递: GET /proxy/setProxy?url=http%3A%2F%2F公网IP%3A8888%2Ftest%2F&content=tomcat
请求回家tomcat的代理加入proxyContainer容器,可以设置多个哦
2.发起请求
请求当前路径地址:GET /proxy/tomcat/index.html?name=hello,就会后台自动请求http://公网IP:8888/test/index.html?name=hello,并将结果返回给客户端
源码实现
ProxyController.java
//package me.muphy;
import cn.hutool.http.HttpUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 手写代理转发工具
* 如Tomcat的路径为:http://127.0.0.1:8888/test/,Get请求资源路径为:http://127.0.0.1:8888/test/user/page?page=1&pageSize=10
* 1.通过请求设置代理
* 经过url编码后,调用: GET /proxy/setProxy?url=http%3A%2F%2F127.0.0.1%3A8888%2Ftest%2F&content=tomcat
* 2.发起请求
* 请求当前路径地址:GET /proxy/tomcat/user/page?page=1&pageSize=10,就会后台自动请求http://127.0.0.1:8888/test/user/page?page=1&pageSize=10,并将结果返回给客户端
*
* @author gzhx
* @date 2022-02-14
*/
@RestController
@RequestMapping("/proxy")
public class ProxyController {
/**
* 代理容器
*/
private static final Map proxyContainer = new HashMap<>();
/**
* 转发GET请求
*
* @author 子安
* @date 2022-05-01
*/
@GetMapping("/**")
public Object proxyGet(HttpServletRequest request) {
String url = getUrl(request);
System.out.println("url:" + url);
if (url == null) {
return "404 " + request.getRequestURI();
}
String forObject = HttpUtil.get(url, 30000);
System.out.println("result:" + forObject);
return forObject;
}
/**
* 转发POST代理
* 如: http://localhost:8080/proxy/
*
* @author 子安
* @date 2022-05-01
*/
@PostMapping("/**")
public Object proxyPost(HttpServletRequest request, String body) {
String url = getUrl(request);
System.out.println("url:" + url);
if (url == null) {
return "404 " + request.getRequestURI();
}
String forObject = HttpUtil.post(url, body, 30000);
System.out.println("result:" + forObject);
return forObject;
}
/**
* 代理PUT代理
*
* @author 子安
* @date 2022-05-01
*/
// @PutMapping("/**")
// public Object proxyPut(HttpServletRequest request, String body) {
// if (StringUtils.isEmpty(proxy)) {
// return "url为空!";
// }
// String requestURI = request.getRequestURI();
// requestURI = requestURI.replaceAll("/?sdzfw/corpwx/proxy/*", "/");
// //String url = (proxy + requestURI).replaceAll("/+", "/");
// String url = proxy + requestURI;
// String queryString = request.getQueryString();
// if(StringUtils.isNotBlank(queryString)){
// url +="?" + queryString;
// }
// System.out.println("url:" + url);
// restTemplate.put(url, body, Map.class);
// return "ok";
// }
/**
* 设置代理
*
* @param url 代理的地址,如: http://127.0.0.1:8888/test/
* @param content 代理的应用路径,如: tomcat
* @author 子安
* @date 2022-05-01
*/
@GetMapping("/setProxy")
public Object setProxy(HttpServletRequest request, String url, String content) {
if (StringUtils.isEmpty(url)) {
return "url不能为空!";
}
if (StringUtils.isEmpty(content)) {
return "content不能为空!";
}
if (url.endsWith("/")) {
url.replaceAll("/+$", "");
}
return proxyContainer.put(content, url);
}
/**
* 查询代理
*
* @author 子安
* @date 2022-05-01
*/
@GetMapping("/getProxy")
public Object getProxy(HttpServletRequest request, String content) {
if (StringUtils.isEmpty(content)) {
return proxyContainer;
}
if (proxyContainer.containsKey(content)) {
return content + "代理不存在!";
}
return proxyContainer.get(content);
}
/**
* 删除代理
*
* @author 子安
* @date 2022-05-01
*/
@GetMapping("/delProxy")
public Object delProxy(HttpServletRequest request, String content) {
if (StringUtils.isEmpty(content)) {
return "content不能为空!";
}
if (proxyContainer.containsKey(content)) {
return content + "代理不存在!";
}
String remove = proxyContainer.remove(content);
return "删除成功,代理信息:" + content + "=" + remove;
}
private String getUrl(HttpServletRequest request) {
String requestURI = request.getRequestURI();
for (Map.Entry entry : proxyContainer.entrySet()) {
if ((requestURI + "/").startsWith("/proxy/" + entry.getKey() + "/")) {
String url = entry.getValue() + requestURI.replaceAll("^/proxy/" + entry.getKey(), "/").replaceAll("/+", "/");
String queryString = request.getQueryString();
if (StringUtils.isNotBlank(queryString)) {
url += "?" + queryString;
}
return url;
}
}
return null;
}
}