Skip to content

Commit d4d1122

Browse files
authored
Add “Override local binding” to http sender
Adds feature parity to http sender compared to TCP sender to specify what source IP should be used. Signed-off-by: Joachim Beckers <joachim.beckers@nexuzhealth.com> Issue: #332
1 parent 5e0e614 commit d4d1122

5 files changed

Lines changed: 164 additions & 69 deletions

File tree

client/src/com/mirth/connect/connectors/http/HttpSender.java

Lines changed: 94 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
/*
2-
* Copyright (c) Mirth Corporation. All rights reserved.
3-
*
4-
* http://www.mirthcorp.com
5-
*
6-
* The software in this package is published under the terms of the MPL license a copy of which has
7-
* been included with this distribution in the LICENSE.txt file.
8-
*/
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: Mirth Corporation
93

104
package com.mirth.connect.connectors.http;
115

@@ -130,7 +124,7 @@ public void changedUpdate(DocumentEvent e) {
130124
checkContentEnabled();
131125
}
132126
});
133-
127+
134128
initToolTips();
135129
initLayout();
136130
}
@@ -148,6 +142,8 @@ public ConnectorProperties getProperties() {
148142
properties.setUseProxyServer(useProxyServerYesRadio.isSelected());
149143
properties.setProxyAddress(proxyAddressField.getText());
150144
properties.setProxyPort(proxyPortField.getText());
145+
properties.setOverrideLocalBinding(overrideLocalBindingYesRadio.isSelected());
146+
properties.setLocalAddress(localAddressField.getText());
151147

152148
if (postButton.isSelected()) {
153149
properties.setMethod("post");
@@ -190,7 +186,7 @@ public ConnectorProperties getProperties() {
190186
properties.setParametersMap(getProperties(queryParametersTable));
191187
properties.setUseParametersVariable(useQueryParamsVariableRadio.isSelected());
192188
properties.setParametersVariable(queryParamsVariableField.getText());
193-
189+
194190
properties.setHeadersMap(getProperties(headersTable));
195191
properties.setUseHeadersVariable(useHeadersVariableRadio.isSelected());
196192
properties.setHeadersVariable(headersVariableField.getText());
@@ -219,6 +215,15 @@ public void setProperties(ConnectorProperties properties) {
219215
proxyAddressField.setText(props.getProxyAddress());
220216
proxyPortField.setText(props.getProxyPort());
221217

218+
if (props.isOverrideLocalBinding()) {
219+
overrideLocalBindingYesRadio.setSelected(true);
220+
overrideLocalBindingYesRadioActionPerformed();
221+
} else {
222+
overrideLocalBindingNoRadio.setSelected(true);
223+
overrideLocalBindingNoRadioActionPerformed();
224+
}
225+
localAddressField.setText(props.getLocalAddress());
226+
222227
if (props.getMethod().equalsIgnoreCase("post")) {
223228
postButton.setSelected(true);
224229
postButtonActionPerformed(null);
@@ -656,6 +661,15 @@ public boolean checkProperties(ConnectorProperties properties, boolean highlight
656661
}
657662
}
658663

664+
if (props.isOverrideLocalBinding()) {
665+
if (props.getLocalAddress().length() <= 3) {
666+
valid = false;
667+
if (highlight) {
668+
localAddressField.setBackground(UIConstants.INVALID_COLOR);
669+
}
670+
}
671+
}
672+
659673
return valid;
660674
}
661675

@@ -670,6 +684,7 @@ public void resetInvalidProperties() {
670684
headersVariableField.setBackground(null);
671685
contentTypeField.setBackground(null);
672686
contentTextArea.setBackground(null);
687+
localAddressField.setBackground(null);
673688
}
674689

675690
@Override
@@ -889,6 +904,12 @@ private void initComponents() {
889904
responseBinaryMimeTypesField = new MirthTextField();
890905
responseBinaryMimeTypesRegexCheckBox = new MirthCheckBox();
891906
patchButton = new MirthRadioButton();
907+
overrideLocalBindingLabel = new JLabel();
908+
overrideLocalBindingButtonGroup = new ButtonGroup();
909+
overrideLocalBindingYesRadio = new MirthRadioButton();
910+
overrideLocalBindingNoRadio = new MirthRadioButton();
911+
localAddressLabel = new JLabel();
912+
localAddressField = new MirthIconTextField();
892913

893914
setBackground(new Color(255, 255, 255));
894915
setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
@@ -926,13 +947,13 @@ public void actionPerformed(ActionEvent evt) {
926947
useQueryParamsTableRadio.addActionListener(event -> {
927948
useQueryParamsVariableFieldsEnabled(false);
928949
});
929-
950+
930951
useQueryParamsVariableRadio.setText("Use Map:");
931952
useQueryParamsVariableRadio.setBackground(new Color(255, 255, 255));
932953
useQueryParamsVariableRadio.addActionListener(event -> {
933954
useQueryParamsVariableFieldsEnabled(true);
934955
});
935-
956+
936957
ButtonGroup queryParamsButtonGroup = new ButtonGroup();
937958
queryParamsButtonGroup.add(useQueryParamsTableRadio);
938959
queryParamsButtonGroup.add(useQueryParamsVariableRadio);
@@ -989,17 +1010,17 @@ public void actionPerformed(ActionEvent evt) {
9891010
useHeadersTableRadio.addActionListener(event -> {
9901011
useHeadersVariableFieldsEnabled(false);
9911012
});
992-
1013+
9931014
useHeadersVariableRadio.setText("Use Map:");
9941015
useHeadersVariableRadio.setBackground(new Color(255, 255, 255));
9951016
useHeadersVariableRadio.addActionListener(event -> {
9961017
useHeadersVariableFieldsEnabled(true);
9971018
});
998-
1019+
9991020
ButtonGroup headersButtonGroup = new ButtonGroup();
10001021
headersButtonGroup.add(useHeadersTableRadio);
10011022
headersButtonGroup.add(useHeadersVariableRadio);
1002-
1023+
10031024
responseContentLabel.setText("Response Content:");
10041025

10051026
responseContentXmlBodyRadio.setBackground(new Color(255, 255, 255));
@@ -1203,8 +1224,38 @@ public void actionPerformed(ActionEvent evt) {
12031224
patchButtonActionPerformed(evt);
12041225
}
12051226
});
1227+
1228+
localAddressLabel.setText("Local Address:");
1229+
1230+
localAddressField.setToolTipText("<html>The local address that the client socket will be bound to, if Override Local Binding is set to Yes.<br/></html>");
1231+
1232+
overrideLocalBindingLabel.setText("Override Local Binding:");
1233+
1234+
overrideLocalBindingYesRadio.setBackground(new Color(255, 255, 255));
1235+
overrideLocalBindingYesRadio.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
1236+
overrideLocalBindingButtonGroup.add(overrideLocalBindingYesRadio);
1237+
overrideLocalBindingYesRadio.setText("Yes");
1238+
overrideLocalBindingYesRadio.setToolTipText("<html>Select Yes to override the local address that the client socket will be bound to.<br/>Select No to use the default values of 0.0.0.0:0.<br/></html>");
1239+
overrideLocalBindingYesRadio.setMargin(new Insets(0, 0, 0, 0));
1240+
overrideLocalBindingYesRadio.addActionListener(new ActionListener() {
1241+
public void actionPerformed(ActionEvent evt) {
1242+
overrideLocalBindingYesRadioActionPerformed();
1243+
}
1244+
});
1245+
1246+
overrideLocalBindingNoRadio.setBackground(new Color(255, 255, 255));
1247+
overrideLocalBindingNoRadio.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
1248+
overrideLocalBindingButtonGroup.add(overrideLocalBindingNoRadio);
1249+
overrideLocalBindingNoRadio.setText("No");
1250+
overrideLocalBindingNoRadio.setToolTipText("<html>Select Yes to override the local address that the client socket will be bound to.<br/>Select No to use the default values of 0.0.0.0:0.<br/></html>");
1251+
overrideLocalBindingNoRadio.setMargin(new Insets(0, 0, 0, 0));
1252+
overrideLocalBindingNoRadio.addActionListener(new ActionListener() {
1253+
public void actionPerformed(ActionEvent evt) {
1254+
overrideLocalBindingNoRadioActionPerformed();
1255+
}
1256+
});
12061257
}
1207-
1258+
12081259
private void initToolTips() {
12091260
urlField.setToolTipText("Enter the URL of the HTTP server to send each message to.");
12101261
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() {
12431294
patchButton.setToolTipText("Selects the HTTP operation used to send each message.");
12441295
useQueryParamsTableRadio.setToolTipText("<html>The table below will be used to populate query parameters.</html>");
12451296
useQueryParamsVariableRadio.setToolTipText("<html>The Java map specified by the following variable will be used to populate query parameters.<br/>The map must have String keys and either String or List&lt;String&gt; values.</html>");
1246-
queryParamsVariableField.setToolTipText("<html>The variable of a Java map to use to populate query parameters.<br/>The map must have String keys and either String or List&lt;String&gt; values.</html>");
1297+
queryParamsVariableField.setToolTipText("<html>The variable of a Java map to use to populate query parameters.<br/>The map must have String keys and either String or List&lt;String&gt; values.</html>");
12471298
useHeadersTableRadio.setToolTipText("<html>The table below will be used to populate headers.</html>");
12481299
useHeadersVariableRadio.setToolTipText("<html>The Java map specified by the following variable will be used to populate headers.<br/>The map must have String keys and either String or List&lt;String&gt; values.</html>");
12491300
headersVariableField.setToolTipText("<html>The variable of a Java map to use to populate headers.<br/>The map must have String keys and either String or List&lt;String&gt; values.</html>");
12501301
}
1251-
1302+
12521303
private void initLayout() {
12531304
setLayout(new MigLayout("insets 0 8 0 8, novisualpadding, hidemode 3, gap 12 6", "[][]6[]", "[][][][][][][][][][][][][][][][][grow][][grow][][][][grow]"));
1254-
1305+
12551306
add(urlLabel, "right");
12561307
add(urlField, "w 312!, sx, split 2");
12571308
add(testConnection, "gapbefore 6");
@@ -1262,6 +1313,11 @@ private void initLayout() {
12621313
add(proxyAddressField, "w 202!, sx");
12631314
add(proxyPortLabel, "newline, right");
12641315
add(proxyPortField, "w 56!, sx");
1316+
add(overrideLocalBindingLabel, "newline, right");
1317+
add(overrideLocalBindingYesRadio, "split 2");
1318+
add(overrideLocalBindingNoRadio);
1319+
add(localAddressLabel, "newline, right");
1320+
add(localAddressField, "w 200!, sx");
12651321
add(methodLabel, "newline, right");
12661322
add(postButton, "split 5");
12671323
add(getButton);
@@ -1476,21 +1532,31 @@ private void dataTypeTextRadioActionPerformed(ActionEvent evt) {
14761532
charsetEncodingCombobox.setEnabled(true);
14771533
}
14781534
}
1479-
1535+
14801536
private void useHeadersVariableFieldsEnabled(boolean useVariable) {
14811537
headersVariableField.setEnabled(useVariable);
14821538
headersTable.setEnabled(!useVariable);
14831539
headersNewButton.setEnabled(!useVariable);
14841540
headersDeleteButton.setEnabled(!useVariable && headersTable.getSelectedRow() > -1);
14851541
}
1486-
1542+
14871543
private void useQueryParamsVariableFieldsEnabled(boolean useVariable) {
14881544
queryParamsVariableField.setEnabled(useVariable);
14891545
queryParametersTable.setEnabled(!useVariable);
14901546
queryParametersNewButton.setEnabled(!useVariable);
14911547
queryParametersDeleteButton.setEnabled(!useVariable && queryParametersTable.getSelectedRow() > -1);
14921548
}
1493-
1549+
1550+
private void overrideLocalBindingYesRadioActionPerformed() {
1551+
localAddressField.setEnabled(true);
1552+
localAddressLabel.setEnabled(true);
1553+
}
1554+
1555+
private void overrideLocalBindingNoRadioActionPerformed() {
1556+
localAddressField.setEnabled(false);
1557+
localAddressLabel.setEnabled(false);
1558+
}
1559+
14941560
private ButtonGroup authenticationButtonGroup;
14951561
private JLabel authenticationLabel;
14961562
private MirthRadioButton authenticationNoRadio;
@@ -1570,4 +1636,10 @@ private void useQueryParamsVariableFieldsEnabled(boolean useVariable) {
15701636
private MirthRadioButton useProxyServerYesRadio;
15711637
private MirthTextField usernameField;
15721638
private JLabel usernameLabel;
1639+
private JLabel overrideLocalBindingLabel;
1640+
private ButtonGroup overrideLocalBindingButtonGroup;
1641+
private MirthRadioButton overrideLocalBindingNoRadio;
1642+
private MirthRadioButton overrideLocalBindingYesRadio;
1643+
private JLabel localAddressLabel;
1644+
private MirthIconTextField localAddressField;
15731645
}

server/src/com/mirth/connect/connectors/http/HttpConnectorServlet.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
/*
2-
* Copyright (c) Mirth Corporation. All rights reserved.
3-
*
4-
* http://www.mirthcorp.com
5-
*
6-
* The software in this package is published under the terms of the MPL license a copy of which has
7-
* been included with this distribution in the LICENSE.txt file.
8-
*/
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: Mirth Corporation
93

104
package com.mirth.connect.connectors.http;
115

@@ -15,8 +9,6 @@
159
import javax.ws.rs.core.Context;
1610
import javax.ws.rs.core.SecurityContext;
1711

18-
import org.apache.commons.lang3.StringUtils;
19-
2012
import com.mirth.connect.client.core.api.MirthApiException;
2113
import com.mirth.connect.server.api.MirthServlet;
2214
import com.mirth.connect.server.util.ConnectorUtil;
@@ -36,9 +28,22 @@ public HttpConnectorServlet(@Context HttpServletRequest request, @Context Securi
3628
public ConnectionTestResponse testConnection(String channelId, String channelName, HttpDispatcherProperties properties) {
3729
try {
3830
URL url = new URL(replacer.replaceValues(properties.getHost(), channelId, channelName));
39-
int port = url.getPort();
4031
// If no port was provided, default to port 80 or 443.
41-
return ConnectorUtil.testConnection(url.getHost(), (port == -1) ? (StringUtils.equalsIgnoreCase(url.getProtocol(), "https") ? 443 : 80) : port, TIMEOUT);
32+
final int port;
33+
if (url.getPort() != -1) {
34+
port = url.getPort();
35+
} else if ("https".equalsIgnoreCase(url.getProtocol())) {
36+
port = 443;
37+
} else {
38+
port = 80;
39+
}
40+
41+
if (!properties.isOverrideLocalBinding()) {
42+
return ConnectorUtil.testConnection(url.getHost(), port, TIMEOUT);
43+
} else {
44+
String localAddr = replacer.replaceValues(properties.getLocalAddress(), channelId, channelName);
45+
return ConnectorUtil.testConnection(url.getHost(), port, TIMEOUT, localAddr);
46+
}
4247
} catch (Exception e) {
4348
throw new MirthApiException(e);
4449
}

server/src/com/mirth/connect/connectors/http/HttpDispatcher.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
/*
2-
* Copyright (c) Mirth Corporation. All rights reserved.
3-
*
4-
* http://www.mirthcorp.com
5-
*
6-
* The software in this package is published under the terms of the MPL license a copy of which has
7-
* been included with this distribution in the LICENSE.txt file.
8-
*/
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: Mirth Corporation
93

104
package com.mirth.connect.connectors.http;
115

126
import java.io.File;
7+
import java.net.InetAddress;
138
import java.net.URI;
149
import java.nio.charset.Charset;
1510
import java.util.ArrayList;
@@ -27,6 +22,7 @@
2722
import javax.mail.util.ByteArrayDataSource;
2823

2924
import com.mirth.connect.client.core.BrandingConstants;
25+
import com.mirth.connect.util.TcpUtil;
3026
import org.apache.commons.collections4.CollectionUtils;
3127
import org.apache.commons.collections4.map.CaseInsensitiveMap;
3228
import org.apache.commons.fileupload.FileUploadBase;
@@ -192,6 +188,7 @@ public void replaceConnectorProperties(ConnectorProperties connectorProperties,
192188
httpDispatcherProperties.setHost(replacer.replaceValues(httpDispatcherProperties.getHost(), connectorMessage));
193189
httpDispatcherProperties.setProxyAddress(replacer.replaceValues(httpDispatcherProperties.getProxyAddress(), connectorMessage));
194190
httpDispatcherProperties.setProxyPort(replacer.replaceValues(httpDispatcherProperties.getProxyPort(), connectorMessage));
191+
httpDispatcherProperties.setLocalAddress(replacer.replaceValues(httpDispatcherProperties.getLocalAddress(), connectorMessage));
195192
httpDispatcherProperties.setResponseBinaryMimeTypes(replacer.replaceValues(httpDispatcherProperties.getResponseBinaryMimeTypes(), connectorMessage));
196193
httpDispatcherProperties.setHeadersMap(replacer.replaceKeysAndValuesInMap(httpDispatcherProperties.getHeadersMap(), connectorMessage));
197194
httpDispatcherProperties.setHeadersVariable(replacer.replaceValues(httpDispatcherProperties.getHeadersVariable(), connectorMessage));
@@ -258,9 +255,9 @@ public Response send(ConnectorProperties connectorProperties, ConnectorMessage c
258255

259256
/*
260257
* If a charset is set in the Content Type field, use that.
261-
*
258+
*
262259
* If the charset is NONE, keep it as null.
263-
*
260+
*
264261
* Otherwise, use the charset from the Character Encoding drop-down menu.
265262
*/
266263
Charset charset = null;
@@ -312,8 +309,14 @@ public Response send(ConnectorProperties connectorProperties, ConnectorMessage c
312309
logger.debug("using authentication with credentials: " + credentials);
313310
}
314311

315-
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(socketTimeout).setSocketTimeout(socketTimeout).setStaleConnectionCheckEnabled(true).build();
316-
context.setRequestConfig(requestConfig);
312+
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
313+
.setConnectTimeout(socketTimeout)
314+
.setSocketTimeout(socketTimeout)
315+
.setStaleConnectionCheckEnabled(true);
316+
if (httpDispatcherProperties.isOverrideLocalBinding()) {
317+
requestConfigBuilder.setLocalAddress(InetAddress.getByName(TcpUtil.getFixedHost(httpDispatcherProperties.getLocalAddress())));
318+
}
319+
context.setRequestConfig(requestConfigBuilder.build());
317320

318321
// Set proxy information
319322
if (httpDispatcherProperties.isUseProxyServer()) {
@@ -444,7 +447,7 @@ public boolean isBinaryContentType(ContentType contentType) {
444447

445448
return new Response(responseStatus, responseData, responseStatusMessage, responseError, validateResponse);
446449
}
447-
450+
448451
protected boolean shouldParseMultipart(HttpDispatcherProperties httpDispatcherProperties, String mimeType) {
449452
// Only parse multipart if XML Body is selected and Parse Multipart is enabled
450453
return httpDispatcherProperties.isResponseXmlBody() && httpDispatcherProperties.isResponseParseMultipart() && mimeType.startsWith(FileUploadBase.MULTIPART);

0 commit comments

Comments
 (0)