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
|
||||
----
|
||||
|
||||
* 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
|
||||
|
||||
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:
|
||||
|
||||
* `--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
|
||||
execution queue. Please have a look at @ref NewFeatures14Async for more details.
|
||||
|
||||
|
|
|
@ -116,6 +116,10 @@ Command-Line Options for arangod {#CommandLineArangod}
|
|||
@anchor CommandLineArangoKeepAliveTimeout
|
||||
@copydetails triagens::rest::ApplicationEndpointServer::_keepAliveTimeout
|
||||
|
||||
@CLEARPAGE
|
||||
@anchor CommandLineArangoAllowMethodOverride
|
||||
@copydetails triagens::rest::ApplicationEndpointServer::_allowMethodOverride
|
||||
|
||||
@CLEARPAGE
|
||||
@anchor CommandLineArangoKeyFile
|
||||
@copydetails triagens::rest::ApplicationEndpointServer::_httpsKeyfile
|
||||
|
|
|
@ -157,7 +157,7 @@ Handler::status_e RestBatchHandler::execute() {
|
|||
|
||||
// set up request object for the part
|
||||
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) {
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
|
|
|
@ -101,6 +101,7 @@ ApplicationEndpointServer::ApplicationEndpointServer (ApplicationServer* applica
|
|||
_httpPort(),
|
||||
_endpoints(),
|
||||
_keepAliveTimeout(300.0),
|
||||
_allowMethodOverride(false),
|
||||
_backlogSize(10),
|
||||
_httpsKeyfile(),
|
||||
_cafile(),
|
||||
|
@ -216,6 +217,7 @@ void ApplicationEndpointServer::setupOptions (map<string, ProgramOptionsDescript
|
|||
;
|
||||
|
||||
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.backlog-size", &_backlogSize, "listen backlog size")
|
||||
;
|
||||
|
@ -543,6 +545,7 @@ bool ApplicationEndpointServer::prepare () {
|
|||
_endpointList.dump();
|
||||
|
||||
_handlerFactory = new HttpHandlerFactory(_authenticationRealm,
|
||||
_allowMethodOverride,
|
||||
_setContext,
|
||||
_contextData);
|
||||
|
||||
|
|
|
@ -404,6 +404,33 @@ namespace triagens {
|
|||
|
||||
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
|
||||
///
|
||||
|
|
|
@ -56,9 +56,11 @@ using namespace std;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
|
||||
bool allowMethodOverride,
|
||||
context_fptr setContext,
|
||||
void* setContextData)
|
||||
: _authenticationRealm(authenticationRealm),
|
||||
_allowMethodOverride(allowMethodOverride),
|
||||
_setContext(setContext),
|
||||
_setContextData(setContextData),
|
||||
_notFound(0) {
|
||||
|
@ -70,6 +72,7 @@ HttpHandlerFactory::HttpHandlerFactory (std::string const& authenticationRealm,
|
|||
|
||||
HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
|
||||
: _authenticationRealm(that._authenticationRealm),
|
||||
_allowMethodOverride(that._allowMethodOverride),
|
||||
_setContext(that._setContext),
|
||||
_setContextData(that._setContextData),
|
||||
_constructors(that._constructors),
|
||||
|
@ -84,9 +87,10 @@ HttpHandlerFactory::HttpHandlerFactory (HttpHandlerFactory const& that)
|
|||
|
||||
HttpHandlerFactory& HttpHandlerFactory::operator= (HttpHandlerFactory const& that) {
|
||||
if (this != &that) {
|
||||
_authenticationRealm = that._authenticationRealm,
|
||||
_setContext = that._setContext,
|
||||
_setContextData = that._setContextData,
|
||||
_authenticationRealm = that._authenticationRealm;
|
||||
_allowMethodOverride = that._allowMethodOverride;
|
||||
_setContext = that._setContext;
|
||||
_setContextData = that._setContextData;
|
||||
_constructors = that._constructors;
|
||||
_datas = that._datas;
|
||||
_prefixes = that._prefixes;
|
||||
|
@ -180,7 +184,8 @@ HttpRequest* HttpHandlerFactory::createRequest (ConnectionInfo const& info,
|
|||
}
|
||||
#endif
|
||||
|
||||
HttpRequest* request = new HttpRequest(info, ptr, length);
|
||||
HttpRequest* request = new HttpRequest(info, ptr, length, _allowMethodOverride);
|
||||
|
||||
if (request != 0) {
|
||||
setRequestContext(request);
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HttpHandlerFactory (std::string const&,
|
||||
bool,
|
||||
context_fptr,
|
||||
void*);
|
||||
|
||||
|
@ -247,6 +248,12 @@ namespace triagens {
|
|||
|
||||
string _authenticationRealm;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief allow overriding HTTP request method with custom headers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool _allowMethodOverride;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set context callback
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -56,7 +56,10 @@ static char const* EMPTY_STR = "";
|
|||
/// @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),
|
||||
_headers(5),
|
||||
_values(10),
|
||||
|
@ -74,7 +77,8 @@ HttpRequest::HttpRequest (ConnectionInfo const& info, char const* header, size_t
|
|||
_databaseName(),
|
||||
_user(),
|
||||
_requestContext(0),
|
||||
_isRequestContextOwner(false) {
|
||||
_isRequestContextOwner(false),
|
||||
_allowMethodOverride(allowMethodOverride) {
|
||||
|
||||
// copy request - we will destroy/rearrange the content to compute the
|
||||
// headers and values in-place
|
||||
|
@ -110,7 +114,8 @@ HttpRequest::HttpRequest ()
|
|||
_databaseName(),
|
||||
_user(),
|
||||
_requestContext(0),
|
||||
_isRequestContextOwner(false) {
|
||||
_isRequestContextOwner(false),
|
||||
_allowMethodOverride(false) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -503,8 +508,10 @@ size_t HttpRequest::bodySize () const {
|
|||
/// {@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);
|
||||
|
||||
if (_body == 0) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -531,7 +538,9 @@ TRI_json_t* HttpRequest::toJson (char** errmsg) {
|
|||
/// @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")
|
||||
_contentLength = TRI_Int64String(value);
|
||||
}
|
||||
|
@ -539,6 +548,22 @@ void HttpRequest::setHeader (char const* key, size_t keyLength, char const* valu
|
|||
parseCookies(value);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -623,7 +648,8 @@ void HttpRequest::setUser (string const& user) {
|
|||
/// @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) {
|
||||
case 3:
|
||||
if (ptr[0] == 'g' && ptr[1] == 'e' && ptr[2] == 't') {
|
||||
|
|
|
@ -119,7 +119,8 @@ namespace triagens {
|
|||
|
||||
HttpRequest (ConnectionInfo const&,
|
||||
char const*,
|
||||
size_t);
|
||||
size_t,
|
||||
bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
|
@ -687,6 +688,13 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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