64850858
2021-07-16 89a9ab4534f10a224f70e546db838423e84a1965
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package com.genersoft.iot.vmp.conf;
 
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.mitre.dsmiley.httpproxy.ProxyServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.ConnectException;
 
@SuppressWarnings(value = {"rawtypes", "unchecked"})
@Configuration
public class ProxyServletConfig {
 
    private final static Logger logger = LoggerFactory.getLogger(ProxyServletConfig.class);
 
    @Autowired
    private IMediaServerService mediaServerService;
 
    @Value("${server.port}")
    private int serverPort;
 
    @Bean
    public ServletRegistrationBean zlmServletRegistrationBean(){
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZLMProxySerlet(),"/zlm/*");
        servletRegistrationBean.setName("zlm_Proxy");
        servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:6080");
        servletRegistrationBean.addUrlMappings();
        if (logger.isDebugEnabled()) {
            servletRegistrationBean.addInitParameter("log", "true");
        }
        return servletRegistrationBean;
    }
 
    class ZLMProxySerlet extends ProxyServlet{
        @Override
        protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
            String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
            IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
            if (mediaInfo != null) {
                if (!StringUtils.isEmpty(queryStr)) {
                    queryStr += "&secret=" + mediaInfo.getSecret();
                }else {
                    queryStr = "secret=" + mediaInfo.getSecret();
                }
            }
            return queryStr;
        }
 
        /**
         * 异常处理
         */
        @Override
        protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){
            try {
                super.handleRequestException(proxyRequest, proxyResonse, e);
            } catch (ServletException servletException) {
                logger.error("zlm 代理失败: ", e);
            } catch (IOException ioException) {
                if (ioException instanceof ConnectException) {
                    logger.error("zlm 连接失败");
                } else if (ioException instanceof ClientAbortException) {
                    logger.error("用户已中断连接,代理终止");
                } else {
                    logger.error("zlm 代理失败: ", e);
                }
            } catch (RuntimeException exception){
                logger.error("zlm 代理失败: ", e);
            }
        }
 
        /**
         * 对于为按照格式请求的可以直接返回404
         */
        @Override
        protected String getTargetUri(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
 
            String uri = null;
            if (mediaInfo != null) {
//                String realRequestURI = requestURI.substring(requestURI.indexOf(mediaInfo.getId())+ mediaInfo.getId().length());
                uri = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort());
            }else {
                uri = "http://127.0.0.1:" + serverPort +"/index/hook/null"; // 只是一个能返回404的请求而已, 其他的也可以
            }
            return uri;
        }
 
        /**
         * 动态替换请求目标
         */
        @Override
        protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            HttpHost host;
            if (mediaInfo != null) {
                host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
            }else {
                host = new HttpHost("127.0.0.1", serverPort);
            }
            return host;
 
        }
 
        /**
         * 根据uri获取流媒体信息
         */
        IMediaServerItem getMediaInfoByUri(String uri){
            String[] split = uri.split("/");
            String mediaServerId = split[2];
            return mediaServerService.getOne(mediaServerId);
        }
 
        /**
         * 去掉url中的标志信息
         */
        @Override
        protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            String url = super.rewriteUrlFromRequest(servletRequest);
            if (mediaInfo == null) {
                return  url;
            }
            return url.replace(mediaInfo.getId() + "/", "");
        }
    }
 
}