X-Accel-Redirect
這篇博客來源於團隊最近的項目方案。團隊最近接了一些合作項目,合作項目免不了要加密/解密、加簽/解籤來保證基本的信息安全。以前,業務團隊是有一套標準的算法供合作方接入,不過難免有些合作項目要按對方的標準來接入。
- 方案一:業務團隊都是針對合作方開發,定製接口;
- 方案二:架一個適配層系統,將業務解放出來。
方案一對業務系統侵入大,而且開發、維護成本高,方案二比較好。但是適配層系統如何將請求轉發到業務系統?nginx提供的內部重定向(X-Accel-Redirect)機制是一個比較好的方式。適配層系統在處理完特殊的解籤後,在response里加一個header(X-Accel-Redirect)指定請求轉發的路徑(業務標準實現的路徑),nginx收到響應報文不會返回給客戶端,而是從指定的業務路徑中請求內容返回客戶端。
用了X-Accel-Redirect機制以後,對外合作項目的請求到達業務系統已經是標準的結構了。請求路徑如下:
爲什麼用內部重定向而不直接用重定向,內部重定向有以下幾點優勢:
- 用戶感覺不到跳轉;
- 業務標準的路徑不用暴露;
- 少一次網絡請求。
舉例
寫兩個接口(/focuse/hello、/focuse/hello2),其中/focuse/hello返回時設置"Accel-Redirect=/focuse/hello2"。我們請求/focuse/hello期望輸出"redirect to hello2!",而不是"hello world!"
/**
* @author :
* @date :Created in 2020/5/15 下午11:56
* @description:
* @modified By:
*/
@RestController
@RequestMapping("/focuse")
public class WebSiteController {
@RequestMapping("hello")
public String hello(HttpServletResponse response) throws Exception{
response.setHeader("X-Accel-Redirect", "/focuse/hello2?custom=" + URLEncoder.encode("redirect to hello2!", "UTF-8"));
return "hello world!";
}
@RequestMapping(value = "hello2")
public String hello2(@RequestParam("custom") String custom) {
return custom;
}
}
啓動應用,端口是8080
配置nginx並啓動,nginx監聽的端口是80,nginx配置80請求代理到8080端口
server {
listen 80;
location / {
proxy_pass http://$host:8080;
}
}
請求:http://127.0.0.1/focuse/hello 輸出redirect to hello2,並且瀏覽器地址欄還是focuse/hello(用戶無感知)