mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/triAGENS/ArangoDB into devel
This commit is contained in:
commit
5570caac29
15
CHANGELOG
15
CHANGELOG
|
@ -1,6 +1,21 @@
|
||||||
v1.4
|
v1.4
|
||||||
----
|
----
|
||||||
|
|
||||||
|
* added startup option `--server.allow-method-override`
|
||||||
|
|
||||||
|
This option can be set to allow overriding the HTTP request method in a request using
|
||||||
|
one of the following custom headers:
|
||||||
|
|
||||||
|
- x-http-method-override
|
||||||
|
- x-http-method
|
||||||
|
- x-method-override
|
||||||
|
|
||||||
|
This allows bypassing proxies and tools that would otherwise just let certain types of
|
||||||
|
requests pass. Enabling this option may impose a security risk, so it should only be
|
||||||
|
used in very controlled environments.
|
||||||
|
|
||||||
|
The default value for this option is `false` (no method overriding allowed).
|
||||||
|
|
||||||
* added "details" URL parameter for bulk import API
|
* added "details" URL parameter for bulk import API
|
||||||
|
|
||||||
Setting the `details` URL parameter to `true` in a call to POST `/_api/import` will make
|
Setting the `details` URL parameter to `true` in a call to POST `/_api/import` will make
|
||||||
|
|
|
@ -425,6 +425,16 @@ Command-Line Options added {#NewFeatures14Options}
|
||||||
|
|
||||||
The following command-line options have been added for _arangod_ in ArangoDB 1.4:
|
The following command-line options have been added for _arangod_ in ArangoDB 1.4:
|
||||||
|
|
||||||
|
* `--server.allow-method-override`: this option can be set to allow overriding the
|
||||||
|
HTTP request method in a request using one of the following custom headers:
|
||||||
|
- x-http-method-override
|
||||||
|
- x-http-method
|
||||||
|
- x-method-override
|
||||||
|
Using this option allows bypassing proxies and tools that would otherwise just
|
||||||
|
let certain types of requests pass. Enabling this option may impose a security
|
||||||
|
risk, so it should only be used in very controlled environments.
|
||||||
|
The default value for this option is `false` (no method overriding allowed).
|
||||||
|
|
||||||
* `--scheduler.maximal-queue-size`: limits the size of the asynchronous request
|
* `--scheduler.maximal-queue-size`: limits the size of the asynchronous request
|
||||||
execution queue. Please have a look at @ref NewFeatures14Async for more details.
|
execution queue. Please have a look at @ref NewFeatures14Async for more details.
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,10 @@ Command-Line Options for arangod {#CommandLineArangod}
|
||||||
@anchor CommandLineArangoKeepAliveTimeout
|
@anchor CommandLineArangoKeepAliveTimeout
|
||||||
@copydetails triagens::rest::ApplicationEndpointServer::_keepAliveTimeout
|
@copydetails triagens::rest::ApplicationEndpointServer::_keepAliveTimeout
|
||||||
|
|
||||||
|
@CLEARPAGE
|
||||||
|
@anchor CommandLineArangoAllowMethodOverride
|
||||||
|
@copydetails triagens::rest::ApplicationEndpointServer::_allowMethodOverride
|
||||||
|
|
||||||
@CLEARPAGE
|
@CLEARPAGE
|
||||||
@anchor CommandLineArangoKeyFile
|
@anchor CommandLineArangoKeyFile
|
||||||
@copydetails triagens::rest::ApplicationEndpointServer::_httpsKeyfile
|
@copydetails triagens::rest::ApplicationEndpointServer::_httpsKeyfile
|
||||||
|
|
|
@ -157,7 +157,7 @@ Handler::status_e RestBatchHandler::execute() {
|
||||||
|
|
||||||
// set up request object for the part
|
// set up request object for the part
|
||||||
LOGGER_TRACE("part header is " << string(headerStart, headerLength));
|
LOGGER_TRACE("part header is " << string(headerStart, headerLength));
|
||||||
HttpRequest* request = new HttpRequest(_request->connectionInfo(), headerStart, headerLength);
|
HttpRequest* request = new HttpRequest(_request->connectionInfo(), headerStart, headerLength, false);
|
||||||
|
|
||||||
if (request == 0) {
|
if (request == 0) {
|
||||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
|
@ -101,6 +101,7 @@ ApplicationEndpointServer::ApplicationEndpointServer (ApplicationServer* applica
|
||||||
_httpPort(),
|
_httpPort(),
|
||||||
_endpoints(),
|
_endpoints(),
|
||||||
_keepAliveTimeout(300.0),
|
_keepAliveTimeout(300.0),
|
||||||
|
_allowMethodOverride(false),
|
||||||
_backlogSize(10),
|
_backlogSize(10),
|
||||||
_httpsKeyfile(),
|
_httpsKeyfile(),
|
||||||
_cafile(),
|
_cafile(),
|
||||||
|
@ -216,6 +217,7 @@ void ApplicationEndpointServer::setupOptions (map<string, ProgramOptionsDescript
|
||||||
;
|
;
|
||||||
|
|
||||||
options[ApplicationServer::OPTIONS_SERVER + ":help-admin"]
|
options[ApplicationServer::OPTIONS_SERVER + ":help-admin"]
|
||||||
|
("server.allow-method-override", &_allowMethodOverride, "allow HTTP method override using special headers")
|
||||||
("server.keep-alive-timeout", &_keepAliveTimeout, "keep-alive timeout in seconds")
|
("server.keep-alive-timeout", &_keepAliveTimeout, "keep-alive timeout in seconds")
|
||||||
("server.backlog-size", &_backlogSize, "listen backlog size")
|
("server.backlog-size", &_backlogSize, "listen backlog size")
|
||||||
;
|
;
|
||||||
|
@ -543,6 +545,7 @@ bool ApplicationEndpointServer::prepare () {
|
||||||
_endpointList.dump();
|
_endpointList.dump();
|
||||||
|
|
||||||
_handlerFactory = new HttpHandlerFactory(_authenticationRealm,
|
_handlerFactory = new HttpHandlerFactory(_authenticationRealm,
|
||||||
|
_allowMethodOverride,
|
||||||
_setContext,
|
_setContext,
|
||||||
_contextData);
|
_contextData);
|
||||||
|
|
||||||
|
|
|
@ -404,6 +404,33 @@ namespace triagens {
|
||||||
|
|
||||||
double _keepAliveTimeout;
|
double _keepAliveTimeout;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief allow HTTP method override via custom headers?
|
||||||
|
///
|
||||||
|
/// @CMDOPT{\--server.allow-method-override}
|
||||||
|
///
|
||||||
|
/// When this option is set to `true`, the HTTP request method will optionally
|
||||||
|
/// be fetched from one of the following HTTP request headers if present in
|
||||||
|
/// the request:
|
||||||
|
///
|
||||||
|
/// - `x-http-method`
|
||||||
|
/// - `x-http-method-override`
|
||||||
|
/// - `x-method-override`
|
||||||
|
///
|
||||||
|
/// If the option is set to `true` and any of these headers is set, the
|
||||||
|
/// request method will be overriden by the value of the header. For example,
|
||||||
|
/// this allows issuing an HTTP DELETE request which to the outside world will
|
||||||
|
/// look like an HTTP GET request. This allows bypassing proxies and tools that
|
||||||
|
/// will only let certain request types pass.
|
||||||
|
///
|
||||||
|
/// Setting this option to `true` may impose a security risk so it should only
|
||||||
|
/// be used in controlled environments.
|
||||||
|
///
|
||||||
|
/// The default value for this option is `false`.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool _allowMethodOverride;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief listen backlog size
|
/// @brief listen backlog size
|
||||||
///
|
///
|
||||||
|
|
|
@ -56,9 +56,11 @@ using namespace std;
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
|
HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
|
||||||
|
bool allowMethodOverride,
|
||||||
context_fptr setContext,
|
context_fptr setContext,
|
||||||
void* setContextData)
|
void* setContextData)
|
||||||
: _authenticationRealm(authenticationRealm),
|
: _authenticationRealm(authenticationRealm),
|
||||||
|
_allowMethodOverride(allowMethodOverride),
|
||||||
_setContext(setContext),
|
_setContext(setContext),
|
||||||
_setContextData(setContextData),
|
_setContextData(setContextData),
|
||||||
_notFound(0) {
|
_notFound(0) {
|
||||||
|
@ -70,6 +72,7 @@ HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
|
||||||
|
|
||||||
HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
|
HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
|
||||||
: _authenticationRealm(that._authenticationRealm),
|
: _authenticationRealm(that._authenticationRealm),
|
||||||
|
_allowMethodOverride(that._allowMethodOverride),
|
||||||
_setContext(that._setContext),
|
_setContext(that._setContext),
|
||||||
_setContextData(that._setContextData),
|
_setContextData(that._setContextData),
|
||||||
_constructors(that._constructors),
|
_constructors(that._constructors),
|
||||||
|
@ -84,9 +87,10 @@ HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
|
||||||
|
|
||||||
HttpHandlerFactory& HttpHandlerFactory::operator= (HttpHandlerFactory const& that) {
|
HttpHandlerFactory& HttpHandlerFactory::operator= (HttpHandlerFactory const& that) {
|
||||||
if (this != &that) {
|
if (this != &that) {
|
||||||
_authenticationRealm = that._authenticationRealm,
|
_authenticationRealm = that._authenticationRealm;
|
||||||
_setContext = that._setContext,
|
_allowMethodOverride = that._allowMethodOverride;
|
||||||
_setContextData = that._setContextData,
|
_setContext = that._setContext;
|
||||||
|
_setContextData = that._setContextData;
|
||||||
_constructors = that._constructors;
|
_constructors = that._constructors;
|
||||||
_datas = that._datas;
|
_datas = that._datas;
|
||||||
_prefixes = that._prefixes;
|
_prefixes = that._prefixes;
|
||||||
|
@ -180,7 +184,8 @@ HttpRequest* HttpHandlerFactory::createRequest (ConnectionInfo const& info,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HttpRequest* request = new HttpRequest(info, ptr, length);
|
HttpRequest* request = new HttpRequest(info, ptr, length, _allowMethodOverride);
|
||||||
|
|
||||||
if (request != 0) {
|
if (request != 0) {
|
||||||
setRequestContext(request);
|
setRequestContext(request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@ namespace triagens {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HttpHandlerFactory (std::string const&,
|
HttpHandlerFactory (std::string const&,
|
||||||
|
bool,
|
||||||
context_fptr,
|
context_fptr,
|
||||||
void*);
|
void*);
|
||||||
|
|
||||||
|
@ -247,6 +248,12 @@ namespace triagens {
|
||||||
|
|
||||||
string _authenticationRealm;
|
string _authenticationRealm;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief allow overriding HTTP request method with custom headers
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool _allowMethodOverride;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief set context callback
|
/// @brief set context callback
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -56,7 +56,10 @@ static char const* EMPTY_STR = "";
|
||||||
/// @brief http request constructor
|
/// @brief http request constructor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HttpRequest::HttpRequest (ConnectionInfo const& info, char const* header, size_t length)
|
HttpRequest::HttpRequest (ConnectionInfo const& info,
|
||||||
|
char const* header,
|
||||||
|
size_t length,
|
||||||
|
bool allowMethodOverride)
|
||||||
: _requestPath(EMPTY_STR),
|
: _requestPath(EMPTY_STR),
|
||||||
_headers(5),
|
_headers(5),
|
||||||
_values(10),
|
_values(10),
|
||||||
|
@ -74,7 +77,8 @@ HttpRequest::HttpRequest (ConnectionInfo const& info, char const* header, size_t
|
||||||
_databaseName(),
|
_databaseName(),
|
||||||
_user(),
|
_user(),
|
||||||
_requestContext(0),
|
_requestContext(0),
|
||||||
_isRequestContextOwner(false) {
|
_isRequestContextOwner(false),
|
||||||
|
_allowMethodOverride(allowMethodOverride) {
|
||||||
|
|
||||||
// copy request - we will destroy/rearrange the content to compute the
|
// copy request - we will destroy/rearrange the content to compute the
|
||||||
// headers and values in-place
|
// headers and values in-place
|
||||||
|
@ -110,7 +114,8 @@ HttpRequest::HttpRequest ()
|
||||||
_databaseName(),
|
_databaseName(),
|
||||||
_user(),
|
_user(),
|
||||||
_requestContext(0),
|
_requestContext(0),
|
||||||
_isRequestContextOwner(false) {
|
_isRequestContextOwner(false),
|
||||||
|
_allowMethodOverride(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -503,8 +508,10 @@ size_t HttpRequest::bodySize () const {
|
||||||
/// {@inheritDoc}
|
/// {@inheritDoc}
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int HttpRequest::setBody (char const* newBody, size_t length) {
|
int HttpRequest::setBody (char const* newBody,
|
||||||
|
size_t length) {
|
||||||
_body = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, newBody, length);
|
_body = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, newBody, length);
|
||||||
|
|
||||||
if (_body == 0) {
|
if (_body == 0) {
|
||||||
return TRI_ERROR_OUT_OF_MEMORY;
|
return TRI_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -531,7 +538,9 @@ TRI_json_t* HttpRequest::toJson (char** errmsg) {
|
||||||
/// @brief sets a header field
|
/// @brief sets a header field
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void HttpRequest::setHeader (char const* key, size_t keyLength, char const* value) {
|
void HttpRequest::setHeader (char const* key,
|
||||||
|
size_t keyLength,
|
||||||
|
char const* value) {
|
||||||
if (keyLength == 14 && memcmp(key, "content-length", keyLength) == 0) { // 14 = strlen("content-length")
|
if (keyLength == 14 && memcmp(key, "content-length", keyLength) == 0) { // 14 = strlen("content-length")
|
||||||
_contentLength = TRI_Int64String(value);
|
_contentLength = TRI_Int64String(value);
|
||||||
}
|
}
|
||||||
|
@ -539,6 +548,22 @@ void HttpRequest::setHeader (char const* key, size_t keyLength, char const* valu
|
||||||
parseCookies(value);
|
parseCookies(value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (_allowMethodOverride &&
|
||||||
|
keyLength >= 13 &&
|
||||||
|
*key == 'x' && *(key + 1) == '-') {
|
||||||
|
// handle x-... headers
|
||||||
|
|
||||||
|
// override HTTP method?
|
||||||
|
if ((keyLength == 13 && memcmp(key, "x-http-method", keyLength) == 0) ||
|
||||||
|
(keyLength == 17 && memcmp(key, "x-method-override", keyLength) == 0) ||
|
||||||
|
(keyLength == 22 && memcmp(key, "x-http-method-override", keyLength) == 0)) {
|
||||||
|
string overridenType(value);
|
||||||
|
StringUtils::tolowerInPlace(&overridenType);
|
||||||
|
|
||||||
|
_type = getRequestType(overridenType.c_str(), overridenType.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_headers.insert(key, keyLength, value);
|
_headers.insert(key, keyLength, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,7 +648,8 @@ void HttpRequest::setUser (string const& user) {
|
||||||
/// @brief determine the header type
|
/// @brief determine the header type
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HttpRequest::HttpRequestType HttpRequest::getRequestType (const char* ptr, const size_t length) {
|
HttpRequest::HttpRequestType HttpRequest::getRequestType (const char* ptr,
|
||||||
|
const size_t length) {
|
||||||
switch (length) {
|
switch (length) {
|
||||||
case 3:
|
case 3:
|
||||||
if (ptr[0] == 'g' && ptr[1] == 'e' && ptr[2] == 't') {
|
if (ptr[0] == 'g' && ptr[1] == 'e' && ptr[2] == 't') {
|
||||||
|
|
|
@ -119,7 +119,8 @@ namespace triagens {
|
||||||
|
|
||||||
HttpRequest (ConnectionInfo const&,
|
HttpRequest (ConnectionInfo const&,
|
||||||
char const*,
|
char const*,
|
||||||
size_t);
|
size_t,
|
||||||
|
bool);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief destructor
|
/// @brief destructor
|
||||||
|
@ -687,6 +688,13 @@ namespace triagens {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool _isRequestContextOwner;
|
bool _isRequestContextOwner;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief whether or not overriding the HTTP method via custom headers
|
||||||
|
/// (x-http-method, x-method-override or x-http-method-override) is allowed
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool _allowMethodOverride;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue