Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
588bb65
Use string_view in CookieParser::before_handle parsing
Sightem Apr 17, 2025
19041b8
Merge pull request #1024 from Sightem/refactor/cookie-parser-string-view
gittiver Oct 15, 2025
b367bc7
replace deprecated macos-13 runner by macos-14
gittiver Oct 19, 2025
2022aad
replaced old trim function based on std::string by one using string_view
gittiver Oct 15, 2025
ae2172b
Bump actions/upload-artifact from 4 to 5
dependabot[bot] Oct 27, 2025
833f0ce
readded condition for sending_buffers (seems get lost on last refacto…
gittiver Nov 15, 2025
43a7b20
Bump actions/checkout from 5 to 6
dependabot[bot] Nov 21, 2025
56bbc7d
returned error code on write and handled in all places where do_write…
gittiver Nov 16, 2025
48c4ef1
move CPM to CROW_BUILD_TESTS scope
Nov 25, 2025
d5ca7f8
CROW_GENERATE_SBOM also need CPM. Fix CMakeLists.txt
Nov 26, 2025
1aa3fbb
Replace uint16_t with size_t for rule/blueprint indices across routin…
Nov 20, 2025
b3ed7b1
added protection against empty get_found_bp result.
Nov 15, 2025
80ba18c
Bump actions/upload-artifact from 5 to 6
dependabot[bot] Dec 15, 2025
2709cb0
Bump dawidd6/action-download-artifact from 11 to 12
dependabot[bot] Dec 25, 2025
5b8c0a1
removed double lookup by count() and find(),
gittiver Dec 29, 2025
7e41d9f
Merge pull request #1131 from CrowCpp/1125-get_header_value-performs-…
gittiver Dec 30, 2025
2e0f203
increment qs only if '&' was found
gittiver Dec 30, 2025
8236cc3
Merge pull request #1132 from CrowCpp/1127-small-oob-read-in-qs_scanv…
gittiver Dec 31, 2025
0acad13
updated external libs catch2 3.10->3.12, cmake-sbom 1.3.0 -> 1.4.0
gittiver Jan 12, 2026
6e5977f
Protect websockets_ by mutex
andrew-guz Jan 23, 2026
38e6a20
Additional warning ofr TSAN and Clang
andrew-guz Jan 26, 2026
80c4311
Bump dawidd6/action-download-artifact from 12 to 14
dependabot[bot] Feb 2, 2026
ab7b5a6
Merge pull request #1139 from CrowCpp/dependabot/github_actions/dawid…
gittiver Feb 3, 2026
773faaa
Merge pull request #1136 from softcom-su/websockets-mutex
gittiver Feb 3, 2026
765958e
Merge branch 'master' into v13 branch
gittiver Feb 3, 2026
1c1cc66
updated version numbers to 1.3.1 and copyright to 2026
gittiver Feb 11, 2026
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
12 changes: 7 additions & 5 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ jobs:
- { os: windows-latest, compiler: msvc, cxx_stdlib: msvc }

steps:

- name: Output Infos
run: |
echo $GIT_REF
echo $GIT_EVENT_REF
echo $GIT_EVENT_TYPE

- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Prepare dependencies
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
Expand Down Expand Up @@ -135,7 +137,7 @@ jobs:
shell: bash

- name: Save report
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'gcc' && matrix.cxx_stdlib == 'libstdc++' && matrix.asio_type == 'boost' && !startsWith(github.ref, 'refs/heads/v')
with:
name: coveralls.json
Expand All @@ -157,7 +159,7 @@ jobs:
shell: bash

- name: Upload Linux packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'gcc' && matrix.cxx_stdlib == 'libstdc++' && matrix.asio_type == 'boost' && startsWith(github.ref, 'refs/heads/v')
with:
name: packages
Expand All @@ -168,7 +170,7 @@ jobs:
${{github.workspace}}/build/crow_all.h.*

- name: Upload Mac OS packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: matrix.os == 'macos-latest' && matrix.compiler == 'clang' && matrix.cxx_stdlib == 'libstdc++' && startsWith(github.ref, 'refs/heads/v')
with:
name: packages
Expand All @@ -178,7 +180,7 @@ jobs:


- name: Upload Windows packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: matrix.os == 'windows-latest' && matrix.compiler == 'msvc' && matrix.cxx_stdlib == 'msvc' && startsWith(github.ref, 'refs/heads/v')
with:
name: packages
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build_bazel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
# ubuntu-18.04 & mac-os do not work due to compile error on asio
# windows-2019 not included to spare free minutes
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Prepare dependencies
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cifuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
fuzz-seconds: 800
output-sarif: true
- name: Upload Crash
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6

# Install dependencies
- name: Prepare dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/doxygen-gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Prepare dependencies
run: sudo apt-get update && sudo apt-get -yq install libasio-dev doxygen mkdocs graphviz zlib1g-dev gcc clang make cmake python3 python3-pip git openssl libssl-dev
- name: prepate pip dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/submit_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
if: github.event.workflow_run.conclusion == 'success'
steps:
- name: Download artifact
uses: dawidd6/action-download-artifact@v11
uses: dawidd6/action-download-artifact@v14
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
workflow_conclusion: success
Expand Down
21 changes: 17 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR)
# Define the project name and language
project(Crow
LANGUAGES CXX
VERSION 1.3.0
VERSION 1.3.1
)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPM.cmake)

# Make sure Findasio.cmake module is found
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

Expand Down Expand Up @@ -59,12 +57,17 @@ option(CROW_RETURNS_OK_ON_HTTP_OPTIONS_REQUEST

option(CROW_ENABLE_SSL "Enable Crow's SSL feature for supporting https" OFF)
option(CROW_ENABLE_COMPRESSION "Enable Crow's Compression feature for supporting compressed http content" OFF)
option(CROW_ENABLE_TSAN "Enable ThreadSanitizer" OFF)

if(CROW_GENERATE_SBOM OR CROW_BUILD_TESTS)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPM.cmake)
endif ()

if(CROW_GENERATE_SBOM)
CPMAddPackage(
NAME cmake-sbom
GITHUB_REPOSITORY DEMCON/cmake-sbom
GIT_TAG v1.3.0
GIT_TAG v1.4.0
DOWNLOAD_ONLY YES
)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}/_deps/cmake-sbom-src/cmake")
Expand All @@ -80,6 +83,16 @@ if(CROW_GENERATE_SBOM)
)
endif()

if(CROW_ENABLE_TSAN)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(STATUS "ThreadSanitizer enabled")
add_compile_options(-fsanitize=thread -fno-omit-frame-pointer)
add_link_options(-fsanitize=thread)
else()
message(WARNING "ThreadSanitizer is exclusive to Clang and cannot be used with any other compilers")
endif()
endif()

#####################################
# Define Targets
#####################################
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = Crow
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 1.3.0
PROJECT_NUMBER = 1.3.1

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
BSD 3-Clause License

Copyright (c) 2014-2017, ipkn
2020-2022, CrowCpp
2020-2026, CrowCpp
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module(name = "crowcpp", version = "1.2.1.2")
module(name = "crowcpp", version = "1.3.1")

bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "rules_cc", version = "0.1.1")
Expand Down
4 changes: 4 additions & 0 deletions include/crow/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ namespace crow

void close_websockets()
{
std::lock_guard<std::mutex> lock{websockets_mutex_};
for (auto websocket : websockets_)
{
CROW_LOG_INFO << "Quitting Websocket: " << websocket;
Expand All @@ -629,11 +630,13 @@ namespace crow

void add_websocket(std::shared_ptr<websocket::connection> conn)
{
std::lock_guard<std::mutex> lock{websockets_mutex_};
websockets_.push_back(conn);
}

void remove_websocket(std::shared_ptr<websocket::connection> conn)
{
std::lock_guard<std::mutex> lock{websockets_mutex_};
websockets_.erase(std::remove(websockets_.begin(), websockets_.end(), conn), websockets_.end());
}

Expand Down Expand Up @@ -846,6 +849,7 @@ namespace crow
bool server_started_{false};
std::condition_variable cv_started_;
std::mutex start_mutex_;
std::mutex websockets_mutex_; ///< \brief mutex to protect websockets_
std::vector<std::shared_ptr<websocket::connection>> websockets_;
};

Expand Down
8 changes: 4 additions & 4 deletions include/crow/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,19 +280,19 @@ namespace crow
struct routing_handle_result
{
bool catch_all{false};
uint16_t rule_index;
std::vector<uint16_t> blueprint_indices;
size_t rule_index;
std::vector<size_t> blueprint_indices;
routing_params r_params;
HTTPMethod method;

routing_handle_result() {}

routing_handle_result(uint16_t rule_index_, std::vector<uint16_t> blueprint_indices_, routing_params r_params_):
routing_handle_result(size_t rule_index_, std::vector<size_t> blueprint_indices_, routing_params r_params_):
rule_index(rule_index_),
blueprint_indices(blueprint_indices_),
r_params(r_params_) {}

routing_handle_result(uint16_t rule_index_, std::vector<uint16_t> blueprint_indices_, routing_params r_params_, HTTPMethod method_):
routing_handle_result(size_t rule_index_, std::vector<size_t> blueprint_indices_, routing_params r_params_, HTTPMethod method_):
rule_index(rule_index_),
blueprint_indices(blueprint_indices_),
r_params(r_params_),
Expand Down
46 changes: 33 additions & 13 deletions include/crow/http_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,13 @@ namespace crow
{
continue_requested = true;
buffers_.clear();
static std::string expect_100_continue = "HTTP/1.1 100 Continue\r\n\r\n";
static const std::string expect_100_continue = "HTTP/1.1 100 Continue\r\n\r\n";
buffers_.emplace_back(expect_100_continue.data(), expect_100_continue.size());
do_write_sync(buffers_);
error_code ec = do_write_sync(buffers_);
if (ec)
{
CROW_LOG_ERROR << ec << " buffer write error happened while handling sending continuation buffer header";
}
}
}

Expand Down Expand Up @@ -299,7 +303,12 @@ namespace crow
while (is.gcount() > 0)
{
buffers[0] = asio::buffer(buf, is.gcount());
do_write_sync(buffers);
error_code ec = do_write_sync(buffers);
if (ec) {
CROW_LOG_ERROR << ec << " - buffer write error happened while sending content of file "
<< res.file_info.path << ". Writing stopped premature.";
break;
}
is.read(buf, sizeof(buf));
}
}
Expand All @@ -318,13 +327,16 @@ namespace crow

void do_write_general()
{
error_code ec;
if (res.body.length() < res_stream_threshold_)
{
res_body_copy_.swap(res.body);
buffers_.emplace_back(res_body_copy_.data(), res_body_copy_.size());

do_write_sync(buffers_);

ec = do_write_sync(buffers_);
if (ec) {
CROW_LOG_ERROR << ec << " - buffer write error happened while sending response. Writing stopped premature.";
}
if (need_to_start_read_after_complete_)
{
need_to_start_read_after_complete_ = false;
Expand All @@ -334,7 +346,10 @@ namespace crow
}
else
{
asio::write(adaptor_.socket(), buffers_); // Write the response start / headers
asio::write(adaptor_.socket(), buffers_,ec); // Write the response start / headers
if (ec) {
CROW_LOG_ERROR << ec << "- buffer write error happened while sending response start / headers. Writing stopped premature.";
}
cancel_deadline_timer();
if (res.body.length() > 0)
{
Expand All @@ -345,7 +360,11 @@ namespace crow
{
size_t to_transfer = CROW_MIN(16384UL, length - transferred);
buffers[0] = asio::const_buffer(data + transferred, to_transfer);
do_write_sync(buffers);
ec = do_write_sync(buffers);
if (ec) {
CROW_LOG_ERROR << ec << " - " << transferred << " - buffer write error happened while sending response. Writing stopped premature.";
break;
}
transferred += to_transfer;
}
}
Expand Down Expand Up @@ -439,10 +458,15 @@ namespace crow
});
}

inline void do_write_sync(std::vector<asio::const_buffer>& buffers)
inline error_code do_write_sync(std::vector<asio::const_buffer>& buffers)
{
error_code ec;
asio::write(adaptor_.socket(), buffers, ec);
if (ec)
{
// CROW_LOG_ERROR << ec << " - happened while sending buffers";
CROW_LOG_DEBUG << this << " from write (sync)(2)";
}

this->res.clear();
this->res_body_copy_.clear();
Expand All @@ -455,11 +479,7 @@ namespace crow
this->parser_.clear();
}

if (ec)
{
CROW_LOG_ERROR << ec << " - happened while sending buffers";
CROW_LOG_DEBUG << this << " from write (sync)(2)";
}
return ec;
}

void cancel_deadline_timer()
Expand Down
15 changes: 8 additions & 7 deletions include/crow/http_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ namespace crow // NOTE: Already documented in "crow/app.h"
#endif

/// Find and return the value associated with the key. (returns an empty string if nothing is found)
template<typename T>
inline const std::string& get_header_value(const T& headers, const std::string& key)
inline const std::string& get_header_value(const ci_map& headers, const std::string& key)
{
if (headers.count(key))
{
return headers.find(key)->second;
static const std::string EMPTY;
const auto it = headers.find(key);
if (it != headers.end()) {
return it->second;
}
else {
return EMPTY;
}
static std::string empty;
return empty;
}

/// An HTTP request.
Expand Down
Loading
Loading