/* * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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.wso2.carbon.transport.http.netty.sender; import io.netty.handler.codec.http.HttpRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.wso2.carbon.messaging.CarbonCallback; import org.wso2.carbon.messaging.CarbonMessage; import org.wso2.carbon.messaging.CarbonMessageProcessor; import org.wso2.carbon.messaging.ClientConnector; import org.wso2.carbon.messaging.exceptions.ClientConnectorException; import org.wso2.carbon.transport.http.netty.common.Constants; import org.wso2.carbon.transport.http.netty.common.HttpRoute; import org.wso2.carbon.transport.http.netty.common.Util; import org.wso2.carbon.transport.http.netty.config.ConfigurationBuilder; import org.wso2.carbon.transport.http.netty.config.SenderConfiguration; import org.wso2.carbon.transport.http.netty.config.TransportProperty; import org.wso2.carbon.transport.http.netty.config.TransportsConfiguration; import org.wso2.carbon.transport.http.netty.internal.HTTPTransportContextHolder; import org.wso2.carbon.transport.http.netty.listener.SourceHandler; import org.wso2.carbon.transport.http.netty.sender.channel.BootstrapConfiguration; import org.wso2.carbon.transport.http.netty.sender.channel.ChannelUtils; import org.wso2.carbon.transport.http.netty.sender.channel.TargetChannel; import org.wso2.carbon.transport.http.netty.sender.channel.pool.ConnectionManager; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * HTTP client connector class which is used for sending message to a backend endpoint. * * @since 4.0.0 */ public class HTTPClientConnector implements ClientConnector { private static final Logger log = LoggerFactory.getLogger(HTTPClientConnector.class); private ConnectionManager connectionManager; private Map<String, SenderConfiguration> senderConfigurations; public HTTPClientConnector() { TransportsConfiguration transportsConfiguration = ConfigurationBuilder.getInstance().getConfiguration(); init(transportsConfiguration.getSenderConfigurations(), transportsConfiguration.getTransportProperties()); } public HTTPClientConnector(Set<SenderConfiguration> senderConfiguration, Set<TransportProperty> transportPropertiesSet) { init(senderConfiguration, transportPropertiesSet); } private void init(Set<SenderConfiguration> senderConfiguration, Set<TransportProperty> transportPropertiesSet) { if (senderConfiguration.isEmpty()) { log.error("Please specify at least one sender configuration"); return; } senderConfigurations = senderConfiguration.stream().collect(Collectors .toMap(senderConf -> senderConf.getScheme().toLowerCase(Locale.getDefault()), config -> config)); Map<String, Object> transportProperties = new HashMap<>(); if (transportPropertiesSet != null && !transportPropertiesSet.isEmpty()) { transportProperties = transportPropertiesSet.stream().collect( Collectors.toMap(TransportProperty::getName, TransportProperty::getValue)); } BootstrapConfiguration.createBootStrapConfiguration(transportProperties); this.connectionManager = ConnectionManager.getInstance(transportProperties); } @Override public boolean send(CarbonMessage msg, CarbonCallback callback, Map<String, String> parameters) throws ClientConnectorException { return send(msg, callback); } @Override public boolean send(CarbonMessage msg, CarbonCallback callback) throws ClientConnectorException { String protocol = (String) msg.getProperty(Constants.PROTOCOL); SenderConfiguration senderConfiguration = senderConfigurations.get(protocol.toLowerCase(Locale.getDefault())); Util.prepareBuiltMessageForTransfer(msg); Util.setupTransferEncodingForRequest(msg); final HttpRequest httpRequest = Util.createHttpRequest(msg); // Fetch Host String host; Object hostProperty = msg.getProperty(Constants.HOST); if (hostProperty != null && hostProperty instanceof String) { host = (String) hostProperty; } else { host = Constants.LOCALHOST; msg.setProperty(Constants.HOST, Constants.LOCALHOST); log.debug("Cannot find property HOST of type string, hence using localhost as the host"); } // Fetch Port int port; Object intProperty = msg.getProperty(Constants.PORT); if (intProperty != null && intProperty instanceof Integer) { port = (int) intProperty; } else { port = senderConfiguration.getSslConfig() != null ? Constants.DEFAULT_HTTPS_PORT : Constants.DEFAULT_HTTP_PORT; msg.setProperty(Constants.PORT, port); log.debug("Cannot find property PORT of type integer, hence using " + port); } final HttpRoute route = new HttpRoute(host, port); SourceHandler srcHandler = (SourceHandler) msg.getProperty(Constants.SRC_HANDLER); if (srcHandler == null) { log.debug("SRC_HANDLER property not found in the message." + " Message is not originated from the HTTP Server connector"); } try { TargetChannel targetChannel = connectionManager. getTargetChannel(route, srcHandler, senderConfiguration, httpRequest, msg, callback); if (targetChannel != null) { TargetHandler targetHandler = targetChannel.getTargetHandler(); targetHandler.setCallback(callback); targetHandler.setIncomingMsg(msg); targetHandler.setConnectionManager(connectionManager); targetHandler.setTargetChannel(targetChannel); if (ChannelUtils.writeContent(targetChannel.getChannel(), httpRequest, msg)) { targetChannel.setRequestWritten(true); // If request written } } } catch (Exception failedCause) { throw new ClientConnectorException(failedCause.getMessage(), failedCause); } return false; } @Override public String getProtocol() { //hardcoded because there is always one sender with set of configurations return Constants.PROTOCOL_NAME; } public void setMessageProcessor(CarbonMessageProcessor carbonMessageProcessor) { HTTPTransportContextHolder.getInstance().setMessageProcessor(carbonMessageProcessor); } }