mirror of https://gitee.com/bigwinds/arangodb
Merge pull request #1798 from ObiWahn/devel
optional velocypack response
This commit is contained in:
commit
7cd428c367
|
@ -43,16 +43,17 @@ void RestBaseHandler::handleError(Exception const& ex) {
|
||||||
generateError(GeneralResponse::responseCode(ex.code()), ex.code(), ex.what());
|
generateError(GeneralResponse::responseCode(ex.code()), ex.code(), ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generates a result from VelocyPack
|
/// @brief generates a result from VelocyPack
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void RestBaseHandler::generateResult(GeneralResponse::ResponseCode code,
|
void RestBaseHandler::generateResult(GeneralResponse::ResponseCode code,
|
||||||
VPackSlice const& slice) {
|
VPackSlice const& slice) {
|
||||||
createResponse(code);
|
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
|
||||||
|
|
||||||
dumpResponse(slice, &VPackOptions::Defaults);
|
createResponse(code);
|
||||||
|
writeResult(slice, VPackOptions::Defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -63,9 +64,7 @@ void RestBaseHandler::generateResult(GeneralResponse::ResponseCode code,
|
||||||
VPackSlice const& slice,
|
VPackSlice const& slice,
|
||||||
std::shared_ptr<TransactionContext> context) {
|
std::shared_ptr<TransactionContext> context) {
|
||||||
createResponse(code);
|
createResponse(code);
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
writeResult(slice,*(context->getVPackOptions()));
|
||||||
|
|
||||||
dumpResponse(slice, context->getVPackOptions());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -90,7 +89,6 @@ void RestBaseHandler::generateError(GeneralResponse::ResponseCode code,
|
||||||
void RestBaseHandler::generateError(GeneralResponse::ResponseCode code,
|
void RestBaseHandler::generateError(GeneralResponse::ResponseCode code,
|
||||||
int errorCode, std::string const& message) {
|
int errorCode, std::string const& message) {
|
||||||
createResponse(code);
|
createResponse(code);
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
|
||||||
|
|
||||||
VPackBuilder builder;
|
VPackBuilder builder;
|
||||||
try {
|
try {
|
||||||
|
@ -106,7 +104,7 @@ void RestBaseHandler::generateError(GeneralResponse::ResponseCode code,
|
||||||
builder.add("errorNum", VPackValue(errorCode));
|
builder.add("errorNum", VPackValue(errorCode));
|
||||||
builder.close();
|
builder.close();
|
||||||
|
|
||||||
dumpResponse(builder.slice(), &VPackOptions::Defaults);
|
writeResult(builder.slice(), VPackOptions::Defaults);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Building the error response failed
|
// Building the error response failed
|
||||||
}
|
}
|
||||||
|
@ -147,3 +145,28 @@ void RestBaseHandler::dumpResponse(VPackSlice const& slice,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief checks if velocypack is expected as answer
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool RestBaseHandler::returnVelocypack() const {
|
||||||
|
auto accept = std::string(_request->header("accept"));
|
||||||
|
if (std::string::npos == accept.find("application/x-velocypack")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief writes volocypack or json to response
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void RestBaseHandler::writeResult(arangodb::velocypack::Slice const& slice, VPackOptions const& options){
|
||||||
|
if(returnVelocypack()) {
|
||||||
|
_response->setContentType("application/x-velocypack");
|
||||||
|
_response->body().appendText(slice.startAs<const char>(),slice.byteSize());
|
||||||
|
} else {
|
||||||
|
_response->setContentType("application/json; charset=utf-8");
|
||||||
|
dumpResponse(slice, &options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,18 +44,15 @@ class RestBaseHandler : public rest::HttpHandler {
|
||||||
public:
|
public:
|
||||||
explicit RestBaseHandler(HttpRequest* request);
|
explicit RestBaseHandler(HttpRequest* request);
|
||||||
|
|
||||||
public:
|
|
||||||
void handleError(basics::Exception const&) override;
|
void handleError(basics::Exception const&) override;
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generates a result from VelocyPack
|
/// @brief generates a result from VelocyPack
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void generateResult(GeneralResponse::ResponseCode,
|
void generateResult(GeneralResponse::ResponseCode,
|
||||||
arangodb::velocypack::Slice const& slice);
|
arangodb::velocypack::Slice const& slice);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generates a result from VelocyPack
|
/// @brief generates a result from VelocyPack
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -81,7 +78,7 @@ class RestBaseHandler : public rest::HttpHandler {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void generateOOMError();
|
void generateOOMError();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generates a canceled message
|
/// @brief generates a canceled message
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -92,6 +89,19 @@ class RestBaseHandler : public rest::HttpHandler {
|
||||||
/// @brief dumps the response as JSON into the response string buffer
|
/// @brief dumps the response as JSON into the response string buffer
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief checks if velocypack is expected as answer
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool returnVelocypack() const;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief write result back to client
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
void writeResult(arangodb::velocypack::Slice const& slice, VPackOptions const& options);
|
||||||
|
|
||||||
|
private:
|
||||||
void dumpResponse(arangodb::velocypack::Slice const& slice,
|
void dumpResponse(arangodb::velocypack::Slice const& slice,
|
||||||
arangodb::velocypack::Options const* options);
|
arangodb::velocypack::Options const* options);
|
||||||
};
|
};
|
||||||
|
|
|
@ -236,7 +236,6 @@ void RestVocbaseBaseHandler::generate20x(
|
||||||
|
|
||||||
VPackSlice slice = result.slice();
|
VPackSlice slice = result.slice();
|
||||||
TRI_ASSERT(slice.isObject() || slice.isArray());
|
TRI_ASSERT(slice.isObject() || slice.isArray());
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
|
||||||
if (slice.isObject()) {
|
if (slice.isObject()) {
|
||||||
_response->setHeaderNC("etag", "\"" + slice.get(TRI_VOC_ATTRIBUTE_REV).copyString() + "\"");
|
_response->setHeaderNC("etag", "\"" + slice.get(TRI_VOC_ATTRIBUTE_REV).copyString() + "\"");
|
||||||
// pre 1.4 location headers withdrawn for >= 3.0
|
// pre 1.4 location headers withdrawn for >= 3.0
|
||||||
|
@ -246,14 +245,9 @@ void RestVocbaseBaseHandler::generate20x(
|
||||||
std::string("/_db/" + _request->databaseName() +
|
std::string("/_db/" + _request->databaseName() +
|
||||||
DOCUMENT_PATH + "/" + escapedHandle));
|
DOCUMENT_PATH + "/" + escapedHandle));
|
||||||
}
|
}
|
||||||
VPackStringBufferAdapter buffer(_response->body().stringBuffer());
|
|
||||||
VPackDumper dumper(&buffer, options);
|
writeResult(slice, *options);
|
||||||
try {
|
|
||||||
dumper.dump(slice);
|
|
||||||
} catch (...) {
|
|
||||||
generateError(GeneralResponse::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
|
||||||
"cannot generate output");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -282,8 +276,7 @@ void RestVocbaseBaseHandler::generatePreconditionFailed(
|
||||||
VPackSlice const& slice) {
|
VPackSlice const& slice) {
|
||||||
|
|
||||||
createResponse(GeneralResponse::ResponseCode::PRECONDITION_FAILED);
|
createResponse(GeneralResponse::ResponseCode::PRECONDITION_FAILED);
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
|
||||||
|
|
||||||
if (slice.isObject()) { // single document case
|
if (slice.isObject()) { // single document case
|
||||||
std::string const rev = VelocyPackHelper::getStringValue(slice, TRI_VOC_ATTRIBUTE_REV, "");
|
std::string const rev = VelocyPackHelper::getStringValue(slice, TRI_VOC_ATTRIBUTE_REV, "");
|
||||||
_response->setHeaderNC("etag", "\"" + rev + "\"");
|
_response->setHeaderNC("etag", "\"" + rev + "\"");
|
||||||
|
@ -306,16 +299,8 @@ void RestVocbaseBaseHandler::generatePreconditionFailed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VPackStringBufferAdapter buffer(_response->body().stringBuffer());
|
|
||||||
auto transactionContext(StandaloneTransactionContext::Create(_vocbase));
|
auto transactionContext(StandaloneTransactionContext::Create(_vocbase));
|
||||||
VPackDumper dumper(&buffer, transactionContext->getVPackOptions());
|
writeResult(builder.slice(), *(transactionContext->getVPackOptions()));
|
||||||
|
|
||||||
try {
|
|
||||||
dumper.dump(builder.slice());
|
|
||||||
} catch (...) {
|
|
||||||
generateError(GeneralResponse::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
|
||||||
"cannot generate output");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -362,34 +347,37 @@ void RestVocbaseBaseHandler::generateDocument(VPackSlice const& document,
|
||||||
|
|
||||||
// and generate a response
|
// and generate a response
|
||||||
createResponse(GeneralResponse::ResponseCode::OK);
|
createResponse(GeneralResponse::ResponseCode::OK);
|
||||||
_response->setContentType("application/json; charset=utf-8");
|
|
||||||
if (!rev.empty()) {
|
if (!rev.empty()) {
|
||||||
_response->setHeaderNC("etag", "\"" + rev + "\"");
|
_response->setHeaderNC("etag", "\"" + rev + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generateBody) {
|
if (generateBody) {
|
||||||
VPackStringBufferAdapter buffer(_response->body().stringBuffer());
|
writeResult(document, *options);
|
||||||
VPackDumper dumper(&buffer, options);
|
|
||||||
try {
|
|
||||||
dumper.dump(document);
|
|
||||||
} catch (...) {
|
|
||||||
generateError(GeneralResponse::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
|
||||||
"cannot generate output");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO can we optimize this?
|
if(returnVelocypack()){
|
||||||
// Just dump some where else to find real length
|
//TODO REVIEW
|
||||||
StringBuffer tmp(TRI_UNKNOWN_MEM_ZONE);
|
_response->setContentType("application/x-velocypack");
|
||||||
// convert object to string
|
_response->headResponse(document.byteSize());
|
||||||
VPackStringBufferAdapter buffer(tmp.stringBuffer());
|
} else {
|
||||||
VPackDumper dumper(&buffer, options);
|
_response->setContentType("application/json; charset=utf-8");
|
||||||
try {
|
|
||||||
dumper.dump(document);
|
// TODO can we optimize this?
|
||||||
} catch (...) {
|
// Just dump some where else to find real length
|
||||||
generateError(GeneralResponse::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
StringBuffer tmp(TRI_UNKNOWN_MEM_ZONE);
|
||||||
"cannot generate output");
|
// convert object to string
|
||||||
|
VPackStringBufferAdapter buffer(tmp.stringBuffer());
|
||||||
|
|
||||||
|
//usual dumping - but not to the response body
|
||||||
|
VPackDumper dumper(&buffer, options);
|
||||||
|
try {
|
||||||
|
dumper.dump(document);
|
||||||
|
} catch (...) {
|
||||||
|
generateError(GeneralResponse::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||||
|
"cannot generate output");
|
||||||
|
}
|
||||||
|
// set the length of what would have been written
|
||||||
|
_response->headResponse(tmp.length());
|
||||||
}
|
}
|
||||||
_response->headResponse(tmp.length());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,9 +477,9 @@ void RestVocbaseBaseHandler::generateTransactionError(
|
||||||
generateError(GeneralResponse::ResponseCode::FORBIDDEN, res);
|
generateError(GeneralResponse::ResponseCode::FORBIDDEN, res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TRI_ERROR_OUT_OF_MEMORY:
|
case TRI_ERROR_OUT_OF_MEMORY:
|
||||||
case TRI_ERROR_LOCK_TIMEOUT:
|
case TRI_ERROR_LOCK_TIMEOUT:
|
||||||
case TRI_ERROR_DEBUG:
|
case TRI_ERROR_DEBUG:
|
||||||
case TRI_ERROR_LOCKED:
|
case TRI_ERROR_LOCKED:
|
||||||
case TRI_ERROR_DEADLOCK: {
|
case TRI_ERROR_DEADLOCK: {
|
||||||
|
@ -517,7 +505,7 @@ void RestVocbaseBaseHandler::generateTransactionError(
|
||||||
generateError(GeneralResponse::ResponseCode::FORBIDDEN, result.code,
|
generateError(GeneralResponse::ResponseCode::FORBIDDEN, result.code,
|
||||||
"collection is read-only");
|
"collection is read-only");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TRI_ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED:
|
case TRI_ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED:
|
||||||
generateError(GeneralResponse::ResponseCode::CONFLICT, result.code,
|
generateError(GeneralResponse::ResponseCode::CONFLICT, result.code,
|
||||||
"cannot create document, unique constraint violated");
|
"cannot create document, unique constraint violated");
|
||||||
|
@ -576,14 +564,14 @@ void RestVocbaseBaseHandler::generateTransactionError(
|
||||||
generateError(GeneralResponse::ResponseCode::NOT_IMPLEMENTED, result.code);
|
generateError(GeneralResponse::ResponseCode::NOT_IMPLEMENTED, result.code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TRI_ERROR_FORBIDDEN: {
|
case TRI_ERROR_FORBIDDEN: {
|
||||||
generateError(GeneralResponse::ResponseCode::FORBIDDEN, result.code);
|
generateError(GeneralResponse::ResponseCode::FORBIDDEN, result.code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TRI_ERROR_OUT_OF_MEMORY:
|
case TRI_ERROR_OUT_OF_MEMORY:
|
||||||
case TRI_ERROR_LOCK_TIMEOUT:
|
case TRI_ERROR_LOCK_TIMEOUT:
|
||||||
case TRI_ERROR_DEBUG:
|
case TRI_ERROR_DEBUG:
|
||||||
case TRI_ERROR_LOCKED:
|
case TRI_ERROR_LOCKED:
|
||||||
case TRI_ERROR_DEADLOCK: {
|
case TRI_ERROR_DEADLOCK: {
|
||||||
|
|
|
@ -249,7 +249,7 @@ class RestVocbaseBaseHandler : public RestBaseHandler {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generate an error message for a transaction error
|
/// @brief generate an error message for a transaction error
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void generateTransactionError(OperationResult const&);
|
void generateTransactionError(OperationResult const&);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue