Skip to content

Commit 6a5fefb

Browse files
feat: add missing http error codes (#1097)
* feature: added missing http error codes * fix: sq * fix: address pr review comments
1 parent e6eb747 commit 6a5fefb

File tree

3 files changed

+91
-103
lines changed

3 files changed

+91
-103
lines changed

services/network/Http.cpp

Lines changed: 39 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,9 @@ namespace services
205205
infra::Tokenizer tokenizer(statusLine, ' ');
206206

207207
auto versionValid = HttpVersionValid(tokenizer.Token(0));
208-
auto optionalStatusCode = HttpStatusCodeFromString(tokenizer.Token(1));
209-
if (versionValid && optionalStatusCode)
210-
{
211-
statusCode = *optionalStatusCode;
208+
auto statusCode = HttpStatusCodeFromString(tokenizer.Token(1));
209+
if (versionValid)
212210
observer.StatusAvailable(statusCode, statusLine);
213-
}
214211
else
215212
{
216213
error = true;
@@ -408,100 +405,14 @@ namespace services
408405
return std::nullopt;
409406
}
410407

411-
std::optional<HttpStatusCode> HttpStatusCodeFromString(infra::BoundedConstString statusCode)
408+
HttpStatusCode HttpStatusCodeFromString(infra::BoundedConstString statusCode)
412409
{
413410
std::underlying_type<services::HttpStatusCode>::type value = 0;
414411

415412
for (std::size_t index = 0; index < statusCode.size(); ++index)
416413
value = value * 10 + statusCode[index] - '0';
417414

418-
switch (value)
419-
{
420-
case 100:
421-
return std::make_optional(HttpStatusCode::Continue);
422-
case 101:
423-
return std::make_optional(HttpStatusCode::SwitchingProtocols);
424-
case 200:
425-
return std::make_optional(HttpStatusCode::OK);
426-
case 201:
427-
return std::make_optional(HttpStatusCode::Created);
428-
case 202:
429-
return std::make_optional(HttpStatusCode::Accepted);
430-
case 203:
431-
return std::make_optional(HttpStatusCode::NonAuthorativeInformation);
432-
case 204:
433-
return std::make_optional(HttpStatusCode::NoContent);
434-
case 205:
435-
return std::make_optional(HttpStatusCode::ResetContent);
436-
case 206:
437-
return std::make_optional(HttpStatusCode::PartialContent);
438-
case 300:
439-
return std::make_optional(HttpStatusCode::MultipleChoices);
440-
case 301:
441-
return std::make_optional(HttpStatusCode::MovedPermanently);
442-
case 302:
443-
return std::make_optional(HttpStatusCode::Found);
444-
case 303:
445-
return std::make_optional(HttpStatusCode::SeeOther);
446-
case 304:
447-
return std::make_optional(HttpStatusCode::NotModified);
448-
case 305:
449-
return std::make_optional(HttpStatusCode::UseProxy);
450-
case 307:
451-
return std::make_optional(HttpStatusCode::TemporaryRedirect);
452-
case 308:
453-
return std::make_optional(HttpStatusCode::PermanentRedirect);
454-
case 400:
455-
return std::make_optional(HttpStatusCode::BadRequest);
456-
case 401:
457-
return std::make_optional(HttpStatusCode::Unauthorized);
458-
case 402:
459-
return std::make_optional(HttpStatusCode::PaymentRequired);
460-
case 403:
461-
return std::make_optional(HttpStatusCode::Forbidden);
462-
case 404:
463-
return std::make_optional(HttpStatusCode::NotFound);
464-
case 405:
465-
return std::make_optional(HttpStatusCode::MethodNotAllowed);
466-
case 406:
467-
return std::make_optional(HttpStatusCode::NotAcceptable);
468-
case 407:
469-
return std::make_optional(HttpStatusCode::ProxyAuthenticationRequired);
470-
case 408:
471-
return std::make_optional(HttpStatusCode::RequestTimeOut);
472-
case 409:
473-
return std::make_optional(HttpStatusCode::Conflict);
474-
case 410:
475-
return std::make_optional(HttpStatusCode::Gone);
476-
case 411:
477-
return std::make_optional(HttpStatusCode::LengthRequired);
478-
case 412:
479-
return std::make_optional(HttpStatusCode::PreconditionFailed);
480-
case 413:
481-
return std::make_optional(HttpStatusCode::RequestEntityTooLarge);
482-
case 414:
483-
return std::make_optional(HttpStatusCode::RequestUriTooLarge);
484-
case 415:
485-
return std::make_optional(HttpStatusCode::UnsupportedMediaType);
486-
case 416:
487-
return std::make_optional(HttpStatusCode::RequestRangeNotSatisfiable);
488-
case 417:
489-
return std::make_optional(HttpStatusCode::ExpectationFailed);
490-
case 500:
491-
return std::make_optional(HttpStatusCode::InternalServerError);
492-
case 501:
493-
return std::make_optional(HttpStatusCode::NotImplemented);
494-
case 502:
495-
return std::make_optional(HttpStatusCode::BadGateway);
496-
case 503:
497-
return std::make_optional(HttpStatusCode::ServiceUnavailable);
498-
case 504:
499-
return std::make_optional(HttpStatusCode::GatewayTimeOut);
500-
case 505:
501-
return std::make_optional(HttpStatusCode::HttpVersionNotSupported);
502-
}
503-
504-
return std::nullopt;
415+
return static_cast<services::HttpStatusCode>(value);
505416
}
506417

507418
infra::BoundedConstString HttpStatusCodeToString(services::HttpStatusCode statusCode)
@@ -578,6 +489,26 @@ namespace services
578489
return "RequestRangeNotSatisfiable";
579490
case services::HttpStatusCode::ExpectationFailed:
580491
return "ExpectationFailed";
492+
case services::HttpStatusCode::MisdirectedRequest:
493+
return "MisdirectedRequest";
494+
case services::HttpStatusCode::UnprocessableContent:
495+
return "UnprocessableContent";
496+
case services::HttpStatusCode::Locked:
497+
return "Locked";
498+
case services::HttpStatusCode::FailedDependency:
499+
return "FailedDependency";
500+
case services::HttpStatusCode::TooEarly:
501+
return "TooEarly";
502+
case services::HttpStatusCode::UpgradeRequired:
503+
return "UpgradeRequired";
504+
case services::HttpStatusCode::PreconditionRequired:
505+
return "PreconditionRequired";
506+
case services::HttpStatusCode::TooManyRequests:
507+
return "TooManyRequests";
508+
case services::HttpStatusCode::RequestHeaderFieldsTooLarge:
509+
return "RequestHeaderFieldsTooLarge";
510+
case services::HttpStatusCode::UnavailableForLegalReasons:
511+
return "UnavailableForLegalReasons";
581512
case services::HttpStatusCode::InternalServerError:
582513
return "InternalServerError";
583514
case services::HttpStatusCode::NotImplemented:
@@ -590,9 +521,19 @@ namespace services
590521
return "GatewayTimeOut";
591522
case services::HttpStatusCode::HttpVersionNotSupported:
592523
return "HttpVersionNotSupported";
524+
case services::HttpStatusCode::VariantAlsoNegotiates:
525+
return "VariantAlsoNegotiates";
526+
case services::HttpStatusCode::InsufficientStorage:
527+
return "InsufficientStorage";
528+
case services::HttpStatusCode::LoopDetected:
529+
return "LoopDetected";
530+
case services::HttpStatusCode::NotExtended:
531+
return "NotExtended";
532+
case services::HttpStatusCode::NetworkAuthenticationRequired:
533+
return "NetworkAuthenticationRequired";
593534
}
594535

595-
std::abort();
536+
return "Unknown HTTP status";
596537
}
597538
}
598539

@@ -614,7 +555,10 @@ namespace infra
614555

615556
TextOutputStream& operator<<(TextOutputStream& stream, services::HttpStatusCode statusCode)
616557
{
617-
stream << services::HttpStatusCodeToString(statusCode);
558+
auto status = services::HttpStatusCodeToString(statusCode);
559+
stream << status;
560+
if (status == "Unknown HTTP status")
561+
stream << ": " << static_cast<int>(statusCode);
618562

619563
return stream;
620564
}

services/network/Http.hpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,27 @@ namespace services
5858
UnsupportedMediaType = 415,
5959
RequestRangeNotSatisfiable = 416,
6060
ExpectationFailed = 417,
61+
MisdirectedRequest = 421,
62+
UnprocessableContent = 422,
63+
Locked = 423,
64+
FailedDependency = 424,
65+
TooEarly = 425,
66+
UpgradeRequired = 426,
67+
PreconditionRequired = 428,
68+
TooManyRequests = 429,
69+
RequestHeaderFieldsTooLarge = 431,
70+
UnavailableForLegalReasons = 451,
6171
InternalServerError = 500,
6272
NotImplemented = 501,
6373
BadGateway = 502,
6474
ServiceUnavailable = 503,
6575
GatewayTimeOut = 504,
66-
HttpVersionNotSupported = 505
76+
HttpVersionNotSupported = 505,
77+
VariantAlsoNegotiates = 506,
78+
InsufficientStorage = 507,
79+
LoopDetected = 508,
80+
NotExtended = 510,
81+
NetworkAuthenticationRequired = 511
6782
};
6883

6984
namespace http_responses
@@ -178,7 +193,7 @@ namespace services
178193
infra::BoundedConstString HttpVerbToString(HttpVerb verb);
179194
std::optional<HttpVerb> HttpVerbFromString(infra::BoundedConstString verb);
180195

181-
std::optional<HttpStatusCode> HttpStatusCodeFromString(infra::BoundedConstString statusCode);
196+
HttpStatusCode HttpStatusCodeFromString(infra::BoundedConstString statusCode);
182197
infra::BoundedConstString HttpStatusCodeToString(services::HttpStatusCode statusCode);
183198
}
184199

services/network/test/TestHttpClient.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,28 @@ INSTANTIATE_TEST_SUITE_P(HttpStatusMessageTest, HttpStatusMessageFormattingTest,
8686
HttpStatusCodeWithString{ services::HttpStatusCode::UnsupportedMediaType, "UnsupportedMediaType" },
8787
HttpStatusCodeWithString{ services::HttpStatusCode::RequestRangeNotSatisfiable, "RequestRangeNotSatisfiable" },
8888
HttpStatusCodeWithString{ services::HttpStatusCode::ExpectationFailed, "ExpectationFailed" },
89+
HttpStatusCodeWithString{ services::HttpStatusCode::MisdirectedRequest, "MisdirectedRequest" },
90+
HttpStatusCodeWithString{ services::HttpStatusCode::UnprocessableContent, "UnprocessableContent" },
91+
HttpStatusCodeWithString{ services::HttpStatusCode::Locked, "Locked" },
92+
HttpStatusCodeWithString{ services::HttpStatusCode::FailedDependency, "FailedDependency" },
93+
HttpStatusCodeWithString{ services::HttpStatusCode::TooEarly, "TooEarly" },
94+
HttpStatusCodeWithString{ services::HttpStatusCode::UpgradeRequired, "UpgradeRequired" },
95+
HttpStatusCodeWithString{ services::HttpStatusCode::PreconditionRequired, "PreconditionRequired" },
96+
HttpStatusCodeWithString{ services::HttpStatusCode::TooManyRequests, "TooManyRequests" },
97+
HttpStatusCodeWithString{ services::HttpStatusCode::RequestHeaderFieldsTooLarge, "RequestHeaderFieldsTooLarge" },
98+
HttpStatusCodeWithString{ services::HttpStatusCode::UnavailableForLegalReasons, "UnavailableForLegalReasons" },
8999
HttpStatusCodeWithString{ services::HttpStatusCode::InternalServerError, "InternalServerError" },
90100
HttpStatusCodeWithString{ services::HttpStatusCode::NotImplemented, "NotImplemented" },
91101
HttpStatusCodeWithString{ services::HttpStatusCode::BadGateway, "BadGateway" },
92102
HttpStatusCodeWithString{ services::HttpStatusCode::ServiceUnavailable, "ServiceUnavailable" },
93103
HttpStatusCodeWithString{ services::HttpStatusCode::GatewayTimeOut, "GatewayTimeOut" },
94-
HttpStatusCodeWithString{ services::HttpStatusCode::HttpVersionNotSupported, "HttpVersionNotSupported" }));
104+
HttpStatusCodeWithString{ services::HttpStatusCode::HttpVersionNotSupported, "HttpVersionNotSupported" },
105+
HttpStatusCodeWithString{ services::HttpStatusCode::VariantAlsoNegotiates, "VariantAlsoNegotiates" },
106+
HttpStatusCodeWithString{ services::HttpStatusCode::InsufficientStorage, "InsufficientStorage" },
107+
HttpStatusCodeWithString{ services::HttpStatusCode::LoopDetected, "LoopDetected" },
108+
HttpStatusCodeWithString{ services::HttpStatusCode::NotExtended, "NotExtended" },
109+
HttpStatusCodeWithString{ services::HttpStatusCode::NetworkAuthenticationRequired, "NetworkAuthenticationRequired" },
110+
HttpStatusCodeWithString{ static_cast<services::HttpStatusCode>(900), "Unknown HTTP status: 900" }));
95111

96112
struct HttpStatusCodeAndString
97113
{
@@ -149,12 +165,27 @@ INSTANTIATE_TEST_SUITE_P(HttpStatusMessageTest, HttpStatusMessageParsingTest,
149165
HttpStatusCodeAndString{ "415", services::HttpStatusCode::UnsupportedMediaType },
150166
HttpStatusCodeAndString{ "416", services::HttpStatusCode::RequestRangeNotSatisfiable },
151167
HttpStatusCodeAndString{ "417", services::HttpStatusCode::ExpectationFailed },
168+
HttpStatusCodeAndString{ "421", services::HttpStatusCode::MisdirectedRequest },
169+
HttpStatusCodeAndString{ "422", services::HttpStatusCode::UnprocessableContent },
170+
HttpStatusCodeAndString{ "423", services::HttpStatusCode::Locked },
171+
HttpStatusCodeAndString{ "424", services::HttpStatusCode::FailedDependency },
172+
HttpStatusCodeAndString{ "425", services::HttpStatusCode::TooEarly },
173+
HttpStatusCodeAndString{ "426", services::HttpStatusCode::UpgradeRequired },
174+
HttpStatusCodeAndString{ "428", services::HttpStatusCode::PreconditionRequired },
175+
HttpStatusCodeAndString{ "429", services::HttpStatusCode::TooManyRequests },
176+
HttpStatusCodeAndString{ "431", services::HttpStatusCode::RequestHeaderFieldsTooLarge },
177+
HttpStatusCodeAndString{ "451", services::HttpStatusCode::UnavailableForLegalReasons },
152178
HttpStatusCodeAndString{ "500", services::HttpStatusCode::InternalServerError },
153179
HttpStatusCodeAndString{ "501", services::HttpStatusCode::NotImplemented },
154180
HttpStatusCodeAndString{ "502", services::HttpStatusCode::BadGateway },
155181
HttpStatusCodeAndString{ "503", services::HttpStatusCode::ServiceUnavailable },
156182
HttpStatusCodeAndString{ "504", services::HttpStatusCode::GatewayTimeOut },
157-
HttpStatusCodeAndString{ "505", services::HttpStatusCode::HttpVersionNotSupported }));
183+
HttpStatusCodeAndString{ "505", services::HttpStatusCode::HttpVersionNotSupported },
184+
HttpStatusCodeAndString{ "506", services::HttpStatusCode::VariantAlsoNegotiates },
185+
HttpStatusCodeAndString{ "507", services::HttpStatusCode::InsufficientStorage },
186+
HttpStatusCodeAndString{ "508", services::HttpStatusCode::LoopDetected },
187+
HttpStatusCodeAndString{ "510", services::HttpStatusCode::NotExtended },
188+
HttpStatusCodeAndString{ "511", services::HttpStatusCode::NetworkAuthenticationRequired }));
158189

159190
class HttpClientTest
160191
: public testing::Test
@@ -410,15 +441,13 @@ TEST_F(HttpClientTest, incorrect_response_version_should_not_call_StatusAvailabl
410441
connection.SimulateDataReceived(infra::StringAsByteRange(infra::BoundedConstString("HTTP/X.Y 200 Success\r\n")));
411442
}
412443

413-
TEST_F(HttpClientTest, incorrect_response_code_should_not_call_StatusAvailable)
444+
TEST_F(HttpClientTest, unexpected_response_code_should_call_StatusAvailable)
414445
{
415446
Connect();
416447

417-
EXPECT_CALL(client, StatusAvailable(testing::_)).Times(0);
448+
EXPECT_CALL(client, StatusAvailable(static_cast<services::HttpStatusCode>(900)));
418449

419450
EXPECT_CALL(connection, AckReceivedMock());
420-
EXPECT_CALL(connection, AbortAndDestroyMock());
421-
EXPECT_CALL(client, Detaching());
422451
client.Subject().Get("/");
423452
ExecuteAllActions();
424453
connection.SimulateDataReceived(infra::StringAsByteRange(infra::BoundedConstString("HTTP/1.1 900 Invalid\r\n")));

0 commit comments

Comments
 (0)