Files
boost_beast/include/beast/http/impl/verb.ipp
T
Vinnie Falco 9a585a82d9 Refactor treatment of request-method (API Change):
fix #397

method enum class is added to represent all known request methods.
Functions are provided to convert from strings to and from the method
enumeration.

The fields container is modified to also work with the enum.
2017-05-30 15:59:50 -07:00

329 lines
6.7 KiB
C++

//
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_HTTP_IMPL_VERB_IPP
#define BEAST_HTTP_IMPL_VERB_IPP
#include <boost/throw_exception.hpp>
#include <stdexcept>
namespace beast {
namespace http {
namespace detail {
template<class = void>
inline
string_view
verb_to_string(verb v)
{
switch(v)
{
case verb::delete_: return "DELETE";
case verb::get: return "GET";
case verb::head: return "HEAD";
case verb::post: return "POST";
case verb::put: return "PUT";
case verb::connect: return "CONNECT";
case verb::options: return "OPTIONS";
case verb::trace: return "TRACE";
case verb::copy: return "COPY";
case verb::lock: return "LOCK";
case verb::mkcol: return "MKCOL";
case verb::move: return "MOVE";
case verb::propfind: return "PROPFIND";
case verb::proppatch: return "PROPPATCH";
case verb::search: return "SEARCH";
case verb::unlock: return "UNLOCK";
case verb::bind: return "BIND";
case verb::rebind: return "REBIND";
case verb::unbind: return "UNBIND";
case verb::acl: return "ACL";
case verb::report: return "REPORT";
case verb::mkactivity: return "MKACTIVITY";
case verb::checkout: return "CHECKOUT";
case verb::merge: return "MERGE";
case verb::msearch: return "M-SEARCH";
case verb::notify: return "NOTIFY";
case verb::subscribe: return "SUBSCRIBE";
case verb::unsubscribe: return "UNSUBSCRIBE";
case verb::patch: return "PATCH";
case verb::purge: return "PURGE";
case verb::mkcalendar: return "MKCALENDAR";
case verb::link: return "LINK";
case verb::unlink: return "UNLINK";
}
BOOST_THROW_EXCEPTION(std::logic_error{"unknown method"});
}
template<class = void>
boost::optional<verb>
string_to_verb(string_view v)
{
/*
ACL
BIND
CHECKOUT
CONNECT
COPY
DELETE
GET
HEAD
LINK
LOCK
M-SEARCH
MERGE
MKACTIVITY
MKCALENDAR
MKCOL
MOVE
NOTIFY
OPTIONS
PATCH
POST
PROPFIND
PROPPATCH
PURGE
PUT
REBIND
REPORT
SEARCH
SUBSCRIBE
TRACE
UNBIND
UNLINK
UNLOCK
UNSUBSCRIBE
*/
if(v.size() < 3)
return boost::none;
auto const eq =
[](string_view sv, char const* s)
{
auto p = sv.data();
for(;;)
{
if(*s != *p)
return false;
++s;
++p;
if(*s == 0)
return *p == 0;
}
};
auto c = v[0];
v.remove_prefix(1);
switch(c)
{
case 'A':
if(v == "CL")
return verb::acl;
break;
case 'B':
if(v == "IND")
return verb::bind;
break;
case 'C':
c = v[0];
v.remove_prefix(1);
switch(c)
{
case 'H':
if(eq(v, "ECKOUT"))
return verb::checkout;
break;
case 'O':
if(eq(v, "NNECT"))
return verb::connect;
if(eq(v, "PY"))
return verb::copy;
// [[fallthrough]]
default:
break;
}
break;
case 'D':
if(eq(v, "ELETE"))
return verb::delete_;
break;
case 'G':
if(eq(v, "ET"))
return verb::get;
break;
case 'H':
if(eq(v, "EAD"))
return verb::head;
break;
case 'L':
if(eq(v, "INK"))
return verb::link;
if(eq(v, "OCK"))
return verb::lock;
break;
case 'M':
c = v[0];
v.remove_prefix(1);
switch(c)
{
case '-':
if(eq(v, "SEARCH"))
return verb::msearch;
break;
case 'E':
if(eq(v, "RGE"))
return verb::merge;
break;
case 'K':
if(eq(v, "ACTIVITY"))
return verb::mkactivity;
if(v[0] == 'C')
{
v.remove_prefix(1);
if(eq(v, "ALENDAR"))
return verb::mkcalendar;
if(eq(v, "OL"))
return verb::mkcol;
break;
}
break;
case 'O':
if(eq(v, "VE"))
return verb::move;
// [[fallthrough]]
default:
break;
}
break;
case 'N':
if(eq(v, "OTIFY"))
return verb::notify;
break;
case 'O':
if(eq(v, "PTIONS"))
return verb::options;
break;
case 'P':
c = v[0];
v.remove_prefix(1);
switch(c)
{
case 'A':
if(eq(v, "TCH"))
return verb::patch;
break;
case 'O':
if(eq(v, "ST"))
return verb::post;
break;
case 'R':
if(eq(v, "OPFIND"))
return verb::propfind;
if(eq(v, "OPPATCH"))
return verb::proppatch;
break;
case 'U':
if(eq(v, "RGE"))
return verb::purge;
if(eq(v, "T"))
return verb::put;
// [[fallthrough]]
default:
break;
}
break;
case 'R':
if(v[0] != 'E')
break;
v.remove_prefix(1);
if(eq(v, "BIND"))
return verb::rebind;
if(eq(v, "PORT"))
return verb::report;
break;
case 'S':
if(eq(v, "EARCH"))
return verb::search;
if(eq(v, "UBSCRIBE"))
return verb::subscribe;
break;
case 'T':
if(eq(v, "RACE"))
return verb::trace;
break;
case 'U':
if(v[0] != 'N')
break;
v.remove_prefix(1);
if(eq(v, "BIND"))
return verb::unbind;
if(eq(v, "LINK"))
return verb::unlink;
if(eq(v, "LOCK"))
return verb::unlock;
if(eq(v, "SUBSCRIBE"))
return verb::unsubscribe;
break;
default:
break;
}
return boost::none;
}
} // detail
inline
string_view
to_string(verb v)
{
return detail::verb_to_string(v);
}
inline
boost::optional<verb>
string_to_verb(string_view s)
{
return detail::string_to_verb(s);
}
} // http
} // beast
#endif