JAVA实现HTTP接口代理,支持视频等大文件代理下载

前言

为避免将外部系统的视频等资源文件的地址直接暴露给用户,有一种思路是再服务端使用http代理隐藏真实地址。
可以使用netty实现http代理服务器,但是可以使用更简单的一段代码进行接口级代理,代理接口收到的请求可以进行鉴权等操作,然后进行正常的协议报文交互。

实现要求是支持视频的下载,代理服务不对文件进行临时下载,直接把文件流交给浏览器。

暂时实现的只有get请求代理,其他类型请求自行修改吧。

实现思路

流程

将客户端请求的headers给RestTemplate示例的代理请求的headers
将地址提供给RestTemplate示例
返回的代理响应的headers也设置到客户端请求的response的headers
响应码也设置到客户端请求的response的headers,适应HTTP/206 “Partial Content等情况

技术

使用的重载restTemplate.execute,会对给定的URI模板执行HTTP方法,使用RequestCallback准备请求,并使用ResponseExtractor读取响应。

代码

	punlich void htttGetProxy(HttpServletRequest clientRequest, HttpServletResponse clientResponse,
                                     String url, int windowSize) {
        try {
            Enumeration<String> clientHeaderNames = clientRequest.getHeaderNames();
            HttpHeaders proxyHeaders = new HttpHeaders();
            while (clientHeaderNames.hasMoreElements()) {
                String headerName = clientHeaderNames.nextElement();
                String header = clientRequest.getHeader(headerName);
                proxyHeaders.add(headerName, header);
            }
            RestTemplate restTemplate = new RestTemplate();
            RequestCallback requestCallback = proxyRequest -> proxyRequest.getHeaders().addAll(proxyHeaders);
            restTemplate.execute(url, HttpMethod.GET, requestCallback, proxyResponse -> {
                proxyResponse.getHeaders().forEach((key, value) -> value.forEach(it -> clientResponse.setHeader(key, it)));
                clientResponse.setStatus(proxyResponse.getStatusCode().value());
                copy(proxyResponse.getBody(), clientResponse.getOutputStream(), windowSize);
                return null;
            });
        } catch (Exception e) {
            log.error("http proxy error", e);
            clientResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }
    }

    public static int copy(InputStream in, OutputStream out, int windowSize) throws IOException {
        org.springframework.util.Assert.notNull(in, "No InputStream specified");
        org.springframework.util.Assert.notNull(out, "No OutputStream specified");
        int byteCount = 0;
        int bytesRead;
        for (byte[] buffer = new byte[windowSize]; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
            out.write(buffer, 0, bytesRead);
        }
        out.flush();
        return byteCount;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值