1
0
Fork 0
arangodb/lib/Rest/GeneralRequest.h

256 lines
8.9 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_REST_GENERAL_REQUEST_H
#define ARANGODB_REST_GENERAL_REQUEST_H 1
#include "Basics/Common.h"
#include "Basics/StringRef.h"
#include "Endpoint/ConnectionInfo.h"
#include "Rest/CommonDefines.h"
#include "Rest/RequestContext.h"
#include <velocypack/Builder.h>
#include <velocypack/Dumper.h>
#include <velocypack/Options.h>
#include <velocypack/velocypack-aliases.h>
namespace arangodb {
namespace velocypack {
class Builder;
struct Options;
} // namespace velocypack
namespace basics {
class StringBuffer;
}
using rest::ContentType;
using rest::ProtocolVersion;
using rest::RequestType;
class GeneralRequest {
GeneralRequest(GeneralRequest const&) = delete;
GeneralRequest& operator=(GeneralRequest const&) = delete;
public:
GeneralRequest(GeneralRequest&&) = default;
public:
// translate the HTTP protocol version
static std::string translateVersion(ProtocolVersion);
// translate an RequestType enum value into an "HTTP method string"
static std::string translateMethod(RequestType);
// translate "HTTP method string" into RequestType enum value
static RequestType translateMethod(std::string const&);
// append RequestType as string value to given String buffer
static void appendMethod(RequestType, arangodb::basics::StringBuffer*);
protected:
static RequestType findRequestType(char const*, size_t const);
public:
GeneralRequest() = default;
explicit GeneralRequest(ConnectionInfo const& connectionInfo)
: _version(ProtocolVersion::UNKNOWN),
_protocol(""),
_connectionInfo(connectionInfo),
_clientTaskId(0),
_requestContext(nullptr),
_isRequestContextOwner(false),
_authenticated(false),
_type(RequestType::ILLEGAL),
_contentType(ContentType::UNSET),
_contentTypeResponse(ContentType::UNSET) {}
virtual ~GeneralRequest();
public:
ProtocolVersion protocolVersion() const { return _version; }
char const* protocol() const { return _protocol; } // http, https or vst
void setProtocol(char const* protocol) { _protocol = protocol; }
ConnectionInfo const& connectionInfo() const { return _connectionInfo; }
uint64_t clientTaskId() const { return _clientTaskId; }
void setClientTaskId(uint64_t clientTaskId) { _clientTaskId = clientTaskId; }
/// Database used for this request, _system by default
TEST_VIRTUAL std::string const& databaseName() const { return _databaseName; }
void setDatabaseName(std::string const& databaseName) {
_databaseName = databaseName;
}
/// @brief User exists on this server or on external auth system
/// and password was checked. Must not imply any access rights
/// to any specific resource.
bool authenticated() const { return _authenticated; }
void setAuthenticated(bool a) { _authenticated = a; }
// @brief User sending this request
TEST_VIRTUAL std::string const& user() const { return _user; }
void setUser(std::string const& user) { _user = user; }
void setUser(std::string&& user) { _user = std::move(user); }
/// @brief the request context depends on the application
TEST_VIRTUAL RequestContext* requestContext() const {
return _requestContext;
}
/// @brief set request context and whether this requests is allowed
/// to delete it
void setRequestContext(RequestContext*, bool);
TEST_VIRTUAL RequestType requestType() const { return _type; }
void setRequestType(RequestType type) { _type = type; }
std::string const& fullUrl() const { return _fullUrl; }
void setFullUrl(char const* begin, char const* end);
// consists of the URL without the host and without any parameters.
std::string const& requestPath() const { return _requestPath; }
void setRequestPath(std::string const& requestPath) {
_requestPath = requestPath;
}
void setRequestPath(char const* begin) { _requestPath = std::string(begin); }
void setRequestPath(char const* begin, char const* end) {
_requestPath = std::string(begin, end - begin);
}
// The request path consists of the URL without the host and without any
// parameters. The request path is split into two parts: the prefix, namely
// the part of the request path that was match by a handler and the suffix
// with all the remaining arguments.
std::string prefix() const { return _prefix; }
void setPrefix(std::string const& prefix) { _prefix = prefix; }
// Returns the request path suffixes in non-URL-decoded form
TEST_VIRTUAL std::vector<std::string> const& suffixes() const {
return _suffixes;
}
// Returns the request path suffixes in URL-decoded form. Note: this will
// re-compute the suffix list on every call!
std::vector<std::string> decodedSuffixes() const;
void addSuffix(std::string&& part);
// VIRTUAL //////////////////////////////////////////////
// return 0 for protocols that
// do not care about message ids
virtual uint64_t messageId() const { return 1; }
virtual arangodb::Endpoint::TransportType transportType() = 0;
// get value from headers map. The key must be lowercase.
std::string const& header(std::string const& key) const;
std::string const& header(std::string const& key, bool& found) const;
std::unordered_map<std::string, std::string> const& headers() const {
return _headers;
}
// the value functions give access to to query string parameters
std::string const& value(std::string const& key) const;
std::string const& value(std::string const& key, bool& found) const;
std::unordered_map<std::string, std::string> const& values() const {
return _values;
}
std::unordered_map<std::string, std::vector<std::string>> const& arrayValues() const {
return _arrayValues;
}
/// @brief returns parsed value, returns valueNotFound if parameter was not found
template <typename T>
T parsedValue(std::string const& key, T valueNotFound);
/// @brief the content length
virtual size_t contentLength() const = 0;
/// @brief unprocessed request payload
virtual arangodb::StringRef rawPayload() const = 0;
/// @brief parsed request payload
virtual VPackSlice payload(arangodb::velocypack::Options const* options = &VPackOptions::Defaults) = 0;
TEST_VIRTUAL std::shared_ptr<VPackBuilder> toVelocyPackBuilderPtr() {
VPackOptions optionsWithUniquenessCheck = VPackOptions::Defaults;
optionsWithUniquenessCheck.checkAttributeUniqueness = true;
return std::make_shared<VPackBuilder>(payload(&optionsWithUniquenessCheck),
&optionsWithUniquenessCheck);
};
std::shared_ptr<VPackBuilder> toVelocyPackBuilderPtrNoUniquenessChecks() {
return std::make_shared<VPackBuilder>(payload());
};
/// @brieg should reflect the Content-Type header
ContentType contentType() const { return _contentType; }
/// @brief should generally reflect the Accept header
ContentType contentTypeResponse() const { return _contentTypeResponse; }
rest::AuthenticationMethod authenticationMethod() const {
return _authenticationMethod;
}
void setAuthenticationMethod(rest::AuthenticationMethod method) {
_authenticationMethod = method;
}
protected:
ProtocolVersion _version;
char const* _protocol; // http, https or vst
// connection info
ConnectionInfo _connectionInfo;
uint64_t _clientTaskId;
std::string _databaseName;
std::string _user;
// request context
RequestContext* _requestContext;
bool _isRequestContextOwner;
bool _authenticated;
rest::AuthenticationMethod _authenticationMethod = rest::AuthenticationMethod::NONE;
// information about the payload
RequestType _type; // GET, POST, ..
std::string _fullUrl;
std::string _requestPath;
std::string _prefix; // part of path matched by rest route
std::vector<std::string> _suffixes;
ContentType _contentType; // UNSET, VPACK, JSON
ContentType _contentTypeResponse;
std::unordered_map<std::string, std::string> _headers;
std::unordered_map<std::string, std::string> _values;
std::unordered_map<std::string, std::vector<std::string>> _arrayValues;
};
} // namespace arangodb
#endif