/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.synapse.transport.nhttp; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.protocol.HTTP; import org.apache.synapse.commons.util.MiscellaneousUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; /** * Store and manage properties that tune the nhttp transport */ public final class NHttpConfiguration { // defaults private static final int WORKERS_CORE_THREADS = 20; private static final int WORKERS_MAX_THREADS = 100; private static final int WORKER_KEEP_ALIVE = 5; private static final int BLOCKING_QUEUE_LENGTH = -1; private static final int IO_WORKER_COUNT = 2; private static final int BUFFER_SIZE = 8192; public static final int MAX_ACTIVE_CON = -1; // server listener private static final String S_T_CORE = "snd_t_core"; private static final String S_T_MAX = "snd_t_max"; private static final String S_T_ALIVE = "snd_alive_sec"; private static final String S_T_QLEN = "snd_qlen"; private static final String S_IO_WORKERS = "snd_io_threads"; private static final String C_MAX_ACTIVE = "max_open_connections"; // client sender private static final String C_T_CORE = "lst_t_core"; private static final String C_T_MAX = "lst_t_max"; private static final String C_T_ALIVE = "lst_alive_sec"; private static final String C_T_QLEN = "lst_qlen"; private static final String C_IO_WORKERS = "lst_io_threads"; // Client error handler private static final String ERROR_HANDLER_POOL_ENABLED = "error_handler_pool_enabled"; private static final String ERROR_HANDLER_T_CORE = "error_handler_t_core"; private static final String ERROR_HANDLER_T_MAX = "error_handler_t_max"; private static final String ERROR_HANDLER_T_ALIVE = "error_handler_alive_sec"; private static final String ERROR_HANDLER_T_QLEN = "error_handler_qlen"; // general private static final String G_BUFFER_SIZE = "nhttp_buffer_size"; private static final String G_DISABLED_HTTP_METHODS = "nhttp_disabled_methods"; //additional rest dispatch handlers private static final String NHTTP_REST_DISPATCHER_SERVICE="nhttp.rest.dispatcher.service"; // URI configurations that determine if it requires custom rest dispatcher private static final String REST_URI_API_REGEX = "rest_uri_api_regex"; private static final String REST_URI_PROXY_REGEX = "rest_uri_proxy_regex"; public static final String TRANSPORT_LISTENER_SHUTDOWN_WAIT_TIME = "transport.listener.shutdown.wait.sec"; public static final int DEFAULT_LISTENER_SHUTDOWN_WAIT_TIME = 0; private static final Log log = LogFactory.getLog(NHttpConfiguration.class); private static NHttpConfiguration _instance = new NHttpConfiguration(); private Properties props; List<String> methods; //Preserve HTTP headers private List<String> preserveHeaders; /** Comma separated list of blocked uris*/ public static final String BLOCK_SERVICE_LIST = "http.block_service_list"; /** Default value for BLOCK_SERVICE_LIST*/ public static final String BLOCK_SERVICE_LIST_DEFAULT = "false"; /** Reverse proxy mode is enabled or not */ private Boolean reverseProxyMode = null; /** Default Synapse service name */ private String nhttpDefaultServiceName = null; private String restUriApiRegex = null; private String restUriProxyRegex = null; private NHttpConfiguration() { try { props = MiscellaneousUtil.loadProperties("nhttp.properties"); populatePreserveHttpHeaders(); } catch (Exception ignore) {} } public static NHttpConfiguration getInstance() { return _instance; } public int getServerCoreThreads() { return getProperty(S_T_CORE, WORKERS_CORE_THREADS); } public int getServerMaxThreads() { return getProperty(S_T_MAX, WORKERS_MAX_THREADS); } public int getServerKeepalive() { return getProperty(S_T_ALIVE, WORKER_KEEP_ALIVE); } public int getServerQueueLen() { return getProperty(S_T_QLEN, BLOCKING_QUEUE_LENGTH); } public int getServerIOWorkers() { return getProperty(S_IO_WORKERS, IO_WORKER_COUNT); } public int getClientCoreThreads() { return getProperty(C_T_CORE, WORKERS_CORE_THREADS); } public int getClientMaxThreads() { return getProperty(C_T_MAX, WORKERS_MAX_THREADS); } public int getClientKeepalive() { return getProperty(C_T_ALIVE, WORKER_KEEP_ALIVE); } public int getClientQueueLen() { return getProperty(C_T_QLEN, BLOCKING_QUEUE_LENGTH); } public int getClientIOWorkers() { return getProperty(C_IO_WORKERS, IO_WORKER_COUNT); } public int getMaxActiveConnections() { return getProperty(C_MAX_ACTIVE, MAX_ACTIVE_CON); } public int getErrorHandlerCoreThreads() { return getProperty(ERROR_HANDLER_T_CORE, getClientCoreThreads()/2); } public int getErrorHandlerTMaxThreads() { return getProperty(ERROR_HANDLER_T_MAX, getClientMaxThreads()/2); } public int getErrorHandlerKeepAlive() { return getProperty(ERROR_HANDLER_T_ALIVE, WORKER_KEEP_ALIVE); } public int getErrorHandlerQueuelen() { return getProperty(ERROR_HANDLER_T_QLEN, BLOCKING_QUEUE_LENGTH); } public boolean isErrorHandlerPoolEnabled() { return getBooleanValue(ERROR_HANDLER_POOL_ENABLED, false); } public int getBufferSize() { return getProperty(G_BUFFER_SIZE, BUFFER_SIZE); } public boolean isKeepAliveDisabled() { return getProperty(NhttpConstants.DISABLE_KEEPALIVE, 0) == 1; } public boolean isCountConnections() { return getBooleanValue(NhttpConstants.COUNT_CONNECTIONS, false); } public String isServiceListBlocked() { return getStringValue(BLOCK_SERVICE_LIST, BLOCK_SERVICE_LIST_DEFAULT); } public String getRESTDispatchService() { return getStringValue(NHTTP_REST_DISPATCHER_SERVICE,""); } public String getRestUriApiRegex() { if (restUriApiRegex == null) { restUriApiRegex = getStringValue(REST_URI_API_REGEX, ""); } return restUriApiRegex; } public String getRestUriProxyRegex() { if (restUriProxyRegex == null) { restUriProxyRegex = getStringValue(REST_URI_PROXY_REGEX, ""); } return restUriProxyRegex; } public int getListenerShutdownWaitTime() { return getProperty(TRANSPORT_LISTENER_SHUTDOWN_WAIT_TIME, DEFAULT_LISTENER_SHUTDOWN_WAIT_TIME)*1000; } /** * Check preserving status of the http header field * * @param httpHeader http header name * @return return true if preserve else false */ public boolean isPreserveHttpHeader(String httpHeader) { if (preserveHeaders == null || preserveHeaders.isEmpty() || httpHeader == null) { return false; } else { return preserveHeaders.contains(httpHeader.toUpperCase()); } } /** * Get properties that tune nhttp transport. Preference to system properties * @param name name of the system/config property * @param def default value to return if the property is not set * @return the value of the property to be used */ public int getProperty(String name, int def) { String val = System.getProperty(name); if (val == null) { val = props.getProperty(name); } if (val!=null) { val = val.trim(); } if (val != null && Integer.valueOf(val) > 0) { if (log.isDebugEnabled()) { log.debug("Using nhttp tuning parameter : " + name + " = " + val); } return Integer.valueOf(val); } return def; } /** * Get properties that tune nhttp transport. Preference to system properties * @param name name of the system/config property * @param def default value to return if the property is not set * @return the value of the property to be used */ public boolean getBooleanValue(String name, boolean def) { String val = System.getProperty(name); if (val == null) { val = props.getProperty(name); } if (val != null && Boolean.parseBoolean(val)) { if (log.isDebugEnabled()) { log.debug("Using nhttp tuning parameter : " + name); } return true; } else if (val != null && !Boolean.parseBoolean(val)) { if (log.isDebugEnabled()) { log.debug("Using nhttp tuning parameter : " + name); } return false; } return def; } /** * Get properties that tune nhttp transport. Preference to system properties * @param name name of the system/config property * @param def default value to return if the property is not set * @return the value of the property to be used */ public String getStringValue(String name, String def) { String val = System.getProperty(name); if (val == null) { val = props.getProperty(name); } return val == null ? def : val; } public boolean isHttpMethodDisabled(String method) { if (methods == null) { methods = new ArrayList<String>(); String methodsString = getStringValue(G_DISABLED_HTTP_METHODS, ""); for (String methodStr : methodsString.split(",")) { methods.add(methodStr.trim().toUpperCase()); } } return methods.contains(method); } private void populatePreserveHttpHeaders() { if (preserveHeaders == null) { preserveHeaders = new ArrayList<String>(); String presHeaders = getStringValue(NhttpConstants.HTTP_HEADERS_PRESERVE, ""); if (presHeaders != null && !presHeaders.isEmpty()) { String[] splitHeaders = presHeaders.toUpperCase().trim().split(","); if (splitHeaders != null && splitHeaders.length > 0) { preserveHeaders.addAll(Arrays.asList(splitHeaders)); } } if (getBooleanValue(NhttpConstants.SERVER_HEADER_PRESERVE, true) && !preserveHeaders.contains(HTTP.SERVER_HEADER.toUpperCase())) { preserveHeaders.add(HTTP.SERVER_HEADER.toUpperCase()); } if (getBooleanValue(NhttpConstants.USER_AGENT_HEADER_PRESERVE, false) && !preserveHeaders.contains(HTTP.USER_AGENT.toUpperCase())) { preserveHeaders.add(HTTP.USER_AGENT.toUpperCase()); } } } /** * Check for reverse proxy mode * * @return whether reverse proxy mode is enabled */ public boolean isReverseProxyMode() { if (reverseProxyMode == null) { reverseProxyMode = Boolean.parseBoolean(System.getProperty("reverseProxyMode")); } return reverseProxyMode.booleanValue(); } /** * Get the default synapse service name * * @return default synapse service name */ public String getNhttpDefaultServiceName() { if (nhttpDefaultServiceName == null) { nhttpDefaultServiceName = getStringValue("nhttp.default.service", "__SynapseService"); } return nhttpDefaultServiceName; } }