HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-thrift / src / test / java / org / apache / hadoop / hbase / thrift / TestThriftHttpServer.java
blobb426cd15b2c0c0ad9d74dfe4df6e4b6eea8550d1
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.thrift;
20 import static org.apache.hadoop.hbase.thrift.TestThriftServerCmdLine.createBoundServer;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.fail;
24 import java.io.IOException;
25 import java.net.HttpURLConnection;
26 import java.net.URL;
27 import java.util.function.Supplier;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.hbase.HBaseClassTestRule;
30 import org.apache.hadoop.hbase.HBaseTestingUtil;
31 import org.apache.hadoop.hbase.HConstants;
32 import org.apache.hadoop.hbase.testclassification.ClientTests;
33 import org.apache.hadoop.hbase.testclassification.LargeTests;
34 import org.apache.hadoop.hbase.thrift.generated.Hbase;
35 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
36 import org.apache.hadoop.hbase.util.EnvironmentEdgeManagerTestHelper;
37 import org.apache.hadoop.hbase.util.IncrementingEnvironmentEdge;
38 import org.apache.hadoop.hbase.util.TableDescriptorChecker;
39 import org.apache.thrift.protocol.TBinaryProtocol;
40 import org.apache.thrift.protocol.TProtocol;
41 import org.apache.thrift.transport.THttpClient;
42 import org.apache.thrift.transport.TTransportException;
43 import org.junit.AfterClass;
44 import org.junit.Assert;
45 import org.junit.BeforeClass;
46 import org.junit.ClassRule;
47 import org.junit.Rule;
48 import org.junit.Test;
49 import org.junit.experimental.categories.Category;
50 import org.junit.rules.ExpectedException;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
54 import org.apache.hbase.thirdparty.com.google.common.base.Joiner;
56 /**
57 * Start the HBase Thrift HTTP server on a random port through the command-line
58 * interface and talk to it from client side.
60 @Category({ClientTests.class, LargeTests.class})
61 public class TestThriftHttpServer {
62 @ClassRule
63 public static final HBaseClassTestRule CLASS_RULE =
64 HBaseClassTestRule.forClass(TestThriftHttpServer.class);
66 private static final Logger LOG =
67 LoggerFactory.getLogger(TestThriftHttpServer.class);
69 protected static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
71 @BeforeClass
72 public static void setUpBeforeClass() throws Exception {
73 TEST_UTIL.getConfiguration().setBoolean(Constants.USE_HTTP_CONF_KEY, true);
74 TEST_UTIL.getConfiguration().setBoolean(TableDescriptorChecker.TABLE_SANITY_CHECKS, false);
75 TEST_UTIL.startMiniCluster();
76 //ensure that server time increments every time we do an operation, otherwise
77 //successive puts having the same timestamp will override each other
78 EnvironmentEdgeManagerTestHelper.injectEdge(new IncrementingEnvironmentEdge());
81 @AfterClass
82 public static void tearDownAfterClass() throws Exception {
83 TEST_UTIL.shutdownMiniCluster();
84 EnvironmentEdgeManager.reset();
87 @Test
88 public void testExceptionThrownWhenMisConfigured() throws IOException {
89 Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
90 conf.set("hbase.thrift.security.qop", "privacy");
91 conf.setBoolean("hbase.thrift.ssl.enabled", false);
92 ExpectedException thrown = ExpectedException.none();
93 ThriftServerRunner tsr = null;
94 try {
95 thrown.expect(IllegalArgumentException.class);
96 thrown.expectMessage("Thrift HTTP Server's QoP is privacy, " +
97 "but hbase.thrift.ssl.enabled is false");
98 tsr = TestThriftServerCmdLine.createBoundServer(() -> new ThriftServer(conf));
99 fail("Thrift HTTP Server starts up even with wrong security configurations.");
100 } catch (Exception e) {
101 LOG.info("Expected!", e);
102 } finally {
103 if (tsr != null) {
104 tsr.close();
109 @Rule
110 public ExpectedException exception = ExpectedException.none();
112 @Test
113 public void testRunThriftServerWithHeaderBufferLength() throws Exception {
114 // Test thrift server with HTTP header length less than 64k
115 try {
116 runThriftServer(1024 * 63);
117 } catch (TTransportException tex) {
118 assertFalse(tex.getMessage().equals("HTTP Response code: 431"));
121 // Test thrift server with HTTP header length more than 64k, expect an exception
122 exception.expect(TTransportException.class);
123 exception.expectMessage("HTTP Response code: 431");
124 runThriftServer(1024 * 64);
127 protected Supplier<ThriftServer> getThriftServerSupplier() {
128 return () -> new ThriftServer(TEST_UTIL.getConfiguration());
131 @Test
132 public void testRunThriftServer() throws Exception {
133 runThriftServer(0);
136 void runThriftServer(int customHeaderSize) throws Exception {
137 // Add retries in case we see stuff like connection reset
138 Exception clientSideException = null;
139 for (int i = 0; i < 10; i++) {
140 clientSideException = null;
141 ThriftServerRunner tsr = createBoundServer(getThriftServerSupplier());
142 String url = "http://" + HConstants.LOCALHOST + ":" + tsr.getThriftServer().listenPort;
143 try {
144 checkHttpMethods(url);
145 talkToThriftServer(url, customHeaderSize);
146 break;
147 } catch (Exception ex) {
148 clientSideException = ex;
149 LOG.info("Client-side Exception", ex);
150 } finally {
151 tsr.close();
152 tsr.join();
153 if (tsr.getRunException() != null) {
154 LOG.error("Invocation of HBase Thrift server threw exception", tsr.getRunException());
155 throw tsr.getRunException();
160 if (clientSideException != null) {
161 LOG.error("Thrift Client", clientSideException);
162 throw clientSideException;
166 private void checkHttpMethods(String url) throws Exception {
167 // HTTP TRACE method should be disabled for security
168 // See https://www.owasp.org/index.php/Cross_Site_Tracing
169 HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
170 conn.setRequestMethod("TRACE");
171 conn.connect();
172 Assert.assertEquals(conn.getResponseMessage(),
173 HttpURLConnection.HTTP_FORBIDDEN, conn.getResponseCode());
176 protected static volatile boolean tableCreated = false;
178 protected void talkToThriftServer(String url, int customHeaderSize) throws Exception {
179 THttpClient httpClient = new THttpClient(url);
180 httpClient.open();
182 if (customHeaderSize > 0) {
183 StringBuilder sb = new StringBuilder();
184 for (int i = 0; i < customHeaderSize; i++) {
185 sb.append("a");
187 httpClient.setCustomHeader("User-Agent", sb.toString());
190 try {
191 TProtocol prot;
192 prot = new TBinaryProtocol(httpClient);
193 Hbase.Client client = new Hbase.Client(prot);
194 if (!tableCreated){
195 TestThriftServer.createTestTables(client);
196 tableCreated = true;
198 TestThriftServer.checkTableList(client);
199 } finally {
200 httpClient.close();