Spring boot implements ultra lightweight gateway (reverse proxy and forwarding)

In our rest service, a middleware interface needs to be exposed to users, but it needs to be authenticated by the rest service. This is a typical gateway usage scenario. Gateway components can be introduced, but the introduction of zuul and other middleware will increase the system complexity. Here, an ultra lightweight gateway is implemented, which only realizes request forwarding and authentication, which are handled by spring security of rest service.

How to forward requests? Students familiar with network requests should be very clear that requests are nothing more than the request method, HTTP header and request body. We can take out these information and pass it through to the forwarded URL.

give an example:

/Graphdb / * * forward to graph_ Server/**

Get forwarding destination address:

private String createRedictUrl(HttpServletRequest request,String routeUrl,String prefix) {
        String queryString = request.getQueryString();
        return routeUrl + request.getRequestURI().replace(prefix,"") +
                (queryString != null ? "?" + queryString : "");
    }

Parse request header and content

Then extract the header, body and other contents from the request to construct a requestentity, which can be requested later with 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;
    }

Transparent forwarding

Finally, resttemplate is used to implement the request:

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

All codes

The following is the full code of lightweight forwarding:

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 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,"") +
                (queryString != null ? "?" + queryString : "");
    }


    private RequestEntity createRequestEntity(HttpServletRequest request,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,headerValue);
            }
        }
        return headers;
    }
}

Spring integration

In spring controller, you can forward the request supported by get \ post \ put \ delete in requestmapping.

@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);
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>