gpt4 book ai didi

java - 如何在WebFlux中正确实现CORS?

转载 作者:行者123 更新时间:2023-12-02 03:06:21 26 4
gpt4 key购买 nike

我想创建一个简单的 Spring Boot/Webflux 服务器来充当 REST API。我目前正在本地尝试测试它。 Webflux 服务器在端口 8080 上运行,我有另一台服务器在端口 3000 上运行提供 html ( React.js )。我想从网站向服务器发出 CORS 请求。为此,我使用 addCorsMappings 方法创建了一个 Java 类,并添加了 @Configuration 注释。我想知道添加注释是否神奇地使 Spring 意识到带注释的类,但根据此 article我还需要在 spring.factories 文件 中添加 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.mypackage.CORSHandler 属性。但是我仍然看到 addCorsMappings 甚至没有被调用(我没有看到日志消息)。作为 Spring Boot 的新手,我还缺少其他配置吗?

这是我的主课:

package com.mypackage;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import reactor.ipc.netty.http.server.HttpServer;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;

public class Server {
private static final Logger log = LogManager.getLogger(Server.class);
public static final String HOST = "localhost";
public static final int PORT = 8080;

public static void main(String[] args) throws Exception {
Server server = new Server();
server.startReactorServer();

System.out.println("Press ENTER to exit.");
System.in.read();
}

public RouterFunction<ServerResponse> routingFunction() {
PersonRepository repository = new DummyPersonRepository();
PersonHandler handler = new PersonHandler(repository);

return nest(path("/person"),
nest(accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getPerson)
.andRoute(method(HttpMethod.GET), handler::listPeople)
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson));
}

public void startReactorServer() {
RouterFunction<ServerResponse> route = routingFunction().filter((request, next) -> {
log.warn(request.path());

if (request.path().contains("person")) {
log.warn("calling next()");
return next.handle(request);
} else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});

HttpHandler httpHandler = toHttpHandler(route);

ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();

}
}

这是我的 CORSHandler 类:

package com.mypackage;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

@Configuration
public class CORSHandler implements WebFluxConfigurer {
private static final Logger log = LogManager.getLogger(CORSHandler.class);

@Override
public void addCorsMappings(CorsRegistry registry) {
log.warn("from addCorsMappings!!");
registry.addMapping("*")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("Content-Type", "Access-Control-Allow-Headers", "Authorization",
"X-Requested-With", "mode")
.allowCredentials(true);
}
}

最佳答案

我目前找到的解决方案是,包含配置方法的类需要作为 AnnotationConfigApplicationContext 上下文的参数。需要将上下文作为参数提供给 WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route)).applicationContext(context)。所以主类看起来像这样:

package com.mypackage;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import reactor.ipc.netty.http.server.HttpServer;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;

@SpringBootApplication
public class Server {
private static final Logger log = LogManager.getLogger(Server.class);
public static final String HOST = "localhost";
public static final int PORT = 8080;

public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CorsConfiguration.class);
Server server = new Server();
server.startReactorServer(ctx);

System.out.println("Press ENTER to exit.");
System.in.read();
}

public RouterFunction<ServerResponse> routingFunction() {
PersonRepository repository = new DummyPersonRepository();
PersonHandler handler = new PersonHandler(repository);

return nest(path("/person"),
nest(accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getPerson)
.andRoute(method(HttpMethod.GET), handler::listPeople)
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson));
}

public void startReactorServer(AnnotationConfigApplicationContext ctx) {
RouterFunction<ServerResponse> route = this.routingFunction().filter((request, next) -> {
log.warn(request.path());

if (request.path().contains("person")) {
log.warn("calling next()");
return next.handle(request);
} else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});

HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route))
.applicationContext(ctx).build();

ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();
}
}

CorsConfiguration类看起来像这样:

package com.mypackage;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Configuration
@EnableWebFlux
public class CorsConfiguration {

private static final Logger log = LogManager.getLogger(CorsConfiguration.class);

private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN, mode";
private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS";
private static final String ALLOWED_ORIGIN = "*";
private static final String MAX_AGE = "3600";

@Bean
public WebFilter corsFilter() {
log.warn("from CorsConfiguration!!!");
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
log.warn("after ServerHttpRequest");
if (CorsUtils.isCorsRequest(request)) {
log.warn("inside isCorsRequest");
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}

在此代码中,调用 corsFilter 并设置 CORS header ,但路由不起作用(返回 404 状态)。

关于java - 如何在WebFlux中正确实现CORS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57021156/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com