1
0
Fork 0
arangodb/lib/ProtocolBuffers/HttpRequestProtobuf.cpp

393 lines
13 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// @brief protobuf http request
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 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 triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2008-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "HttpRequestProtobuf.h"
#include "BasicsC/strings.h"
#include "Basics/StringUtils.h"
using namespace triagens::basics;
using namespace triagens::rest;
using namespace std;
// -----------------------------------------------------------------------------
// --SECTION-- local constants
// -----------------------------------------------------------------------------
static char const* EMPTY_STR = "";
// -----------------------------------------------------------------------------
// --SECTION-- class HttpRequestProtobuf
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief http request constructor
////////////////////////////////////////////////////////////////////////////////
HttpRequestProtobuf::HttpRequestProtobuf (PB_ArangoBatchMessage const& message)
: HttpRequest(),
_valid(false),
_request(0) {
if (message.type() == PB_BLOB_REQUEST) {
_valid = true;
_request = &message.blobrequest();
switch (_request->requesttype()) {
case PB_REQUEST_TYPE_DELETE:
_type = HTTP_REQUEST_DELETE;
break;
case PB_REQUEST_TYPE_GET:
_type = HTTP_REQUEST_GET;
break;
case PB_REQUEST_TYPE_HEAD:
_type = HTTP_REQUEST_HEAD;
break;
case PB_REQUEST_TYPE_POST:
_type = HTTP_REQUEST_POST;
break;
case PB_REQUEST_TYPE_PUT:
_type = HTTP_REQUEST_PUT;
break;
case PB_REQUEST_TYPE_PATCH:
_type = HTTP_REQUEST_PATCH;
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
HttpRequestProtobuf::~HttpRequestProtobuf () {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- HttpRequest methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
char const* HttpRequestProtobuf::requestPath () const {
return _request->url().c_str();
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void HttpRequestProtobuf::write (TRI_string_buffer_t* buffer) const {
switch (_type) {
case HTTP_REQUEST_GET:
TRI_AppendString2StringBuffer(buffer, "GET ", 4);
break;
case HTTP_REQUEST_POST:
TRI_AppendString2StringBuffer(buffer, "POST ", 5);
break;
case HTTP_REQUEST_PUT:
TRI_AppendString2StringBuffer(buffer, "PUT ", 4);
break;
case HTTP_REQUEST_DELETE:
TRI_AppendString2StringBuffer(buffer, "DELETE ", 7);
break;
case HTTP_REQUEST_HEAD:
TRI_AppendString2StringBuffer(buffer, "HEAD ", 5);
break;
case HTTP_REQUEST_PATCH:
TRI_AppendString2StringBuffer(buffer, "PATCH ", 6);
break;
default:
TRI_AppendString2StringBuffer(buffer, "UNKNOWN ", 8);
break;
}
// do NOT url-encode the path, we need to distingush between
// "/document/a/b" and "/document/a%2fb"
TRI_AppendStringStringBuffer(buffer, _request->url().c_str());
// generate the request parameters
bool first = true;
for (::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->values().begin();
i != _request->values().end();
++i) {
PB_ArangoKeyValue const& kv = *i;
if (first) {
TRI_AppendCharStringBuffer(buffer, '?');
first = false;
}
else {
TRI_AppendCharStringBuffer(buffer, '&');
}
TRI_AppendUrlEncodedStringStringBuffer(buffer, kv.key().c_str());
TRI_AppendCharStringBuffer(buffer, '=');
TRI_AppendUrlEncodedStringStringBuffer(buffer, kv.value().c_str());
}
TRI_AppendString2StringBuffer(buffer, " HTTP/1.1\r\n", 11);
// generate the header fields
for (::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->headers().begin();
i != _request->headers().end();
++i) {
PB_ArangoKeyValue const& kv = *i;
TRI_AppendStringStringBuffer(buffer, kv.key().c_str());
TRI_AppendString2StringBuffer(buffer, ": ", 2);
TRI_AppendStringStringBuffer(buffer, kv.value().c_str());
TRI_AppendString2StringBuffer(buffer, "\r\n", 2);
}
TRI_AppendString2StringBuffer(buffer, "content-length: ", 16);
TRI_AppendUInt64StringBuffer(buffer, _request->content().size());
TRI_AppendString2StringBuffer(buffer, "\r\n\r\n", 4);
TRI_AppendString2StringBuffer(buffer, _request->content().c_str(), _request->content().size());
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
size_t HttpRequestProtobuf::contentLength () const {
return _request->content().size();
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
char const* HttpRequestProtobuf::header (char const* key) const {
map<string, string> result;
::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->headers().begin();
for (; i != _request->headers().end(); ++i) {
PB_ArangoKeyValue const& kv = *i;
if (TRI_EqualString(key, kv.key().c_str())) {
return kv.value().c_str();
}
}
return EMPTY_STR;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
char const* HttpRequestProtobuf::header (char const* key, bool& found) const {
map<string, string> result;
::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->headers().begin();
for (; i != _request->headers().end(); ++i) {
PB_ArangoKeyValue const& kv = *i;
if (TRI_EqualString(key, kv.key().c_str())) {
found = true;
return kv.value().c_str();
}
}
found = false;
return EMPTY_STR;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
map<string, string> HttpRequestProtobuf::headers () const {
map<string, string> result;
::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->headers().begin();
for (; i != _request->headers().end(); ++i) {
PB_ArangoKeyValue const& kv = *i;
result[kv.key()] = kv.value();
}
result["content-length"] = StringUtils::itoa(_request->content().size());
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
char const* HttpRequestProtobuf::value (char const* key) const {
map<string, string> result;
::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->values().begin();
for (; i != _request->values().end(); ++i) {
PB_ArangoKeyValue const& kv = *i;
if (TRI_EqualString(key, kv.key().c_str())) {
return kv.value().c_str();
}
}
return EMPTY_STR;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
char const* HttpRequestProtobuf::value (char const* key, bool& found) const {
map<string, string> result;
::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->values().begin();
for (; i != _request->values().end(); ++i) {
PB_ArangoKeyValue const& kv = *i;
if (TRI_EqualString(key, kv.key().c_str())) {
found = true;
return kv.value().c_str();
}
}
found = false;
return EMPTY_STR;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
map<string, string> HttpRequestProtobuf::values () const {
map<string, string> result;
::google::protobuf::RepeatedPtrField< PB_ArangoKeyValue >::const_iterator i = _request->values().begin();
for (; i != _request->values().end(); ++i) {
PB_ArangoKeyValue const& kv = *i;
result[kv.key()] = kv.value();
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
char const* HttpRequestProtobuf::body () const {
return _request->content().c_str();
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
size_t HttpRequestProtobuf::bodySize () const {
return _request->content().size();
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
int HttpRequestProtobuf::setBody (char const* newBody, size_t length) {
return TRI_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Rest
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief true if message is valid
////////////////////////////////////////////////////////////////////////////////
bool HttpRequestProtobuf::isValid () const {
return _valid;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
// End: