亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

用springboot搭建http轉發服務器

2024-01-02 02:13:55
187
0

說到http轉發,很容易想到用Nginx,因為Nginx性能好,配置簡單。但如果希望能動態配置路由規則,或者在轉發時增加自己的邏輯,使用Nginx就比較難實現。

本文將講述如何使用springboot來搭建一個http轉發服務器,實現http請求的動態轉發。

實現http轉發服務器,需要兩個東西:

1)請求轉發器,負責接收請求以及轉發請求

2)轉發規則

 

先說轉發規則,轉發規則可以用一張表(proxy_route)來儲存,主要字段如下:

1)prefix,請求前綴

2)targetUrl,轉發地址

3)description,規則說明

 

錄好轉發規則后,后面直接上轉發器的代碼

@RestController
@RequestMapping(ProxyController.PROXY_PREFIX)
public class ProxyController {
	public final static String PROXY_PREFIX = "/proxy";

	@Autowired
	private ServletContext servletContext;

	@Autowired
	private IProxyService proxyService;

        // 待轉發的請求總入口
	@RequestMapping(value = "/**")
	public ResponseEntity<?> catchAll(HttpServletRequest request, HttpServletResponse response) {
		// String tenantId = 從session中獲取租戶ID;

		String prefix = "/" + servletContext.getContextPath() + "/" + PROXY_PREFIX;
		prefix = prefix.replaceAll("/+", "/");
		// 獲取 /** 內容
		String uri = request.getRequestURI();
		String targetPath = uri.substring(prefix.length());
		return proxyService.redirect(tenantId, request, response, targetPath);
	}
}

 

@Service
public class ProxyServiceImpl implements IProxyService {

	private RestTemplate restTemplate;

	@PostConstruct
	private void init() {
		restTemplate = new RestTemplate();
		restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
	}

	@Override
	public ResponseEntity<?> redirect(String tenantId, HttpServletRequest request, HttpServletResponse response,
			String targetPath) {
		String redirectUrl = null;
		try {
			// build up the redirect URL
			redirectUrl = createRedictUrl(tenantId, request, targetPath);
			RequestEntity<?> requestEntity = createRequestEntity(request, redirectUrl);
			return route(requestEntity);
		} catch (ProxyRouteNotFoundException e) {
			log.error("找不到符合的轉發路由:" + targetPath, e);
			return new ResponseEntity<String>("Proxy Route Not Found", HttpStatus.BAD_REQUEST);
		} catch (Exception e) {
			log.error("請求轉發[" + targetPath + "]失敗", e);
			return new ResponseEntity<String>("REDIRECT ERROR: " + e.getMessage() + ", URL: " + redirectUrl,
					HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	private String createRedictUrl(String tenantId, HttpServletRequest request, String targetPath) {
		String queryString = request.getQueryString();
		String targetUrl = getTargetUrl(tenantId, targetPath);
		return targetUrl + (queryString != null ? "?" + queryString : "");
	}

	private String getTargetUrl(String tenantId, String targetPath) {
		// 尋找匹配的轉發規則
	}

	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);
		Object body = parseRequestBody(request);
		return new RequestEntity<>(body, headers, httpMethod, new URI(url));
	}

	private ResponseEntity<?> route(RequestEntity<?> requestEntity) {
		RestTemplate restTemplate = new RestTemplate();
		ResponseEntity<byte[]> response = restTemplate.exchange(requestEntity, byte[].class);
		return response;
	}

	private Object parseRequestBody(HttpServletRequest request) throws IOException {
		InputStream inputStream = request.getInputStream();
		return StreamUtils.copyToByteArray(inputStream);
	}

	private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) throws IOException {
		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;
	}
}

 

如果有上傳文件的請求轉發需求,則需要修改下,其中MultipartFileResource類是spring 5.1以上才有,5.1以下的項目可以直接把這個類拷到自己項目中使用。

        private Object parseRequestBody(HttpServletRequest request) throws IOException {
		// 支持文件上傳
		if (request instanceof StandardMultipartHttpServletRequest) {
			StandardMultipartHttpServletRequest fileReq = (StandardMultipartHttpServletRequest) request;
			MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
			for (String key : fileReq.getFileMap().keySet()) {
				parts.add(key, new MultipartFileResource(fileReq.getFile(key)));
			}
			return parts;
		}
		InputStream inputStream = request.getInputStream();
		return StreamUtils.copyToByteArray(inputStream);
	}

 

上述http請求轉發器,雖然性能比不上Nginx,但可以動態實現http請求的轉發,也方便加入自己的業務邏輯。

0條評論
0 / 1000
白龍馬
14文章數
0粉絲數
白龍馬
14 文章 | 0 粉絲
原創

用springboot搭建http轉發服務器

2024-01-02 02:13:55
187
0

說到http轉發,很容易想到用Nginx,因為Nginx性能好,配置簡單。但如果希望能動態配置路由規則,或者在轉發時增加自己的邏輯,使用Nginx就比較難實現。

本文將講述如何使用springboot來搭建一個http轉發服務器,實現http請求的動態轉發。

實現http轉發服務器,需要兩個東西:

1)請求轉發器,負責接收請求以及轉發請求

2)轉發規則

 

先說轉發規則,轉發規則可以用一張表(proxy_route)來儲存,主要字段如下:

1)prefix,請求前綴

2)targetUrl,轉發地址

3)description,規則說明

 

錄好轉發規則后,后面直接上轉發器的代碼

@RestController
@RequestMapping(ProxyController.PROXY_PREFIX)
public class ProxyController {
	public final static String PROXY_PREFIX = "/proxy";

	@Autowired
	private ServletContext servletContext;

	@Autowired
	private IProxyService proxyService;

        // 待轉發的請求總入口
	@RequestMapping(value = "/**")
	public ResponseEntity<?> catchAll(HttpServletRequest request, HttpServletResponse response) {
		// String tenantId = 從session中獲取租戶ID;

		String prefix = "/" + servletContext.getContextPath() + "/" + PROXY_PREFIX;
		prefix = prefix.replaceAll("/+", "/");
		// 獲取 /** 內容
		String uri = request.getRequestURI();
		String targetPath = uri.substring(prefix.length());
		return proxyService.redirect(tenantId, request, response, targetPath);
	}
}

 

@Service
public class ProxyServiceImpl implements IProxyService {

	private RestTemplate restTemplate;

	@PostConstruct
	private void init() {
		restTemplate = new RestTemplate();
		restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
	}

	@Override
	public ResponseEntity<?> redirect(String tenantId, HttpServletRequest request, HttpServletResponse response,
			String targetPath) {
		String redirectUrl = null;
		try {
			// build up the redirect URL
			redirectUrl = createRedictUrl(tenantId, request, targetPath);
			RequestEntity<?> requestEntity = createRequestEntity(request, redirectUrl);
			return route(requestEntity);
		} catch (ProxyRouteNotFoundException e) {
			log.error("找不到符合的轉發路由:" + targetPath, e);
			return new ResponseEntity<String>("Proxy Route Not Found", HttpStatus.BAD_REQUEST);
		} catch (Exception e) {
			log.error("請求轉發[" + targetPath + "]失敗", e);
			return new ResponseEntity<String>("REDIRECT ERROR: " + e.getMessage() + ", URL: " + redirectUrl,
					HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	private String createRedictUrl(String tenantId, HttpServletRequest request, String targetPath) {
		String queryString = request.getQueryString();
		String targetUrl = getTargetUrl(tenantId, targetPath);
		return targetUrl + (queryString != null ? "?" + queryString : "");
	}

	private String getTargetUrl(String tenantId, String targetPath) {
		// 尋找匹配的轉發規則
	}

	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);
		Object body = parseRequestBody(request);
		return new RequestEntity<>(body, headers, httpMethod, new URI(url));
	}

	private ResponseEntity<?> route(RequestEntity<?> requestEntity) {
		RestTemplate restTemplate = new RestTemplate();
		ResponseEntity<byte[]> response = restTemplate.exchange(requestEntity, byte[].class);
		return response;
	}

	private Object parseRequestBody(HttpServletRequest request) throws IOException {
		InputStream inputStream = request.getInputStream();
		return StreamUtils.copyToByteArray(inputStream);
	}

	private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) throws IOException {
		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;
	}
}

 

如果有上傳文件的請求轉發需求,則需要修改下,其中MultipartFileResource類是spring 5.1以上才有,5.1以下的項目可以直接把這個類拷到自己項目中使用。

        private Object parseRequestBody(HttpServletRequest request) throws IOException {
		// 支持文件上傳
		if (request instanceof StandardMultipartHttpServletRequest) {
			StandardMultipartHttpServletRequest fileReq = (StandardMultipartHttpServletRequest) request;
			MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
			for (String key : fileReq.getFileMap().keySet()) {
				parts.add(key, new MultipartFileResource(fileReq.getFile(key)));
			}
			return parts;
		}
		InputStream inputStream = request.getInputStream();
		return StreamUtils.copyToByteArray(inputStream);
	}

 

上述http請求轉發器,雖然性能比不上Nginx,但可以動態實現http請求的轉發,也方便加入自己的業務邏輯。

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0