You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Camel Rest DSL搭配Jetty组件时CORS响应头填充异常问题咨询

解决Camel Rest DSL + Jetty下动态匹配CORS Origin的问题

Camel Rest DSL的默认CORS处理逻辑会直接将配置的Access-Control-Allow-Origin值原样返回,不会根据请求的Origin头动态匹配并返回对应值。要实现匹配允许列表返回请求Origin、不匹配则返回错误的需求,需要绕过Camel的默认CORS配置,通过自定义逻辑处理,以下是两种可行方案:

方案一:自定义Processor拦截处理CORS逻辑

  1. 关闭Camel默认CORS配置
    删掉或注释掉原配置中所有camel.rest.cors-headers相关项,避免Camel覆盖自定义响应头。

  2. 编写动态CORS处理Processor
    实现Camel的Processor接口,在其中完成Origin校验、响应头设置和OPTIONS预检请求处理:

    import org.apache.camel.Exchange;
    import org.apache.camel.Processor;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    public class DynamicCorsProcessor implements Processor {
        // 允许的Origin规则集合
        private final Set<String> allowedOriginPatterns = Set.of(
            "*.example.com", "*.example1.com", "*.example2.com"
        );
    
        @Override
        public void process(Exchange exchange) throws Exception {
            HttpServletRequest request = exchange.getIn().getBody(HttpServletRequest.class);
            String requestOrigin = request.getHeader("Origin");
    
            // 跳过非跨域请求(无Origin头)
            if (requestOrigin == null) {
                return;
            }
    
            // 校验请求Origin是否匹配允许规则
            boolean isAllowed = allowedOriginPatterns.stream()
                .anyMatch(pattern -> {
                    // 将通配符转为正则表达式
                    String regex = pattern.replace("*", ".*").replace(".", "\\.");
                    return Pattern.compile(regex).matcher(requestOrigin).matches();
                });
    
            if (isAllowed) {
                // 设置CORS响应头
                exchange.getOut().setHeader("Access-Control-Allow-Origin", requestOrigin);
                exchange.getOut().setHeader("Access-Control-Allow-Credentials", "true");
                exchange.getOut().setHeader("Access-Control-Max-Age", "3600");
                exchange.getOut().setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH");
                exchange.getOut().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent, Authorization, x-omit");
    
                // 处理OPTIONS预检请求,直接返回200
                if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                    exchange.getOut().setHeader(Exchange.HTTP_RESPONSE_CODE, 200);
                    exchange.getOut().setBody(null);
                }
            } else {
                // 不允许的Origin,返回403错误
                exchange.getOut().setHeader(Exchange.HTTP_RESPONSE_CODE, 403);
                exchange.getOut().setBody("Invalid Origin");
            }
        }
    }
    
  3. 绑定Processor到路由
    可以将Processor绑定到单个Rest路由,或者通过全局拦截器作用于所有Jetty端点:

    // 单个路由绑定
    restConfiguration().component("jetty").port(8080);
    rest("/api")
        .get("/resource")
        .route()
        .process(new DynamicCorsProcessor())
        .to("direct:handleResource");
    
    // 全局拦截所有Jetty请求
    interceptFrom("jetty:*")
        .process(new DynamicCorsProcessor());
    

方案二:集成Jetty原生CorsFilter

Jetty自带的CorsFilter支持动态匹配请求Origin,且优先级高于Camel的默认处理,步骤如下:

  1. 关闭Camel默认CORS配置
    同方案一,移除所有camel.rest.cors-headers配置。

  2. 配置Jetty CorsFilter并集成Camel
    手动创建Jetty服务器和上下文,添加CorsFilter后绑定Camel的Servlet:

    import org.apache.camel.component.jetty.CamelHttpTransportServlet;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.servlet.ServletHolder;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    import org.eclipse.jetty.servlets.CorsFilter;
    import javax.servlet.DispatcherType;
    import java.util.EnumSet;
    
    public class JettyCorsSetup {
        public static void main(String[] args) throws Exception {
            // 初始化Jetty服务器
            Server jettyServer = new Server(8080);
    
            // 创建Servlet上下文
            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");
    
            // 配置Jetty CorsFilter
            CorsFilter corsFilter = new CorsFilter();
            corsFilter.setAllowedOrigins("*.example.com,*.example1.com,*.example2.com");
            corsFilter.setAllowedMethods("GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH");
            corsFilter.setAllowedHeaders("Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent, Authorization, x-omit");
            corsFilter.setAllowCredentials(true);
            corsFilter.setMaxAge(3600);
            corsFilter.setAllowOriginRegex(true); // 启用正则匹配通配符规则
            context.addFilter(corsFilter, "/*", EnumSet.allOf(DispatcherType.class));
    
            // 绑定Camel Servlet到上下文
            ServletHolder camelServletHolder = new ServletHolder(new CamelHttpTransportServlet());
            context.addServlet(camelServletHolder, "/api/*");
    
            // 启动Jetty
            jettyServer.setHandler(context);
            jettyServer.start();
    
            // 初始化Camel上下文和路由
            org.apache.camel.CamelContext camelContext = new org.apache.camel.impl.DefaultCamelContext();
            camelContext.addRoutes(new org.apache.camel.builder.RouteBuilder() {
                @Override
                public void configure() throws Exception {
                    rest("/api")
                        .get("/resource")
                        .to("direct:handleResource");
    
                    from("direct:handleResource")
                        .setBody(constant("Success"));
                }
            });
            camelContext.start();
        }
    }
    

注意事项

  • 必须确保Camel的默认CORS配置已完全关闭,否则会覆盖自定义设置的响应头。
  • 通配符匹配时,*.example.com会匹配sub.example.com但不会匹配example.com,如果需要包含顶级域名,需单独添加example.com到允许列表。
  • 对于OPTIONS预检请求,需确保返回正确的响应头和200状态码,否则浏览器会阻止后续请求。

内容的提问来源于stack exchange,提问作者Navinya Shende

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:20:24