Detect content type when there's multiple elements.

This commit is contained in:
rakshasa
2025-05-04 10:25:56 +02:00
committed by Jari Sundell
parent 877c00d54e
commit 303edab9ec
2 changed files with 47 additions and 22 deletions
+45 -21
View File
@@ -20,16 +20,6 @@
namespace rpc {
// If bufferSize is zero then memcpy won't do anything.
inline void
SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) {
char* tmp = new char[size];
std::memcpy(tmp, buffer, bufferSize);
::free(m_buffer);
m_buffer = tmp;
}
void
SCgiTask::open(SCgi* parent, int fd) {
m_parent = parent;
@@ -150,18 +140,8 @@ SCgiTask::event_read() {
m_body = current + 1;
header_size = std::distance(m_buffer, m_body);
if (content_type == "") {
// If no CONTENT_TYPE was supplied, peek at the body to check if it's JSON
// { is a single request object, while [ is a batch array
if (*m_body == '{' || *m_body == '[')
m_content_type = ContentType::JSON;
} else if (content_type == "application/json") {
m_content_type = ContentType::JSON;
} else if (content_type == "text/xml") {
m_content_type = ContentType::XML;
} else {
if (!detect_content_type(content_type))
goto event_read_failed;
}
if ((unsigned int)(content_length + header_size) < m_buffer_size) {
m_buffer_size = content_length + header_size;
@@ -234,6 +214,50 @@ SCgiTask::event_error() {
close();
}
static inline bool
scgi_match_content_type(const std::string& content_type, const char* type) {
std::string::size_type pos = content_type.find_first_of(" ;");
if (pos == std::string::npos)
return content_type == type;
return content_type.compare(0, pos, type) == 0;
}
bool
SCgiTask::detect_content_type(const std::string& content_type) {
if (content_type.empty()) {
// If no CONTENT_TYPE was supplied, peek at the body to check if it's JSON
// { is a single request object, while [ is a batch array
if (*m_body == '{' || *m_body == '[')
m_content_type = ContentType::JSON;
else
m_content_type = ContentType::XML;
} else if (scgi_match_content_type(content_type, "application/json")) {
m_content_type = ContentType::JSON;
} else if (scgi_match_content_type(content_type, "text/xml")) {
m_content_type = ContentType::XML;
} else {
// If the content type is not JSON or XML, we don't know how to handle it.
return false;
}
return true;
}
// If bufferSize is zero then memcpy won't do anything.
void
SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) {
char* tmp = new char[size];
std::memcpy(tmp, buffer, bufferSize);
::free(m_buffer);
m_buffer = tmp;
}
void
SCgiTask::receive_call(const char* buffer, uint32_t length) {
// TODO: Rewrite RpcManager.process to pass the result buffer instead of having to copy it.
+2 -1
View File
@@ -38,7 +38,8 @@ public:
utils::SocketFd& get_fd() { return *reinterpret_cast<utils::SocketFd*>(&m_fileDesc); }
private:
inline void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize);
bool detect_content_type(const std::string& content_type);
void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize);
void receive_call(const char* buffer, uint32_t length);
void receive_write(const char* buffer, uint32_t length);