fix #2018 cors support
This commit is contained in:
parent
0643349425
commit
8eadcbb48b
5 changed files with 231 additions and 0 deletions
102
src/main/java/org/codelibs/fess/filter/CorsFilter.java
Normal file
102
src/main/java/org/codelibs/fess/filter/CorsFilter.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2012-2019 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.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CorsFilter implements Filter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CorsFilter.class);
|
||||
|
||||
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 (logger.isDebugEnabled()) {
|
||||
logger.debug("allowOrigin: " + allowOrigin);
|
||||
}
|
||||
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 (httpRequest.getMethod().equals(OPTIONS)) {
|
||||
httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -199,6 +199,21 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
/** The key of the configuration. e.g. */
|
||||
String API_DASHBOARD_RESPONSE_HEADERS = "api.dashboard.response.headers";
|
||||
|
||||
/** The key of the configuration. e.g. * */
|
||||
String API_CORS_ALLOW_ORIGIN = "api.cors.allow.origin";
|
||||
|
||||
/** The key of the configuration. e.g. GET, POST, OPTIONS, DELETE, PUT */
|
||||
String API_CORS_ALLOW_METHODS = "api.cors.allow.methods";
|
||||
|
||||
/** The key of the configuration. e.g. 3600 */
|
||||
String API_CORS_MAX_AGE = "api.cors.max.age";
|
||||
|
||||
/** The key of the configuration. e.g. Origin, Content-Type, Accept, Authorization */
|
||||
String API_CORS_ALLOW_HEADERS = "api.cors.allow.headers";
|
||||
|
||||
/** The key of the configuration. e.g. true */
|
||||
String API_CORS_ALLOW_CREDENTIALS = "api.cors.allow.credentials";
|
||||
|
||||
/** The key of the configuration. e.g. */
|
||||
String VIRTUAL_HOST_HEADERS = "virtual.host.headers";
|
||||
|
||||
|
@ -1847,6 +1862,56 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
*/
|
||||
Integer getApiDashboardResponseHeadersAsInteger();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'api.cors.allow.origin'. <br>
|
||||
* The value is, e.g. * <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getApiCorsAllowOrigin();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'api.cors.allow.methods'. <br>
|
||||
* The value is, e.g. GET, POST, OPTIONS, DELETE, PUT <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getApiCorsAllowMethods();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'api.cors.max.age'. <br>
|
||||
* The value is, e.g. 3600 <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getApiCorsMaxAge();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'api.cors.max.age' as {@link Integer}. <br>
|
||||
* The value is, e.g. 3600 <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
* @throws NumberFormatException When the property is not integer.
|
||||
*/
|
||||
Integer getApiCorsMaxAgeAsInteger();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'api.cors.allow.headers'. <br>
|
||||
* The value is, e.g. Origin, Content-Type, Accept, Authorization <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getApiCorsAllowHeaders();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'api.cors.allow.credentials'. <br>
|
||||
* The value is, e.g. true <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getApiCorsAllowCredentials();
|
||||
|
||||
/**
|
||||
* Is the property for the key 'api.cors.allow.credentials' true? <br>
|
||||
* The value is, e.g. true <br>
|
||||
* @return The determination, true or false. (if not found, exception but basically no way)
|
||||
*/
|
||||
boolean isApiCorsAllowCredentials();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'virtual.host.headers'. <br>
|
||||
* The value is, e.g. <br>
|
||||
|
@ -6202,6 +6267,34 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
return getAsInteger(FessConfig.API_DASHBOARD_RESPONSE_HEADERS);
|
||||
}
|
||||
|
||||
public String getApiCorsAllowOrigin() {
|
||||
return get(FessConfig.API_CORS_ALLOW_ORIGIN);
|
||||
}
|
||||
|
||||
public String getApiCorsAllowMethods() {
|
||||
return get(FessConfig.API_CORS_ALLOW_METHODS);
|
||||
}
|
||||
|
||||
public String getApiCorsMaxAge() {
|
||||
return get(FessConfig.API_CORS_MAX_AGE);
|
||||
}
|
||||
|
||||
public Integer getApiCorsMaxAgeAsInteger() {
|
||||
return getAsInteger(FessConfig.API_CORS_MAX_AGE);
|
||||
}
|
||||
|
||||
public String getApiCorsAllowHeaders() {
|
||||
return get(FessConfig.API_CORS_ALLOW_HEADERS);
|
||||
}
|
||||
|
||||
public String getApiCorsAllowCredentials() {
|
||||
return get(FessConfig.API_CORS_ALLOW_CREDENTIALS);
|
||||
}
|
||||
|
||||
public boolean isApiCorsAllowCredentials() {
|
||||
return is(FessConfig.API_CORS_ALLOW_CREDENTIALS);
|
||||
}
|
||||
|
||||
public String getVirtualHostHeaders() {
|
||||
return get(FessConfig.VIRTUAL_HOST_HEADERS);
|
||||
}
|
||||
|
@ -8491,6 +8584,11 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
defaultMap.put(FessConfig.API_JSON_RESPONSE_HEADERS, "");
|
||||
defaultMap.put(FessConfig.API_GSA_RESPONSE_HEADERS, "");
|
||||
defaultMap.put(FessConfig.API_DASHBOARD_RESPONSE_HEADERS, "");
|
||||
defaultMap.put(FessConfig.API_CORS_ALLOW_ORIGIN, "*");
|
||||
defaultMap.put(FessConfig.API_CORS_ALLOW_METHODS, "GET, POST, OPTIONS, DELETE, PUT");
|
||||
defaultMap.put(FessConfig.API_CORS_MAX_AGE, "3600");
|
||||
defaultMap.put(FessConfig.API_CORS_ALLOW_HEADERS, "Origin, Content-Type, Accept, Authorization");
|
||||
defaultMap.put(FessConfig.API_CORS_ALLOW_CREDENTIALS, "true");
|
||||
defaultMap.put(FessConfig.VIRTUAL_HOST_HEADERS, "");
|
||||
defaultMap.put(FessConfig.HTTP_PROXY_HOST, "");
|
||||
defaultMap.put(FessConfig.HTTP_PROXY_PORT, "8080");
|
||||
|
|
|
@ -70,6 +70,8 @@ import org.lastaflute.web.validation.theme.typed.LongTypeValidator;
|
|||
|
||||
public interface FessProp {
|
||||
|
||||
String CORS_ALLOW_ORIGIN = "CorsAllowOrigin";
|
||||
|
||||
String API_DASHBOARD_RESPONSE_HEADER_LIST = "apiDashboardResponseHeaderList";
|
||||
|
||||
String API_JSON_RESPONSE_HEADER_LIST = "apiJsonResponseHeaderList";
|
||||
|
@ -1969,4 +1971,17 @@ public interface FessProp {
|
|||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
String getApiCorsAllowOrigin();
|
||||
|
||||
default List<String> getApiCorsAllowOriginList() {
|
||||
List<String> list = (List<String>) propMap.get(CORS_ALLOW_ORIGIN);
|
||||
if (list == null) {
|
||||
list =
|
||||
split(getApiCorsAllowOrigin(), "\n").get(
|
||||
stream -> stream.map(String::trim).filter(StringUtil::isNotEmpty).collect(Collectors.toList()));
|
||||
propMap.put(CORS_ALLOW_ORIGIN, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,11 @@ api.search.scroll=false
|
|||
api.json.response.headers=
|
||||
api.gsa.response.headers=
|
||||
api.dashboard.response.headers=
|
||||
api.cors.allow.origin=*
|
||||
api.cors.allow.methods=GET, POST, OPTIONS, DELETE, PUT
|
||||
api.cors.max.age=3600
|
||||
api.cors.allow.headers=Origin, Content-Type, Accept, Authorization
|
||||
api.cors.allow.credentials=true
|
||||
|
||||
# Virtual Host: Host:fess.codelibs.org=fess
|
||||
virtual.host.headers=
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>corsFilter</filter-name>
|
||||
<filter-class>org.codelibs.fess.filter.CorsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>webApiFilter</filter-name>
|
||||
<filter-class>org.codelibs.fess.filter.WebApiFilter</filter-class>
|
||||
|
@ -77,6 +82,12 @@
|
|||
<dispatcher>INCLUDE</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>corsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>webApiFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
|
|
Loading…
Add table
Reference in a new issue