diff --git a/client/src/com/mirth/connect/connectors/http/HttpSender.java b/client/src/com/mirth/connect/connectors/http/HttpSender.java
index a049a8183..fac40106e 100644
--- a/client/src/com/mirth/connect/connectors/http/HttpSender.java
+++ b/client/src/com/mirth/connect/connectors/http/HttpSender.java
@@ -1,11 +1,5 @@
-/*
- * Copyright (c) Mirth Corporation. All rights reserved.
- *
- * http://www.mirthcorp.com
- *
- * The software in this package is published under the terms of the MPL license a copy of which has
- * been included with this distribution in the LICENSE.txt file.
- */
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: Mirth Corporation
package com.mirth.connect.connectors.http;
@@ -130,7 +124,7 @@ public void changedUpdate(DocumentEvent e) {
checkContentEnabled();
}
});
-
+
initToolTips();
initLayout();
}
@@ -148,6 +142,8 @@ public ConnectorProperties getProperties() {
properties.setUseProxyServer(useProxyServerYesRadio.isSelected());
properties.setProxyAddress(proxyAddressField.getText());
properties.setProxyPort(proxyPortField.getText());
+ properties.setOverrideLocalBinding(overrideLocalBindingYesRadio.isSelected());
+ properties.setLocalAddress(localAddressField.getText());
if (postButton.isSelected()) {
properties.setMethod("post");
@@ -190,7 +186,7 @@ public ConnectorProperties getProperties() {
properties.setParametersMap(getProperties(queryParametersTable));
properties.setUseParametersVariable(useQueryParamsVariableRadio.isSelected());
properties.setParametersVariable(queryParamsVariableField.getText());
-
+
properties.setHeadersMap(getProperties(headersTable));
properties.setUseHeadersVariable(useHeadersVariableRadio.isSelected());
properties.setHeadersVariable(headersVariableField.getText());
@@ -219,6 +215,15 @@ public void setProperties(ConnectorProperties properties) {
proxyAddressField.setText(props.getProxyAddress());
proxyPortField.setText(props.getProxyPort());
+ if (props.isOverrideLocalBinding()) {
+ overrideLocalBindingYesRadio.setSelected(true);
+ overrideLocalBindingYesRadioActionPerformed();
+ } else {
+ overrideLocalBindingNoRadio.setSelected(true);
+ overrideLocalBindingNoRadioActionPerformed();
+ }
+ localAddressField.setText(props.getLocalAddress());
+
if (props.getMethod().equalsIgnoreCase("post")) {
postButton.setSelected(true);
postButtonActionPerformed(null);
@@ -656,6 +661,15 @@ public boolean checkProperties(ConnectorProperties properties, boolean highlight
}
}
+ if (props.isOverrideLocalBinding()) {
+ if (props.getLocalAddress().length() <= 3) {
+ valid = false;
+ if (highlight) {
+ localAddressField.setBackground(UIConstants.INVALID_COLOR);
+ }
+ }
+ }
+
return valid;
}
@@ -670,6 +684,7 @@ public void resetInvalidProperties() {
headersVariableField.setBackground(null);
contentTypeField.setBackground(null);
contentTextArea.setBackground(null);
+ localAddressField.setBackground(null);
}
@Override
@@ -889,6 +904,12 @@ private void initComponents() {
responseBinaryMimeTypesField = new MirthTextField();
responseBinaryMimeTypesRegexCheckBox = new MirthCheckBox();
patchButton = new MirthRadioButton();
+ overrideLocalBindingLabel = new JLabel();
+ overrideLocalBindingButtonGroup = new ButtonGroup();
+ overrideLocalBindingYesRadio = new MirthRadioButton();
+ overrideLocalBindingNoRadio = new MirthRadioButton();
+ localAddressLabel = new JLabel();
+ localAddressField = new MirthIconTextField();
setBackground(new Color(255, 255, 255));
setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
@@ -926,13 +947,13 @@ public void actionPerformed(ActionEvent evt) {
useQueryParamsTableRadio.addActionListener(event -> {
useQueryParamsVariableFieldsEnabled(false);
});
-
+
useQueryParamsVariableRadio.setText("Use Map:");
useQueryParamsVariableRadio.setBackground(new Color(255, 255, 255));
useQueryParamsVariableRadio.addActionListener(event -> {
useQueryParamsVariableFieldsEnabled(true);
});
-
+
ButtonGroup queryParamsButtonGroup = new ButtonGroup();
queryParamsButtonGroup.add(useQueryParamsTableRadio);
queryParamsButtonGroup.add(useQueryParamsVariableRadio);
@@ -989,17 +1010,17 @@ public void actionPerformed(ActionEvent evt) {
useHeadersTableRadio.addActionListener(event -> {
useHeadersVariableFieldsEnabled(false);
});
-
+
useHeadersVariableRadio.setText("Use Map:");
useHeadersVariableRadio.setBackground(new Color(255, 255, 255));
useHeadersVariableRadio.addActionListener(event -> {
useHeadersVariableFieldsEnabled(true);
});
-
+
ButtonGroup headersButtonGroup = new ButtonGroup();
headersButtonGroup.add(useHeadersTableRadio);
headersButtonGroup.add(useHeadersVariableRadio);
-
+
responseContentLabel.setText("Response Content:");
responseContentXmlBodyRadio.setBackground(new Color(255, 255, 255));
@@ -1203,8 +1224,38 @@ public void actionPerformed(ActionEvent evt) {
patchButtonActionPerformed(evt);
}
});
+
+ localAddressLabel.setText("Local Address:");
+
+ localAddressField.setToolTipText("The local address that the client socket will be bound to, if Override Local Binding is set to Yes.
");
+
+ overrideLocalBindingLabel.setText("Override Local Binding:");
+
+ overrideLocalBindingYesRadio.setBackground(new Color(255, 255, 255));
+ overrideLocalBindingYesRadio.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ overrideLocalBindingButtonGroup.add(overrideLocalBindingYesRadio);
+ overrideLocalBindingYesRadio.setText("Yes");
+ overrideLocalBindingYesRadio.setToolTipText("Select Yes to override the local address that the client socket will be bound to.
Select No to use the default values of 0.0.0.0:0.
");
+ overrideLocalBindingYesRadio.setMargin(new Insets(0, 0, 0, 0));
+ overrideLocalBindingYesRadio.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ overrideLocalBindingYesRadioActionPerformed();
+ }
+ });
+
+ overrideLocalBindingNoRadio.setBackground(new Color(255, 255, 255));
+ overrideLocalBindingNoRadio.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ overrideLocalBindingButtonGroup.add(overrideLocalBindingNoRadio);
+ overrideLocalBindingNoRadio.setText("No");
+ overrideLocalBindingNoRadio.setToolTipText("Select Yes to override the local address that the client socket will be bound to.
Select No to use the default values of 0.0.0.0:0.
");
+ overrideLocalBindingNoRadio.setMargin(new Insets(0, 0, 0, 0));
+ overrideLocalBindingNoRadio.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ overrideLocalBindingNoRadioActionPerformed();
+ }
+ });
}
-
+
private void initToolTips() {
urlField.setToolTipText("Enter the URL of the HTTP server to send each message to.");
queryParametersTable.setToolTipText("Query parameters are encoded as x=y pairs as part of the request URL, separated from it by a '?' and from each other by an '&'.");
@@ -1243,15 +1294,15 @@ private void initToolTips() {
patchButton.setToolTipText("Selects the HTTP operation used to send each message.");
useQueryParamsTableRadio.setToolTipText("The table below will be used to populate query parameters.");
useQueryParamsVariableRadio.setToolTipText("The Java map specified by the following variable will be used to populate query parameters.
The map must have String keys and either String or List<String> values.");
- queryParamsVariableField.setToolTipText("The variable of a Java map to use to populate query parameters.
The map must have String keys and either String or List<String> values.");
+ queryParamsVariableField.setToolTipText("The variable of a Java map to use to populate query parameters.
The map must have String keys and either String or List<String> values.");
useHeadersTableRadio.setToolTipText("The table below will be used to populate headers.");
useHeadersVariableRadio.setToolTipText("The Java map specified by the following variable will be used to populate headers.
The map must have String keys and either String or List<String> values.");
headersVariableField.setToolTipText("The variable of a Java map to use to populate headers.
The map must have String keys and either String or List<String> values.");
}
-
+
private void initLayout() {
setLayout(new MigLayout("insets 0 8 0 8, novisualpadding, hidemode 3, gap 12 6", "[][]6[]", "[][][][][][][][][][][][][][][][][grow][][grow][][][][grow]"));
-
+
add(urlLabel, "right");
add(urlField, "w 312!, sx, split 2");
add(testConnection, "gapbefore 6");
@@ -1262,6 +1313,11 @@ private void initLayout() {
add(proxyAddressField, "w 202!, sx");
add(proxyPortLabel, "newline, right");
add(proxyPortField, "w 56!, sx");
+ add(overrideLocalBindingLabel, "newline, right");
+ add(overrideLocalBindingYesRadio, "split 2");
+ add(overrideLocalBindingNoRadio);
+ add(localAddressLabel, "newline, right");
+ add(localAddressField, "w 200!, sx");
add(methodLabel, "newline, right");
add(postButton, "split 5");
add(getButton);
@@ -1476,21 +1532,31 @@ private void dataTypeTextRadioActionPerformed(ActionEvent evt) {
charsetEncodingCombobox.setEnabled(true);
}
}
-
+
private void useHeadersVariableFieldsEnabled(boolean useVariable) {
headersVariableField.setEnabled(useVariable);
headersTable.setEnabled(!useVariable);
headersNewButton.setEnabled(!useVariable);
headersDeleteButton.setEnabled(!useVariable && headersTable.getSelectedRow() > -1);
}
-
+
private void useQueryParamsVariableFieldsEnabled(boolean useVariable) {
queryParamsVariableField.setEnabled(useVariable);
queryParametersTable.setEnabled(!useVariable);
queryParametersNewButton.setEnabled(!useVariable);
queryParametersDeleteButton.setEnabled(!useVariable && queryParametersTable.getSelectedRow() > -1);
}
-
+
+ private void overrideLocalBindingYesRadioActionPerformed() {
+ localAddressField.setEnabled(true);
+ localAddressLabel.setEnabled(true);
+ }
+
+ private void overrideLocalBindingNoRadioActionPerformed() {
+ localAddressField.setEnabled(false);
+ localAddressLabel.setEnabled(false);
+ }
+
private ButtonGroup authenticationButtonGroup;
private JLabel authenticationLabel;
private MirthRadioButton authenticationNoRadio;
@@ -1570,4 +1636,10 @@ private void useQueryParamsVariableFieldsEnabled(boolean useVariable) {
private MirthRadioButton useProxyServerYesRadio;
private MirthTextField usernameField;
private JLabel usernameLabel;
+ private JLabel overrideLocalBindingLabel;
+ private ButtonGroup overrideLocalBindingButtonGroup;
+ private MirthRadioButton overrideLocalBindingNoRadio;
+ private MirthRadioButton overrideLocalBindingYesRadio;
+ private JLabel localAddressLabel;
+ private MirthIconTextField localAddressField;
}
diff --git a/server/src/com/mirth/connect/connectors/http/HttpConnectorServlet.java b/server/src/com/mirth/connect/connectors/http/HttpConnectorServlet.java
index ff6684845..766bbe597 100644
--- a/server/src/com/mirth/connect/connectors/http/HttpConnectorServlet.java
+++ b/server/src/com/mirth/connect/connectors/http/HttpConnectorServlet.java
@@ -1,11 +1,5 @@
-/*
- * Copyright (c) Mirth Corporation. All rights reserved.
- *
- * http://www.mirthcorp.com
- *
- * The software in this package is published under the terms of the MPL license a copy of which has
- * been included with this distribution in the LICENSE.txt file.
- */
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: Mirth Corporation
package com.mirth.connect.connectors.http;
@@ -15,8 +9,6 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
-import org.apache.commons.lang3.StringUtils;
-
import com.mirth.connect.client.core.api.MirthApiException;
import com.mirth.connect.server.api.MirthServlet;
import com.mirth.connect.server.util.ConnectorUtil;
@@ -36,9 +28,22 @@ public HttpConnectorServlet(@Context HttpServletRequest request, @Context Securi
public ConnectionTestResponse testConnection(String channelId, String channelName, HttpDispatcherProperties properties) {
try {
URL url = new URL(replacer.replaceValues(properties.getHost(), channelId, channelName));
- int port = url.getPort();
// If no port was provided, default to port 80 or 443.
- return ConnectorUtil.testConnection(url.getHost(), (port == -1) ? (StringUtils.equalsIgnoreCase(url.getProtocol(), "https") ? 443 : 80) : port, TIMEOUT);
+ final int port;
+ if (url.getPort() != -1) {
+ port = url.getPort();
+ } else if ("https".equalsIgnoreCase(url.getProtocol())) {
+ port = 443;
+ } else {
+ port = 80;
+ }
+
+ if (!properties.isOverrideLocalBinding()) {
+ return ConnectorUtil.testConnection(url.getHost(), port, TIMEOUT);
+ } else {
+ String localAddr = replacer.replaceValues(properties.getLocalAddress(), channelId, channelName);
+ return ConnectorUtil.testConnection(url.getHost(), port, TIMEOUT, localAddr);
+ }
} catch (Exception e) {
throw new MirthApiException(e);
}
diff --git a/server/src/com/mirth/connect/connectors/http/HttpDispatcher.java b/server/src/com/mirth/connect/connectors/http/HttpDispatcher.java
index 8bd865700..91bbd2af0 100644
--- a/server/src/com/mirth/connect/connectors/http/HttpDispatcher.java
+++ b/server/src/com/mirth/connect/connectors/http/HttpDispatcher.java
@@ -1,15 +1,10 @@
-/*
- * Copyright (c) Mirth Corporation. All rights reserved.
- *
- * http://www.mirthcorp.com
- *
- * The software in this package is published under the terms of the MPL license a copy of which has
- * been included with this distribution in the LICENSE.txt file.
- */
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: Mirth Corporation
package com.mirth.connect.connectors.http;
import java.io.File;
+import java.net.InetAddress;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -27,6 +22,7 @@
import javax.mail.util.ByteArrayDataSource;
import com.mirth.connect.client.core.BrandingConstants;
+import com.mirth.connect.util.TcpUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.apache.commons.fileupload.FileUploadBase;
@@ -192,6 +188,7 @@ public void replaceConnectorProperties(ConnectorProperties connectorProperties,
httpDispatcherProperties.setHost(replacer.replaceValues(httpDispatcherProperties.getHost(), connectorMessage));
httpDispatcherProperties.setProxyAddress(replacer.replaceValues(httpDispatcherProperties.getProxyAddress(), connectorMessage));
httpDispatcherProperties.setProxyPort(replacer.replaceValues(httpDispatcherProperties.getProxyPort(), connectorMessage));
+ httpDispatcherProperties.setLocalAddress(replacer.replaceValues(httpDispatcherProperties.getLocalAddress(), connectorMessage));
httpDispatcherProperties.setResponseBinaryMimeTypes(replacer.replaceValues(httpDispatcherProperties.getResponseBinaryMimeTypes(), connectorMessage));
httpDispatcherProperties.setHeadersMap(replacer.replaceKeysAndValuesInMap(httpDispatcherProperties.getHeadersMap(), connectorMessage));
httpDispatcherProperties.setHeadersVariable(replacer.replaceValues(httpDispatcherProperties.getHeadersVariable(), connectorMessage));
@@ -258,9 +255,9 @@ public Response send(ConnectorProperties connectorProperties, ConnectorMessage c
/*
* If a charset is set in the Content Type field, use that.
- *
+ *
* If the charset is NONE, keep it as null.
- *
+ *
* Otherwise, use the charset from the Character Encoding drop-down menu.
*/
Charset charset = null;
@@ -312,8 +309,14 @@ public Response send(ConnectorProperties connectorProperties, ConnectorMessage c
logger.debug("using authentication with credentials: " + credentials);
}
- RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(socketTimeout).setSocketTimeout(socketTimeout).setStaleConnectionCheckEnabled(true).build();
- context.setRequestConfig(requestConfig);
+ final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
+ .setConnectTimeout(socketTimeout)
+ .setSocketTimeout(socketTimeout)
+ .setStaleConnectionCheckEnabled(true);
+ if (httpDispatcherProperties.isOverrideLocalBinding()) {
+ requestConfigBuilder.setLocalAddress(InetAddress.getByName(TcpUtil.getFixedHost(httpDispatcherProperties.getLocalAddress())));
+ }
+ context.setRequestConfig(requestConfigBuilder.build());
// Set proxy information
if (httpDispatcherProperties.isUseProxyServer()) {
@@ -444,7 +447,7 @@ public boolean isBinaryContentType(ContentType contentType) {
return new Response(responseStatus, responseData, responseStatusMessage, responseError, validateResponse);
}
-
+
protected boolean shouldParseMultipart(HttpDispatcherProperties httpDispatcherProperties, String mimeType) {
// Only parse multipart if XML Body is selected and Parse Multipart is enabled
return httpDispatcherProperties.isResponseXmlBody() && httpDispatcherProperties.isResponseParseMultipart() && mimeType.startsWith(FileUploadBase.MULTIPART);
diff --git a/server/src/com/mirth/connect/connectors/http/HttpDispatcherProperties.java b/server/src/com/mirth/connect/connectors/http/HttpDispatcherProperties.java
index 5689c2e4d..8892dda27 100644
--- a/server/src/com/mirth/connect/connectors/http/HttpDispatcherProperties.java
+++ b/server/src/com/mirth/connect/connectors/http/HttpDispatcherProperties.java
@@ -1,11 +1,6 @@
-/*
- * Copyright (c) Mirth Corporation. All rights reserved.
- *
- * http://www.mirthcorp.com
- *
- * The software in this package is published under the terms of the MPL license a copy of which has
- * been included with this distribution in the LICENSE.txt file.
- */
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: Mirth Corporation
+
package com.mirth.connect.connectors.http;
@@ -32,6 +27,8 @@ public class HttpDispatcherProperties extends ConnectorProperties implements Des
private boolean useProxyServer;
private String proxyAddress;
private String proxyPort;
+ private boolean overrideLocalBinding;
+ private String localAddress;
private String method;
private Map> headers;
private Map> parameters;
@@ -63,6 +60,8 @@ public HttpDispatcherProperties() {
this.useProxyServer = false;
this.proxyAddress = "";
this.proxyPort = "";
+ this.overrideLocalBinding = false;
+ this.localAddress = "0.0.0.0";
this.method = "post";
this.headers = new LinkedHashMap>();
this.useHeadersVariable = false;
@@ -96,6 +95,8 @@ public HttpDispatcherProperties(HttpDispatcherProperties props) {
useProxyServer = props.isUseProxyServer();
proxyAddress = props.getProxyAddress();
proxyPort = props.getProxyPort();
+ overrideLocalBinding = props.isOverrideLocalBinding();
+ localAddress = props.getLocalAddress();
method = props.getMethod();
headers = new LinkedHashMap>();
@@ -162,6 +163,22 @@ public void setProxyPort(String proxyPort) {
this.proxyPort = proxyPort;
}
+ public boolean isOverrideLocalBinding() {
+ return overrideLocalBinding;
+ }
+
+ public void setOverrideLocalBinding(boolean overrideLocalBinding) {
+ this.overrideLocalBinding = overrideLocalBinding;
+ }
+
+ public String getLocalAddress() {
+ return localAddress;
+ }
+
+ public void setLocalAddress(String localAddress) {
+ this.localAddress = localAddress;
+ }
+
public String getMethod() {
return method;
}
@@ -173,7 +190,7 @@ public void setMethod(String method) {
public Map> getHeadersMap() {
return headers;
}
-
+
public boolean isUseHeadersVariable() {
return useHeadersVariable;
}
@@ -189,7 +206,7 @@ public void setHeadersMap(Map> headers) {
public String getHeadersVariable() {
return this.headersVariable;
}
-
+
public void setHeadersVariable(String headerVariable) {
this.headersVariable = headerVariable;
}
@@ -209,11 +226,11 @@ public boolean isUseParametersVariable() {
public void setUseParametersVariable(boolean useParametersVariable) {
this.useParametersVariable = useParametersVariable;
}
-
+
public String getParametersVariable() {
return this.parametersVariable;
}
-
+
public void setParametersVariable(String variableName) {
this.parametersVariable = variableName;
}
@@ -513,8 +530,8 @@ public void migrate3_2_0(DonkeyElement element) {
@Override public void migrate3_6_0(DonkeyElement element) {}
@Override public void migrate3_7_0(DonkeyElement element) {}
@Override public void migrate3_9_0(DonkeyElement element) {}
- @Override public void migrate3_11_0(DonkeyElement element) {}
- @Override public void migrate3_11_1(DonkeyElement element) {}
+ @Override public void migrate3_11_0(DonkeyElement element) {}
+ @Override public void migrate3_11_1(DonkeyElement element) {}
@Override public void migrate3_12_0(DonkeyElement element) {}// @formatter:on
@Override
diff --git a/server/src/com/mirth/connect/server/util/ConnectorUtil.java b/server/src/com/mirth/connect/server/util/ConnectorUtil.java
index 3ffef5a53..820711985 100644
--- a/server/src/com/mirth/connect/server/util/ConnectorUtil.java
+++ b/server/src/com/mirth/connect/server/util/ConnectorUtil.java
@@ -1,11 +1,5 @@
-/*
- * Copyright (c) Mirth Corporation. All rights reserved.
- *
- * http://www.mirthcorp.com
- *
- * The software in this package is published under the terms of the MPL license a copy of which has
- * been included with this distribution in the LICENSE.txt file.
- */
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: Mirth Corporation
package com.mirth.connect.server.util;
@@ -22,6 +16,10 @@ public static ConnectionTestResponse testConnection(String host, int port, int t
return testConnection(host, port, timeout, null, 0);
}
+ public static ConnectionTestResponse testConnection(String host, int port, int timeout, String localAddr) throws Exception {
+ return testConnection(host, port, timeout, localAddr, 0);
+ }
+
public static ConnectionTestResponse testConnection(String host, int port, int timeout, String localAddr, int localPort) throws Exception {
Socket socket = null;
InetSocketAddress address = null;