smiley-http-proxy-servlet 反向代理

简介: 背景 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

背景

 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

 简单来说,你的反向代理服务器会接收请求,但其自身不处理该请求,而是对请求经过一些处理,例如添加日志、缓存、身份验证等服务,然后再将请求转发到相应的应用服务器中进行处理,最后将处理结果返回。

 HTTP-Proxy-Servlet是基于Filter进行服务代理,只需要进行相关的配置之后,就能进行服务代理,同时核心文件只有2个,容易理解和进行改动,但是存在的问题是只能代理一个url,不能代理多个不同的url,这部分是可以基于源码进行改造。


源码目录

img_0299b9337bcf040eb34d1d14eb09e498.png
http-proxy-servlet
  • http-proxy-servlet的源码文件非常简单,只有两个文件。
  • ProxyServlet.java重写了spring的HttpServlet,参数初始化都在ProxyServlet初始化。
  • 针对改造我们只需要改造ProxyServlet.java文件即可。


源码改造

  • http-proxy-servlet的代理配置针对代理URL只能定位到一个URL,如果想内部逻辑判断转发多个URL只能进行代码改造。
  • 核心改造逻辑在于改造init()方法、initTarget()方法、service()方法。
  • initTarget()方法内部解析spring的配置初始化核心对象。
  • service()方法内部根据逻辑判断重定向逻辑。
public class ProxyServlet extends HttpServlet {
 
  // 省略相关代码
  protected String targetUri;
  protected URI targetUriObj;//new URI(targetUri)
  protected HttpHost targetHost;//URIUtils.extractHost(targetUriObj);

  // 晴天哥新增代码
  protected String nTargetUri;
  protected URI nTargetUriObj;//new URI(nTargetUri)
  protected HttpHost nTargetHost;//URIUtils.extractHost(nTargetUriObj);

  private static AtomicLong counter = new AtomicLong(0);

  private HttpClient proxyClient;

  @Override
  public void init() throws ServletException {
    // 省略相关代码

    // 核心在于初始化这个链接
    initTarget();//sets target*

    proxyClient = createHttpClient(buildRequestConfig());
  }


  protected RequestConfig buildRequestConfig() {
    // 省略相关代码
  }

  protected void initTarget() throws ServletException {
    targetUri = getConfigParam(P_TARGET_URI);
    if (targetUri == null) {
        throw new ServletException(P_TARGET_URI + " is required.");
    }
    //test it's valid
    try {
      targetUriObj = new URI(targetUri);
    } catch (Exception e) {
      throw new ServletException("Trying to process targetUri init parameter: "+e,e);
    }
    targetHost = URIUtils.extractHost(targetUriObj);

    // 晴天哥新增代码
    nTargetUri = getConfigParam(N_P_TARGET_URI);
    if (null == nTargetUri) {
        throw new ServletException(N_P_TARGET_URI + " is required.");
    }

    try {
        nTargetUriObj = new URI(nTargetUri);
    } catch (Exception e) {
        throw new ServletException("Trying to process targetUri init parameter: "+e,e);
    }

    nTargetHost = URIUtils.extractHost(nTargetUriObj);
  }


  protected void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
      throws ServletException, IOException {
      // 晴天哥新增代码
      long flag = counter.incrementAndGet();
    if (servletRequest.getAttribute(ATTR_TARGET_URI) == null) {
        if (0 == flag % 2) {
            servletRequest.setAttribute(ATTR_TARGET_URI, targetUri);
        } else {
            servletRequest.setAttribute(ATTR_TARGET_URI, nTargetUri);
        }
    }
    if (servletRequest.getAttribute(ATTR_TARGET_HOST) == null) {
        if (0 == flag % 2) {
            servletRequest.setAttribute(ATTR_TARGET_HOST, targetHost);
        } else {
            servletRequest.setAttribute(ATTR_TARGET_HOST, nTargetHost);
        }
    }

    String method = servletRequest.getMethod();
    String proxyRequestUri = rewriteUrlFromRequest(servletRequest);
    HttpRequest proxyRequest;

    if (servletRequest.getHeader(HttpHeaders.CONTENT_LENGTH) != null ||
        servletRequest.getHeader(HttpHeaders.TRANSFER_ENCODING) != null) {
      proxyRequest = newProxyRequestWithEntity(method, proxyRequestUri, servletRequest);
    } else {
      proxyRequest = new BasicHttpRequest(method, proxyRequestUri);
    }

    copyRequestHeaders(servletRequest, proxyRequest);

    setXForwardedForHeader(servletRequest, proxyRequest);

    HttpResponse proxyResponse = null;
    try {
      // 执行请求部分逻辑
      proxyResponse = doExecute(servletRequest, servletResponse, proxyRequest);

      // 省略相关代码
    } catch (Exception e) {
      handleRequestException(proxyRequest, e);
    }
  }
}


demo

  • 1、修改源码后mvn打包生成jar包。
  • 2、引入pom.xml依赖包
  <dependencies>
    <dependency>
      <groupId>org.mitre.dsmiley.httpproxy</groupId>
      <artifactId>smiley-http-proxy-servlet</artifactId>
        <version>1.11-SNAPSHOT</version>
    </dependency>
  </dependencies>
  • 3、 配置spring web.xml
<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>solr</servlet-name>
    <servlet-class>org.mitre.dsmiley.httpproxy.ProxyServlet</servlet-class>
    <init-param>
      <param-name>targetUri</param-name>
      <param-value>http://sports.sina.com.cn:80/nba/</param-value>
    </init-param>
      <init-param>
          <param-name>n_targetUri</param-name>
          <param-value>http://sports.qq.com:80</param-value>
      </init-param>
    <init-param>
      <param-name>log</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>solr</servlet-name>
    <url-pattern>/solr/*</url-pattern>
  </servlet-mapping>

</web-app>

效果图

  • localhost:8080/solr的请求可以定向到新浪体育或腾讯体育地址
img_7c0a2ad9b93abe3469fefeb3ad4f16c4.png

img_516a0408304cbd98452978c2881452dd.png


参考地址

https://github.com/lebron374/HTTP-Proxy-Servlet

目录
相关文章
|
3月前
|
网络协议 网络架构
HTTP方法有哪些?
HTTP方法有哪些?
|
Web App开发 应用服务中间件 Apache
Apache HTTP配置反向代理入门
Apache HTTP配置反向代理入门 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器或者外部网络上其它IP地址服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
1978 0
|
3月前
|
存储 缓存 索引
2.1.3 http服务器的实现
2.1.3 http服务器的实现
|
4月前
|
存储 缓存
短效http代理ip和动态http代理有什么联系?
随着科技的发展和进步,使用代理ip的使用人数也层出不穷,一些互联网企业因为业务的需要使用http动态代理ip也越来越多,那么短效http代理ip和动态http代理有什么联系?接下来小编就给大家介绍一下
37 0
短效http代理ip和动态http代理有什么联系?
|
5月前
|
Java Apache
apache的Http请求
apache的Http请求
41 0
|
11月前
|
缓存 监控 负载均衡
http代理(proxy)配置都有哪些方法?
今天我将和大家探讨关于HTTP proxy配置的不同方法。在网络通信中,HTTP proxy配置(或称为IP代理)起着重要的作用,它允许我们在客户端和服务器之间建立中间代理,从而实现匿名性、访问控制和性能优化等目的。
|
7月前
|
JavaScript 网络安全
使用 http-proxy 对网络请求进行代理
创建一个代理 HTTP 服务器,监听在端口 8089 上。因此该代理服务器接收到任何发送到 8089 端口的 HTTP 请求,都会自动将其发送到 targetUrl 指定的 sap 网站上。
95 0
|
7月前
HTTP服务器
HTTP服务器
|
8月前
|
Web App开发 缓存 负载均衡
什么是HTTP代理?HTTP代理的作用?HTTP代理怎么设置?
HTTP代理是一种充当客户端和服务器之间的中间人的服务器。当客户端发起请求时,HTTP代理会拦截请求并将其转发给目标服务器。一旦目标服务器响应,HTTP代理会拦截响应并将其转发回客户端。HTTP代理可以被用于多种场景,例如加强安全、缓存内容以加速访问、访问受限资源等等。在这篇文章中,我们将会讨论HTTP代理的作用、类型以及如何设置它。
什么是HTTP代理?HTTP代理的作用?HTTP代理怎么设置?
|
大数据
使用代理http时出现503服务不可用的原因是什么?
在使用IP代理时,有时候会遇到503服务不可用的错误提示,这个错误通常是由于代理服务器无法连接到目标服务器而导致的。
使用代理http时出现503服务不可用的原因是什么?