Shinsuke Sugaya 2 роки тому
батько
коміт
9edc268a96

+ 25 - 0
src/main/java/org/codelibs/fess/cors/CorsHandler.java

@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012-2023 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.cors;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public abstract class CorsHandler {
+
+    public abstract void process(String origin, ServletRequest request, ServletResponse response);
+
+}

+ 43 - 0
src/main/java/org/codelibs/fess/cors/CorsHandlerFactory.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-2023 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.cors;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class CorsHandlerFactory {
+    private static final Logger logger = LogManager.getLogger(CorsHandlerFactory.class);
+
+    protected Map<String, CorsHandler> handerMap = new HashMap<>();
+
+    public void add(final String origin, final CorsHandler handler) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("Loaded {}", origin);
+        }
+        handerMap.put(origin, handler);
+    }
+
+    public CorsHandler get(final String origin) {
+        final CorsHandler handler = handerMap.get(origin);
+        if (handler != null) {
+            return handler;
+        }
+        return handerMap.get("*");
+    }
+}

+ 56 - 0
src/main/java/org/codelibs/fess/cors/DefaultCorsHandler.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-2023 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.cors;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.codelibs.fess.mylasta.direction.FessConfig;
+import org.codelibs.fess.util.ComponentUtil;
+
+public class DefaultCorsHandler extends CorsHandler {
+
+    protected static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
+
+    protected static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
+
+    protected static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
+
+    protected static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
+
+    protected static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
+
+    @PostConstruct
+    public void register() {
+        final CorsHandlerFactory factory = ComponentUtil.getCorsHandlerFactory();
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        fessConfig.getApiCorsAllowOriginList().forEach(s -> factory.add(s, this));
+    }
+
+    @Override
+    public void process(final String origin, final ServletRequest request, final ServletResponse response) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        final HttpServletResponse httpResponse = (HttpServletResponse) response;
+        httpResponse.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+        httpResponse.addHeader(ACCESS_CONTROL_ALLOW_METHODS, fessConfig.getApiCorsAllowMethods());
+        httpResponse.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, fessConfig.getApiCorsAllowHeaders());
+        httpResponse.addHeader(ACCESS_CONTROL_MAX_AGE, fessConfig.getApiCorsMaxAge());
+        httpResponse.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, fessConfig.getApiCorsAllowCredentials());
+    }
+
+}

+ 16 - 50
src/main/java/org/codelibs/fess/filter/CorsFilter.java

@@ -28,7 +28,8 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.codelibs.core.lang.StringUtil;
-import org.codelibs.fess.mylasta.direction.FessConfig;
+import org.codelibs.fess.cors.CorsHandler;
+import org.codelibs.fess.cors.CorsHandlerFactory;
 import org.codelibs.fess.util.ComponentUtil;
 
 public class CorsFilter implements Filter {
@@ -37,66 +38,31 @@ public class CorsFilter implements Filter {
 
     protected static final String OPTIONS = "OPTIONS";
 
-    protected static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
-
-    protected static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
-
-    protected static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
-
-    protected static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
-
-    protected static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
-
-    protected static final String WILDCARD = "*";
-
     @Override
     public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
             throws IOException, ServletException {
         final HttpServletRequest httpRequest = (HttpServletRequest) request;
         final String origin = httpRequest.getHeader("Origin");
-        if (StringUtil.isBlank(origin)) {
-            chain.doFilter(request, response);
-            return;
-        }
-
-        if (logger.isDebugEnabled()) {
-            logger.debug("HTTP Request: {}", httpRequest.getMethod());
-        }
-
-        final FessConfig fessConfig = ComponentUtil.getFessConfig();
-
-        final String allowOrigin = getAllowOrigin(fessConfig, origin);
-        if (StringUtil.isNotBlank(allowOrigin)) {
+        if (StringUtil.isNotBlank(origin)) {
             if (logger.isDebugEnabled()) {
-                logger.debug("allowOrigin: {}", allowOrigin);
+                logger.debug("HTTP Request: {}", httpRequest.getMethod());
             }
-            final HttpServletResponse httpResponse = (HttpServletResponse) response;
-            httpResponse.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigin);
-            httpResponse.addHeader(ACCESS_CONTROL_ALLOW_METHODS, fessConfig.getApiCorsAllowMethods());
-            httpResponse.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, fessConfig.getApiCorsAllowHeaders());
-            httpResponse.addHeader(ACCESS_CONTROL_MAX_AGE, fessConfig.getApiCorsMaxAge());
-            httpResponse.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, fessConfig.getApiCorsAllowCredentials());
-
-            if (OPTIONS.equals(httpRequest.getMethod())) {
-                httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
-                return;
+            final CorsHandlerFactory factory = ComponentUtil.getCorsHandlerFactory();
+            final CorsHandler handler = factory.get(origin);
+            if (handler != null) {
+                handler.process(origin, request, response);
+
+                if (OPTIONS.equals(httpRequest.getMethod())) {
+                    final HttpServletResponse httpResponse = (HttpServletResponse) response;
+                    httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
+                    return;
+                }
+            } else if (logger.isDebugEnabled()) {
+                logger.debug("No CorsHandler for {}", origin);
             }
         }
 
         chain.doFilter(request, response);
     }
 
-    protected String getAllowOrigin(final FessConfig fessConfig, final String origin) {
-        final String allowOrigin = fessConfig.getApiCorsAllowOrigin();
-        if (StringUtil.isBlank(allowOrigin)) {
-            return StringUtil.EMPTY;
-        }
-
-        if (WILDCARD.equals(allowOrigin)) {
-            return allowOrigin;
-        }
-
-        return fessConfig.getApiCorsAllowOriginList().stream().filter(s -> s.equals(origin)).findFirst().orElse(StringUtil.EMPTY);
-    }
-
 }

+ 7 - 0
src/main/java/org/codelibs/fess/util/ComponentUtil.java

@@ -27,6 +27,7 @@ import org.codelibs.core.crypto.CachedCipher;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.fess.api.WebApiManagerFactory;
 import org.codelibs.fess.auth.AuthenticationManager;
+import org.codelibs.fess.cors.CorsHandlerFactory;
 import org.codelibs.fess.crawler.client.CrawlerClientCreator;
 import org.codelibs.fess.crawler.client.CrawlerClientFactory;
 import org.codelibs.fess.crawler.entity.EsAccessResult;
@@ -211,6 +212,8 @@ public final class ComponentUtil {
 
     private static final String CRAWLER_STATS_HELPER = "crawlerStatsHelper";
 
+    private static final String CORS_HANDLER_FACTORY = "corsHandlerFactory";
+
     private static IndexingHelper indexingHelper;
 
     private static CrawlingConfigHelper crawlingConfigHelper;
@@ -512,6 +515,10 @@ public final class ComponentUtil {
         return getComponent(CRAWLER_STATS_HELPER);
     }
 
+    public static CorsHandlerFactory getCorsHandlerFactory() {
+        return getComponent(CORS_HANDLER_FACTORY);
+    }
+
     public static <T> T getComponent(final Class<T> clazz) {
         try {
             return SingletonLaContainer.getComponent(clazz);

+ 1 - 0
src/main/resources/app.xml

@@ -9,6 +9,7 @@
 	<include path="fess.xml"/>
 	<include path="fess_ldap.xml"/>
 	<include path="fess_api.xml"/>
+	<include path="fess_cors.xml"/>
 	<include path="fess_dict.xml"/>
 	<include path="fess_job.xml"/>
 	<include path="fess_thumbnail.xml"/>

+ 11 - 0
src/main/resources/fess_cors.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE components PUBLIC "-//DBFLUTE//DTD LastaDi 1.0//EN"
+	"http://dbflute.org/meta/lastadi10.dtd">
+<components>
+	<component name="corsHandlerFactory" class="org.codelibs.fess.cors.CorsHandlerFactory">
+	</component>
+
+	<component name="defaultCorsHandler" class="org.codelibs.fess.cors.DefaultCorsHandler">
+	</component>
+
+</components>