Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ set(DROGON_UTIL_HEADERS
lib/inc/drogon/utils/FunctionTraits.h
lib/inc/drogon/utils/HttpConstraint.h
lib/inc/drogon/utils/OStringStream.h
lib/inc/drogon/utils/ParsingUtils.h
lib/inc/drogon/utils/Utilities.h
lib/inc/drogon/utils/monitoring.h)
install(FILES ${DROGON_UTIL_HEADERS}
Expand Down
100 changes: 100 additions & 0 deletions lib/inc/drogon/utils/ParsingUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
*
* @file ParsingUtils.h
* Shared parsing utilities for HTTP and multipart parsing
*
* Copyright 2024, Drogon. All rights reserved.
* https://github.com/drogonframework/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/

#pragma once

#include <cctype>
#include <string_view>
#include <utility>

namespace drogon
{
namespace utils
{

/**
* @brief Check if a string_view starts with another string_view
*/
inline bool startsWith(const std::string_view &a, const std::string_view &b)
{
if (a.size() < b.size())
{
return false;
}
for (size_t i = 0; i < b.size(); i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}

/**
* @brief Check if a string_view starts with another string_view
* (case-insensitive)
*/
inline bool startsWithIgnoreCase(const std::string_view &a,
const std::string_view &b)
{
if (a.size() < b.size())
{
return false;
}
for (size_t i = 0; i < b.size(); i++)
{
const auto lhs = std::tolower(static_cast<unsigned char>(a[i]));
const auto rhs = std::tolower(static_cast<unsigned char>(b[i]));
if (lhs != rhs)
{
return false;
}
}
return true;
}

/**
* @brief Parse a single HTTP header line into name and value
* @param begin Pointer to the start of the line
* @param end Pointer to the end of the line (not including CRLF)
* @return A pair of (header_name, header_value) string_views
*/
inline std::pair<std::string_view, std::string_view> parseLine(
const char *begin,
const char *end)
{
auto p = begin;
while (p != end)
{
if (*p == ':')
{
if (p + 1 != end && *(p + 1) == ' ')
{
return std::make_pair(std::string_view(begin, p - begin),
std::string_view(p + 2, end - p - 2));
}
else
{
return std::make_pair(std::string_view(begin, p - begin),
std::string_view(p + 1, end - p - 1));
}
}
++p;
}
return std::make_pair(std::string_view(), std::string_view());
}

} // namespace utils
} // namespace drogon
27 changes: 2 additions & 25 deletions lib/src/MultiPart.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "HttpFileImpl.h"
#include <drogon/MultiPart.h>
#include <drogon/utils/Utilities.h>
#include <drogon/utils/ParsingUtils.h>
#include <drogon/config.h>
#include <algorithm>
#include <fcntl.h>
Expand All @@ -29,6 +30,7 @@
#endif

using namespace drogon;
using drogon::utils::parseLine;

const std::vector<HttpFile> &MultiPartParser::getFiles() const
{
Expand Down Expand Up @@ -87,31 +89,6 @@ int MultiPartParser::parse(const HttpRequestPtr &req)
return parse(req, contentType.data() + (pos + 9), pos2 - (pos + 9));
}

static std::pair<std::string_view, std::string_view> parseLine(
const char *begin,
const char *end)
{
auto p = begin;
while (p != end)
{
if (*p == ':')
{
if (p + 1 != end && *(p + 1) == ' ')
{
return std::make_pair(std::string_view(begin, p - begin),
std::string_view(p + 2, end - p - 2));
}
else
{
return std::make_pair(std::string_view(begin, p - begin),
std::string_view(p + 1, end - p - 1));
}
}
++p;
}
return std::make_pair(std::string_view(), std::string_view());
}

int MultiPartParser::parseEntity(const HttpRequestPtr &req,
const char *begin,
const char *end)
Expand Down
63 changes: 4 additions & 59 deletions lib/src/MultipartStreamParser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,12 @@

#include "MultipartStreamParser.h"
#include <cassert>
#include <drogon/utils/ParsingUtils.h>

using namespace drogon;

static bool startsWith(const std::string_view &a, const std::string_view &b)
{
if (a.size() < b.size())
{
return false;
}
for (size_t i = 0; i < b.size(); i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}

static bool startsWithIgnoreCase(const std::string_view &a,
const std::string_view &b)
{
if (a.size() < b.size())
{
return false;
}
for (size_t i = 0; i < b.size(); i++)
{
if (::tolower(a[i]) != ::tolower(b[i]))
{
return false;
}
}
return true;
}
using drogon::utils::parseLine;
using drogon::utils::startsWith;
using drogon::utils::startsWithIgnoreCase;

MultipartStreamParser::MultipartStreamParser(const std::string &contentType)
{
Expand Down Expand Up @@ -86,32 +57,6 @@ MultipartStreamParser::MultipartStreamParser(const std::string &contentType)
crlfDashBoundary_ = crlf_ + dash_ + boundary_;
}

// TODO: same function in HttpRequestParser.cc
static std::pair<std::string_view, std::string_view> parseLine(
const char *begin,
const char *end)
{
auto p = begin;
while (p != end)
{
if (*p == ':')
{
if (p + 1 != end && *(p + 1) == ' ')
{
return std::make_pair(std::string_view(begin, p - begin),
std::string_view(p + 2, end - p - 2));
}
else
{
return std::make_pair(std::string_view(begin, p - begin),
std::string_view(p + 1, end - p - 1));
}
}
++p;
}
return std::make_pair(std::string_view(), std::string_view());
}

void drogon::MultipartStreamParser::parse(
const char *data,
size_t length,
Expand Down
Loading