在创建React App项目时,将其代理到Spring Boot进行开发
由於在開發中的create-react-app創建的項目中,我在配置中設置代理以將其連接到Spring Boot應用程序時遇到了困難,所以在這裡記錄一下。
create-react-app的版本為5.0.1,Spring Boot的版本為2.7.3。
如果可以通过代理选项来解决,就没有问题。
参考Proxying API Requests in Development方法。
"proxy": "http://localhost:8080"
只需添加
这样的配合是可能的。很简单吧。
只需注意的是,仅在浏览器请求的Accept头中没有text/html时才会被代理。
在手动设置代理时出现问题
例如,对于我的情况而言,需要进行文件下载处理,并且必须放弃使用代理选项。因此,我参考了文档。
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:8080',
changeOrigin: true,
})
);
app.use(
'/resource',
createProxyMiddleware({
target: 'http://localhost:8080',
changeOrigin: true,
})
);
};
在尝试时,所有与Spring Boot的通信都返回了403禁止访问错误。响应消息的正文中包含了“无效的CORS请求”的内容。
造成这个结果的因素
当比较使用代理选项和手动设置时,我们可以确认在Spring Boot端的行为差异,这是由CorsFilter进行调用的。
public class DefaultCorsProcessor implements CorsProcessor {
public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request,
HttpServletResponse response) throws IOException {
〜 省略 〜
if (!CorsUtils.isCorsRequest(request)) {
return true;
}
在`CorsUtils.isCorsRequest`方法中,前者被判定为`false`,表示不是跨域请求,而后者被判定为跨域请求。
在`CorsUtils.isCorsRequest`方法内部,当`host`头和`origin`头的方案(schema)、主机名、端口号中任意一项不相同时,将被判定为跨域请求。
在每个设置中,Spring Boot接收的值如下所示。
- hostヘッダにないスキーマは、HttpServletRequest.getScheme()より取得。この値は、Tomcatの場合、受信したコネクタで決まる。
换句话说,
-
- changeOriginという名前のイメージと異なり、hostヘッダが変わって、originヘッダは変わりません。
- changeOrigin: false (デフォルト)なら、実態と異なるhostヘッダの値である気持ち悪さはありますが、CORSでエラーにはなりません。
所以,本以为通过设置为true来避免CORS问题,结果却不小心陷入了CORS问题,唉。。。orz
处理
尽管本来不应该忽略CORS设置,但由于目前正在开发中,我选择保持changeOrigin: true,并禁用Spring Boot端的CORS检查。
如果使用GraphQL Java Kickstart的GraphQL Spring Boot,则以下是配置。
graphql:
servlet:
cors-enabled: false