spring boot实现超轻量级网关(反向代理、转发)
在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景。可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定。
如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式、HTTP header,以及请求body,我们将这些信息取出来,透传给转发的url即可。
举例:
/graphdb/** 转发到 Graph_Server/**
获取转发目的地址:
private String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) {
String queryString = request.getQueryString();
return routeUrl + request.getRequestURI().replace(prefix, "") +
(queryString != null ? "?" + queryString : "");
}
解析请求头和内容
然后从request中提取出header、body等内容,构造一个RequestEntity
,后续可以用RestTemplate
来请求。
private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException {
String method = request.getMethod();
HttpMethod httpMethod = HttpMethod.resolve(method);
MultiValueMap<String, String> headers = parseRequestHeader(request);
byte[] body = parseRequestBody(request);
return new RequestEntity<>(body, headers, httpMethod, new URI(url));
}
private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
InputStream inputStream = request.getInputStream();
return StreamUtils.copyToByteArray(inputStream);
}
private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders();
List<String> headerNames = Collections.list(request.getHeaderNames());
for (String headerName : headerNames) {
List<String> headerValues = Collections.list(request.getHeaders(headerName));
for (String headerValue : headerValues) {
headers.add(headerName, headerValue);
}
}
return headers;
}
透明转发
最后用RestTemplate
来实现请求:
private ResponseEntity<String> route(RequestEntity requestEntity) {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.exchange(requestEntity, String.class);
}
全部代码
以下是轻量级转发全部代码:
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
@Service
public class RoutingDelegate {
public ResponseEntity<String> redirect(HttpServletRequest request, HttpServletResponse response,String routeUrl, String prefix) {
try {
// build up the redirect URL
String redirectUrl = createRedictUrl(request,routeUrl, prefix);
RequestEntity requestEntity = createRequestEntity(request, redirectUrl);
return route(requestEntity);
} catch (Exception e) {
return new ResponseEntity("REDIRECT ERROR", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) {
String queryString = request.getQueryString();
return routeUrl + request.getRequestURI().replace(prefix, "") +
(queryString != null ? "?" + queryString : "");
}
private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException {
String method = request.getMethod();
HttpMethod httpMethod = HttpMethod.resolve(method);
MultiValueMap<String, String> headers = parseRequestHeader(request);
byte[] body = parseRequestBody(request);
return new RequestEntity<>(body, headers, httpMethod, new URI(url));
}
private ResponseEntity<String> route(RequestEntity requestEntity) {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.exchange(requestEntity, String.class);
}
private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
InputStream inputStream = request.getInputStream();
return StreamUtils.copyToByteArray(inputStream);
}
private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders();
List<String> headerNames = Collections.list(request.getHeaderNames());
for (String headerName : headerNames) {
List<String> headerValues = Collections.list(request.getHeaders(headerName));
for (String headerValue : headerValues) {
headers.add(headerName, headerValue);
}
}
return headers;
}
}
Spring 集成
Spring Controller,RequestMapping里把GET \ POST\PUT\DELETE 支持的请求带上,就能实现转发了。
@RestController
@RequestMapping(GraphDBController.DELEGATE_PREFIX)
@Api(value = "GraphDB", tags = {
"graphdb-Api"
})
public class GraphDBController {
@Autowired
GraphProperties graphProperties;
public final static String DELEGATE_PREFIX = "/graphdb";
@Autowired
private RoutingDelegate routingDelegate;
@RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity catchAll(HttpServletRequest request, HttpServletResponse response) {
return routingDelegate.redirect(request, response, graphProperties.getGraphServer(), DELEGATE_PREFIX);
}
}
分类: java编程
标签: java
+加关注
3
0
« 上一篇: hugegraph 支持sparql 与cypher
» 下一篇: hugegraph 存取数据解析
posted @ 2020-11-18 10:11 JadePeng 阅读(13349) 评论(4) 编辑 收藏 举报
登录后才能查看或发表评论,立即 登录 或者 逛逛 博客园首页
【推荐】在 ASP.NET Core 中运行 WebForms 业务代码
【推荐】园子周边第二季:更大的鼠标垫,没有logo的鼠标垫
【推荐】阿里云云市场联合博客园推出开发者商店,欢迎关注
【推荐】会员力量,点亮园子希望,期待您升级成为园子会员
编辑推荐:
· 日常 Bug 排查 - 连接突然全部关闭
· 「动画进阶」极具创意的鼠标交互动画
· WPF 稳定的全屏化窗口方法
· 云服务器遭到黑客入侵植入木马病毒排查过程
· HTTPS 是如何进行安全传输的 ?
阅读排行:
· 一个不知名的开源项目可以带来多少收入
· 厉害了!12秒将百万数据通过EasyExcel导入MySQL数据库中
· 日常Bug排查-连接突然全部关闭
· Visual Studio中的四款代码格式化工具
· C#.Net筑基-模式匹配汇总
公告
欢迎关注作者微信公众号, 一起交流软件开发
关注作者同名微信公众号
昵称: JadePeng
园龄: 15年8个月
粉丝: 353
关注: 22
+加关注
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
28 | 29 | 30 | 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 | 1 | |||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
搜索
常用链接
最新随笔
- 1.LLM生态下爬虫程序的现状与未来
- 2.浅谈sparse vec检索工程化实现
- 3.BGE M3-Embedding 模型介绍
- 4.Sparse稀疏检索介绍与实践
- 5.知识图谱增强的KG-RAG框架
- 6.知识图谱在RAG中的应用探讨
- 7.深度解读RAGFlow的深度文档理解DeepDoc
- 8.RAG 范式、技术和趋势
- 9.In-batch negatives Embedding模型介绍与实践
- 10.ReACT介绍与llama_index ReActAgent实践
我的标签
积分与排名
- 积分 - 440046
- 排名 - 1627
随笔分类 (217)
- ASP.NET编程(12)
- java编程(64)
- jenkins X实践系列(4)
- LLM相关(11)
- 编程周边(26)
- 机器学习(14)
- 架构与选型(14)
- 前端开发(21)
- 搜索引擎(14)
- 移动开发(6)
- 云原生开发(17)
- 知识图谱(14)
随笔档案 (222)
- 2024年5月(1)
- 2024年4月(6)
- 2024年3月(5)
- 2024年2月(4)
- 2024年1月(4)
- 2023年12月(1)
- 2023年10月(1)
- 2023年9月(2)
- 2023年7月(1)
- 2023年2月(2)
- 2022年12月(2)
- 2022年5月(1)
- 2022年3月(1)
- 2021年12月(3)
- 2021年11月(1)
- 更多
阅读排行榜
- 1. Spring Boot配置文件放在jar外部(97399)
- 2. \x 开头编码的数据解码成中文(91256)
- 3. spring security实现动态配置url权限的两种方法(62346)
- 4. Docker+Jenkins持续集成环境(1)使用Docker搭建Jenkins+Docker持续集成环境(61949)
- 5. 基于spring security 实现前后端分离项目权限控制(60346)
评论排行榜
- 1. asp.net MVC 权限设计(续)(65)
- 2. asp.net MVC 权限设计(51)
- 3. 网易云音乐无版权音乐补全工具(24)
- 4. 使用贝叶斯做英文拼写检查(c#)(15)
- 5. 10款精选的用于构建良好易用性网站的jQuery插件(15)
推荐排行榜
- 1. 网易云音乐无版权音乐补全工具(46)
- 2. asp.net MVC 权限设计(续)(23)
- 3. Spring Boot配置文件放在jar外部(17)
- 4. 开源工具软件XMusicDownloader——音乐下载神器(16)
- 5. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南(16)
最新评论
- 1. Re:RAG 范式、技术和趋势
-
要不你转战知乎吧
- --b612小王子
- 2. Re:RAG 范式、技术和趋势
-
不错啊,怎么没人点点赞,多好的文章!
- --b612小王子
- 3. Re:知识图谱在RAG中的应用探讨
-
云里雾里
- --bluce chen
- 4. Re:知识图谱在RAG中的应用探讨
-
RGA是啥
- --daconglee
- 5. Re:IDEA看代码必备插件Call Graph 介绍及使用方法
- @JadePeng 公司的内容不能完全暴露给外部啊,,,有本地运行的大模型能胜任么,😔...
- --Cat-shark