1
0
Fork 0

add translator to VelocyPackHelper and headerOption to Vpp Protocol

This commit is contained in:
Jan Christoph Uhde 2016-08-23 13:05:50 +02:00
parent 86f887db92
commit 8f5e6f65d6
9 changed files with 142 additions and 96 deletions

View File

@ -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<basics::StringBuffer> 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<VppRequest> 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<VppResponse> response(
new VppResponse(GeneralResponse::ResponseCode::SERVER_ERROR,
chunkHeader._messageID));
response->setHeaderOptions(&_headerOptions);
executeRequest(std::move(request), std::move(response));
}
}

View File

@ -113,6 +113,7 @@ class VppCommTask : public GeneralCommTask {
// will be cleaned
};
ProcessReadVariables _processReadVariables;
velocypack::Options _headerOptions;
struct ChunkHeader {
std::size_t _headerLength;

View File

@ -49,6 +49,7 @@ unsigned long long XXH64(const void* input, size_t length,
using VelocyPackHelper = arangodb::basics::VelocyPackHelper;
static std::unique_ptr<VPackAttributeTranslator> Translator;
static std::unique_ptr<VPackAttributeTranslator> HeaderTranslator;
static std::unique_ptr<VPackAttributeExcludeHandler> 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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -77,6 +77,8 @@ class VppRequest : public GeneralRequest {
return arangodb::Endpoint::TransportType::VPP;
};
void setHeaderOptions(VPackOptions* options) { _headerOptions = options; }
std::unordered_map<std::string, std::string> 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<std::string, std::vector<std::string>> _arrayValues;
uint64_t _messageId;
const std::unordered_map<std::string, std::string> _cookies; // TODO remove
VPackOptions* _headerOptions;
void parseHeaderInformation();
};

View File

@ -27,6 +27,8 @@
#include <velocypack/Builder.h>
#include <velocypack/Dumper.h>
#include <velocypack/Options.h>
#include <velocypack/AttributeTranslator.h>
#include <velocypack/Buffer.h>
#include <velocypack/velocypack-aliases.h>
#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<uint8_t> 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<int>(meta::underlyingValue(_responseCode))));
builder.close();
// options.Defaults.attributeTranslator = nullptr;
_header = builder.steal();
return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
VPackSlice(_payload.data()), _messageId,

View File

@ -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<uint8_t> _payload;
uint64_t _messageId;
bool _generateBody; // this must be true if payload should be send
VPackOptions* _headerOptions;
};
}