Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/rest-cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/python2

import sys, os, string, re

Expand Down
11 changes: 6 additions & 5 deletions src/rest/exceptions.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#ifndef REST_CPP_EXCEPTIONS_H
#define REST_CPP_EXCEPTIONS_H
#define CREATE(NAME, PARENT, MESSAGE) class NAME : public PARENT { public: virtual const char* what() const throw() { return (MESSAGE); } virtual int code() {return 401; }};
#define ERROR(NAME, CODE, MESSAGE) class NAME : public Error { public: virtual const char* what() const throw() { return (MESSAGE); } virtual int code() { return (CODE); } };
#define ERROR(NAME, CODE) class NAME : public Error { public: virtual const char* what() const throw() { return STATUS::messages.at((CODE)).c_str(); } virtual int code() { return (int)(CODE); } };

#include <exception>
#include "http.h"

namespace REST {

Expand All @@ -20,10 +21,10 @@ namespace REST {
namespace HTTP {
CREATE(Error, Exception, "Unknown HTTP protocol error");

ERROR(NotAuthorized, 401, "Not Authorized");
ERROR(NotFound, 404, "Not Found");
ERROR(MethodNotAllowed, 405, "Method Not Allowed");
ERROR(NotImplemented, 501, "Not Implemented");
ERROR(NotAuthorized, STATUS::Code::Unauthorized);
ERROR(NotFound, STATUS::Code::NotFound);
ERROR(MethodNotAllowed, STATUS::Code::MethodNotAllowed);
ERROR(NotImplemented, STATUS::Code::NotImplemented);
}
}

Expand Down
149 changes: 149 additions & 0 deletions src/rest/http.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#ifndef REST_CPP_HTTP_H
#define REST_CPP_HTTP_H

#include <string>
#include <map>

namespace REST {
namespace HTTP {
namespace STATUS {
enum Code {
Continue=100,
SwitchingProtocols=101,
Processing=102,
OK=200,
Created=201,
Accepted=202,
NonAuthoritativeInformation=203,
NoContent=204,
ResetContent=205,
PartialContent=206,
MultiStatus=207,
AlreadyReported=208,
IMUsed=226,
MultipleChoices=300,
MovedPermanently=301,
Found=302,
SeeOther=303,
NotModified=304,
UseProxy=305,
TemporaryRedirect=307,
PermanentRedirect=308,
BadRequest=400,
Unauthorized=401,
PaymentRequired=402,
Forbidden=403,
NotFound=404,
MethodNotAllowed=405,
NotAcceptable=406,
ProxyAuthenticationRequired=407,
RequestTimeout=408,
Conflict=409,
Gone=410,
LengthRequired=411,
PreconditionFailed=412,
RequestEntityTooLarge=413,
RequestURITooLong=414,
UnsupportedMediaType=415,
RequestedRangeNotSatisfiable=416,
ExpectationFailed=417,
ImATeapot=418,
EnhanceYourCalm=420,
UnprocessableEntity=422,
Locked=423,
FailedDependency=424,
UpgradeRequired=426,
PreconditionRequired=428,
TooManyRequests=429,
RequestHeaderFieldsTooLarge=431,
NoResponse=444,
RetryWith=449,
ClientClosedRequest=499,
InternalServerError=500,
NotImplemented=501,
BadGateway=502,
ServiceUnavailable=503,
GatewayTimeout=504,
HTTPVersionNotSupported=505,
VariantAlsoNegotiates=506,
InsufficientStorage=507,
LoopDetected=508,
BandwidthLimitExceeded=509,
NotExtended=510,
NetworkAuthenticationRequired=511,
NetworkReadTimeoutError=598,
NetworkConnectTimeoutError=599
};

const static std::map<Code, std::string> messages {
{(Code) 100, "Continue"},
{(Code) 101, "Switching Protocols"},
{(Code) 102, "Processing (WebDAV)"},
{(Code) 200, "OK"},
{(Code) 201, "Created"},
{(Code) 202, "Accepted"},
{(Code) 203, "Non-Authoritative Information"},
{(Code) 204, "No Content"},
{(Code) 205, "Reset Content"},
{(Code) 206, "Partial Content"},
{(Code) 207, "Multi-Status (WebDAV)"},
{(Code) 208, "Already Reported (WebDAV)"},
{(Code) 226, "IM Used"},
{(Code) 300, "Multiple Choices"},
{(Code) 301, "Moved Permanently"},
{(Code) 302, "Found"},
{(Code) 303, "See Other"},
{(Code) 304, "Not Modified"},
{(Code) 305, "Use Proxy"},
{(Code) 307, "Temporary Redirect"},
{(Code) 308, "Permanent Redirect (experiemental)"},
{(Code) 400, "Bad Request"},
{(Code) 401, "Unauthorized"},
{(Code) 402, "Payment Required"},
{(Code) 403, "Forbidden"},
{(Code) 404, "Not Found"},
{(Code) 405, "Method Not Allowed"},
{(Code) 406, "Not Acceptable"},
{(Code) 407, "Proxy Authentication Required"},
{(Code) 408, "Request Timeout"},
{(Code) 409, "Conflict"},
{(Code) 410, "Gone"},
{(Code) 411, "Length Required"},
{(Code) 412, "Precondition Failed"},
{(Code) 413, "Request Entity Too Large"},
{(Code) 414, "Request-URI Too Long"},
{(Code) 415, "Unsupported Media Type"},
{(Code) 416, "Requested Range Not Satisfiable"},
{(Code) 417, "Expectation Failed"},
{(Code) 418, "I'm a teapot (RFC 2324)"},
{(Code) 420, "Enhance Your Calm (Twitter)"},
{(Code) 422, "Unprocessable Entity (WebDAV)"},
{(Code) 423, "Locked (WebDAV)"},
{(Code) 424, "Failed Dependency (WebDAV)"},
{(Code) 426, "Upgrade Required"},
{(Code) 428, "Precondition Required"},
{(Code) 429, "Too Many Requests"},
{(Code) 431, "Request Header Fields Too Large"},
{(Code) 444, "No Response (Nginx)"},
{(Code) 449, "Retry With (Microsoft)"},
{(Code) 499, "Client Closed Request (Nginx)"},
{(Code) 500, "Internal Server Error"},
{(Code) 501, "Not Implemented"},
{(Code) 502, "Bad Gateway"},
{(Code) 503, "Service Unavailable"},
{(Code) 504, "Gateway Timeout"},
{(Code) 505, "HTTP Version Not Supported"},
{(Code) 506, "Variant Also Negotiates (Experimental)"},
{(Code) 507, "Insufficient Storage (WebDAV)"},
{(Code) 508, "Loop Detected (WebDAV)"},
{(Code) 509, "Bandwidth Limit Exceeded (Apache)"},
{(Code) 510, "Not Extended"},
{(Code) 511, "Network Authentication Required"},
{(Code) 598, "Network read timeout error"},
{(Code) 599, "Network connect timeout error"}
};
}
}
}

#endif
7 changes: 6 additions & 1 deletion src/rest/response.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Response::Response(Request::shared request) {
}

Response::Response(Request::shared request, HTTP::Error &error) : Response(request) {
status = error.code();
status = (HTTP::STATUS::Code) error.code();
status_message = error.what();
use_json();
data["error"]["code"] = status;
Expand Down Expand Up @@ -52,6 +52,11 @@ size_t Response::send(Json::FastWriter &json_writer) {
return bytes_sent;
}

void Response::set_status(HTTP::STATUS::Code code) {
status = code;
status_message = HTTP::STATUS::messages.at(code);
}

Response::~Response() {
}

Expand Down
8 changes: 4 additions & 4 deletions src/rest/response.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "exceptions.h"
#include "request.h"
#include "json/json.h"
#include "http.h"

#include <chrono>
#include <string>
Expand All @@ -25,23 +26,22 @@ class Response {
typedef std::unique_ptr<Response> unique;
~Response();


int status = 200;
std::string status_message = "OK";
std::string raw;
std::map< std::string, std::string > headers;

void use_json();

Json::Value data;

void set_status(HTTP::STATUS::Code);

private:
Response(Request::shared request);
Response(Request::shared request, HTTP::Error &error);
size_t send(Json::FastWriter &json_writer);

std::chrono::high_resolution_clock::time_point start_time;
HTTP::STATUS::Code status = HTTP::STATUS::Code::OK;
std::string status_message = HTTP::STATUS::messages.at(status);

int handle;
bool is_json = false;
Expand Down
28 changes: 0 additions & 28 deletions src/rest/router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,6 @@ namespace REST {
delete root;
}

bool Router::Node::Less::operator()(const Node* a, const Node* b) const {
if (a->path[0] == '*')
return false;
if (b->path[0] == '*')
return true;

if (a->path[0] == ':')
if (b->path[0] != ':')
return false;
if (b->path[0] == ':')
if (a->path[0] != ':')
return true;

return a->path < b->path;
}

bool Router::Node::Unifiable::operator()(const Node* a, const Node* b) const {
if (a == nullptr || b == nullptr)
return false;

if (!b->path.empty() && (b->path[0] == '*' || b->path[0] == ':'))
return false;
if (!a->path.empty() && (a->path[0] == '*' || a->path[0] == ':'))
return true;

return a->path == b->path;
}

void Router::print() {
std::cout << "Available routes:\n";
root->print(1);
Expand Down
28 changes: 26 additions & 2 deletions src/rest/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,35 @@ class Router {

public:
static struct Less {
bool operator()(const Node* a, const Node* b) const;
bool operator()(const Node* a, const Node* b) const {
if (a->path[0] == '*')
return false;
if (b->path[0] == '*')
return true;

if (a->path[0] == ':')
if (b->path[0] != ':')
return false;
if (b->path[0] == ':')
if (a->path[0] != ':')
return true;

return a->path < b->path;
}
} less;

static struct Unifiable {
bool operator()(const Node* a, const Node* b) const;
bool operator()(const Node* a, const Node* b) const {
if (a == nullptr || b == nullptr)
return false;

if (!b->path.empty() && (b->path[0] == '*' || b->path[0] == ':'))
return false;
if (!a->path.empty() && (a->path[0] == '*' || a->path[0] == ':'))
return true;

return a->path == b->path;
}
} unifiable;

static struct Equal {
Expand Down