a bit better way to treah handlers

This commit is contained in:
Blue 2023-12-13 17:33:11 -03:00
parent f0d205dee7
commit 3fe6d25448
Signed by: blue
GPG key ID: 9B203B252A63EE38
16 changed files with 291 additions and 95 deletions

View file

@ -3,6 +3,8 @@
#include "request.h"
#include "response/response.h"
constexpr static const char* GET("GET");
constexpr static const char* REQUEST_METHOD("REQUEST_METHOD");
@ -16,9 +18,18 @@ constexpr static const char* SERVER_NAME("SERVER_NAME");
//
// constexpr static const char* SCRIPT_NAME("SCRIPT_NAME");
constexpr std::array<
std::pair<std::string_view, Request::Method>,
static_cast<uint8_t>(Request::Method::unknown)
> methods = {{
{"GET", Request::Method::get},
{"POST", Request::Method::post}
}};
Request::Request ():
state(State::initial),
raw()
raw(),
response(nullptr)
{}
Request::~Request() {
@ -36,12 +47,17 @@ void Request::terminate() {
}
}
bool Request::isGet() const {
if (state != State::accepted)
throw std::runtime_error("An attempt to read request type on a wrong request state");
Request::Method Request::method() const {
if (state == State::initial)
throw std::runtime_error("An attempt to read request method on not accepted request");
std::string_view method(FCGX_GetParam(REQUEST_METHOD, raw.envp));
return method == GET;
for (const auto& pair : methods) {
if (pair.first == method)
return pair.second;
}
return Request::Method::unknown;
}
bool Request::wait(int socketDescriptor) {
@ -59,20 +75,61 @@ bool Request::wait(int socketDescriptor) {
return result;
}
OStream Request::getOutputStream() {
if (state != State::accepted)
throw std::runtime_error("An attempt to request output stream on a wrong request state");
OStream Request::getOutputStream(const Response* response) {
validateResponse(response);
return OStream(raw.out);
}
OStream Request::getErrorStream() {
if (state != State::accepted)
throw std::runtime_error("An attempt to request error stream on a wrong request state");
OStream Request::getErrorStream(const Response* response) {
validateResponse(response);
return OStream(raw.err);
}
void Request::responseIsComplete(const Response* response) {
switch (state) {
case State::initial:
throw std::runtime_error("An attempt to mark the request as complete, but it wasn't even accepted yet");
break;
case State::accepted:
throw std::runtime_error("An attempt to mark the request as complete, but it wasn't responded");
break;
case State::responding:
if (Request::response != response)
throw std::runtime_error("An attempt to mark the request as complete by the different response who actually started responding");
Request::response = nullptr;
state = State::responded;
break;
case State::responded:
throw std::runtime_error("An attempt to mark the request as a complete for the second time");
break;
}
}
void Request::validateResponse(const Response* response) {
switch (state) {
case State::initial:
throw std::runtime_error("An attempt to request stream while the request wasn't even accepted yet");
break;
case State::accepted:
Request::response = response;
state = State::responding;
break;
case State::responding:
if (Request::response != response)
throw std::runtime_error("Error handling a request: first time one response started replying, then another continued");
break;
case State::responded:
throw std::runtime_error("An attempt to request stream on a request that was already done responding");
break;
}
}
Request::State Request::currentState() const {
return state;
}
std::string Request::getPath(const std::string& serverName) const {
if (state != State::accepted)
throw std::runtime_error("An attempt to request path on a wrong request state");

View file

@ -6,6 +6,8 @@
#include <memory>
#include <stdexcept>
#include <string_view>
#include <array>
#include <map>
#include <fcgiapp.h>
@ -13,14 +15,22 @@
#include "stream/ostream.h"
class Response;
class Request {
public:
enum class State {
initial,
accepted,
responding,
responded
};
enum class Method {
get,
post,
unknown
};
Request();
~Request();
Request(const Request& other) = delete;
@ -30,17 +40,24 @@ public:
bool wait(int socketDescriptor);
void terminate();
bool isGet() const;
OStream getOutputStream();
OStream getErrorStream();
Method method() const;
State currentState() const;
OStream getOutputStream(const Response* response);
OStream getErrorStream(const Response* response);
void responseIsComplete(const Response* response);
std::string getPath(const std::string& serverName) const;
std::string getServerName() const;
void printEnvironment(std::ostream& out);
void printEnvironment(nlohmann::json& out);
private:
void validateResponse(const Response* response);
private:
State state;
FCGX_Request raw;
const Response* response;
};