Skip to content

Commit b1af64a

Browse files
authored
Add WebDAV HTTP methods (PROPFIND, MKCOL, COPY, MOVE) (#2505)
1 parent ef1f344 commit b1af64a

4 files changed

Lines changed: 137 additions & 0 deletions

File tree

lib/inc/drogon/HttpTypes.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ enum HttpMethod
195195
Delete,
196196
Options,
197197
Patch,
198+
Propfind,
199+
Mkcol,
200+
Copy,
201+
Move,
198202
Invalid
199203
};
200204

@@ -280,6 +284,14 @@ inline std::string_view to_string_view(drogon::HttpMethod method)
280284
return "OPTIONS";
281285
case drogon::HttpMethod::Patch:
282286
return "PATCH";
287+
case drogon::HttpMethod::Propfind:
288+
return "PROPFIND";
289+
case drogon::HttpMethod::Mkcol:
290+
return "MKCOL";
291+
case drogon::HttpMethod::Copy:
292+
return "COPY";
293+
case drogon::HttpMethod::Move:
294+
return "MOVE";
283295
default:
284296
return "INVALID";
285297
}

lib/src/HttpRequestImpl.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,18 @@ const char *HttpRequestImpl::methodString() const
658658
case Patch:
659659
result = "PATCH";
660660
break;
661+
case Propfind:
662+
result = "PROPFIND";
663+
break;
664+
case Mkcol:
665+
result = "MKCOL";
666+
break;
667+
case Copy:
668+
result = "COPY";
669+
break;
670+
case Move:
671+
result = "MOVE";
672+
break;
661673
default:
662674
break;
663675
}
@@ -693,6 +705,14 @@ bool HttpRequestImpl::setMethod(const char *start, const char *end)
693705
{
694706
method_ = Head;
695707
}
708+
else if (m == "COPY")
709+
{
710+
method_ = Copy;
711+
}
712+
else if (m == "MOVE")
713+
{
714+
method_ = Move;
715+
}
696716
else
697717
{
698718
method_ = Invalid;
@@ -703,6 +723,10 @@ bool HttpRequestImpl::setMethod(const char *start, const char *end)
703723
{
704724
method_ = Patch;
705725
}
726+
else if (m == "MKCOL")
727+
{
728+
method_ = Mkcol;
729+
}
706730
else
707731
{
708732
method_ = Invalid;
@@ -728,6 +752,16 @@ bool HttpRequestImpl::setMethod(const char *start, const char *end)
728752
method_ = Invalid;
729753
}
730754
break;
755+
case 8:
756+
if (m == "PROPFIND")
757+
{
758+
method_ = Propfind;
759+
}
760+
else
761+
{
762+
method_ = Invalid;
763+
}
764+
break;
731765
default:
732766
method_ = Invalid;
733767
break;

lib/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" AND BUILD_SHARED_LIBS)
4343
else()
4444
set(UNITTEST_SOURCES ${UNITTEST_SOURCES} ../src/HttpFileImpl.cc
4545
unittests/HttpFileTest.cc
46+
unittests/HttpMethodTest.cc
4647
unittests/WebsocketResponseTest.cc)
4748
endif()
4849

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include <drogon/drogon_test.h>
2+
#include <drogon/HttpTypes.h>
3+
#include "../../lib/src/HttpRequestImpl.h"
4+
5+
using namespace drogon;
6+
7+
// Helper: parse a method string through HttpRequestImpl::setMethod
8+
static std::pair<bool, HttpMethod> parseMethod(const std::string &str)
9+
{
10+
HttpRequestImpl req(nullptr);
11+
bool ok = req.setMethod(str.data(), str.data() + str.size());
12+
return {ok, req.method()};
13+
}
14+
15+
DROGON_TEST(StandardHttpMethods)
16+
{
17+
auto [ok, m] = parseMethod("GET");
18+
CHECK(ok);
19+
CHECK(m == Get);
20+
21+
std::tie(ok, m) = parseMethod("POST");
22+
CHECK(ok);
23+
CHECK(m == Post);
24+
25+
std::tie(ok, m) = parseMethod("PUT");
26+
CHECK(ok);
27+
CHECK(m == Put);
28+
29+
std::tie(ok, m) = parseMethod("DELETE");
30+
CHECK(ok);
31+
CHECK(m == Delete);
32+
33+
std::tie(ok, m) = parseMethod("HEAD");
34+
CHECK(ok);
35+
CHECK(m == Head);
36+
37+
std::tie(ok, m) = parseMethod("OPTIONS");
38+
CHECK(ok);
39+
CHECK(m == Options);
40+
41+
std::tie(ok, m) = parseMethod("PATCH");
42+
CHECK(ok);
43+
CHECK(m == Patch);
44+
}
45+
46+
DROGON_TEST(WebDavMethods)
47+
{
48+
auto [ok, m] = parseMethod("PROPFIND");
49+
CHECK(ok);
50+
CHECK(m == Propfind);
51+
52+
std::tie(ok, m) = parseMethod("MKCOL");
53+
CHECK(ok);
54+
CHECK(m == Mkcol);
55+
56+
std::tie(ok, m) = parseMethod("COPY");
57+
CHECK(ok);
58+
CHECK(m == Copy);
59+
60+
std::tie(ok, m) = parseMethod("MOVE");
61+
CHECK(ok);
62+
CHECK(m == Move);
63+
}
64+
65+
DROGON_TEST(WebDavMethodStrings)
66+
{
67+
CHECK(to_string_view(Propfind) == "PROPFIND");
68+
CHECK(to_string_view(Mkcol) == "MKCOL");
69+
CHECK(to_string_view(Copy) == "COPY");
70+
CHECK(to_string_view(Move) == "MOVE");
71+
}
72+
73+
DROGON_TEST(InvalidMethodsRejected)
74+
{
75+
auto [ok, m] = parseMethod("INVALID");
76+
CHECK(!ok);
77+
CHECK(m == Invalid);
78+
79+
std::tie(ok, m) = parseMethod("LOCK");
80+
CHECK(!ok);
81+
CHECK(m == Invalid);
82+
83+
std::tie(ok, m) = parseMethod("");
84+
CHECK(!ok);
85+
CHECK(m == Invalid);
86+
87+
std::tie(ok, m) = parseMethod("G");
88+
CHECK(!ok);
89+
CHECK(m == Invalid);
90+
}

0 commit comments

Comments
 (0)