Browse Source

HTTP: Add 'http.publish_port' setting to the HTTP module

This change adds a 'http.publish_port' setting to the HTTP module to configure
the port which HTTP clients should use when communicating with the node. This
is useful when running on a bridged network interface or when running behind
a proxy or firewall.

Closes #8807
Closes #8137
Peter Fabian Mitchell 11 years ago
parent
commit
b2bab05c29

+ 5 - 0
docs/reference/modules/http.asciidoc

@@ -25,6 +25,11 @@ The following are the settings that can be configured for HTTP:
 |Setting |Description
 |`http.port` |A bind port range. Defaults to `9200-9300`.
 
+|`http.publish_port` |The port that HTTP clients should use when
+communicating with this node. Useful when a cluster node is behind a
+proxy or firewall and the `http.port` is not directly addressable
+from the outside. Defaults to the actual port assigned via `http.port`.
+
 |`http.bind_host` |The host address to bind the HTTP service to. Defaults to `http.host` (if set) or `network.bind_host`.
 
 |`http.publish_host` |The host address to publish for HTTP clients to connect to. Defaults to `http.host` (if set) or `network.publish_host`.

+ 7 - 1
src/main/java/org/elasticsearch/http/netty/NettyHttpServerTransport.java

@@ -109,6 +109,8 @@ public class NettyHttpServerTransport extends AbstractLifecycleComponent<HttpSer
 
     private final String publishHost;
 
+    private int publishPort;
+
     private final String tcpNoDelay;
     private final String tcpKeepAlive;
     private final Boolean reuseAddress;
@@ -154,6 +156,7 @@ public class NettyHttpServerTransport extends AbstractLifecycleComponent<HttpSer
         this.port = componentSettings.get("port", settings.get("http.port", "9200-9300"));
         this.bindHost = componentSettings.get("bind_host", settings.get("http.bind_host", settings.get("http.host")));
         this.publishHost = componentSettings.get("publish_host", settings.get("http.publish_host", settings.get("http.host")));
+        this.publishPort = componentSettings.getAsInt("publish_port", settings.getAsInt("http.publish_port", 0));
         this.tcpNoDelay = componentSettings.get("tcp_no_delay", settings.get(TCP_NO_DELAY, "true"));
         this.tcpKeepAlive = componentSettings.get("tcp_keep_alive", settings.get(TCP_KEEP_ALIVE, "true"));
         this.reuseAddress = componentSettings.getAsBoolean("reuse_address", settings.getAsBoolean(TCP_REUSE_ADDRESS, NetworkUtils.defaultReuseAddress()));
@@ -266,8 +269,11 @@ public class NettyHttpServerTransport extends AbstractLifecycleComponent<HttpSer
 
         InetSocketAddress boundAddress = (InetSocketAddress) serverChannel.getLocalAddress();
         InetSocketAddress publishAddress;
+        if (0 == publishPort) {
+            publishPort = boundAddress.getPort();
+        }
         try {
-            publishAddress = new InetSocketAddress(networkService.resolvePublishHostAddress(publishHost), boundAddress.getPort());
+            publishAddress = new InetSocketAddress(networkService.resolvePublishHostAddress(publishHost), publishPort);
         } catch (Exception e) {
             throw new BindTransportException("Failed to resolve publish address", e);
         }

+ 60 - 0
src/test/java/org/elasticsearch/http/netty/HttpPublishPortTests.java

@@ -0,0 +1,60 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.elasticsearch.http.netty;
+
+import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
+import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
+import org.elasticsearch.common.settings.ImmutableSettings;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.BoundTransportAddress;
+import org.elasticsearch.common.transport.InetSocketTransportAddress;
+import org.elasticsearch.node.internal.InternalNode;
+import org.elasticsearch.test.ElasticsearchIntegrationTest;
+import org.junit.Test;
+
+import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
+import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.*;
+
+@ClusterScope(scope = Scope.SUITE, numDataNodes = 1)
+public class HttpPublishPortTests extends ElasticsearchIntegrationTest {
+
+    @Override
+    protected Settings nodeSettings(int nodeOrdinal) {
+        return ImmutableSettings.settingsBuilder()
+                .put(super.nodeSettings(nodeOrdinal))
+                .put(InternalNode.HTTP_ENABLED, true)
+                .put("http.publish_port", 9080)
+                .build();
+    }
+
+    @Test
+    public void testHttpPublishPort() throws Exception {
+        NodesInfoResponse response = client().admin().cluster().prepareNodesInfo().clear().setHttp(true).get();
+        assertThat(response.getNodes(), arrayWithSize(greaterThanOrEqualTo(1)));
+        NodeInfo nodeInfo = response.getNodes()[0];
+
+        BoundTransportAddress address = nodeInfo.getHttp().address();
+        assertThat(address.publishAddress(), instanceOf(InetSocketTransportAddress.class));
+
+        InetSocketTransportAddress publishAddress = (InetSocketTransportAddress) address.publishAddress();
+        assertThat(publishAddress.address().getPort(), is(9080));
+    }
+}