首页 > 新闻资讯 > >正文

spring boot实现超轻量级网关(反向代理、转发)|今亮点

来源:博客园2023-04-20 19:03:36


(资料图)

spring boot实现超轻量级网关(反向代理、转发)

原文连接 https://www.cnblogs.com/xiaoqi/p/spring-boot-route.html

在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景。可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定。

如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式、HTTP header,以及请求body,我们将这些信息取出来,透传给转发的url即可。

举例:

/router/** 转发到 businessServer/**

获取转发目的地址:

private String createRedirectUrl(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 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 parseRequestHeader(HttpServletRequest request) {        HttpHeaders headers = new HttpHeaders();        List headerNames = Collections.list(request.getHeaderNames());        for (String headerName : headerNames) {            List headerValues = Collections.list(request.getHeaders(headerName));            for (String headerValue : headerValues) {                headers.add(headerName, headerValue);            }        }        return headers;    }

透明转发

最后用RestTemplate来实现请求:

private ResponseEntity route(RequestEntity requestEntity) {        RestTemplate restTemplate = new RestTemplate();        return restTemplate.exchange(requestEntity, String.class);    }

全部代码

以下是轻量级转发全部代码:

import com.jyw.router.miniapp.service.IRouterService;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;/** * @author 黑子桑 * @ClassName IRouterServiceImpl * @Description TODO * @Date 2023/4/20 13:32 **/@Servicepublic class RouterServiceImpl implements IRouterService {    @Override    public ResponseEntity redirect(HttpServletRequest request, HttpServletResponse response,String routeUrl, String prefix) {        try {            // build up the redirect URL            String redirectUrl = createRedirectUrl(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 createRedirectUrl(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 headers = parseRequestHeader(request);        byte[] body = parseRequestBody(request);        return new RequestEntity<>(body, headers, httpMethod, new URI(url));    }    private ResponseEntity 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 parseRequestHeader(HttpServletRequest request) {        HttpHeaders headers = new HttpHeaders();        List headerNames = Collections.list(request.getHeaderNames());        for (String headerName : headerNames) {            List headerValues = Collections.list(request.getHeaders(headerName));            for (String headerValue : headerValues) {                headers.add(headerName, headerValue);            }        }        return headers;    }}

标签:

下一篇:
上一篇: