diff --git a/arangod/GeneralServer/VppCommTask.cpp b/arangod/GeneralServer/VppCommTask.cpp index 031bd69ae0..d1aa4f36b4 100644 --- a/arangod/GeneralServer/VppCommTask.cpp +++ b/arangod/GeneralServer/VppCommTask.cpp @@ -31,6 +31,7 @@ #include "GeneralServer/GeneralServerFeature.h" #include "GeneralServer/RestHandler.h" #include "GeneralServer/RestHandlerFactory.h" +#include "Rest/CommonDefines.h" #include "Logger/LoggerFeature.h" #include "Scheduler/Scheduler.h" #include "Scheduler/SchedulerFeature.h" @@ -160,12 +161,15 @@ std::unique_ptr createChunkForNetworkSingle( VppCommTask::VppCommTask(GeneralServer* server, TRI_socket_t sock, ConnectionInfo&& info, double timeout) : Task("VppCommTask"), - GeneralCommTask(server, sock, std::move(info), timeout) { + GeneralCommTask(server, sock, std::move(info), timeout), + _headerOptions(VPackOptions::Defaults) { _protocol = "vpp"; _readBuffer->reserve( _bufferLength); // ATTENTION <- this is required so we do not // loose information during a resize // connectionStatisticsAgentSetVpp(); + _headerOptions.attributeTranslator = + basics::VelocyPackHelper::getHeaderTranslator(); } void VppCommTask::addResponse(VppResponse* response) { @@ -397,7 +401,7 @@ bool VppCommTask::processRead() { if (doExecute) { VPackSlice header = message.header(); LOG_TOPIC(DEBUG, Logger::COMMUNICATION) - << "got request:" << header.toJson(); + << "got request:" << header.toJson(&_headerOptions); int type = meta::underlyingValue(GeneralRequest::RequestType::ILLEGAL); try { type = header.get("type").getInt(); @@ -412,6 +416,7 @@ bool VppCommTask::processRead() { // the handler will take ownersip of this pointer std::unique_ptr request(new VppRequest( _connectionInfo, std::move(message), chunkHeader._messageID)); + request->setHeaderOptions(&_headerOptions); GeneralServerFeature::HANDLER_FACTORY->setRequestContext(request.get()); // make sure we have a database if (request->requestContext() == nullptr) { @@ -426,6 +431,7 @@ bool VppCommTask::processRead() { std::unique_ptr response( new VppResponse(GeneralResponse::ResponseCode::SERVER_ERROR, chunkHeader._messageID)); + response->setHeaderOptions(&_headerOptions); executeRequest(std::move(request), std::move(response)); } } diff --git a/arangod/GeneralServer/VppCommTask.h b/arangod/GeneralServer/VppCommTask.h index 94d2c3fb4c..762d9c106d 100644 --- a/arangod/GeneralServer/VppCommTask.h +++ b/arangod/GeneralServer/VppCommTask.h @@ -113,6 +113,7 @@ class VppCommTask : public GeneralCommTask { // will be cleaned }; ProcessReadVariables _processReadVariables; + velocypack::Options _headerOptions; struct ChunkHeader { std::size_t _headerLength; diff --git a/lib/Basics/VelocyPackHelper.cpp b/lib/Basics/VelocyPackHelper.cpp index 5c4ddb5a72..a3587f6c41 100644 --- a/lib/Basics/VelocyPackHelper.cpp +++ b/lib/Basics/VelocyPackHelper.cpp @@ -49,6 +49,7 @@ unsigned long long XXH64(const void* input, size_t length, using VelocyPackHelper = arangodb::basics::VelocyPackHelper; static std::unique_ptr Translator; +static std::unique_ptr HeaderTranslator; static std::unique_ptr ExcludeHandler; // attribute exclude handler for skipping over system attributes @@ -130,6 +131,17 @@ void VelocyPackHelper::initialize() { TRI_ASSERT(VPackSlice(Translator->translate(ToAttribute - AttributeBase)) .copyString() == StaticStrings::ToString); + HeaderTranslator.reset(new VPackAttributeTranslator); + HeaderTranslator->add("version", 6); + HeaderTranslator->add("type", 7); + HeaderTranslator->add("database", 8); + HeaderTranslator->add("requestType", 9); + HeaderTranslator->add("request", 0); + HeaderTranslator->add("parameter", -1); + HeaderTranslator->add("meta", -2); + HeaderTranslator->add("responseCode", -3); + HeaderTranslator->seal(); + // initialize exclude handler for system attributes ExcludeHandler.reset(new SystemAttributeExcludeHandler); } @@ -159,6 +171,11 @@ arangodb::velocypack::AttributeTranslator* VelocyPackHelper::getTranslator() { return Translator.get(); } +arangodb::velocypack::AttributeTranslator* +VelocyPackHelper::getHeaderTranslator() { + return HeaderTranslator.get(); +} + bool VelocyPackHelper::AttributeSorterUTF8::operator()( std::string const& l, std::string const& r) const { // use UTF-8-based comparison of attribute names diff --git a/lib/Basics/VelocyPackHelper.h b/lib/Basics/VelocyPackHelper.h index 30113a1377..823151265a 100644 --- a/lib/Basics/VelocyPackHelper.h +++ b/lib/Basics/VelocyPackHelper.h @@ -57,6 +57,7 @@ class VelocyPackHelper { static arangodb::velocypack::AttributeExcludeHandler* getExcludeHandler(); static arangodb::velocypack::AttributeTranslator* getTranslator(); + static arangodb::velocypack::AttributeTranslator* getHeaderTranslator(); struct VPackHash { size_t operator()(arangodb::velocypack::Slice const&) const; diff --git a/lib/Rest/CommonDefines.h b/lib/Rest/CommonDefines.h index ba5637dca5..c24c1d0b6c 100644 --- a/lib/Rest/CommonDefines.h +++ b/lib/Rest/CommonDefines.h @@ -26,97 +26,97 @@ namespace arangodb { -enum class ContentType { - CUSTOM, // use Content-Type from _headers - JSON, // application/json - VPACK, // application/x-velocypack - TEXT, // text/plain - HTML, // text/html - DUMP, // application/x-arango-dump - UNSET -}; - -enum class ProtocolVersion { HTTP_1_0, HTTP_1_1, VPP_1_0, UNKNOWN }; - -enum ConnectionType { - CONNECTION_NONE, - CONNECTION_KEEP_ALIVE, - CONNECTION_CLOSE -}; -// VSTREAM_CRED: This method is used for sending Authentication -// request,i.e; username and password. +// enum class ContentType { +// CUSTOM, // use Content-Type from _headers +// JSON, // application/json +// VPACK, // application/x-velocypack +// TEXT, // text/plain +// HTML, // text/html +// DUMP, // application/x-arango-dump +// UNSET +// }; // -// VSTREAM_REGISTER: This Method is used for registering event of -// some kind +// enum class ProtocolVersion { HTTP_1_0, HTTP_1_1, VPP_1_0, UNKNOWN }; // -// VSTREAM_STATUS: Returns STATUS code and message for a given -// request -enum class RequestType { - DELETE_REQ = 0, // windows redefines DELETE - GET, - HEAD, - OPTIONS, - POST, - PUT, - PATCH, - VSTREAM_CRED, - VSTREAM_REGISTER, - VSTREAM_STATUS, - ILLEGAL // must be last -}; - -enum class ResponseCode { - CONTINUE = 100, - SWITCHING_PROTOCOLS = 101, - PROCESSING = 102, - - OK = 200, - CREATED = 201, - ACCEPTED = 202, - PARTIAL = 203, - NO_CONTENT = 204, - RESET_CONTENT = 205, - PARTIAL_CONTENT = 206, - - MOVED_PERMANENTLY = 301, - FOUND = 302, - SEE_OTHER = 303, - NOT_MODIFIED = 304, - TEMPORARY_REDIRECT = 307, - PERMANENT_REDIRECT = 308, - - BAD = 400, - UNAUTHORIZED = 401, - PAYMENT_REQUIRED = 402, - FORBIDDEN = 403, - NOT_FOUND = 404, - METHOD_NOT_ALLOWED = 405, - NOT_ACCEPTABLE = 406, - REQUEST_TIMEOUT = 408, - CONFLICT = 409, - GONE = 410, - LENGTH_REQUIRED = 411, - PRECONDITION_FAILED = 412, - REQUEST_ENTITY_TOO_LARGE = 413, - REQUEST_URI_TOO_LONG = 414, - UNSUPPORTED_MEDIA_TYPE = 415, - REQUESTED_RANGE_NOT_SATISFIABLE = 416, - EXPECTATION_FAILED = 417, - I_AM_A_TEAPOT = 418, - UNPROCESSABLE_ENTITY = 422, - LOCKED = 423, - PRECONDITION_REQUIRED = 428, - TOO_MANY_REQUESTS = 429, - REQUEST_HEADER_FIELDS_TOO_LARGE = 431, - UNAVAILABLE_FOR_LEGAL_REASONS = 451, - - SERVER_ERROR = 500, - NOT_IMPLEMENTED = 501, - BAD_GATEWAY = 502, - SERVICE_UNAVAILABLE = 503, - HTTP_VERSION_NOT_SUPPORTED = 505, - BANDWIDTH_LIMIT_EXCEEDED = 509, - NOT_EXTENDED = 510 -}; +// enum ConnectionType { +// CONNECTION_NONE, +// CONNECTION_KEEP_ALIVE, +// CONNECTION_CLOSE +// }; +// // VSTREAM_CRED: This method is used for sending Authentication +// // request,i.e; username and password. +// // +// // VSTREAM_REGISTER: This Method is used for registering event of +// // some kind +// // +// // VSTREAM_STATUS: Returns STATUS code and message for a given +// // request +// enum class RequestType { +// DELETE_REQ = 0, // windows redefines DELETE +// GET, +// HEAD, +// OPTIONS, +// POST, +// PUT, +// PATCH, +// VSTREAM_CRED, +// VSTREAM_REGISTER, +// VSTREAM_STATUS, +// ILLEGAL // must be last +// }; +// +// enum class ResponseCode { +// CONTINUE = 100, +// SWITCHING_PROTOCOLS = 101, +// PROCESSING = 102, +// +// OK = 200, +// CREATED = 201, +// ACCEPTED = 202, +// PARTIAL = 203, +// NO_CONTENT = 204, +// RESET_CONTENT = 205, +// PARTIAL_CONTENT = 206, +// +// MOVED_PERMANENTLY = 301, +// FOUND = 302, +// SEE_OTHER = 303, +// NOT_MODIFIED = 304, +// TEMPORARY_REDIRECT = 307, +// PERMANENT_REDIRECT = 308, +// +// BAD = 400, +// UNAUTHORIZED = 401, +// PAYMENT_REQUIRED = 402, +// FORBIDDEN = 403, +// NOT_FOUND = 404, +// METHOD_NOT_ALLOWED = 405, +// NOT_ACCEPTABLE = 406, +// REQUEST_TIMEOUT = 408, +// CONFLICT = 409, +// GONE = 410, +// LENGTH_REQUIRED = 411, +// PRECONDITION_FAILED = 412, +// REQUEST_ENTITY_TOO_LARGE = 413, +// REQUEST_URI_TOO_LONG = 414, +// UNSUPPORTED_MEDIA_TYPE = 415, +// REQUESTED_RANGE_NOT_SATISFIABLE = 416, +// EXPECTATION_FAILED = 417, +// I_AM_A_TEAPOT = 418, +// UNPROCESSABLE_ENTITY = 422, +// LOCKED = 423, +// PRECONDITION_REQUIRED = 428, +// TOO_MANY_REQUESTS = 429, +// REQUEST_HEADER_FIELDS_TOO_LARGE = 431, +// UNAVAILABLE_FOR_LEGAL_REASONS = 451, +// +// SERVER_ERROR = 500, +// NOT_IMPLEMENTED = 501, +// BAD_GATEWAY = 502, +// SERVICE_UNAVAILABLE = 503, +// HTTP_VERSION_NOT_SUPPORTED = 505, +// BANDWIDTH_LIMIT_EXCEEDED = 509, +// NOT_EXTENDED = 510 +// }; } #endif diff --git a/lib/Rest/VppRequest.cpp b/lib/Rest/VppRequest.cpp index 9e1db8c36a..ed4d5903dc 100644 --- a/lib/Rest/VppRequest.cpp +++ b/lib/Rest/VppRequest.cpp @@ -64,7 +64,8 @@ VppRequest::VppRequest(ConnectionInfo const& connectionInfo, : GeneralRequest(connectionInfo), _message(std::move(message)), _headers(nullptr), - _messageId(messageId) { + _messageId(messageId), + _headerOptions(nullptr) { _protocol = "vpp"; _contentType = ContentType::VPACK; _contentTypeResponse = ContentType::VPACK; diff --git a/lib/Rest/VppRequest.h b/lib/Rest/VppRequest.h index 014eae53e0..2e08a918b9 100644 --- a/lib/Rest/VppRequest.h +++ b/lib/Rest/VppRequest.h @@ -77,6 +77,8 @@ class VppRequest : public GeneralRequest { return arangodb::Endpoint::TransportType::VPP; }; + void setHeaderOptions(VPackOptions* options) { _headerOptions = options; } + std::unordered_map const& headers() const override; // get value from headers map. The key must be lowercase. std::string const& header(std::string const& key) const override; @@ -102,6 +104,7 @@ class VppRequest : public GeneralRequest { std::unordered_map> _arrayValues; uint64_t _messageId; const std::unordered_map _cookies; // TODO remove + VPackOptions* _headerOptions; void parseHeaderInformation(); }; diff --git a/lib/Rest/VppResponse.cpp b/lib/Rest/VppResponse.cpp index ffaa4e4512..1c1e45c489 100644 --- a/lib/Rest/VppResponse.cpp +++ b/lib/Rest/VppResponse.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include "Basics/Exceptions.h" @@ -38,13 +40,19 @@ #include "Meta/conversion.h" #include "Rest/VppRequest.h" +#include "CommonDefines.h" + using namespace arangodb; using namespace arangodb::basics; bool VppResponse::HIDE_PRODUCT_HEADER = false; VppResponse::VppResponse(ResponseCode code, uint64_t id) - : GeneralResponse(code), _header(nullptr), _payload(), _messageId(id) { + : GeneralResponse(code), + _header(nullptr), + _payload(), + _messageId(id), + _headerOptions(nullptr) { _contentType = ContentType::VPACK; _connectionType = CONNECTION_KEEP_ALIVE; } @@ -69,14 +77,20 @@ void VppResponse::setPayload(arangodb::velocypack::Slice const& slice, VPackMessageNoOwnBuffer VppResponse::prepareForNetwork() { // initalize builder with vpackbuffer. then we do not need to // steal the header and can avoid the shared pointer - VPackBuilder builder; + + // VPackBuffer buffer; + // VPackBuilder builder(buffer); + VPackBuilder builder(_headerOptions); builder.openObject(); builder.add("version", VPackValue(int(1))); - builder.add("type", VPackValue(int(1))); // 2 == response + builder.add("type", VPackValue(int(2))); // 2 == response builder.add( "responseCode", VPackValue(static_cast(meta::underlyingValue(_responseCode)))); builder.close(); + + // options.Defaults.attributeTranslator = nullptr; + _header = builder.steal(); return VPackMessageNoOwnBuffer(VPackSlice(_header->data()), VPackSlice(_payload.data()), _messageId, diff --git a/lib/Rest/VppResponse.h b/lib/Rest/VppResponse.h index 733a595723..8218c80a23 100644 --- a/lib/Rest/VppResponse.h +++ b/lib/Rest/VppResponse.h @@ -57,6 +57,8 @@ class VppResponse : public GeneralResponse { return arangodb::Endpoint::TransportType::VPP; }; + void setHeaderOptions(VPackOptions* options) { _headerOptions = options; } + VPackMessageNoOwnBuffer prepareForNetwork(); private: @@ -67,6 +69,7 @@ class VppResponse : public GeneralResponse { VPackBuffer _payload; uint64_t _messageId; bool _generateBody; // this must be true if payload should be send + VPackOptions* _headerOptions; }; }