首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在webflux中使用WebFilter corsFilter时,为什么请求返回404状态?

在webflux中使用WebFilter corsFilter时,为什么请求返回404状态?
EN

Stack Overflow用户
提问于 2019-07-15 05:00:56
回答 1查看 651关注 0票数 0

我想使用函数端点在Spring Webflux中构建一个REST api。对于CORS,我使用WebFilter corsFilter方法来设置所需的标头。我确实看到该方法被调用(我看到了来自它的日志消息),并且我看到响应上的头确实是我在Webflux api中设置的头。但是,一旦我开始使用corsFilter,请求就会返回404状态(之前它们会返回JSON)。我怀疑corsFilter不会将请求传递给路由器功能。为什么会这样呢?

具体地说,我想知道这一行是否足以连接cors配置和路由:

代码语言:javascript
运行
复制
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route))
        .applicationContext(ctx).build();

这是我的主类:

代码语言:javascript
运行
复制
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();
    }
}

这是我的CORS配置类:

代码语言:javascript
运行
复制
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);
        };
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-16 02:29:07

为了在定义端点时使用函数式方法,Spring Boot的官方文档提供了一个非常简单的示例。

FooBarApplication.class这是我们的主类。

代码语言:javascript
运行
复制
@SpringBootApplication
public class FooBarApplication {

    public static void main(String[] args) {
        SpringApplication.run(FooBarApplication.class, args);
    }

}

RoutingConfiguration.class (或者你想叫它的任何东西)

代码语言:javascript
运行
复制
@Configuration
public class RoutingConfiguration {

    @Bean
    public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
        return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
                .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
                .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
    }

}

@Component
public class UserHandler {

    public Mono<ServerResponse> getUser(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> deleteUser(ServerRequest request) {
        // ...
    }
}

任何带有@Configuration注释的类都将在启动时运行,并运行所有带有@Bean注释的方法。因此,这将运行monoRouterFunction并为我们设置所有路由。

示例取自官方spring boot文档Spring boot webflux向下滚动一点。

编辑:作为附注,@EnableWebFlux注释意味着您将禁用webflux的自动配置,并手动设置upp配置。如果你刚刚开始(我知道这个名字很容易误导),我不建议你这样做。你可以在这里阅读Spring WebFlux Auto-configuration的webflux自动配置。

EDIT2: WebFlux有一个内置的CorsFilter,您只需对其进行配置即可使用。

代码语言:javascript
运行
复制
@Bean
CorsWebFilter corsWebFilter() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowedOrigins(Arrays.asList("http://allowed-origin.com"));
    corsConfig.setMaxAge(8000L);
    corsConfig.addAllowedMethod("PUT");
    corsConfig.addAllowedHeader("Baeldung-Allowed");

    UrlBasedCorsConfigurationSource source =
  new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);

    return new CorsWebFilter(source);
}

取自Enabling CORS with a WebFilter的示例

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57031142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档