在创建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"

只需添加

undefined

这样的配合是可能的。很简单吧。

只需注意的是,仅在浏览器请求的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ヘッダoriginヘッダproxyオブションlocalhost:8080http://localhost:8080手動設定(changeOrigin: true)localhost:8080http://localhost:3000手動設定(changeOrigin: false)localhost:3000http://localhost:3000
    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
广告
将在 10 秒后关闭
bannerAds