在React中,在POST请求之前禁用OPTIONS请求。

3

我有一个基于Typescript的React应用程序,托管在我的个人电脑上。我使用Spring gateway将请求转发到另一个微服务。GET请求运行良好,但对于POST请求,我会收到以下错误信息:

跨域资源共享(CORS)策略阻止了从' http://localhost:3000 '到'http://1.1.1.1:8080/api/support/tickets/create'的XMLHttpRequest访问,被请求的资源未包含响应头中的Access-Control-Allow-Origin,拒绝访问。

我遇到了这个Spring Cloud Gateway问题:https://github.com/spring-cloud/spring-cloud-gateway/issues/229

Spring Cloud配置如下:

@Bean
public RouteLocator routes(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingFactory) {
    return builder.routes()
            .route("route_id",
                    route -> route
                            .path("/api/support/tickets/**")
                            .filters(f -> f.rewritePath("/api/support/tickets/(?<RID>.*)", "/support/tickets/${RID}"))
                            .uri("lb://merchant-hub-admin-service")
            )
            .build();
}

React 代码:

export async function getTicket(id: string) {
  return await axios.get(`${baseUrl}/support/tickets/ticket/${id}`);
}

export async function postTicket(
  data: TicketFullDTO
): Promise<AxiosResponse<TicketFullDTO>> {
  return await axios.post<TicketFullDTO>(
    `${baseUrl}/support/tickets/create`, data);
}

这是由于购买 Spring Cloud Gateway 引起的:https://github.com/spring-cloud/spring-cloud-gateway/issues/2472 我尝试实现这个解决方案:
@Bean
public RoutePredicateHandlerMapping tusRoutePredicateHandlerMapping(FilteringWebHandler webHandler,
                                                                    RouteLocator routeLocator,
                                                                    GlobalCorsProperties globalCorsProperties,
                                                                    Environment environment) {
    RoutePredicateHandlerMapping routePredicateHandlerMapping = new RoutePredicateHandlerMapping(webHandler,
            routeLocator, globalCorsProperties, environment);
    routePredicateHandlerMapping.setCorsProcessor(new CrackCorsProcessor());
    return routePredicateHandlerMapping;
}

import org.springframework.lang.Nullable;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.DefaultCorsProcessor;
import org.springframework.web.server.ServerWebExchange;

public class CrackCorsProcessor extends DefaultCorsProcessor {
    @Override
    public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exchange) {
        return false;
    }
}

但是它没有起作用。你知道我怎么可以解决这个问题吗?


是的,我尝试过了,但它并没有解决问题。 - Peter Penzov
Postman或类似工具在POST请求中显示哪些响应头? - kevinSpaceyIsKeyserSöze
也许这是一个相关的问题:https://dev59.com/nlUL5IYBdhLWcg3wv6Vx#51666685? - Elias
是的,但它们托管在不同的机器上。当它们在同一台机器上时,CORS会阻止请求。 - Peter Penzov
Cors 关心的是域名,而不是机器。 - Mordechai
显示剩余6条评论
2个回答

3

CORS实际上是浏览器的一个功能,你可以在开发区域中禁用它。

当网站URL和API URL不匹配时,浏览器应该为非匹配的URL调用OPTIONS方法。如果这两个URL不匹配,则浏览器必须调用后端API的OPTIONS方法来获取允许继续进行的权限,在生产环境中,如果你的网站URL和API不匹配,你应该询问你的后端或DevOps团队来解决,但对于开发区域,有一些事情你可以做:

  • if you are using CRA, the previous answer can help you.

  • if you are using custom configuration and you have a Webpack config file, add this line to your Webpack and it can help you:

    module.exports = {
      devServer: {
        proxy: 'http://1.1.1.1:8080',
      },
    
  • another cute way is directly disabling security in your Chrome to have an easy development, put these commands in their related OS and run, you will run a new instance of chrome without security (without OPTIONS call):

    ## macOS
    open -na Google\ Chrome --args --user-data-dir=/tmp/temporary-chrome-profile-dir --disable-web-security --disable-site-isolation-trials
    
    ## windows
    chrome.exe --disable-web-security
    
    ## linux
    google-chrome --disable-web-security
    

欲了解有关上一个项目的更多信息,请阅读此帖子


2

看起来您的问题只涉及本地开发。

创建React应用程序通过支持dev服务器作为代理来解决这个问题,以访问您的API端点。

只需在package.json文件中的proxy键中添加API域名即可。更多信息请查看这里

对于生产环境,您应该将它们都托管在同一域名下(使用反向代理根据URL路径路由静态内容和api请求),或者在后端找到一个永久的Cors友好解决方案。

Cors是浏览器功能,无法禁用。但是,当不使用POST方法时,可以绕过预检但仍无法访问响应主体,除非设置了正确的标头。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接