You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by al...@apache.org on 2019/10/17 23:02:35 UTC
[kudu] branch branch-1.11.x updated: webserver: support HTTP
OPTIONS requests
This is an automated email from the ASF dual-hosted git repository.
alexey pushed a commit to branch branch-1.11.x
in repository https://gitbox.apache.org/repos/asf/kudu.git
The following commit(s) were added to refs/heads/branch-1.11.x by this push:
new fa5c92a webserver: support HTTP OPTIONS requests
fa5c92a is described below
commit fa5c92a18e1e37a3e29bb99bcb024f55d9a37cfd
Author: Adar Dembo <ad...@cloudera.com>
AuthorDate: Mon Oct 14 18:14:28 2019 -0700
webserver: support HTTP OPTIONS requests
This is a port of IMPALA-8982 to Kudu, including:
- Updating squeasel to a newer revision that handles OPTIONS rather than
responding with an HTTP 500 error code.
- Modifying the webserver to let squeasel handle OPTIONS, bypassing SPNEGO
authentication.
Change-Id: Icc2328d41ebb30c9ab1b25cb28fcc7e56cc8a25b
Reviewed-on: http://gerrit.cloudera.org:8080/14439
Reviewed-by: Alexey Serbin <as...@cloudera.com>
Tested-by: Adar Dembo <ad...@cloudera.com>
Reviewed-by: Thomas Tauber-Marshall <tm...@cloudera.com>
(cherry picked from commit d6a6b54b175032c7d13d231ef6d156ef9d0e3ab0)
Reviewed-on: http://gerrit.cloudera.org:8080/14475
Tested-by: Alexey Serbin <as...@cloudera.com>
Reviewed-by: Adar Dembo <ad...@cloudera.com>
---
src/kudu/server/webserver-test.cc | 19 +++++++++++++++++++
src/kudu/server/webserver.cc | 6 ++++++
src/kudu/util/curl_util.cc | 28 +++++++++++++++++++++-------
src/kudu/util/curl_util.h | 8 ++++++++
thirdparty/vars.sh | 2 +-
5 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/src/kudu/server/webserver-test.cc b/src/kudu/server/webserver-test.cc
index cb6253f..82ee16b 100644
--- a/src/kudu/server/webserver-test.cc
+++ b/src/kudu/server/webserver-test.cc
@@ -110,6 +110,14 @@ class WebserverTest : public KuduTest {
url_ = Substitute("http://$0", addr_.ToString());
}
+ void RunTestOptions() {
+ curl_.set_custom_method("OPTIONS");
+ curl_.set_return_headers(true);
+ ASSERT_OK(curl_.FetchURL(url_, &buf_));
+ ASSERT_STR_CONTAINS(buf_.ToString(),
+ "Allow: GET, POST, HEAD, OPTIONS, PROPFIND, MKCOL");
+ }
+
protected:
virtual void MaybeSetupSpnego(WebserverOptions* /*opts*/) {}
@@ -285,6 +293,12 @@ TEST_F(SpnegoWebserverTest, TestTruncatedTokens) {
} while (!token.empty());
}
+// Tests that even if we don't provide adequate authentication information in
+// an OPTIONS request, the server still honors it.
+TEST_F(SpnegoWebserverTest, TestAuthNotRequiredForOptions) {
+ NO_FATALS(RunTestOptions());
+}
+
TEST_F(WebserverTest, TestIndexPage) {
curl_.set_return_headers(true);
ASSERT_OK(curl_.FetchURL(url_, &buf_));
@@ -449,6 +463,11 @@ TEST_F(WebserverTest, TestStaticFiles) {
ASSERT_EQ("Remote error: HTTP 403", s.ToString());
}
+// Test that HTTP OPTIONS requests are permitted.
+TEST_F(WebserverTest, TestHttpOptions) {
+ NO_FATALS(RunTestOptions());
+}
+
class WebserverAdvertisedAddressesTest : public KuduTest {
public:
void SetUp() override {
diff --git a/src/kudu/server/webserver.cc b/src/kudu/server/webserver.cc
index 7e34cd5..5efcf1d 100644
--- a/src/kudu/server/webserver.cc
+++ b/src/kudu/server/webserver.cc
@@ -459,6 +459,12 @@ sq_callback_result_t Webserver::BeginRequestCallbackStatic(
sq_callback_result_t Webserver::BeginRequestCallback(
struct sq_connection* connection,
struct sq_request_info* request_info) {
+ if (strncmp("OPTIONS", request_info->request_method, 7) == 0) {
+ // Let Squeasel deal with the request. OPTIONS requests should not require
+ // authentication, so do this before doing SPNEGO.
+ return SQ_CONTINUE_HANDLING;
+ }
+
if (opts_.require_spnego) {
const char* authz_header = sq_get_header(connection, "Authorization");
string resp_header, authn_princ;
diff --git a/src/kudu/util/curl_util.cc b/src/kudu/util/curl_util.cc
index e80d481..14e247c 100644
--- a/src/kudu/util/curl_util.cc
+++ b/src/kudu/util/curl_util.cc
@@ -21,6 +21,8 @@
#include <cstdint>
#include <mutex>
#include <ostream>
+#include <string>
+#include <vector>
#include <curl/curl.h>
#include <glog/logging.h>
@@ -30,6 +32,9 @@
#include "kudu/util/faststring.h"
#include "kudu/util/scoped_cleanup.h"
+using std::string;
+using std::vector;
+
namespace kudu {
namespace {
@@ -74,21 +79,21 @@ EasyCurl::~EasyCurl() {
curl_easy_cleanup(curl_);
}
-Status EasyCurl::FetchURL(const std::string& url, faststring* dst,
- const std::vector<std::string>& headers) {
+Status EasyCurl::FetchURL(const string& url, faststring* dst,
+ const vector<string>& headers) {
return DoRequest(url, nullptr, dst, headers);
}
-Status EasyCurl::PostToURL(const std::string& url,
- const std::string& post_data,
+Status EasyCurl::PostToURL(const string& url,
+ const string& post_data,
faststring* dst) {
return DoRequest(url, &post_data, dst);
}
-Status EasyCurl::DoRequest(const std::string& url,
- const std::string* post_data,
+Status EasyCurl::DoRequest(const string& url,
+ const string* post_data,
faststring* dst,
- const std::vector<std::string>& headers) {
+ const vector<string>& headers) {
CHECK_NOTNULL(dst)->clear();
if (!verify_peer_) {
@@ -135,6 +140,15 @@ Status EasyCurl::DoRequest(const std::string& url,
post_data->c_str())));
}
+ // Done after CURLOPT_POSTFIELDS in case that resets the method (the docs[1]
+ // are unclear on whether that happens).
+ //
+ // 1. https://curl.haxx.se/libcurl/c/CURLOPT_POSTFIELDS.html
+ if (!custom_method_.empty()) {
+ RETURN_NOT_OK(TranslateError(curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST,
+ custom_method_.c_str())));
+ }
+
RETURN_NOT_OK(TranslateError(curl_easy_setopt(curl_, CURLOPT_HTTPAUTH, CURLAUTH_ANY)));
if (timeout_.Initialized()) {
RETURN_NOT_OK(TranslateError(curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1)));
diff --git a/src/kudu/util/curl_util.h b/src/kudu/util/curl_util.h
index 6b4ea9e..86f01da 100644
--- a/src/kudu/util/curl_util.h
+++ b/src/kudu/util/curl_util.h
@@ -18,6 +18,7 @@
#define KUDU_UTIL_CURL_UTIL_H
#include <string>
+#include <utility>
#include <vector>
#include "kudu/gutil/macros.h"
@@ -77,6 +78,11 @@ class EasyCurl {
verbose_ = v;
}
+ // Overrides curl's HTTP method handling with a custom method string.
+ void set_custom_method(std::string m) {
+ custom_method_ = std::move(m);
+ }
+
private:
// Do a request. If 'post_data' is non-NULL, does a POST.
// Otherwise, does a GET.
@@ -86,6 +92,8 @@ class EasyCurl {
const std::vector<std::string>& headers = {});
CURL* curl_;
+ std::string custom_method_;
+
// Whether to verify the server certificate.
bool verify_peer_ = true;
diff --git a/thirdparty/vars.sh b/thirdparty/vars.sh
index 1c386c0..1b007f7 100644
--- a/thirdparty/vars.sh
+++ b/thirdparty/vars.sh
@@ -97,7 +97,7 @@ RAPIDJSON_SOURCE=$TP_SOURCE_DIR/$RAPIDJSON_NAME
# export NAME=squeasel-$(git rev-parse HEAD)
# git archive HEAD --prefix=$NAME/ -o /tmp/$NAME.tar.gz
# s3cmd put -P /tmp/$NAME.tar.gz s3://cloudera-thirdparty-libs/$NAME.tar.gz
-SQUEASEL_VERSION=7973705170f4744d1806e32695f7ea1e8308ee95
+SQUEASEL_VERSION=36dc66b8723980feb32196a94b46734eb5eafbf9
SQUEASEL_NAME=squeasel-$SQUEASEL_VERSION
SQUEASEL_SOURCE=$TP_SOURCE_DIR/$SQUEASEL_NAME