时间:2021-05-19
在我们的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;@Servicepublic 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); }}到此这篇关于spring boot实现超轻量级网关(反向代理、转发)的文章就介绍到这了,更多相关spring boot轻量级网关内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
一、前言 nginx作为目前更流行的开源反向代理HTTPServer,用于实现资源缓存、webserver负载均衡等功能,由于其轻量级、高性能、高可靠等特点在
NginxNginx简单介绍一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器Nginx命令参数nginx-t测试配置是否正确n
一、什么是Spring?Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架二、如何在程序中获取Spring配置的bean呢?方法一:在初
一、简介这是一款基于JS实现的超轻量级桌面版聊天软件。主要适用于私有云项目内部聊天,企业内部管理通讯等功能,主要通讯协议websocket。也支持web网页聊天
反向代理(ReverseProxy)是什么?反向代理(ReverseProxy)是指以代理服务器来接受Internet上的连接请求,将请求转发给内部或者其他网络