Full Code of libcpr/cpr for AI

master 8573f1d76657 cached
197 files
845.4 KB
215.4k tokens
882 symbols
1 requests
Download .txt
Showing preview only (897K chars total). Download the full file or copy to clipboard to get everything.
Repository: libcpr/cpr
Branch: master
Commit: 8573f1d76657
Files: 197
Total size: 845.4 KB

Directory structure:
gitextract_di3av8n9/

├── .clang-format
├── .clang-tidy
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   └── feature-request.yml
│   ├── dependabot.yml
│   └── workflows/
│       ├── build-deb.yml
│       ├── build-nuget.yml
│       ├── ci.yml
│       ├── clang-format.yml
│       ├── clang-tidy.yml
│       ├── cppcheck.yml
│       └── readme-updater.yml
├── .gitignore
├── .vscode/
│   └── tasks.json
├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── cmake/
│   ├── FindMbedTLS.cmake
│   ├── clang-tidy.cmake
│   ├── clear_variable.cmake
│   ├── code_coverage.cmake
│   ├── cppcheck.cmake
│   ├── cprConfig-ssl.cmake.in
│   ├── cprConfig.cmake.in
│   ├── cprver.h.in
│   ├── libpsl.cmake
│   ├── mongoose.CMakeLists.txt
│   ├── sanitizer.cmake
│   ├── std_fs_support_test.cpp
│   └── zlib_external.cmake
├── cppcheck-suppressions.xml
├── cpr/
│   ├── CMakeLists.txt
│   ├── accept_encoding.cpp
│   ├── async.cpp
│   ├── auth.cpp
│   ├── callback.cpp
│   ├── cert_info.cpp
│   ├── connection_pool.cpp
│   ├── cookies.cpp
│   ├── cprtypes.cpp
│   ├── curl_container.cpp
│   ├── curlholder.cpp
│   ├── curlmultiholder.cpp
│   ├── error.cpp
│   ├── file.cpp
│   ├── interceptor.cpp
│   ├── multipart.cpp
│   ├── multiperform.cpp
│   ├── parameters.cpp
│   ├── payload.cpp
│   ├── proxies.cpp
│   ├── proxyauth.cpp
│   ├── redirect.cpp
│   ├── response.cpp
│   ├── session.cpp
│   ├── sse.cpp
│   ├── ssl_ctx.cpp
│   ├── threadpool.cpp
│   ├── timeout.cpp
│   ├── unix_socket.cpp
│   └── util.cpp
├── cpr-config.cmake
├── include/
│   ├── CMakeLists.txt
│   └── cpr/
│       ├── accept_encoding.h
│       ├── api.h
│       ├── async.h
│       ├── async_wrapper.h
│       ├── auth.h
│       ├── bearer.h
│       ├── body.h
│       ├── body_view.h
│       ├── buffer.h
│       ├── callback.h
│       ├── cert_info.h
│       ├── connect_timeout.h
│       ├── connection_pool.h
│       ├── cookies.h
│       ├── cpr.h
│       ├── cprtypes.h
│       ├── curl_container.h
│       ├── curlholder.h
│       ├── curlmultiholder.h
│       ├── error.h
│       ├── file.h
│       ├── filesystem.h
│       ├── http_version.h
│       ├── interceptor.h
│       ├── interface.h
│       ├── limit_rate.h
│       ├── local_port.h
│       ├── local_port_range.h
│       ├── low_speed.h
│       ├── multipart.h
│       ├── multiperform.h
│       ├── parameters.h
│       ├── payload.h
│       ├── proxies.h
│       ├── proxyauth.h
│       ├── range.h
│       ├── redirect.h
│       ├── reserve_size.h
│       ├── resolve.h
│       ├── response.h
│       ├── secure_string.h
│       ├── session.h
│       ├── singleton.h
│       ├── sse.h
│       ├── ssl_ctx.h
│       ├── ssl_options.h
│       ├── status_codes.h
│       ├── threadpool.h
│       ├── timeout.h
│       ├── unix_socket.h
│       ├── user_agent.h
│       ├── util.h
│       └── verbose.h
├── nuget/
│   ├── build/
│   │   └── native/
│   │       ├── libcpr.props
│   │       └── libcpr.targets
│   └── libcpr.nuspec
├── package-build/
│   ├── build-package.sh
│   └── debian-libcpr/
│       ├── README.Debian
│       ├── changelog
│       ├── control
│       ├── copyright
│       ├── libcpr-dev.install
│       ├── libcpr1.install
│       ├── rules
│       └── source/
│           └── format
├── scripts/
│   ├── check_clang_format.sh
│   ├── delete_build_dir.sh
│   └── run_clang_format.sh
└── test/
    ├── CMakeLists.txt
    ├── LICENSE
    ├── abstractServer.cpp
    ├── abstractServer.hpp
    ├── alternating_tests.cpp
    ├── async_tests.cpp
    ├── callback_tests.cpp
    ├── connection_pool_tests.cpp
    ├── curlholder_tests.cpp
    ├── data/
    │   ├── certificates/
    │   │   ├── ca-bundle.crt
    │   │   ├── client.crt
    │   │   ├── root-ca.crt
    │   │   ├── server.crt
    │   │   └── sub-ca.crt
    │   ├── client.cnf
    │   ├── generate-certificates.sh
    │   ├── keys/
    │   │   ├── client.key
    │   │   ├── root-ca.key
    │   │   ├── server.key
    │   │   ├── server.pub
    │   │   └── sub-ca.key
    │   ├── root-ca.cnf
    │   ├── server.cnf
    │   ├── sub-ca.cnf
    │   ├── test_file.txt
    │   ├── test_file_hello_äüöp_2585.txt
    │   └── test_file_hello_äüöp_2585_你好.txt
    ├── delete_tests.cpp
    ├── download_tests.cpp
    ├── encoded_auth_tests.cpp
    ├── error_tests.cpp
    ├── file_upload_tests.cpp
    ├── get_tests.cpp
    ├── head_tests.cpp
    ├── httpServer.cpp
    ├── httpServer.hpp
    ├── httpsServer.cpp
    ├── httpsServer.hpp
    ├── interceptor_multi_tests.cpp
    ├── interceptor_tests.cpp
    ├── multiasync_tests.cpp
    ├── multiasync_tests.hpp
    ├── multiperform_tests.cpp
    ├── options_tests.cpp
    ├── patch_tests.cpp
    ├── post_tests.cpp
    ├── prepare_tests.cpp
    ├── proxy_auth_tests.cpp
    ├── proxy_tests.cpp
    ├── put_tests.cpp
    ├── raw_body_tests.cpp
    ├── resolve_tests.cpp
    ├── session_tests.cpp
    ├── singleton_tests.cpp
    ├── singleton_tests.hpp
    ├── sse_tests.cpp
    ├── ssl_tests.cpp
    ├── structures_tests.cpp
    ├── testUtils.cpp
    ├── testUtils.hpp
    ├── testUtils_tests.cpp
    ├── threadpool_tests.cpp
    ├── util_tests.cpp
    └── version_tests.cpp

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
---
Language:        Cpp
# BasedOnStyle:  Google
AccessModifierOffset: -2
AlignAfterOpenBracket: true
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
BinPackArguments: true
ColumnLimit: 500
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: None
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard:        Auto
IndentWidth:     4
TabWidth:        8
UseTab:          Never
BreakBeforeBraces: Attach
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles:  false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterCStyleCast: true
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 8
CommentPragmas:  '^ IWYU pragma:'
SpaceBeforeParens: ControlStatements
...


================================================
FILE: .clang-tidy
================================================
---
Checks: '*,
-cppcoreguidelines-pro-type-static-cast-downcast,
-fuchsia-default-arguments-calls,
-fuchsia-default-arguments,
-fuchsia-default-arguments-declarations,
-fuchsia-overloaded-operator,
-fuchsia-statically-constructed-objects,
-hicpp-use-auto,
-modernize-use-auto,
-modernize-use-trailing-return-type,
-readability-implicit-bool-conversion,
-readability-const-return-type,
-google-runtime-references,
-misc-non-private-member-variables-in-classes,
-llvm-include-order,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-pro-type-vararg,
-hicpp-vararg,
-cppcoreguidelines-owning-memory,
-llvmlibc-callee-namespace,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-hicpp-no-array-decay,
-modernize-pass-by-value,
-cppcoreguidelines-pro-bounds-constant-array-index,
-hicpp-signed-bitwise,
-llvmlibc-implementation-in-namespace,
-llvmlibc-restrict-system-libc-headers,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-altera-unroll-loops,
-altera-id-dependent-backward-branch,
-bugprone-easily-swappable-parameters,
-modernize-return-braced-init-list,
-abseil-string-find-str-contains,
-cppcoreguidelines-avoid-magic-numbers,
-readability-magic-numbers,
-cppcoreguidelines-avoid-do-while,
-llvmlibc-inline-function-decl,
-altera-struct-pack-align,
-boost-use-ranges,
-cppcoreguidelines-special-member-functions,
-hicpp-special-member-functions,
-misc-header-include-cycle,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-google-explicit-constructor,
-hicpp-explicit-conversions
'
WarningsAsErrors: '*'
HeaderFilterRegex: 'include\/cpr\/.*\.h(pp)?'
FormatStyle: file


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: "🐛 Bug report"
description: Something in cpr is not working as expected? Create a report to help us improve.
labels: ["Needs Investigation :mag:", "Bug :bug:"]
body:
- type: markdown
  attributes:
    value: |
      Provide a general summary of the issue in the Title above.
      Use Markdown to highlight and format your code!
      [https://guides.github.com/pdfs/markdown-cheatsheet-online.pdf](https://guides.github.com/pdfs/markdown-cheatsheet-online.pdf)
      [https://developers.google.com/blockly/guides/modify/contribute/write_a_good_issue](https://developers.google.com/blockly/guides/modify/contribute/write_a_good_issue)
      ⚠️⚠️ If you do not use this template, we will simply close your issue. There are no exceptions for this! These steps, especially the part at the end, are very important to solve your problem quickly and efficiently. Please remember that we are not paid to solve or even answer your issues, so we do all this work in OUR free time. ⚠️⚠️
- type: textarea
  attributes:
    label: Description
    description: A clear and concise description of what the bug is.
    placeholder: What happened? Also tell us, what did you expect to happen?
  validations:
      required: true
- type: textarea
  attributes:
    label: Example/How to Reproduce
    description: "Provide a link to a live example, or an unambiguous set of steps to reproduce this bug. Include code to reproduce, if relevant."
    value: |
      1. Create a `cpr::Session`
      2. Set option ...
      3. Perform the request
      4. See error
  validations:
    required: true
- type: textarea
  attributes:
    label: Possible Fix
    description: A possible fix for your issue.
    placeholder: Not obligatory, but suggest a fix or reason for the bug.
  validations:
    required: false
- type: dropdown
  attributes:
    label: Where did you get it from?
    multiple: true
    options:
      - GitHub (branch e.g. master)
      - vcpkg
      - conan
      - NuGet
      - Other (specify in "Additional Context/Your Environment")
  validations:
    required: true
- type: textarea
  attributes:
    label: Additional Context/Your Environment
    description: Provide some additional context for your issue and your environment your are trying to use cpr in.
    value: |
        - OS:
        - Version:
  validations:
    required: true


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.yml
================================================
name: "✨ Feature request"
description: Suggest an idea for this project.
labels: ["Needs Investigation :mag:", "Feature :sparkles:"]
body:
- type: markdown
  attributes:
    value: |
      Provide a general summary of the feature in the Title above.
      Use Markdown to highlight and format your code!
      [https://guides.github.com/pdfs/markdown-cheatsheet-online.pdf](https://guides.github.com/pdfs/markdown-cheatsheet-online.pdf)
      [https://developers.google.com/blockly/guides/modify/contribute/write_a_good_issue](https://developers.google.com/blockly/guides/modify/contribute/write_a_good_issue)
      ⚠️⚠️ If you do not use this template, we will simply close your feature request. There are no exceptions for this! These steps are very important to solve your problem quickly and efficiently. Please remember that we are not paid to solve or even answer your feature requests, so we do all this work in OUR free time. ⚠️⚠️
- type: markdown
  attributes:
    value: |
      Thanks for suggesting new features or pointing our missing functionality.  
      Please describe your request in detail so we can understand your ideas. Feel free to upload additional material such as mockups, diagrams, or sketches.
- type: textarea
  attributes:
    label: Is your feature request related to a problem?
    description: Please describe. A clear and concise description of what the problem is.
    placeholder: Ex. I'm always frustrated when ...
- type: textarea
  attributes:
    label: Possible Solution
    description: Describe the solution you'd like.
  validations:
      required: true
- type: textarea
  attributes:
    label: Alternatives
    description: A clear and concise description of any alternative solutions or features you've considered.
- type: textarea
  attributes:
    label: Additional Context
    description: Add any other context or screenshots about the feature request here.


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"


================================================
FILE: .github/workflows/build-deb.yml
================================================
name: Build Debian Package
on:
  push:
    tags: [ '[0-9]+.[0-9]+.[0-9]+' ]
  workflow_dispatch:
    inputs:
      version:
        description: 'The optional semantic version number. If not supplied the version from the main cpr CMake project will be used.'
        type: string

jobs:
  package-ubuntu-latest-amd64:
    runs-on: ubuntu-latest
    steps:
    - name: "Checkout"
      uses: actions/checkout@v6
      # Install packages necessary for building libcpr and package
    - name: "Update package list"
      run: sudo apt update
    - name: "Install cpr dependencies"
      run: sudo apt install -y libssl-dev libcurl4-openssl-dev libpsl-dev
    - name: "Install building tools"
      run: sudo apt install -y cmake debmake devscripts debhelper
      # Set version number
    - name: Set version based on input
      if: ${{ inputs.version }}
      run: echo "RELEASE_VERSION=${{ inputs.version }}" >> "$GITHUB_ENV"
    - name: Set version based on ref
      if: ${{ !inputs.version }}
      run: |
        mkdir -p build
        pushd build
        cmake .. -DCPR_BUILD_VERSION_OUTPUT_ONLY=ON -DCPR_USE_SYSTEM_LIB_PSL=ON -DCPR_USE_SYSTEM_CURL=ON
        echo "RELEASE_VERSION=$(cat version.txt)" >> $GITHUB_ENV
        popd
        rm -rf build
    - name: Print Version
      run: echo "deb version will be '${{ env.RELEASE_VERSION }}'"
      # Build package of runtime library
    - name: "Package build of runtime library"
      env: 
        VERSION: ${{ env.RELEASE_VERSION }}
      run: bash package-build/build-package.sh $(pwd)

    - name: "Upload deb-packages"
      uses: actions/upload-artifact@v6
      with:
        name: artifact-deb
        path: ./*.deb


================================================
FILE: .github/workflows/build-nuget.yml
================================================
name: Build NuGet Package
on:
  push:
    tags: [ '[0-9]+.[0-9]+.[0-9]+' ]
  workflow_dispatch:
    inputs:
      version:
        description: 'The optional semantic version number. If not supplied the branch/tag will be used.'
        type: string
      no_publish:
          description: 'Prevent publishing the NuGet package. Just build it and then upload it as an artifact.'
          type: boolean
          default: false

jobs:
  package-nuget:
    runs-on: windows-2022

    # Use PowerShell everywhere unless a step overrides it.
    defaults:
      run:
        shell: pwsh

    steps:
    # ────────────────────────────── Version handling ─────────────────────────────
    - name: Set version from manual input
      if: ${{ github.event_name == 'workflow_dispatch' && inputs.version != '' }}
      run: |
        "RELEASE_VERSION=${{ inputs.version }}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

    - name: Set version from Git ref
      if: ${{ env.RELEASE_VERSION == '' }}
      run: |
        $ref = "${{ github.ref }}".Split('/')[-1]
        "RELEASE_VERSION=$ref" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

    - name: Print version
      run: Write-Host "NuGet package version will be '$env:RELEASE_VERSION'."

    # ───────────────────────────── Repository & tools ────────────────────────────
    - uses: actions/checkout@v6

    - uses: actions/setup-python@v6
  
    - name: Install meson
      run: pip install meson

    # Prepare output folder paths
    - name: Prepare NuGet output layout
      shell: bash
      run: |
        set -eux
        mkdir -p "$GITHUB_WORKSPACE/nuget/build/native/{x86,x64}/{Debug,Release}"
        cp README.md "$GITHUB_WORKSPACE/nuget"

    # ─────────────────────────────── Build x86 ─────────────────────────────────
    - name: Enable MSVC x86 toolchain
      uses: ilammy/msvc-dev-cmd@v1
      with:
        arch: x86

    - name: Configure & build Release x86
      run: |
        cmake -S . -B build-release-x86  -G "Visual Studio 17 2022" -A Win32 -DCMAKE_INSTALL_PREFIX="$env:GITHUB_WORKSPACE/nuget/build/native/x86/Release" -DBUILD_SHARED_LIBS=ON -DCURL_ZLIB=OFF -DCMAKE_BUILD_TYPE=Release
        cmake --build build-release-x86 --config Release --target install

    - name: Configure & build Debug x86
      run: |
        cmake -S . -B build-debug-x86 -G "Visual Studio 17 2022" -A Win32 -DCMAKE_INSTALL_PREFIX="$env:GITHUB_WORKSPACE/nuget/build/native/x86/Debug" -DBUILD_SHARED_LIBS=ON -DCURL_ZLIB=OFF -DCMAKE_BUILD_TYPE=Debug
        cmake --build build-debug-x86 --config Debug --target install

    # ─────────────────────────────── Build x64 ─────────────────────────────────
    - name: Enable MSVC x64 toolchain
      uses: ilammy/msvc-dev-cmd@v1
      with:
        arch: x64

    - name: Configure & build Release x64
      run: |
        cmake -S . -B build-release-x64 -G "Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX="$env:GITHUB_WORKSPACE/nuget/build/native/x64/Release" -DBUILD_SHARED_LIBS=ON -DCURL_ZLIB=OFF -DCMAKE_BUILD_TYPE=Release
        cmake --build build-release-x64 --config Release --target install

    - name: Configure & build Debug x64
      run: |
        cmake -S . -B build-debug-x64 -G "Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX="$env:GITHUB_WORKSPACE/nuget/build/native/x64/Debug" -DBUILD_SHARED_LIBS=ON -DCURL_ZLIB=OFF -DCMAKE_BUILD_TYPE=Debug
        cmake --build build-debug-x64 --config Debug --target install

    # ────────────────────────── Pack, push, artefact ─────────────────────────────
    - name: Create NuGet package
      env:
        COMMIT_HASH: ${{ github.sha }}
      run: nuget pack "$env:GITHUB_WORKSPACE/nuget/libcpr.nuspec" -OutputDirectory "$env:GITHUB_WORKSPACE" -Properties "VERSION=$env:RELEASE_VERSION;COMMIT_HASH=$env:COMMIT_HASH"

    - name: Publish package to NuGet.org
      if: ${{ !inputs.no_publish }}
      env:
        NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
      run: nuget push "$env:GITHUB_WORKSPACE\*.nupkg" $env:NUGET_API_KEY -Source https://api.nuget.org/v3/index.json

    - name: Upload built .nupkg as workflow artefact
      uses: actions/upload-artifact@v6
      with:
        name: artifact-nuget
        path: '*.nupkg'


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull request. Yes, this will run stuff twice in case we create a PR from inside this repo. I'm open for better solutions, where I do not have to specify each brach individually for the 'push' trigger.

env:
  # Enable verbose output.
  # Repeat up to 5 times to deal with flaky tests.
  CTEST_OPTIONS: "--repeat until-pass:5 --output-on-failure"
  # The OpenSSL path for CI runs. Found via 'brew info openssl'.
  MACOS_OPENSSL_ROOT_DIR: "/opt/homebrew/Cellar/openssl@3/3.3.0"

jobs:
  ubuntu-clang-openssl:
    strategy:
      matrix:
        container: ["ubuntu:latest", "ubuntu:rolling"]
        systemCurl: [ON, OFF]
        buildType: [Debug, Release]
    runs-on: ubuntu-latest
    container: ${{ matrix.container }}
    steps:
    - name: Update package list
      run: apt update
    - name: Install Dependencies
      run: apt install -y git libssl-dev cmake build-essential clang libcurl4-openssl-dev libpsl-dev meson libunistring-dev
      env:
        DEBIAN_FRONTEND: noninteractive
    - name: Setup cmake
      uses: jwlawson/actions-setup-cmake@v2.1
      with:
        cmake-version: '3.22.x'
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_SYSTEM_CURL: ${{ matrix.systemCurl }}
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: clang
        cxx: clang++
        build-type: ${{ matrix.buildType }}
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  ubuntu-gcc-openssl:
    strategy:
      matrix:
        container: ["ubuntu:latest", "ubuntu:rolling"]
        systemCurl: [ON, OFF]
        buildType: [Debug, Release]
    runs-on: ubuntu-latest
    container: ${{ matrix.container }}
    steps:
    - name: Update package list
      run: apt update
    - name: Install Dependencies
      run: apt install -y git libssl-dev cmake build-essential libcurl4-openssl-dev libpsl-dev meson libunistring-dev
      env:
        DEBIAN_FRONTEND: noninteractive
    - name: Setup cmake
      uses: jwlawson/actions-setup-cmake@v2.1
      with:
        cmake-version: '3.22.x'
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_SYSTEM_CURL: ${{ matrix.systemCurl }}
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: gcc
        cxx: g++
        build-type: ${{ matrix.buildType }}
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  ubuntu-gcc-mbedtls:
    runs-on: ubuntu-latest
    steps:
    - name: Update package list
      run: sudo apt update
    - name: Install Dependencies
      run: sudo apt install -y git libssl-dev libmbedtls-dev cmake build-essential libpsl-dev meson libunistring-dev
      env:
        DEBIAN_FRONTEND: noninteractive
    - name: Setup cmake
      uses: jwlawson/actions-setup-cmake@v2.1
      with:
        cmake-version: '3.22.x'
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_MBEDTLS_BACKEND: ON
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: gcc
        cxx: g++
        build-type: Release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  fedora-clang-openssl:
    runs-on: ubuntu-latest
    container: "fedora:latest"
    steps:
    - name: Update package list
      run: dnf update -y
    - name: Install Dependencies
      run: dnf install -y gcc g++ clang git make openssl-devel libcurl-devel cmake libpsl-devel libunistring-devel meson
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_SYSTEM_CURL: OFF
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: clang
        cxx: clang++
        build-type: Release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  fedora-gcc-openssl:
    strategy:
      matrix:
        systemCurl: [ON, OFF]
        buildType: [Debug, Release]
    runs-on: ubuntu-latest
    container: "fedora:latest"
    steps:
    - name: Update package list
      run: dnf update -y
    - name: Install Dependencies
      run: dnf install -y gcc g++ clang git make openssl-devel libcurl-devel cmake libpsl-devel libunistring-devel meson
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_SYSTEM_CURL: ${{ matrix.systemCurl }}
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: gcc
        cxx: g++
        build-type: ${{ matrix.buildType }}
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  fedora-gcc-openssl-no-psl:
    runs-on: ubuntu-latest
    container: "fedora:latest"
    steps:
    - name: Update package list
      run: dnf update -y
    - name: Install Dependencies
      run: dnf install -y git gcc g++ make openssl-devel cmake libunistring-devel
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_SYSTEM_CURL: OFF
        CPR_CURL_USE_LIBPSL: OFF
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: gcc
        cxx: g++
        build-type: release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  fedora-gcc-ssl-sanitizer:
    strategy:
      matrix:
        buildType: [UdefSan, LeakSan, AddrSan] # ThreadSan is disabled for now until all problems are resolved: https://github.com/libcpr/cpr/issues/451
    runs-on: ubuntu-latest
    container: "fedora:latest" # Use fedora for an up to date version of all sanitizers
    steps:
    - name: Update package list
      run: dnf update -y
    - name: Install Dependencies
      run: dnf install -y gcc g++ clang git make openssl-devel libasan libubsan liblsan libtsan cmake libpsl-devel libunistring-devel meson
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: gcc
        cxx: g++
        build-type: ${{ matrix.buildType }}
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  windows-msvc-ssl:
    strategy:
      matrix:
        buildType: [Debug, Release]
    runs-on: windows-latest
    steps:
    - uses: actions/setup-python@v6
    - name: Install meson
      run: pip install meson
    - name: Setup MSVC environment
      uses: ilammy/msvc-dev-cmd@v1
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CMAKE_GENERATOR: "Visual Studio 17 2022"
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: OFF
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        build-type: ${{ matrix.buildType }}
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  windows-msvc-openssl:
    runs-on: windows-latest
    steps:
    - uses: actions/setup-python@v6
    - name: Install meson
      run: pip install meson
    - name: Setup MSVC environment
      uses: ilammy/msvc-dev-cmd@v1
    - name: Install OpenSSL
      run: choco install openssl -y
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CMAKE_GENERATOR: "Visual Studio 17 2022"
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        build-type: Release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}
  
  macos-clang-ssl:
    strategy:
      matrix:
        buildType: [Debug, Release]
    runs-on: macos-latest
    steps:
    - name: Install libpsl
      run: brew install libpsl
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: OFF
        CPR_USE_SYSTEM_LIB_PSL: ON
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: clang
        cxx: clang++
        build-type: ${{ matrix.buildType }}
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  macos-clang-darwinssl:
    runs-on: macos-latest
    steps:
    - name: Install libpsl
      run: brew install libpsl
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: OFF
        CPR_FORCE_DARWINSSL_BACKEND: ON
        CPR_USE_SYSTEM_LIB_PSL: ON
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: clang
        cxx: clang++
        build-type: Release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}

  macos-clang-openssl:
    runs-on: macos-latest
    steps:
    - name: Install OpenSSL
      run: brew install openssl
    - name: Install libpsl
      run: brew install libpsl
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_SYSTEM_LIB_PSL: ON
        OPENSSL_ROOT_DIR: "${{ env.MACOS_OPENSSL_ROOT_DIR }}"
        OPENSSL_LIBRARIES: "${{ env.MACOS_OPENSSL_ROOT_DIR }}/lib"
        LDFLAGS: "-L${{ env.MACOS_OPENSSL_ROOT_DIR }}/lib"
        CPPFLAGS: "-I${{ env.MACOS_OPENSSL_ROOT_DIR }}/include"
        PKG_CONFIG_PATH: "${{ env.MACOS_OPENSSL_ROOT_DIR }}/lib/pkgconfig"
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: clang
        cxx: clang++
        build-type: Release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}
  
  macos-clang-openssl-boost:
    runs-on: macos-latest
    steps:
    - name: Install Boost
      run: brew install boost
    - name: Install OpenSSL
      run: brew install openssl
    - name: Install libpsl
      run: brew install libpsl
    - name: Checkout
      uses: actions/checkout@v6
    - name: "Build & Test"
      env:
        CPR_BUILD_TESTS: ON
        CPR_BUILD_TESTS_SSL: ON
        CPR_FORCE_OPENSSL_BACKEND: ON
        CPR_USE_BOOST_FILESYSTEM: ON
        CPR_USE_SYSTEM_LIB_PSL: ON
        OPENSSL_ROOT_DIR: "${{ env.MACOS_OPENSSL_ROOT_DIR }}"
        OPENSSL_LIBRARIES: "${{ env.MACOS_OPENSSL_ROOT_DIR }}/lib"
        LDFLAGS: "-L${{ env.MACOS_OPENSSL_ROOT_DIR }}/lib"
        CPPFLAGS: "-I${{ env.MACOS_OPENSSL_ROOT_DIR }}/include"
        PKG_CONFIG_PATH: "${{ env.MACOS_OPENSSL_ROOT_DIR }}/lib/pkgconfig"
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{ github.workspace }}/build
        source-dir: ${{ github.workspace }}
        cc: clang
        cxx: clang++
        build-type: Release
        run-test: true
        ctest-options: ${{ env.CTEST_OPTIONS }}


================================================
FILE: .github/workflows/clang-format.yml
================================================
name: "Test Clang Format"

on: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull request. Yes, this will run stuff twice in case we create a PR from inside this repo. I'm open for better solutions, where I do not have to specify each brach individually for the 'push' trigger.

jobs:
  clang-format:
    runs-on: ubuntu-latest
    container: fedora:latest
    steps:
    - name: Update package list
      run: sudo dnf update -y
    - name: Install clang-format
      run: sudo dnf install -y clang-tools-extra
    - name: Checkout
      uses: actions/checkout@v6
    - name: Check format
      run: bash scripts/check_clang_format.sh

================================================
FILE: .github/workflows/clang-tidy.yml
================================================
name: "Test Clang Tidy"

on: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull request. Yes, this will run stuff twice in case we create a PR from inside this repo. I'm open for better solutions, where I do not have to specify each brach individually for the 'push' trigger.

jobs:
  clang-tidy:
    runs-on: ubuntu-latest
    container: fedora:latest
    steps:
    - name: Update package list
      run: sudo dnf update -y
    - name: Install dependencies
      run: sudo dnf install -y openssl-devel cmake git gcc clang ninja-build libpsl-devel meson
    - name: Install clang-tidy
      run: sudo dnf install -y clang-tools-extra
    - name: Checkout
      uses: actions/checkout@v6
    - name: "[Release g++] Build & Test"
      env:
        CPR_BUILD_TESTS: ON
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{github.workspace}}/build
        source-dir: ${{github.workspace}}
        cc: clang
        cxx: clang++
        build-type: Release
        run-test: false
        configure-options: -DCPR_ENABLE_LINTING=ON

================================================
FILE: .github/workflows/cppcheck.yml
================================================
name: "Test cppcheck"

on: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull request. Yes, this will run stuff twice in case we create a PR from inside this repo. I'm open for better solutions, where I do not have to specify each brach individually for the 'push' trigger.

jobs:
  cppcheck:
    runs-on: ubuntu-latest
    container: "fedora:latest" # Use fedora for an up to date version of cppcheck
    steps:
    - name: Checkout
      uses: actions/checkout@v6
    - name: Update package list
      run: dnf update -y
    - name: Install Dependencies
      run: dnf install -y gcc clang git gcc gdb make openssl-devel cmake libpsl-devel cppcheck meson
    - name: "[Release g++] Build"
      env:
        CPR_ENABLE_CPPCHECK: ON
        # Avoid parallel runs so only the resulting error file is not being written by multiple processes at the same time.
        CMAKE_BUILD_PARALLEL_LEVEL: 1
      uses: ashutoshvarma/action-cmake-build@master
      with:
        build-dir: ${{github.workspace}}/build
        source-dir: ${{github.workspace}}
        cc: gcc
        cxx: g++
        build-type: Release
        run-test: false

================================================
FILE: .github/workflows/readme-updater.yml
================================================
name: Update GIT_TAG In Readme
on:
  release:
    types: [published]

# Workflow configuration
env:
  OUTPUT_BRANCH: "master"
  COMMIT_MESSAGE: "Update GIT_TAG on new release"

jobs:
  update-git-tag:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
    - name: "Checkout"
      uses: actions/checkout@v6
      with:
        ref: ${{github.sha}}
    - name: "Replace GIT_TAG"
      run: sed -i -re 's/(GIT_TAG) [0-9a-f]+/\1 ${{github.sha}}/' README.md
    - name: "Commit changes"
      uses: stefanzweifel/git-auto-commit-action@v7
      with:
        commit_message: ${{env.COMMIT_MESSAGE}}
        branch: ${{env.OUTPUT_BRANCH}}


================================================
FILE: .gitignore
================================================
# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

# CMake
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake
install_manifest.txt

# Custom
build/
!nuget/build

# Jekyll stuff
_includes/
_site/

# Vim
.ycm_extra_conf.py*
*.swp

# VSCode
.vscode/*
!.vscode/tasks.json
.vs/
!.vs/tasks.json

# clangd
.cache/

# compilation database
# used in various editor configurations, such as vim & YcM
compile_commands.json

# macOS
.DS_Store

# CLion
.idea/


================================================
FILE: .vscode/tasks.json
================================================
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "🗑️ Delete build dir",
            "type": "shell",
            "command": "${workspaceFolder}/scripts/delete_build_dir.sh",
            "problemMatcher": [],
            "group": {
                "kind": "build"
            },
            "presentation": {
                "clear": true
            },
            "options": {
                "cwd": "${workspaceFolder}"
            }
        },
        {
            "label": "📝 Run clang-format",
            "type": "shell",
            "command": "${workspaceFolder}/scripts/run_clang_format.sh",
            "args": [
                "cpr",
                "include",
                "test"
            ],
            "problemMatcher": [],
            "group": {
                "kind": "build"
            },
            "presentation": {
                "clear": true
            },
            "options": {
                "cwd": "${workspaceFolder}"
            }
        },
        {
            "label": "📑 Check clang-format",
            "type": "shell",
            "command": "${workspaceFolder}/scripts/check_clang_format.sh",
            "args": [
                "cpr",
                "include",
                "test"
            ],
            "problemMatcher": [],
            "group": {
                "kind": "build"
            },
            "presentation": {
                "clear": true
            },
            "options": {
                "cwd": "${workspaceFolder}"
            }
        }
    ]
}

================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.18)
project(cpr VERSION 1.15.0 LANGUAGES CXX)

math(EXPR cpr_VERSION_NUM "${cpr_VERSION_MAJOR} * 0x10000 + ${cpr_VERSION_MINOR} * 0x100 + ${cpr_VERSION_PATCH}" OUTPUT_FORMAT HEXADECIMAL)
configure_file("${cpr_SOURCE_DIR}/cmake/cprver.h.in" "${cpr_BINARY_DIR}/cpr_generated_includes/cpr/cprver.h")

# Only change the folder behavior if cpr is not a subproject
if(${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
    set_property(GLOBAL PROPERTY USE_FOLDERS ON)
    set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake")
    set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
    set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
    set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # generate compile_commands.json to be used by other tools (e.g. vs code)
else()
    # Check required c++ standard of parent project
    if(CMAKE_CXX_STANDARD)
        set(PARENT_CXX_STANDARD ${CMAKE_CXX_STANDARD})
        message(STATUS "CXX standard of parent project: ${PARENT_CXX_STANDARD}")
    endif()
endif()

# Avoid the dll boilerplate code for windows
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

if (PARENT_CXX_STANDARD)
    # Don't set CMAKE_CXX_STANDARD if it is already set by parent project
    if (PARENT_CXX_STANDARD LESS 17)
        message(FATAL_ERROR "cpr ${cpr_VERSION} does not support ${PARENT_CXX_STANDARD}. Please use cpr <= 1.9.x")
    endif()
else()
    # Set standard version if not already set by potential parent project
    set(CMAKE_CXX_STANDARD 17)
endif()

message(STATUS "CXX standard: ${CMAKE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(CPR_LIBRARIES cpr CACHE INTERNAL "")

macro(cpr_option OPTION_NAME OPTION_TEXT OPTION_DEFAULT)
    option(${OPTION_NAME} ${OPTION_TEXT} ${OPTION_DEFAULT})
    if(DEFINED ENV{${OPTION_NAME}})
        # Allow overriding the option through an environment variable
        set(${OPTION_NAME} $ENV{${OPTION_NAME}})
    endif()
    if(${OPTION_NAME})
        add_definitions(-D${OPTION_NAME})
    endif()
    message(STATUS "  ${OPTION_NAME}: ${${OPTION_NAME}}")
endmacro()

message(STATUS "C++ Requests CMake Options")
message(STATUS "=======================================================")
cpr_option(CPR_GENERATE_COVERAGE "Set to ON to generate coverage reports." OFF)
cpr_option(CPR_CURL_NOSIGNAL "Set to ON to disable use of signals in libcurl." OFF)
cpr_option(CURL_VERBOSE_LOGGING "Curl verbose logging during building curl" OFF)
cpr_option(CPR_USE_SYSTEM_GTEST "If ON, this project will look in the system paths for an installed gtest library. If none is found it will use the built-in one." OFF)
cpr_option(CPR_USE_SYSTEM_CURL "If enabled we will use the curl lib already installed on this system." OFF)
cpr_option(CPR_USE_EXISTING_CURL_TARGET "Use an existing libcurl cmake target instead of having the cpr project source the dependency itself." OFF)
cpr_option(CPR_CURL_USE_LIBPSL "Since curl 8.13 curl depends on libpsl (https://everything.curl.dev/build/deps.html#libpsl). By default cpr keeps this as a secure default enabled wich in turn requires meson as build dependency. If set to OFF, psl support inside curl will be disabled." ON)
cpr_option(CPR_USE_SYSTEM_LIB_PSL "If enabled we will use the psl lib already installed on this system. Else meson is required as build dependency. Only relevant in case 'CPR_CURL_USE_LIBPSL' is set to ON." ${CPR_USE_SYSTEM_CURL})
cpr_option(CPR_ENABLE_CURL_HTTP_ONLY "If enabled we will only use the HTTP/HTTPS protocols from CURL. If disabled, all the CURL protocols are enabled. This is useful if your project uses libcurl and you need support for other CURL features e.g. sending emails." ON)
cpr_option(CPR_ENABLE_SSL "Enables or disables the SSL backend. Required to perform HTTPS requests." ON)
cpr_option(CPR_FORCE_OPENSSL_BACKEND "Force to use the OpenSSL backend. If CPR_FORCE_OPENSSL_BACKEND, CPR_FORCE_DARWINSSL_BACKEND, CPR_FORCE_MBEDTLS_BACKEND, and CPR_FORCE_WINSSL_BACKEND are set to to OFF, cpr will try to automatically detect the best available SSL backend (WinSSL - Windows, OpenSSL - Linux, DarwinSSL - Mac ...)." OFF)
cpr_option(CPR_FORCE_WINSSL_BACKEND "Force to use the WinSSL backend. If CPR_FORCE_OPENSSL_BACKEND, CPR_FORCE_DARWINSSL_BACKEND, CPR_FORCE_MBEDTLS_BACKEND, and CPR_FORCE_WINSSL_BACKEND are set to to OFF, cpr will try to automatically detect the best available SSL backend (WinSSL - Windows, OpenSSL - Linux, DarwinSSL - Mac ...)." OFF)
cpr_option(CPR_FORCE_DARWINSSL_BACKEND "Force to use the DarwinSSL backend. If CPR_FORCE_OPENSSL_BACKEND, CPR_FORCE_DARWINSSL_BACKEND, CPR_FORCE_MBEDTLS_BACKEND, and CPR_FORCE_WINSSL_BACKEND are set to to OFF, cpr will try to automatically detect the best available SSL backend (WinSSL - Windows, OpenSSL - Linux, DarwinSSL - Mac ...)." OFF)
cpr_option(CPR_FORCE_MBEDTLS_BACKEND "Force to use the Mbed TLS backend. If CPR_FORCE_OPENSSL_BACKEND, CPR_FORCE_DARWINSSL_BACKEND, CPR_FORCE_MBEDTLS_BACKEND, and CPR_FORCE_WINSSL_BACKEND are set to to OFF, cpr will try to automatically detect the best available SSL backend (WinSSL - Windows, OpenSSL - Linux, DarwinSSL - Mac ...)." OFF)
cpr_option(CPR_ENABLE_LINTING "Set to ON to enable clang linting." OFF)
cpr_option(CPR_ENABLE_CPPCHECK "Set to ON to enable Cppcheck static analysis. Requires CPR_BUILD_TESTS and CPR_BUILD_TESTS_SSL to be OFF to prevent checking google tests source code." OFF)
cpr_option(CPR_BUILD_TESTS "Set to ON to build cpr tests." OFF)
cpr_option(CPR_BUILD_TESTS_SSL "Set to ON to build cpr ssl tests" ${CPR_BUILD_TESTS})
cpr_option(CPR_BUILD_TESTS_PROXY "Set to ON to build proxy tests. They fail in case there is no valid proxy server available in proxy_tests.cpp" OFF)
cpr_option(CPR_BUILD_VERSION_OUTPUT_ONLY "Set to ON to only export the version into 'build/version.txt' and exit" OFF)
cpr_option(CPR_SKIP_CA_BUNDLE_SEARCH "Skip searching for Certificate Authority certs. Turn ON for systems like iOS where file access is restricted and prevents https from working." OFF)
cpr_option(CPR_USE_BOOST_FILESYSTEM "Set to ON to use the Boost.Filesystem library. This is useful, on, e.g., Apple platforms, where std::filesystem may not always be available when targeting older OS versions." OFF)
cpr_option(CPR_DEBUG_SANITIZER_FLAG_THREAD "Enables the ThreadSanitizer for debug builds." OFF)
cpr_option(CPR_DEBUG_SANITIZER_FLAG_ADDR "Enables the AddressSanitizer for debug builds." OFF)
cpr_option(CPR_DEBUG_SANITIZER_FLAG_LEAK "Enables the LeakSanitizer for debug builds." OFF)
cpr_option(CPR_DEBUG_SANITIZER_FLAG_UB "Enables the UndefinedBehaviorSanitizer for debug builds." OFF)
cpr_option(CPR_DEBUG_SANITIZER_FLAG_ALL "Enables all sanitizers for debug builds except the ThreadSanitizer since it is incompatible with the other sanitizers." OFF)
message(STATUS "=======================================================")

if (MSVC)
    if (BUILD_SHARED_LIBS)
        message(STATUS "Build windows dynamic libs.")
    else()
        # Add this to build windows pure static library.
        message(STATUS "Build windows static libs.")
    endif()
endif()

# Save the project version as txt file for deb and NuGet builds
if(CPR_BUILD_VERSION_OUTPUT_ONLY)
    message(STATUS "Printing version and exiting...")
    file(WRITE "${CMAKE_BINARY_DIR}/version.txt" "${PROJECT_VERSION}")
    return()
endif()

if (CPR_FORCE_USE_SYSTEM_CURL)
    message(WARNING "The variable CPR_FORCE_USE_SYSTEM_CURL is deprecated, please use CPR_USE_SYSTEM_CURL instead")
    set(CPR_USE_SYSTEM_CURL ${CPR_FORCE_USE_SYSTEM_CURL})
endif()

include(GNUInstallDirs)
include(FetchContent)
include(cmake/code_coverage.cmake)
include(cmake/sanitizer.cmake)
include(cmake/clear_variable.cmake)

# So CMake can find FindMbedTLS.cmake
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")

# Linting
if(CPR_ENABLE_LINTING)
    include(cmake/clang-tidy.cmake)
endif()

# Cppcheck
if(CPR_ENABLE_CPPCHECK)
    if(CPR_BUILD_TESTS OR CPR_BUILD_TESTS_SSL)
        message(FATAL_ERROR "Cppcheck is incompatible with building tests. Make sure to disable CPR_ENABLE_CPPCHECK or disable tests by setting CPR_BUILD_TESTS and CPR_BUILD_TESTS_SSL to OFF. This is because Cppcheck would try to check the google tests source code and then fail. ")
    endif()
    include(cmake/cppcheck.cmake)
endif()

# SSL
if(CPR_ENABLE_SSL)
    if(CPR_FORCE_OPENSSL_BACKEND OR CPR_FORCE_WINSSL_BACKEND OR CPR_FORCE_DARWINSSL_BACKEND OR CPR_FORCE_MBEDTLS_BACKEND)
        message(STATUS "Disabled SSL backend auto detect since either CPR_FORCE_OPENSSL_BACKEND, CPR_FORCE_DARWINSSL_BACKEND, CPR_FORCE_MBEDTLS_BACKEND, or CPR_FORCE_WINSSL_BACKEND is enabled.")
        set(DETECT_SSL_BACKEND OFF CACHE INTERNAL "" FORCE)
    else()
        message(STATUS "Automatically detecting SSL backend.")
        set(DETECT_SSL_BACKEND ON CACHE INTERNAL "" FORCE)
    endif()

    if(CPR_FORCE_WINSSL_BACKEND AND (NOT WIN32))
        message(FATAL_ERROR "WinSSL is only available on Windows! Use either OpenSSL (CPR_FORCE_OPENSSL_BACKEND) or DarwinSSL (CPR_FORCE_DARWINSSL_BACKEND) instead.")
    endif()

    if(DETECT_SSL_BACKEND)
        message(STATUS "Detecting SSL backend...")
        if(WIN32)
            message(STATUS "SSL auto detect: Using WinSSL.")
            set(SSL_BACKEND_USED "WinSSL")
        elseif(APPLE)
            message(STATUS "SSL auto detect: Using DarwinSSL.")
            set(CPR_BUILD_TESTS_SSL OFF)
            set(SSL_BACKEND_USED "DarwinSSL")
        else()
            find_package(OpenSSL)
            if(OPENSSL_FOUND)
                message(STATUS "SSL auto detect: Using OpenSSL.")
                set(SSL_BACKEND_USED "OpenSSL")
            else()
                find_package(MbedTLS)
                if(MBEDTLS_FOUND)
                    set(SSL_BACKEND_USED "MbedTLS")
                else()
                    message(FATAL_ERROR "No valid SSL backend found! Please install OpenSSL, Mbed TLS or disable SSL by setting CPR_ENABLE_SSL to OFF.")
                endif()
            endif()
        endif()
    else()
        if(CPR_FORCE_OPENSSL_BACKEND)
            find_package(OpenSSL)
            if(OPENSSL_FOUND)
                message(STATUS "Using OpenSSL.")
                set(SSL_BACKEND_USED "OpenSSL")
            else()
                message(FATAL_ERROR "CPR_FORCE_OPENSSL_BACKEND enabled but we were not able to find OpenSSL!")
            endif()
        elseif(CPR_FORCE_WINSSL_BACKEND)
            message(STATUS "Using WinSSL.")
            set(SSL_BACKEND_USED "WinSSL")
        elseif(CPR_FORCE_DARWINSSL_BACKEND)
            message(STATUS "Using DarwinSSL.")
            set(CPR_BUILD_TESTS_SSL OFF)
            set(SSL_BACKEND_USED "DarwinSSL")
        elseif(CPR_FORCE_MBEDTLS_BACKEND)
            message(STATUS "Using Mbed TLS.")
            set(CPR_BUILD_TESTS_SSL OFF)
            set(SSL_BACKEND_USED "MbedTLS")
        endif()
    endif()
endif()

if(SSL_BACKEND_USED STREQUAL "OpenSSL")
# Fix missing OpenSSL includes for Windows since in 'ssl_ctx.cpp' we include OpenSSL directly
find_package(OpenSSL REQUIRED)
    add_compile_definitions(OPENSSL_BACKEND_USED)
endif()

# Curl configuration
if(CPR_USE_EXISTING_CURL_TARGET)
    message(STATUS "cpr skipping management of curl dependency (CPR_USE_EXISTING_CURL_TARGET is set to ON).")
elseif(CPR_USE_SYSTEM_CURL)
    if(CPR_ENABLE_SSL)
        find_package(CURL COMPONENTS HTTP HTTPS)
        if(CURL_FOUND)
            message(STATUS "Curl ${CURL_VERSION_STRING} found on this system.")

            # To be able to load certificates under Windows when using OpenSSL:
            if(CMAKE_USE_OPENSSL AND WIN32 AND (NOT (CURL_VERSION_STRING VERSION_GREATER_EQUAL "7.71.0")))
                message(FATAL_ERROR "Your system curl version (${CURL_VERSION_STRING}) is too old to support OpenSSL on Windows which requires curl >= 7.71.0. Update your curl version, use WinSSL, disable SSL or use the built-in version of curl.")
            endif()
        else()
            find_package(CURL COMPONENTS HTTP)
            if(CURL_FOUND)
                message(FATAL_ERROR "Curl found on this system but WITHOUT HTTPS/SSL support. Either disable SSL by setting CPR_ENABLE_SSL to OFF or use the built-in version of curl by setting CPR_USE_SYSTEM_CURL to OFF.")
            else()
                message(FATAL_ERROR "Curl not found on this system. To use the built-in version set CPR_USE_SYSTEM_CURL to OFF.")
            endif()
        endif()
    else()
        find_package(CURL COMPONENTS HTTP)
        if(CURL_FOUND)
            message(STATUS "Curl found on this system.")
        else()
            message(FATAL_ERROR "Curl not found on this system. To use the built-in version set CPR_USE_SYSTEM_CURL to OFF.")
        endif()
    endif()

    # Check for the minimum supported curl version 
    if(NOT (CURL_VERSION_STRING VERSION_GREATER_EQUAL "7.64.0"))
        message(FATAL_ERROR "Your system curl version (${CURL_VERSION_STRING}) is too old! curl >= 7.64.0 is required. Update your curl version, or use the build in curl version e.g. via `cmake .. -DCPR_USE_SYSTEM_CURL=OFF` during CMake configure.")
    endif()
else()
    message(STATUS "Configuring built-in curl...")

    # ZLIB is optional for curl
    # to disable it:
    # * from command line:
    #     -DCURL_ZLIB=OFF
    # * from CMake script:
    if (CURL_ZLIB OR CURL_ZLIB STREQUAL AUTO OR NOT DEFINED CACHE{CURL_ZLIB})
        include(cmake/zlib_external.cmake)
    endif()

    if (CPR_ENABLE_CURL_HTTP_ONLY)
        # We only need HTTP (and HTTPS) support:
        set(HTTP_ONLY ON CACHE INTERNAL "" FORCE)
    endif()
    set(BUILD_CURL_EXE OFF CACHE INTERNAL "" FORCE)
    set(BUILD_TESTING OFF)

    if (CURL_VERBOSE_LOGGING)
        message(STATUS "Enabled curl debug features")
        set(ENABLE_DEBUG ON CACHE INTERNAL "" FORCE)
    endif()

    if (CPR_ENABLE_SSL)
        set(CURL_ENABLE_SSL ON CACHE INTERNAL "" FORCE)
        if(ANDROID)
            set(CURL_CA_PATH "/system/etc/security/cacerts" CACHE INTERNAL "")
        elseif(CPR_SKIP_CA_BUNDLE_SEARCH)
            set(CURL_CA_PATH "none" CACHE INTERNAL "")
        else()
            set(CURL_CA_PATH "auto" CACHE INTERNAL "")
        endif()

        if(CPR_SKIP_CA_BUNDLE_SEARCH)
            set(CURL_CA_BUNDLE "none" CACHE INTERNAL "")
        elseif(NOT DEFINED CURL_CA_BUNDLE)
            set(CURL_CA_BUNDLE "auto" CACHE INTERNAL "")
        endif()

        if(SSL_BACKEND_USED STREQUAL "WinSSL")
            set(CURL_USE_SCHANNEL ON CACHE INTERNAL "" FORCE)
            set(CURL_WINDOWS_SSPI ON CACHE INTERNAL "" FORCE)
        endif()

        if(SSL_BACKEND_USED STREQUAL "OpenSSL")
            set(CURL_USE_OPENSSL ON CACHE INTERNAL "" FORCE)
        endif()

        if(SSL_BACKEND_USED STREQUAL "DarwinSSL")
            set(CURL_USE_SECTRANSP ON CACHE INTERNAL "" FORCE)
        endif()

        if(SSL_BACKEND_USED STREQUAL "MbedTLS")
            set(CURL_USE_MBEDTLS ON CACHE INTERNAL "" FORCE)
        endif()

        message(STATUS "Enabled curl SSL")
    else()
        set(CURL_ENABLE_SSL OFF CACHE INTERNAL "" FORCE)

        set(CURL_CA_PATH "none" CACHE INTERNAL "" FORCE)
        set(CURL_USE_SCHANNEL OFF CACHE INTERNAL "" FORCE)
        set(CURL_WINDOWS_SSPI OFF CACHE INTERNAL "" FORCE)
        set(CURL_USE_OPENSSL OFF CACHE INTERNAL "" FORCE)
        set(CURL_USE_SECTRANSP OFF CACHE INTERNAL "" FORCE)
        set(CURL_USE_MBEDTLS OFF CACHE INTERNAL "" FORCE)
        message(STATUS "Disabled curl SSL")
    endif()
    # Disable linting for curl
    clear_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)

    if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
        cmake_policy(SET CMP0135 NEW)
    endif()

    # Since curl 8.13, curl depends on lib psl
    set(CURL_USE_LIBPSL ${CPR_CURL_USE_LIBPSL} CACHE INTERNAL "" FORCE)
    if(CPR_CURL_USE_LIBPSL AND NOT CPR_USE_SYSTEM_LIB_PSL)
        include(libpsl)
    endif()

    FetchContent_Declare(curl URL https://github.com/curl/curl/releases/download/curl-8_13_0/curl-8.13.0.tar.xz
                              URL_HASH SHA256=4a093979a3c2d02de2fbc00549a32771007f2e78032c6faa5ecd2f7a9e152025) # the file hash for curl-8.13.0.tar.xz
    FetchContent_MakeAvailable(curl)

    restore_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)
endif()

# Depending on which version of libcurl we are using the CMake target is called differently
if(TARGET libcurl)
    # Old curl CMake target name
    set(CURL_LIB libcurl)
else()
    # New curl CMake target name
    set(CURL_LIB CURL::libcurl)
endif()

# GTest configuration
if(CPR_BUILD_TESTS)
    if(CPR_USE_SYSTEM_GTEST)
        find_package(GTest)
    endif()
    if(NOT CPR_USE_SYSTEM_GTEST OR NOT GTEST_FOUND)
        message(STATUS "Not using system gtest, using built-in googletest project instead.")
        if(MSVC)
            # By default, GTest compiles on Windows in CRT static linkage mode. We use this
            # variable to force it into using the CRT in dynamic linkage (DLL), just as CPR
            # does.
            set(gtest_force_shared_crt ON CACHE BOOL "Force gtest to use the shared c runtime")
        endif()

        # Disable linting for google test
        clear_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)

        FetchContent_Declare(googletest
                             URL                    https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
                             URL_HASH               SHA256=8ad598c73ad796e0d8280b082cebd82a630d73e73cd3c70057938a6501bba5d7 # the file hash for release-1.14.0.tar.gz
                             USES_TERMINAL_DOWNLOAD TRUE)   # <---- This is needed only for Ninja to show download progress
        FetchContent_MakeAvailable(googletest)

        restore_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)
        
        add_library(gtest_int INTERFACE)
        target_link_libraries(gtest_int INTERFACE gtest)
        target_include_directories(gtest_int INTERFACE ${googletest_SOURCE_DIR}/include)

        add_library(GTest::GTest ALIAS gtest_int)
       
        # Group under the "tests/gtest" project folder in IDEs such as Visual Studio.
    set_property(TARGET gtest PROPERTY FOLDER "tests/gtest")
    set_property(TARGET gtest_main PROPERTY FOLDER "tests/gtest")
    endif()
endif()


# Mongoose configuration
if(CPR_BUILD_TESTS)
    message(STATUS "Building mongoose project for test support.")

    if(CPR_BUILD_TESTS_SSL)
        if(NOT CPR_ENABLE_SSL)
            message(FATAL_ERROR "OpenSSL is required to build SSL test but CPR_ENABLE_SSL is disabled. Either set CPR_ENABLE_SSL to ON or disable CPR_BUILD_TESTS_SSL.")
        endif()

        if(NOT(SSL_BACKEND_USED STREQUAL "OpenSSL"))
            message(FATAL_ERROR "OpenSSL is required for SSL test, but it seams like OpenSSL is not being used as SSL backend. Either set CPR_BUILD_TESTS_SSL to OFF or set CPR_FORCE_OPENSSL_BACKEND to ON and try again.")
        endif()

        set(ENABLE_SSL_TESTS ON CACHE INTERNAL "")
    else()
        set(ENABLE_SSL_TESTS OFF CACHE INTERNAL "")
    endif()

    # Disable linting for mongoose
    clear_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)

    FetchContent_Declare(mongoose 
                         URL                    https://github.com/cesanta/mongoose/archive/7.7.tar.gz
                         URL_HASH               SHA256=4e5733dae31c3a81156af63ca9aa3a6b9b736547f21f23c3ab2f8e3f1ecc16c0 # the hash for 7.7.tar.gz
                         USES_TERMINAL_DOWNLOAD TRUE # This is needed only for Ninja to show download progress
                         SOURCE_SUBDIR          "?") # Nonexistent directory to prevent FetchContent_MakeAvailable from calling add_subdirectory and duplicating the mongoose target
    if (NOT mongoose_POPULATED)
        FetchContent_MakeAvailable(mongoose)

        file(INSTALL cmake/mongoose.CMakeLists.txt DESTINATION ${mongoose_SOURCE_DIR})
        file(RENAME ${mongoose_SOURCE_DIR}/mongoose.CMakeLists.txt ${mongoose_SOURCE_DIR}/CMakeLists.txt)
        add_subdirectory(${mongoose_SOURCE_DIR} ${mongoose_BINARY_DIR})

    endif()
    # Group under the "external" project folder in IDEs such as Visual Studio.
    set_property(TARGET mongoose PROPERTY FOLDER "external")
    restore_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)
endif()

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Werror")
    if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        # Disable C++98 compatibility support in clang: https://github.com/libcpr/cpr/issues/927
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-nonportable-system-include-path -Wno-exit-time-destructors -Wno-undef -Wno-global-constructors -Wno-switch-enum -Wno-old-style-cast -Wno-covered-switch-default -Wno-undefined-func-template")
    endif()
endif()

add_subdirectory(cpr)
add_subdirectory(include)

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND CPR_BUILD_TESTS)
    # Disable linting for tests since they are currently not up to the standard
    clear_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)
    enable_testing()
    add_subdirectory(test)
    restore_variable(DESTINATION CMAKE_CXX_CLANG_TIDY BACKUP CMAKE_CXX_CLANG_TIDY_BKP)
endif()


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
cc@libcpr.org.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to C++ Requests

Please fork this repository and contribute back using [pull requests](https://github.com/libcpr/cpr/pulls). Features can be requested using [issues](https://github.com/libcpr/cpr/issues). All code, comments, and critiques are greatly appreciated.

## Formatting

To avoid unproductive debates on formatting, this project uses `clang-format` to ensure a consistent style across all source files. Currently, `clang-format` 3.8 is the version of `clang-format` we use. The format file can be found [here](https://github.com/libcpr/cpr/blob/master/.clang-format). To install `clang-format` on Ubuntu, run this:

```
apt-get install clang-format-3.8
```

To install `clang-format` on OS X, run this:

```
brew install clang-format
```

Note that `brew` might install a later version of `clang-format`, but it should be mostly compatible with what's run on the Travis servers.

To run `clang-format` on every source file, run this in the root directory:

```
./scripts/run_clang_format.sh cpr include/cpr
```

This should indicate which files need formatting and also show a diff of the requested changes. More specific usage instructions can be found on the official [LLVM website](http://releases.llvm.org/3.8.0/tools/clang/docs/ClangFormat.html).


================================================
FILE: LICENSE
================================================
This license applies to everything except the contents of the "test"
directory and its subdirectories.

MIT License

Copyright (c) 2017-2021 Huu Nguyen
Copyright (c) 2022 libcpr and many other contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
# C++ Requests: Curl for People <img align="right" height="40" src="http://i.imgur.com/d9Xtyts.png">

[![Documentation](https://img.shields.io/badge/docs-online-informational?style=flat&link=https://docs.libcpr.dev/)](https://docs.libcpr.dev/)
![CI](https://github.com/libcpr/cpr/workflows/CI/badge.svg)
[![Gitter](https://badges.gitter.im/libcpr/community.svg)](https://gitter.im/libcpr/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)

## Announcements

* This project is being maintained by [Fabian Sauter](https://github.com/com8) and [Kilian Traub](https://github.com/KingKili).
* For quick help, and discussion libcpr also offers a [gitter](https://gitter.im/libcpr/community?utm_source=share-link&utm_medium=link&utm_campaign=share-link) chat.

## Supported Releases
| Release                   | Min. C++ Standard | Status                   | Notes |
|---------------------------|-------------------|--------------------------|-------|
| master                    | `cpp17`           | ![alt text][preview]     |       |
| 1.14.x                    | `cpp17`           | ![alt text][supported]   |       |
| 1.10.x - 1.13.x           | `cpp17`           | ![alt text][unsupported] |       |
| <= 1.9.x                  | `cpp11`           | ![alt text][unsupported] |       |

[unsupported]: https://img.shields.io/badge/-unsupported-red "unsupported"
[supported]: https://img.shields.io/badge/-supported-green "supported"
[preview]: https://img.shields.io/badge/-preview-orange "preview"

## TLDR

C++ Requests is a simple wrapper around [libcurl](http://curl.haxx.se/libcurl) inspired by the excellent [Python Requests](https://github.com/kennethreitz/requests) project.

Despite its name, libcurl's easy interface is far from simple, and errors and frustration often arise from mistakes or misuse. By leveraging the more expressive features of `C++17` (or `C++11` if using cpr <`= 1.9.x), this library distills the process of making network calls into a few clear and concise idioms.

Here's a quick GET request:

```c++
#include <cpr/cpr.h>

int main(int argc, char** argv) {
    cpr::Response r = cpr::Get(cpr::Url{"https://api.github.com/repos/whoshuu/cpr/contributors"},
                      cpr::Authentication{"user", "pass", cpr::AuthMode::BASIC},
                      cpr::Parameters{{"anon", "true"}, {"key", "value"}});
    r.status_code;                  // 200
    r.header["content-type"];       // application/json; charset=utf-8
    r.text;                         // JSON text string
    return 0;
}
```

And here's [less functional, more complicated code, without cpr](https://gist.github.com/whoshuu/2dc858b8730079602044).

## Documentation

[![Documentation](https://img.shields.io/badge/docs-online-informational?style=for-the-badge&link=https://docs.libcpr.dev/)](https://docs.libcpr.dev/)
You can find the latest documentation [here](https://docs.libcpr.dev/). It's a work in progress, but it should give you a better idea of how to use the library than the [tests](https://github.com/libcpr/cpr/tree/master/test) currently do.

## Features

C++ Requests currently supports:

* Custom headers
* URL-encoded parameters
* URL-encoded POST values
* Multipart form POST upload
* File POST upload
* Basic authentication
* Bearer authentication
* Digest authentication
* NTLM authentication
* Connection and request timeout specification
* Timeout for low speed connection
* Asynchronous requests
* :cookie: support!
* Proxy support
* Callback interfaces
* PUT methods
* DELETE methods
* HEAD methods
* OPTIONS methods
* PATCH methods
* Thread Safe access to [libCurl](https://curl.haxx.se/libcurl/c/threadsafe.html)
* OpenSSL and WinSSL support for HTTPS requests
* Server Sent Events (SSE) handling

## Planned

For a quick overview about the planned features, have a look at the next [Milestones](https://github.com/libcpr/cpr/milestones).

## Usage

### CMake

#### fetch_content:
If you already have a CMake project you need to integrate C++ Requests with, the primary way is to use `fetch_content`.
Add the following to your `CMakeLists.txt`.


```cmake
include(FetchContent)
FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git
                         GIT_TAG f091b2c061b307ee89b164c39976fc9202a1c79d.12.0) # Replace with your desired git commit from: https://github.com/libcpr/cpr/releases
FetchContent_MakeAvailable(cpr)
```

This will produce the target `cpr::cpr` which you can link against the typical way:

```cmake
target_link_libraries(your_target_name PRIVATE cpr::cpr)
```

That should do it!
There's no need to handle `libcurl` yourself. All dependencies are taken care of for you.
All of this can be found in an example [**here**](https://github.com/libcpr/example-cmake-fetch-content).

#### find_package():
If you prefer not to use `fetch_content`, you can download, build, and install the library and then use CMake `find_package()` function to integrate it into a project.

**Note:** this feature is feasible only if CPR_USE_SYSTEM_CURL is set. (see [#645](https://github.com/libcpr/cpr/pull/645))
```Bash
git clone https://github.com/libcpr/cpr.git
cd cpr && mkdir build && cd build
cmake .. -DCPR_USE_SYSTEM_CURL=ON
cmake --build . --parallel
sudo cmake --install .
```
#### Build Static Library
As an alternative if you want to switch between a static or shared version of cpr use ['-DBUILD_SHARED_LIBS=ON/OFF'](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html).
```Bash
git clone https://github.com/libcpr/cpr.git
cd cpr && mkdir build && cd build
cmake .. -DCPR_USE_SYSTEM_CURL=ON -DBUILD_SHARED_LIBS=OFF
cmake --build . --parallel
sudo cmake --install .
```

In your `CMakeLists.txt`:
```cmake
find_package(cpr REQUIRED)
add_executable(your_target_name your_target_name.cpp)
target_link_libraries(your_target_name PRIVATE cpr::cpr)
```

#### Tests
`cpr` provides a bunch of tests that can be executed via the following commands.
```Bash
git clone https://github.com/libcpr/cpr.git
cd cpr && mkdir build && cd build
cmake .. -DCPR_BUILD_TESTS=ON # There are other test related options like 'CPR_BUILD_TESTS_SSL' and 'CPR_BUILD_TESTS_PROXY'
cmake --build . --parallel
ctest -VV # -VV is optional since it enables verbose output
```

### Bazel
`cpr` can be added as an extension by adding the following lines to your bazel MODULE file (tested with Bazel 8). Edit the versions as needed.
```starlark
bazel_dep(name = "curl", version = "8.8.0.bcr.3")
git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
    name = "cpr",
    build_file = "//path/to/build:cpr.BUILD",
    commit = "516cb3e5f4e38bede088f69fcf122c6089e38f00",
    remote = "https://github.com/libcpr/cpr.git",
    patches = ["//path/to/patch:cpr.PATCH"]
)
```

```starlark
// cpr.BUILD
cc_library(
    name = "cpr",
    hdrs = glob(["include/**/*.h"]),
    includes = ["include"],
    visibility = ["//visibility:public"],

    srcs = glob(["cpr/**/*.cpp"]),
    deps = [
        "@curl//:curl"
    ],
)
```

```starlark
// Remove this line: cpr.PATCH
--- include/cpr/cpr.h
+++ include/cpr/cpr.h
@@ -10,7 +10,6 @@
 #include "cpr/connection_pool.h"
 #include "cpr/cookies.h"
 #include "cpr/cprtypes.h"
-#include "cpr/cprver.h"
 #include "cpr/curl_container.h"
 #include "cpr/curlholder.h"
 #include "cpr/error.h"
```

### Packages for Linux Distributions

Alternatively, you may install a package specific to your Linux distribution. Since so few distributions currently have a package for cpr, most users will not be able to run your program with this approach.

Currently, we are aware of packages for the following distributions:

* [Arch Linux (AUR)](https://aur.archlinux.org/packages/cpr)
* [Fedora Linux](https://src.fedoraproject.org/rpms/cpr)

If there's no package for your distribution, try making one! If you do, and it is added to your distribution's repositories, please submit a pull request to add it to the list above. However, please only do this if you plan to actively maintain the package.

### NuGet Package

For Windows, there is also a libcpr NuGet package available. Currently, x86 and x64 builds are supported with release and debug configuration.

The package can be found here: [NuGet.org](https://www.nuget.org/packages/libcpr/)

### Port for macOS

On macOS you may install cpr via [MacPorts.org](https://ports.macports.org/port/cpr) (arm64, x86_64, powerpc)

### FreeBSD Port

On FreeBSD, you can issue `pkg install cpr` or use the Ports tree to install it.

## Requirements

The only explicit requirements are:

* A `C++17` compatible compiler such as Clang or GCC. The minimum required version of GCC is unknown, so if anyone has trouble building this library with a specific version of GCC, do let us know.
* In case you only have a `C++11` compatible compiler available, all versions below cpr 1.9.x are for you. The 1.10.0 release of cpr switches to `C++17` as a requirement.
* If you would like to perform https requests `OpenSSL` and its development libraries are required.
* If you do not use the built-in version of [curl](https://github.com/curl/curl) but instead use your systems version, make sure you use a version `>= 7.71.0`. Lower versions are not supported. This means you need Debian `>= 11` or Ubuntu `>= 22.04 LTS`.
* [`The Meson Build System`](https://mesonbuild.com/) is required build PSL from source ([PSL support for curl](https://everything.curl.dev/build/deps.html#libpsl)). For more information take a look at the `CPR_CURL_USE_LIBPSL` and `CPR_USE_SYSTEM_LIB_PSL` CMake options.

## Building cpr - Using vcpkg

You can download and install cpr using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
```Bash
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install cpr
```
The `cpr` port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.

## Building cpr - Using Conan

You can download and install `cpr` using the [Conan](https://conan.io/) package manager. Setup your CMakeLists.txt (see [Conan documentation](https://docs.conan.io/en/latest/integrations/build_system.html) on how to use MSBuild, Meson and others).
An example can be found [**here**](https://github.com/libcpr/example-cmake-conan).

The `cpr` package in Conan is kept up to date by Conan contributors. If the version is out of date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the `conan-center-index` repository.


================================================
FILE: cmake/FindMbedTLS.cmake
================================================
# Source: https://github.com/curl/curl/blob/curl-7_82_0/CMake/FindMbedTLS.cmake
find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)

find_library(MBEDTLS_LIBRARY mbedtls)
find_library(MBEDX509_LIBRARY mbedx509)
find_library(MBEDCRYPTO_LIBRARY mbedcrypto)

set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}")

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MbedTLS DEFAULT_MSG
    MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)

mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)


================================================
FILE: cmake/clang-tidy.cmake
================================================
# Include this file if and only if you want to use clang-tidy linter.

if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
    if (NOT ${CPR_LINTER_PATH} STREQUAL "")
        get_filename_component(CLANG_TIDY_HINT_FILENAME ${CPR_LINTER_PATH} NAME)
        get_filename_component(CLANG_TIDY_HINT_PATH ${CPR_LINTER_PATH} DIRECTORY)
    endif ()

    find_program(CLANG_TIDY_EXECUTABLE NAMES clang-tidy ${CLANG_TIDY_HINT_FILENAME} HINTS ${CLANG_TIDY_HINT_PATH} REQUIRED)
    mark_as_advanced(CLANG_TIDY_EXECUTABLE)

    message(STATUS "Enabling clang-tidy: ${CLANG_TIDY_EXECUTABLE}")
    set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE};-warnings-as-errors=*")
else ()
    message(FATAL_ERROR "Clang-tidy is not supported when building for windows")
endif ()


================================================
FILE: cmake/clear_variable.cmake
================================================
macro(clear_variable)
    cmake_parse_arguments(CLEAR_VAR "" "DESTINATION;BACKUP;REPLACE" "" ${ARGN})
    set(${CLEAR_VAR_BACKUP} ${${CLEAR_VAR_DESTINATION}})
    set(${CLEAR_VAR_DESTINATION} ${CLEAR_VAR_REPLACE})
endmacro()

macro(restore_variable)
    cmake_parse_arguments(CLEAR_VAR "" "DESTINATION;BACKUP" "" ${ARGN})
    set(${CLEAR_VAR_DESTINATION} ${${CLEAR_VAR_BACKUP}})
    unset(${CLEAR_VAR_BACKUP})
endmacro()


================================================
FILE: cmake/code_coverage.cmake
================================================
# Code coverage
if(CPR_BUILD_TESTS AND CPR_GENERATE_COVERAGE)
    set(CMAKE_BUILD_TYPE COVERAGE CACHE INTERNAL "Coverage enabled build")
    message(STATUS "Enabling gcov support")
    if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        set(COVERAGE_FLAG "--coverage")
    endif()
    set(CMAKE_CXX_FLAGS_COVERAGE
        "-g -O0 ${COVERAGE_FLAG} -fprofile-arcs -ftest-coverage"
        CACHE STRING "Flags used by the C++ compiler during coverage builds."
        FORCE)
    set(CMAKE_C_FLAGS_COVERAGE
        "-g -O0 ${COVERAGE_FLAG} -fprofile-arcs -ftest-coverage"
        CACHE STRING "Flags used by the C compiler during coverage builds."
        FORCE)
    set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
        ""
        CACHE STRING "Flags used for linking binaries during coverage builds."
        FORCE)
    set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
        ""
        CACHE STRING "Flags used by the shared libraries linker during coverage builds."
        FORCE)
    mark_as_advanced(
        CMAKE_CXX_FLAGS_COVERAGE
        CMAKE_C_FLAGS_COVERAGE
        CMAKE_EXE_LINKER_FLAGS_COVERAGE
        CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
endif()


================================================
FILE: cmake/cppcheck.cmake
================================================
# Include this file if and only if you want to use cppcheck.

if (NOT ${CPR_CPPCHECK_PATH} STREQUAL "")
    get_filename_component(CPPCHECK_HINT_FILENAME ${CPR_CPPCHECK_PATH} NAME)
    get_filename_component(CPPCHECK_HINT_PATH ${CPR_CPPCHECK_PATH} DIRECTORY)
endif ()

find_program(CMAKE_CXX_CPPCHECK NAMES cppcheck ${CPPCHECK_HINT_FILENAME} HINTS ${CPPCHECK_HINT_PATH} REQUIRED)
message(STATUS "Found cppcheck: ${CMAKE_CXX_CPPCHECK}")

list(APPEND CMAKE_CXX_CPPCHECK
        "--xml"
        "--error-exitcode=1"
        "--enable=warning,style"
        "--force"
        "--inline-suppr"
        "--addon=y2038"
        "--std=c++${CMAKE_CXX_STANDARD}"
        "--cppcheck-build-dir=${PROJECT_BINARY_DIR}"
        "--suppress-xml=${PROJECT_SOURCE_DIR}/cppcheck-suppressions.xml"
        "--output-file=${PROJECT_BINARY_DIR}/cppcheck.xml"
        "--check-level=normal"
)


================================================
FILE: cmake/cprConfig-ssl.cmake.in
================================================
include(CMakeFindDependencyMacro)
@PACKAGE_INIT@

find_dependency(CURL REQUIRED)
find_dependency(OpenSSL REQUIRED)

include(${CMAKE_CURRENT_LIST_DIR}/cprTargets.cmake)

check_required_components(cpr)

================================================
FILE: cmake/cprConfig.cmake.in
================================================
include(CMakeFindDependencyMacro)
@PACKAGE_INIT@

find_dependency(CURL REQUIRED)

include(${CMAKE_CURRENT_LIST_DIR}/cprTargets.cmake)

check_required_components(cpr)

================================================
FILE: cmake/cprver.h.in
================================================
#ifndef CPR_CPRVER_H
#define CPR_CPRVER_H

/**
 * CPR version as a string.
 **/
#define CPR_VERSION "${cpr_VERSION}"

/**
 * CPR version split up into parts.
 **/
#define CPR_VERSION_MAJOR ${cpr_VERSION_MAJOR}
#define CPR_VERSION_MINOR ${cpr_VERSION_MINOR}
#define CPR_VERSION_PATCH ${cpr_VERSION_PATCH}

/**
 * CPR version as a single hex digit.
 * it can be split up into three parts:
 * 0xAABBCC
 * AA: The current CPR major version number in a hex format.
 * BB: The current CPR minor version number in a hex format.
 * CC: The current CPR patch version number in a hex format.
 *
 * Examples:
 * '0x010702' -> 01.07.02 -> CPR_VERSION: 1.7.2
 * '0xA13722' -> A1.37.22 -> CPR_VERSION: 161.55.34
 **/
#define CPR_VERSION_NUM ${cpr_VERSION_NUM}

#endif


================================================
FILE: cmake/libpsl.cmake
================================================
# Builds libpsl which is especially necessary on Windows since there it is not available via e.g. a package manager.

include(ExternalProject)
find_program(MESON_PATH meson)

if(MESON_PATH STREQUAL "MESON_PATH-NOTFOUND")
    message(FATAL_ERROR "meson not found. Please make sure you have meson installed on your system (https://mesonbuild.com/Getting-meson.html). Meson is required for building libpsl for curl on Windows.")
    return()
endif()

FetchContent_Declare(libpsl_src GIT_REPOSITORY https://github.com/rockdaboot/libpsl.git
                                GIT_TAG 0.21.5)
FetchContent_MakeAvailable(libpsl_src) # sets libpsl_src_SOURCE_DIR / _BINARY_DIR

set(LIBPSL_SOURCE_DIR "${libpsl_src_SOURCE_DIR}")
set(LIBPSL_BUILD_DIR "${libpsl_src_BINARY_DIR}")
set(LIBPSL_INSTALL_DIR "${CMAKE_BINARY_DIR}/libpsl_src-install")
file(MAKE_DIRECTORY "${LIBPSL_BUILD_DIR}")

string(TOLOWER "${CMAKE_SYSTEM_NAME}" MESON_TARGET_HOST_SYSTEM_NAME)
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" MESON_TARGET_SYSTEM_PROCESSOR_LOWER)
if(MESON_TARGET_SYSTEM_PROCESSOR_LOWER MATCHES "^(x86_64|amd64)$")
    set(MESON_TARGET_HOST_CPU_FAMILY "x86_64")
elseif(MESON_TARGET_SYSTEM_PROCESSOR_LOWER MATCHES "^(i.86|x86)$")
    set(MESON_TARGET_HOST_CPU_FAMILY "x86")
elseif(MESON_TARGET_SYSTEM_PROCESSOR_LOWER MATCHES "^(armv7|armv6|arm)$")
    set(MESON_TARGET_HOST_CPU_FAMILY "arm")
elseif(MESON_TARGET_SYSTEM_PROCESSOR_LOWER MATCHES "^(aarch64|arm64)$")
    set(MESON_TARGET_HOST_CPU_FAMILY "aarch64")
else()
    set(MESON_TARGET_HOST_CPU_FAMILY "${MESON_TARGET_SYSTEM_PROCESSOR_LOWER}")
endif()

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(MESON_BUILD_TYPE debug)
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
    set(MESON_BUILD_TYPE debugoptimized)
else()
     set(MESON_BUILD_TYPE release)
endif()

include (TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
    set(MESON_ENDIAN "big")
else()
    set(MESON_ENDIAN "little")
endif()

# libpsl is plain C. Make sure CMake initializes a C tool-chain.
if(NOT CMAKE_C_COMPILER)
    enable_language(C) # initializes CMAKE_C_COMPILER, CMAKE_AR, …
endif()

# Write a meson cross compilation file to allow cross compiling
# for example for building NuGet packages although usually it is not required.
file(WRITE "${CMAKE_BINARY_DIR}/libpsl-meson-cross.txt" "[binaries]
c = '${CMAKE_C_COMPILER}'
cpp = '${CMAKE_CXX_COMPILER}'
ar = '${CMAKE_AR}'
strip = '${CMAKE_STRIP}'

[host_machine]
system = '${MESON_TARGET_HOST_SYSTEM_NAME}'
cpu_family = '${MESON_TARGET_HOST_CPU_FAMILY}'
cpu = '${MESON_TARGET_HOST_CPU_FAMILY}'
endian = '${MESON_ENDIAN}'
")

# Meson configure
# We only care about static libraries of psl. In case you need a dynamic version, feel free to add support for it.
message(STATUS "Configuring libpsl...")
execute_process(COMMAND "${MESON_PATH}" setup
                        "${LIBPSL_BUILD_DIR}"
                        "${LIBPSL_SOURCE_DIR}"
                        -Dtests=false
                        -Ddocs=false
                        --cross-file "${CMAKE_BINARY_DIR}/libpsl-meson-cross.txt"
                        --buildtype=${MESON_BUILD_TYPE}
                        --prefix "${LIBPSL_INSTALL_DIR}"
                        --default-library=static
                RESULT_VARIABLE MESON_SETUP_RC)
if(MESON_SETUP_RC)
    message(FATAL_ERROR "Meson setup for libpsl failed!")
endif()

# Meson build
message(STATUS "Building libpsl...")
execute_process(COMMAND "${MESON_PATH}" compile -C "${LIBPSL_BUILD_DIR}"
                RESULT_VARIABLE MESON_COMPILE_RC
)
if(MESON_COMPILE_RC)
    message(FATAL_ERROR "Meson compile for libpsl failed!")
endif()

# Meson install
message(STATUS "Installing libpsl...")
execute_process(COMMAND "${MESON_PATH}" install -C "${LIBPSL_BUILD_DIR}"
                RESULT_VARIABLE MESON_INSTALL_RC)
if(MESON_INSTALL_RC)
    message(FATAL_ERROR "Meson install for libpsl failed!")
endif()

list(APPEND CMAKE_INCLUDE_PATH "${LIBPSL_INSTALL_DIR}/include")

if(EXISTS "${LIBPSL_INSTALL_DIR}/lib64")
    set(LIBPSL_LIBRARY "${LIBPSL_INSTALL_DIR}/lib/libpsl.a")
    list(APPEND CMAKE_LIBRARY_PATH "${LIBPSL_INSTALL_DIR}/lib64")
else()
    set(LIBPSL_LIBRARY "${LIBPSL_INSTALL_DIR}/lib/libpsl.a")
    list(APPEND CMAKE_LIBRARY_PATH "${LIBPSL_INSTALL_DIR}/lib")
endif()

set(LIBPSL_INCLUDE_DIR  "${LIBPSL_INSTALL_DIR}/include")

# Workaround for Windows compilation.
# Ref: https://github.com/microsoft/vcpkg/pull/38847/files#diff-922fe829582a7e5acf5b0c35181daa63064fc12a2c889c5d89a19e5e02113f1bL44
add_compile_definitions(PSL_STATIC=1)


================================================
FILE: cmake/mongoose.CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.15)
project(mongoose C)


add_library(mongoose STATIC mongoose.c)
target_include_directories(mongoose PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

if(ENABLE_SSL_TESTS)
    # Enable mongoose SSL
    target_compile_definitions(mongoose PUBLIC MG_ENABLE_OPENSSL)
    target_link_libraries(mongoose PUBLIC OpenSSL::SSL)

    # Fix macOS and Windows invalid OpenSSL include path
    target_include_directories(mongoose PUBLIC "${OPENSSL_INCLUDE_DIR}")
endif()


================================================
FILE: cmake/sanitizer.cmake
================================================
include(CheckCXXSourceCompiles)

set(ALL_ACTIVE_SAN_FLAGS "")

 # No sanitizers when cross compiling to prevent stuff like this: https://github.com/whoshuu/cpr/issues/582
if(NOT CMAKE_CROSSCOMPILING)
    function(cpr_check_sanitizer_compile flags result_var)
        set(PREV_FLAG ${CMAKE_REQUIRED_FLAGS})
        set(CMAKE_REQUIRED_FLAGS "${flags}")
        check_cxx_source_compiles("int main() { return 0; }" ${result_var})
        set(CMAKE_REQUIRED_FLAGS ${PREV_FLAG})
    endfunction()

    # Thread sanitizer
    set(THREAD_SAN_FLAGS "-fsanitize=thread")
    if(CPR_DEBUG_SANITIZER_FLAG_THREAD)
        cpr_check_sanitizer_compile("${THREAD_SAN_FLAGS}" THREAD_SANITIZER_AVAILABLE_AND_ENABLED)
        if(NOT THREAD_SANITIZER_AVAILABLE_AND_ENABLED)
            message(FATAL_ERROR "ThreadSanitizer requested but the test program failed to compile with ${THREAD_SAN_FLAGS}.")
        endif()
    endif()

    # Address sanitizer
    set(ADDR_SAN_FLAGS "-fsanitize=address")
    if(CPR_DEBUG_SANITIZER_FLAG_ADDR)
        cpr_check_sanitizer_compile("${ADDR_SAN_FLAGS}" ADDRESS_SANITIZER_AVAILABLE_AND_ENABLED)
        if(NOT ADDRESS_SANITIZER_AVAILABLE_AND_ENABLED)
            message(FATAL_ERROR "AddressSanitizer requested but the test program failed to compile with ${ADDR_SAN_FLAGS}.")
        endif()
    endif()

    # Leak sanitizer
    set(LEAK_SAN_FLAGS "-fsanitize=leak")
    if(CPR_DEBUG_SANITIZER_FLAG_LEAK)
        cpr_check_sanitizer_compile("${LEAK_SAN_FLAGS}" LEAK_SANITIZER_AVAILABLE_AND_ENABLED)
        if(NOT LEAK_SANITIZER_AVAILABLE_AND_ENABLED)
            message(FATAL_ERROR "LeakSanitizer requested but the test program failed to compile with ${LEAK_SAN_FLAGS}.")
        endif()
    endif()

    # Undefined behavior sanitizer
    set(UDEF_SAN_FLAGS "-fsanitize=undefined")
    if(CPR_DEBUG_SANITIZER_FLAG_UB)
        cpr_check_sanitizer_compile("${UDEF_SAN_FLAGS}" UNDEFINED_BEHAVIOR_SANITIZER_AVAILABLE_AND_ENABLED)
        if(NOT UNDEFINED_BEHAVIOR_SANITIZER_AVAILABLE_AND_ENABLED)
            message(FATAL_ERROR "UndefinedBehaviorSanitizer requested but the test program failed to compile with ${UDEF_SAN_FLAGS}.")
        endif()
    endif()

    # All sanitizer (without thread sanitizer)
    if(CPR_DEBUG_SANITIZER_FLAG_ALL)
        cpr_check_sanitizer_compile("${ADDR_SAN_FLAGS} ${UDEF_SAN_FLAGS} ${LEAK_SAN_FLAGS}" ALL_SANITIZERS_AVAILABLE_AND_ENABLED)
        if(NOT ALL_SANITIZERS_AVAILABLE_AND_ENABLED)
            message(FATAL_ERROR "All sanitizers requested but the test program failed to compile with ${ADDR_SAN_FLAGS} ${UDEF_SAN_FLAGS} ${LEAK_SAN_FLAGS}.")
        endif()
        set(ALL_ACTIVE_SAN_FLAGS "${ADDR_SAN_FLAGS} ${UDEF_SAN_FLAGS} ${LEAK_SAN_FLAGS}")
    endif()

    if(THREAD_SANITIZER_AVAILABLE_AND_ENABLED)
        set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${THREAD_SAN_FLAGS}" CACHE INTERNAL "Flags used by the C compiler during thread sanitizer builds." FORCE)
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${THREAD_SAN_FLAGS}" CACHE INTERNAL "Flags used by the C++ compiler during thread sanitizer builds." FORCE)
        set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Flags used for the linker during thread sanitizer builds" FORCE)
    elseif(ALL_SANITIZERS_AVAILABLE_AND_ENABLED)
        set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${ALL_ACTIVE_SAN_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE INTERNAL "Flags used by the C compiler during most possible sanitizer builds." FORCE)
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${ALL_ACTIVE_SAN_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE INTERNAL "Flags used by the C++ compiler during most possible sanitizer builds." FORCE)
        set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Flags used for the linker during most possible sanitizer builds" FORCE)
    elseif(ADDRESS_SANITIZER_AVAILABLE_AND_ENABLED)
        set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${ADDR_SAN_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE INTERNAL "Flags used by the C compiler during address sanitizer builds." FORCE)
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${ADDR_SAN_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE INTERNAL "Flags used by the C++ compiler during address sanitizer builds." FORCE)
        set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Flags used for the linker during address sanitizer builds" FORCE)
    elseif(LEAK_SANITIZER_AVAILABLE_AND_ENABLED)
        set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${LEAK_SAN_FLAGS} -fno-omit-frame-pointer" CACHE INTERNAL "Flags used by the C compiler during leak sanitizer builds." FORCE)
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${LEAK_SAN_FLAGS} -fno-omit-frame-pointer" CACHE INTERNAL "Flags used by the C++ compiler during leak sanitizer builds." FORCE)
        set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Flags used for the linker during leak sanitizer builds" FORCE)
    elseif(UNDEFINED_BEHAVIOR_SANITIZER_AVAILABLE_AND_ENABLED)
        set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${UDEF_SAN_FLAGS}" CACHE INTERNAL "Flags used by the C compiler during undefined behavior sanitizer builds." FORCE)
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${UDEF_SAN_FLAGS}" CACHE INTERNAL "Flags used by the C++ compiler during undefined behavior sanitizer builds." FORCE)
        set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Flags used for the linker during undefined behavior sanitizer builds" FORCE)
    endif()
endif()


================================================
FILE: cmake/std_fs_support_test.cpp
================================================
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

int main() {
    auto cwd = fs::current_path();
}


================================================
FILE: cmake/zlib_external.cmake
================================================
# ZLIB

# Fix Windows missing "zlib.dll":
if(WIN32 AND (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}))
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/$<CONFIG> CACHE INTERNAL "" FORCE)
endif()

set(ZLIB_COMPAT ON CACHE INTERNAL "" FORCE)
set(ZLIB_ENABLE_TESTS OFF CACHE INTERNAL "" FORCE)

FetchContent_Declare(zlib
                    GIT_REPOSITORY https://github.com/zlib-ng/zlib-ng
                    GIT_TAG 2.1.3
                    USES_TERMINAL_DOWNLOAD TRUE)
FetchContent_MakeAvailable(zlib)

# Fix Windows zlib dll names from "zlibd1.dll" to "zlib.dll":
if(WIN32 AND BUILD_SHARED_LIBS)
    set_target_properties(zlib PROPERTIES OUTPUT_NAME "zlib")
    set_target_properties(zlib PROPERTIES DEBUG_POSTFIX "")
    set_target_properties(zlib PROPERTIES SUFFIX ".dll")
endif()


================================================
FILE: cppcheck-suppressions.xml
================================================
<?xml version="1.0"?>
<suppressions>
    <!-- Exclude Paths -->
    <suppress>
        <id>*</id>
        <fileName>*/build/*</fileName>
    </suppress>
    <suppress>
        <id>CheckLevelMaxBranches</id>
    </suppress>
    <suppress>
        <id>noExplicitConstructor</id>
    </suppress>
    <suppress>
        <id>knownConditionTrueFalse</id>
        <fileName>*/include/cpr/async_wrapper.h</fileName>
    </suppress>
    <suppress>
        <id>y2038-unsafe-call</id>
        <fileName>*/cpr/cookies.cpp</fileName>
    </suppress>
    <!-- Known Limitation/Bug: https://github.com/libcpr/cpr/issues/1174 -->
    <suppress>
        <id>y2038-unsafe-call</id>
        <fileName>*/include/cpr/low_speed.h</fileName>
    </suppress>
    <!-- No reason to check third party includes -->
    <suppress>
        <id>y2038-unsafe-call</id>
        <fileName>*/curl/curl.h</fileName>
    </suppress>
    <suppress>
        <id>normalCheckLevelMaxBranches</id>
    </suppress>
    <suppress>
        <id>constParameterPointer</id>
        <fileName>*/cpr/util.cpp</fileName>
    </suppress>
    <suppress>
        <id>postfixOperator</id>
    </suppress>
    <suppress>
        <id>syntaxError</id>
        <fileName>*/cpr/util.cpp</fileName>
    </suppress>
</suppressions>

================================================
FILE: cpr/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.15)

add_library(cpr
        accept_encoding.cpp
        async.cpp
        auth.cpp
        callback.cpp
        cert_info.cpp
        connection_pool.cpp
        cookies.cpp
        cprtypes.cpp
        curl_container.cpp
        curlholder.cpp
        error.cpp
        file.cpp
        multipart.cpp
        parameters.cpp
        payload.cpp
        proxies.cpp
        proxyauth.cpp
        session.cpp
        sse.cpp
        threadpool.cpp
        timeout.cpp
        unix_socket.cpp
        util.cpp
        response.cpp
        redirect.cpp
        interceptor.cpp
        ssl_ctx.cpp
        curlmultiholder.cpp
        multiperform.cpp)

add_library(cpr::cpr ALIAS cpr)

target_link_libraries(cpr PUBLIC ${CURL_LIB}) # todo should be private, but first dependencies in ssl_options need to be removed

# Fix missing OpenSSL includes for Windows since in 'ssl_ctx.cpp' we include OpenSSL directly
if(SSL_BACKEND_USED STREQUAL "OpenSSL")
        target_link_libraries(cpr PRIVATE OpenSSL::SSL)
        target_include_directories(cpr PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()

# Set version for shared libraries.
set_target_properties(cpr
        PROPERTIES
        VERSION ${${PROJECT_NAME}_VERSION}
        SOVERSION ${${PROJECT_NAME}_VERSION_MAJOR})

# Import GNU common install directory variables
include(GNUInstallDirs)

install(TARGETS cpr
        EXPORT cprTargets
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

if(CPR_USE_SYSTEM_CURL)
        # Include CMake helpers for package config files
        # Follow this installation guideline: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html
        include(CMakePackageConfigHelpers)

        write_basic_package_version_file(
                "${PROJECT_BINARY_DIR}/cpr/cprConfigVersion.cmake"
                VERSION ${${PROJECT_NAME}_VERSION}
                COMPATIBILITY ExactVersion)

        if(SSL_BACKEND_USED STREQUAL "OpenSSL")
            configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/cprConfig-ssl.cmake.in
                "${PROJECT_BINARY_DIR}/cpr/cprConfig.cmake"
                INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpr)
        else()
            configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/cprConfig.cmake.in
                "${PROJECT_BINARY_DIR}/cpr/cprConfig.cmake"
                INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpr)
        endif()

        install(FILES ${PROJECT_BINARY_DIR}/cpr/cprConfig.cmake
                ${PROJECT_BINARY_DIR}/cpr/cprConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpr)
endif()

install(EXPORT cprTargets
        FILE cprTargets.cmake
        NAMESPACE cpr::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpr)


================================================
FILE: cpr/accept_encoding.cpp
================================================
#include "cpr/accept_encoding.h"

#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <numeric>
#include <stdexcept>
#include <string>
#include <utility>

namespace cpr {

AcceptEncoding::AcceptEncoding(const std::initializer_list<AcceptEncodingMethods>& methods) {
    methods_.clear();
    std::transform(methods.begin(), methods.end(), std::inserter(methods_, methods_.begin()), [&](cpr::AcceptEncodingMethods method) { return cpr::AcceptEncodingMethodsStringMap.at(method); });
}

AcceptEncoding::AcceptEncoding(const std::initializer_list<std::string>& string_methods) : methods_{string_methods} {}

bool AcceptEncoding::empty() const noexcept {
    return methods_.empty();
}

const std::string AcceptEncoding::getString() const {
    return std::accumulate(std::next(methods_.begin()), methods_.end(), *methods_.begin(), [](std::string a, std::string b) { return std::move(a) + ", " + std::move(b); });
}

[[nodiscard]] bool AcceptEncoding::disabled() const {
    if (methods_.find(cpr::AcceptEncodingMethodsStringMap.at(AcceptEncodingMethods::disabled)) != methods_.end()) {
        if (methods_.size() != 1) {
            throw std::invalid_argument("AcceptEncoding does not accept any other values if 'disabled' is present. You set the following encodings: " + getString());
        }
        return true;
    }
    return false;
}

} // namespace cpr


================================================
FILE: cpr/async.cpp
================================================
#include "cpr/async.h"

namespace cpr {

// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
CPR_SINGLETON_IMPL(GlobalThreadPool);

} // namespace cpr


================================================
FILE: cpr/auth.cpp
================================================
#include "cpr/auth.h"

#include <string_view>

namespace cpr {

Authentication::Authentication(std::string_view username, std::string_view password, AuthMode auth_mode) : auth_mode_{auth_mode} {
    auth_string_.reserve(username.size() + 1 + password.size());
    auth_string_ += username;
    auth_string_ += ':';
    auth_string_ += password;
}

const char* Authentication::GetAuthString() const noexcept {
    return auth_string_.c_str();
}

AuthMode Authentication::GetAuthMode() const noexcept {
    return auth_mode_;
}
} // namespace cpr


================================================
FILE: cpr/callback.cpp
================================================
#include "cpr/callback.h"
#include "cpr/cprtypes.h"
#include <functional>

namespace cpr {
void CancellationCallback::SetProgressCallback(ProgressCallback& u_cb) {
    user_cb.emplace(std::reference_wrapper{u_cb});
}

bool CancellationCallback::operator()(cpr_pf_arg_t dltotal, cpr_pf_arg_t dlnow, cpr_pf_arg_t ultotal, cpr_pf_arg_t ulnow) const {
    const bool const_operation = !(cancellation_state->load());
    return user_cb ? (const_operation && (*user_cb)(dltotal, dlnow, ultotal, ulnow)) : const_operation;
}
} // namespace cpr


================================================
FILE: cpr/cert_info.cpp
================================================
#include "cpr/cert_info.h"
#include <cstddef>
#include <string>

namespace cpr {

std::string& CertInfo::operator[](const size_t& pos) {
    return cert_info_[pos];
}

CertInfo::iterator CertInfo::begin() {
    return cert_info_.begin();
}
CertInfo::iterator CertInfo::end() {
    return cert_info_.end();
}

CertInfo::const_iterator CertInfo::begin() const {
    return cert_info_.begin();
}

CertInfo::const_iterator CertInfo::end() const {
    return cert_info_.end();
}

CertInfo::const_iterator CertInfo::cbegin() const {
    return cert_info_.cbegin();
}

CertInfo::const_iterator CertInfo::cend() const {
    return cert_info_.cend();
}

void CertInfo::emplace_back(const std::string& str) {
    cert_info_.emplace_back(str);
}

void CertInfo::push_back(const std::string& str) {
    cert_info_.push_back(str);
}

void CertInfo::pop_back() {
    cert_info_.pop_back();
}
} // namespace cpr


================================================
FILE: cpr/connection_pool.cpp
================================================
#include "cpr/connection_pool.h"
#include <curl/curl.h>
#include <memory>
#include <mutex>

namespace cpr {
ConnectionPool::ConnectionPool() {
    CURLSH* curl_share = curl_share_init();
    this->connection_mutex_ = std::make_shared<std::mutex>();

    auto lock_f = +[](CURL* /*handle*/, curl_lock_data /*data*/, curl_lock_access /*access*/, void* userptr) {
        std::mutex* lock = static_cast<std::mutex*>(userptr);
        lock->lock(); // cppcheck-suppress localMutex  // False positive: mutex is used as callback for libcurl, not local scope
    };

    auto unlock_f = +[](CURL* /*handle*/, curl_lock_data /*data*/, void* userptr) {
        std::mutex* lock = static_cast<std::mutex*>(userptr);
        lock->unlock();
    };

    curl_share_setopt(curl_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
    curl_share_setopt(curl_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
    curl_share_setopt(curl_share, CURLSHOPT_USERDATA, this->connection_mutex_.get());
    curl_share_setopt(curl_share, CURLSHOPT_LOCKFUNC, lock_f);
    curl_share_setopt(curl_share, CURLSHOPT_UNLOCKFUNC, unlock_f);

    this->curl_sh_ = std::shared_ptr<CURLSH>(curl_share, [](CURLSH* ptr) {
        // Make sure to reset callbacks before cleanup to avoid deadlocks
        curl_share_setopt(ptr, CURLSHOPT_LOCKFUNC, nullptr);
        curl_share_setopt(ptr, CURLSHOPT_UNLOCKFUNC, nullptr);
        curl_share_cleanup(ptr);
    });
}

void ConnectionPool::SetupHandler(CURL* easy_handler) const {
    curl_easy_setopt(easy_handler, CURLOPT_SHARE, this->curl_sh_.get());
}

} // namespace cpr

================================================
FILE: cpr/cookies.cpp
================================================
#include "cpr/cookies.h"
#include "cpr/curlholder.h"
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>
#include <string_view>

namespace cpr {
const std::string& Cookie::GetDomain() const {
    return domain_;
}

bool Cookie::IsIncludingSubdomains() const {
    return includeSubdomains_;
}

const std::string& Cookie::GetPath() const {
    return path_;
}

bool Cookie::IsHttpsOnly() const {
    return httpsOnly_;
}

std::chrono::system_clock::time_point Cookie::GetExpires() const {
    return expires_;
}

std::string Cookie::GetExpiresString() const {
    std::stringstream ss;
    std::tm tm{};
    const std::time_t tt = std::chrono::system_clock::to_time_t(expires_);
#ifdef _WIN32
    gmtime_s(&tm, &tt);
#else
    // NOLINTNEXTLINE(misc-include-cleaner,cert-err33-c) False positive since <ctime> is included. Also ignore the ret value here.
    gmtime_r(&tt, &tm);
#endif
    ss << std::put_time(&tm, "%a, %d %b %Y %H:%M:%S GMT");
    return ss.str();
}

const std::string& Cookie::GetName() const {
    return name_;
}

const std::string& Cookie::GetValue() const {
    return value_;
}

std::string Cookies::GetEncoded(const CurlHolder& holder) const {
    std::stringstream stream;
    for (const cpr::Cookie& item : cookies_) {
        // Depending on if encoding is set to "true", we will URL-encode cookies
        stream << (encode ? std::string_view{holder.urlEncode(item.GetName())} : std::string_view{item.GetName()}) << "=";

        // special case version 1 cookies, which can be distinguished by
        // beginning and trailing quotes
        if (!item.GetValue().empty() && item.GetValue().front() == '"' && item.GetValue().back() == '"') {
            stream << item.GetValue();
        } else {
            // Depending on if encoding is set to "true", we will URL-encode cookies
            stream << (encode ? std::string_view{holder.urlEncode(item.GetValue())} : std::string_view{item.GetValue()});
        }
        stream << "; ";
    }
    return stream.str();
}

cpr::Cookie& Cookies::operator[](size_t pos) {
    return cookies_[pos];
}

Cookies::iterator Cookies::begin() {
    return cookies_.begin();
}

Cookies::iterator Cookies::end() {
    return cookies_.end();
}

Cookies::const_iterator Cookies::begin() const {
    return cookies_.begin();
}

Cookies::const_iterator Cookies::end() const {
    return cookies_.end();
}

Cookies::const_iterator Cookies::cbegin() const {
    return cookies_.cbegin();
}

Cookies::const_iterator Cookies::cend() const {
    return cookies_.cend();
}

void Cookies::emplace_back(const Cookie& str) {
    cookies_.emplace_back(str);
}

bool Cookies::empty() const {
    return cookies_.empty();
}

void Cookies::push_back(const Cookie& str) {
    cookies_.push_back(str);
}

void Cookies::pop_back() {
    cookies_.pop_back();
}

} // namespace cpr


================================================
FILE: cpr/cprtypes.cpp
================================================
#include "cpr/cprtypes.h"
#include <algorithm>
#include <cctype>
#include <string>


namespace cpr {
bool CaseInsensitiveCompare::operator()(const std::string& a, const std::string& b) const noexcept {
    return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](unsigned char ac, unsigned char bc) { return std::tolower(ac) < std::tolower(bc); });
}
} // namespace cpr


================================================
FILE: cpr/curl_container.cpp
================================================
#include "cpr/curl_container.h"
#include "cpr/curlholder.h"
#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <string>

namespace cpr {
template <class T>
CurlContainer<T>::CurlContainer(const std::initializer_list<T>& containerList) : containerList_(containerList) {}

template <class T>
void CurlContainer<T>::Add(const std::initializer_list<T>& containerList) {
    std::transform(containerList.begin(), containerList.end(), std::back_inserter(containerList_), [](const T& elem) { return std::move(elem); });
}

template <class T>
void CurlContainer<T>::Add(const T& element) {
    containerList_.push_back(std::move(element));
}

template <>
const std::string CurlContainer<Parameter>::GetContent(const CurlHolder& holder) const {
    std::string content{};
    for (const Parameter& parameter : containerList_) {
        if (!content.empty()) {
            content += "&";
        }

        const std::string escapedKey = encode ? std::string{holder.urlEncode(parameter.key)} : parameter.key;
        if (parameter.value.empty()) {
            content += escapedKey;
        } else {
            const std::string escapedValue = encode ? std::string{holder.urlEncode(parameter.value)} : parameter.value;
            content += escapedKey + "=";
            content += escapedValue;
        }
    }

    return content;
}

template <>
const std::string CurlContainer<Parameter>::GetContent() const {
    std::string content{};
    for (const Parameter& parameter : containerList_) {
        if (!content.empty()) {
            content += "&";
        }

        if (parameter.value.empty()) {
            content += parameter.key;
        } else {
            content += parameter.key + "=";
            content += parameter.value;
        }
    }

    return content;
}

template <>
const std::string CurlContainer<Pair>::GetContent(const CurlHolder& holder) const {
    std::string content{};
    for (const cpr::Pair& element : containerList_) {
        if (!content.empty()) {
            content += "&";
        }
        const std::string escaped = encode ? std::string{holder.urlEncode(element.value)} : element.value;
        content += element.key + "=" + escaped;
    }

    return content;
}

template <>
const std::string CurlContainer<Pair>::GetContent() const {
    std::string content{};
    for (const cpr::Pair& element : containerList_) {
        if (!content.empty()) {
            content += "&";
        }
        content += element.key + "=" + element.value;
    }

    return content;
}

template class CurlContainer<Pair>;
template class CurlContainer<Parameter>;

} // namespace cpr


================================================
FILE: cpr/curlholder.cpp
================================================
#include "cpr/curlholder.h"
#include "cpr/secure_string.h"
#include <cassert>
#include <curl/curl.h>
#include <curl/easy.h>
#include <string_view>

namespace cpr {
CurlHolder::CurlHolder() {
    /**
     * Allow multithreaded access to CPR by locking curl_easy_init().
     * curl_easy_init() is not thread safe.
     * References:
     * https://curl.haxx.se/libcurl/c/curl_easy_init.html
     * https://curl.haxx.se/libcurl/c/threadsafe.html
     **/
    curl_easy_init_mutex_().lock();
    // NOLINTNEXTLINE (cppcoreguidelines-prefer-member-initializer) since we need it to happen inside the lock
    handle = curl_easy_init();
    curl_easy_init_mutex_().unlock();

    assert(handle);
}

CurlHolder::CurlHolder(CurlHolder&& old) noexcept : handle(old.handle), chunk(old.chunk), resolveCurlList(old.resolveCurlList), multipart(old.multipart), error(old.error) {
    // Avoid double free
    old.handle = nullptr;
    old.chunk = nullptr;
    old.resolveCurlList = nullptr;
    old.multipart = nullptr;
}

CurlHolder::~CurlHolder() {
    curl_slist_free_all(chunk);
    curl_slist_free_all(resolveCurlList);
    curl_mime_free(multipart);
    curl_easy_cleanup(handle);
}

CurlHolder& CurlHolder::operator=(CurlHolder&& old) noexcept {
    // Free the previous stuff
    curl_slist_free_all(chunk);
    curl_slist_free_all(resolveCurlList);
    curl_mime_free(multipart);
    curl_easy_cleanup(handle);

    // Move
    handle = old.handle;
    chunk = old.chunk;
    resolveCurlList = old.resolveCurlList;
    multipart = old.multipart;
    error = old.error;

    // Avoid double free
    old.handle = nullptr;
    old.chunk = nullptr;
    old.resolveCurlList = nullptr;
    old.multipart = nullptr;
    return *this;
}

util::SecureString CurlHolder::urlEncode(std::string_view s) const {
    assert(handle);
    char* output = curl_easy_escape(handle, s.data(), static_cast<int>(s.length()));
    if (output) {
        util::SecureString result = output;
        curl_free(output);
        return result;
    }
    return "";
}

util::SecureString CurlHolder::urlDecode(std::string_view s) const {
    assert(handle);
    char* output = curl_easy_unescape(handle, s.data(), static_cast<int>(s.length()), nullptr);
    if (output) {
        util::SecureString result = output;
        curl_free(output);
        return result;
    }
    return "";
}
} // namespace cpr


================================================
FILE: cpr/curlmultiholder.cpp
================================================
#include "cpr/curlmultiholder.h"
#include <cassert>
#include <curl/multi.h>

namespace cpr {

CurlMultiHolder::CurlMultiHolder() : handle{curl_multi_init()} {
    assert(handle);
}

CurlMultiHolder::~CurlMultiHolder() {
    curl_multi_cleanup(handle);
}

} // namespace cpr


================================================
FILE: cpr/error.cpp
================================================
#include "cpr/error.h"
#include <cstdint>
#include <curl/curl.h>
#include <curl/curlver.h>

namespace cpr {
// NOLINTBEGIN(bugprone-branch-clone) Fine in this case
ErrorCode Error::getErrorCodeForCurlError(std::int32_t curl_code) {
    switch (curl_code) {
        case CURLE_OK:
            return ErrorCode::OK;
        case CURLE_UNSUPPORTED_PROTOCOL:
            return ErrorCode::UNSUPPORTED_PROTOCOL;
        case CURLE_FAILED_INIT:
            return ErrorCode::FAILED_INIT;
        case CURLE_URL_MALFORMAT:
            return ErrorCode::URL_MALFORMAT;
        case CURLE_NOT_BUILT_IN:
            return ErrorCode::NOT_BUILT_IN;
        case CURLE_COULDNT_RESOLVE_PROXY:
            return ErrorCode::COULDNT_RESOLVE_PROXY;
        case CURLE_COULDNT_RESOLVE_HOST:
            return ErrorCode::COULDNT_RESOLVE_HOST;
        case CURLE_COULDNT_CONNECT:
            return ErrorCode::COULDNT_CONNECT;

// Name changed in curl >= 7.51.0.
#if LIBCURL_VERSION_NUM >= 0x073300
        case CURLE_WEIRD_SERVER_REPLY:
            return ErrorCode::WEIRD_SERVER_REPLY;
#else
        case CURLE_FTP_WEIRD_SERVER_REPLY:
            return ErrorCode::WEIRD_SERVER_REPLY;
#endif

        case CURLE_REMOTE_ACCESS_DENIED:
            return ErrorCode::REMOTE_ACCESS_DENIED;
        case CURLE_HTTP2:
            return ErrorCode::HTTP2;
        case CURLE_QUOTE_ERROR:
            return ErrorCode::QUOTE_ERROR;
        case CURLE_HTTP_RETURNED_ERROR:
            return ErrorCode::HTTP_RETURNED_ERROR;
        case CURLE_WRITE_ERROR:
            return ErrorCode::WRITE_ERROR;
        case CURLE_UPLOAD_FAILED:
            return ErrorCode::UPLOAD_FAILED;
        case CURLE_READ_ERROR:
            return ErrorCode::READ_ERROR;
        case CURLE_OUT_OF_MEMORY:
            return ErrorCode::OUT_OF_MEMORY;
        case CURLE_OPERATION_TIMEDOUT:
            return ErrorCode::OPERATION_TIMEDOUT;
        case CURLE_RANGE_ERROR:
            return ErrorCode::RANGE_ERROR;
        case CURLE_HTTP_POST_ERROR:
            return ErrorCode::HTTP_POST_ERROR;
        case CURLE_SSL_CONNECT_ERROR:
            return ErrorCode::SSL_CONNECT_ERROR;
        case CURLE_BAD_DOWNLOAD_RESUME:
            return ErrorCode::BAD_DOWNLOAD_RESUME;
        case CURLE_FILE_COULDNT_READ_FILE:
            return ErrorCode::FILE_COULDNT_READ_FILE;
        case CURLE_FUNCTION_NOT_FOUND:
            return ErrorCode::FUNCTION_NOT_FOUND;
        case CURLE_ABORTED_BY_CALLBACK:
            return ErrorCode::ABORTED_BY_CALLBACK;
        case CURLE_BAD_FUNCTION_ARGUMENT:
            return ErrorCode::BAD_FUNCTION_ARGUMENT;
        case CURLE_INTERFACE_FAILED:
            return ErrorCode::INTERFACE_FAILED;
        case CURLE_TOO_MANY_REDIRECTS:
            return ErrorCode::TOO_MANY_REDIRECTS;
        case CURLE_UNKNOWN_OPTION:
            return ErrorCode::UNKNOWN_OPTION;

// Added in curl 7.78.0.
#if LIBCURL_VERSION_NUM >= 0x074E00
        case CURLE_SETOPT_OPTION_SYNTAX:
            return ErrorCode::SETOPT_OPTION_SYNTAX;
#endif

        case CURLE_GOT_NOTHING:
            return ErrorCode::GOT_NOTHING;
        case CURLE_SSL_ENGINE_NOTFOUND:
            return ErrorCode::SSL_ENGINE_NOTFOUND;
        case CURLE_SSL_ENGINE_SETFAILED:
            return ErrorCode::SSL_ENGINE_SETFAILED;
        case CURLE_SEND_ERROR:
            return ErrorCode::SEND_ERROR;
        case CURLE_RECV_ERROR:
            return ErrorCode::RECV_ERROR;
        case CURLE_SSL_CERTPROBLEM:
            return ErrorCode::SSL_CERTPROBLEM;
        case CURLE_SSL_CIPHER:
            return ErrorCode::SSL_CIPHER;
        case CURLE_PEER_FAILED_VERIFICATION:
            return ErrorCode::PEER_FAILED_VERIFICATION;
        case CURLE_BAD_CONTENT_ENCODING:
            return ErrorCode::BAD_CONTENT_ENCODING;
        case CURLE_FILESIZE_EXCEEDED:
            return ErrorCode::FILESIZE_EXCEEDED;
        case CURLE_USE_SSL_FAILED:
            return ErrorCode::USE_SSL_FAILED;
        case CURLE_SEND_FAIL_REWIND:
            return ErrorCode::SEND_FAIL_REWIND;
        case CURLE_SSL_ENGINE_INITFAILED:
            return ErrorCode::SSL_ENGINE_INITFAILED;

// Added in curl 7.13.1.
#if LIBCURL_VERSION_NUM >= 0x070D01
        case CURLE_LOGIN_DENIED:
            return ErrorCode::LOGIN_DENIED;
#endif

// Added in curl 7.16.0.
#if LIBCURL_VERSION_NUM >= 0x071000
        case CURLE_SSL_CACERT_BADFILE:
            return ErrorCode::SSL_CACERT_BADFILE;
#endif

// Added in curl 7.16.1.
#if LIBCURL_VERSION_NUM >= 0x071001
        case CURLE_SSL_SHUTDOWN_FAILED:
            return ErrorCode::SSL_SHUTDOWN_FAILED;
#endif

// Added in curl 7.18.2.
#if LIBCURL_VERSION_NUM >= 0x071202
        case CURLE_AGAIN:
            return ErrorCode::AGAIN;
#endif

// Added in curl 7.19.0.
#if LIBCURL_VERSION_NUM >= 0x071300
        case CURLE_SSL_CRL_BADFILE:
            return ErrorCode::SSL_CRL_BADFILE;
        case CURLE_SSL_ISSUER_ERROR:
            return ErrorCode::SSL_ISSUER_ERROR;
#endif

// Added in curl 7.21.0.
#if LIBCURL_VERSION_NUM >= 0x071500
        case CURLE_CHUNK_FAILED:
            return ErrorCode::CHUNK_FAILED;
#endif

// Added in curl 7.30.0.
#if LIBCURL_VERSION_NUM >= 0x071E00
        case CURLE_NO_CONNECTION_AVAILABLE:
            return ErrorCode::NO_CONNECTION_AVAILABLE;
#endif

// Added in curl 7.39.0.
#if LIBCURL_VERSION_NUM >= 0x072700
        case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
            return ErrorCode::SSL_PINNEDPUBKEYNOTMATCH;
#endif

// Added in curl 7.41.0.
#if LIBCURL_VERSION_NUM >= 0x072900
        case CURLE_SSL_INVALIDCERTSTATUS:
            return ErrorCode::SSL_INVALIDCERTSTATUS;
#endif

// Added in curl 7.49.0.
#if LIBCURL_VERSION_NUM >= 0x073100
        case CURLE_HTTP2_STREAM:
            return ErrorCode::HTTP2_STREAM;
#endif
        case CURLE_PARTIAL_FILE:
            return ErrorCode::PARTIAL_FILE;

// Added in curl 7.59.0.
#if LIBCURL_VERSION_NUM >= 0x073B00
        case CURLE_RECURSIVE_API_CALL:
            return ErrorCode::RECURSIVE_API_CALL;
#endif

// Added in curl 7.66.0.
#if LIBCURL_VERSION_NUM >= 0x074200
        case CURLE_AUTH_ERROR:
            return ErrorCode::AUTH_ERROR;
#endif

// Added in curl 7.68.0.
#if LIBCURL_VERSION_NUM >= 0x074400
        case CURLE_HTTP3:
            return ErrorCode::HTTP3;
#endif

// Added in curl 7.69.0.
#if LIBCURL_VERSION_NUM >= 0x074500
        case CURLE_QUIC_CONNECT_ERROR:
            return ErrorCode::QUIC_CONNECT_ERROR;
#endif

// Added in curl 7.73.0.
#if LIBCURL_VERSION_NUM >= 0x074900
        case CURLE_PROXY:
            return ErrorCode::PROXY;
#endif

// Added in curl 7.77.0.
#if LIBCURL_VERSION_NUM >= 0x074D00
        case CURLE_SSL_CLIENTCERT:
            return ErrorCode::SSL_CLIENTCERT;
#endif

// Added in curl 7.84.0.
#if LIBCURL_VERSION_NUM >= 0x075400
        case CURLE_UNRECOVERABLE_POLL:
            return ErrorCode::UNRECOVERABLE_POLL;
#endif

// Added in curl 7.6.0.
#if LIBCURL_VERSION_NUM >= 0x080600
        case CURLE_TOO_LARGE:
            return ErrorCode::TOO_LARGE;
#endif
        default:
            return ErrorCode::UNKNOWN_ERROR;
    }
}
// NOLINTEND(bugprone-branch-clone)
} // namespace cpr

================================================
FILE: cpr/file.cpp
================================================
#include "cpr/file.h"
#include <initializer_list>
#include <string>
#include <utility>

namespace cpr {

Files::Files(const std::initializer_list<std::string>& p_filepaths) : files(p_filepaths.begin(), p_filepaths.end()) {}

Files::iterator Files::begin() {
    return files.begin();
}

Files::iterator Files::end() {
    return files.end();
}

Files::const_iterator Files::begin() const {
    return files.begin();
}

Files::const_iterator Files::end() const {
    return files.end();
}

Files::const_iterator Files::cbegin() const {
    return files.cbegin();
}

Files::const_iterator Files::cend() const {
    return files.cend();
}

void Files::emplace_back(const File& file) {
    files.emplace_back(file);
}

void Files::push_back(const File& file) {
    files.push_back(file);
}

void Files::pop_back() {
    files.pop_back();
}

Files& Files::operator=(const Files& other) {
    if (&other != this) {
        files = other.files;
    }
    return *this;
}

Files& Files::operator=(Files&& old) noexcept {
    if (&old != this) {
        files = std::move(old.files);
    }
    return *this;
}
} // namespace cpr


================================================
FILE: cpr/interceptor.cpp
================================================
#include "cpr/interceptor.h"
#include "cpr/callback.h"
#include "cpr/multiperform.h"
#include "cpr/response.h"
#include "cpr/session.h"
#include <cstddef>
#include <iosfwd>
#include <stdexcept>
#include <vector>

namespace cpr {

Response Interceptor::proceed(Session& session) {
    return session.proceed();
}

Response Interceptor::proceed(Session& session, ProceedHttpMethod httpMethod) {
    switch (httpMethod) {
        case ProceedHttpMethod::DELETE_REQUEST:
            return session.Delete();
        case ProceedHttpMethod::GET_REQUEST:
            return session.Get();
        case ProceedHttpMethod::HEAD_REQUEST:
            return session.Head();
        case ProceedHttpMethod::OPTIONS_REQUEST:
            return session.Options();
        case ProceedHttpMethod::PATCH_REQUEST:
            return session.Patch();
        case ProceedHttpMethod::POST_REQUEST:
            return session.Post();
        case ProceedHttpMethod::PUT_REQUEST:
            return session.Put();
        default:
            throw std::invalid_argument{"Can't proceed the session with the provided http method!"};
    }
}

Response Interceptor::proceed(Session& session, ProceedHttpMethod httpMethod, std::ofstream& file) {
    if (httpMethod == ProceedHttpMethod::DOWNLOAD_FILE_REQUEST) {
        return session.Download(file);
    }
    throw std::invalid_argument{"std::ofstream argument is only valid for ProceedHttpMethod::DOWNLOAD_FILE!"};
}

Response Interceptor::proceed(Session& session, ProceedHttpMethod httpMethod, const WriteCallback& write) {
    if (httpMethod == ProceedHttpMethod::DOWNLOAD_CALLBACK_REQUEST) {
        return session.Download(write);
    }
    throw std::invalid_argument{"WriteCallback argument is only valid for ProceedHttpMethod::DOWNLOAD_CALLBACK!"};
}

std::vector<Response> InterceptorMulti::proceed(MultiPerform& multi) {
    return multi.proceed();
}

void InterceptorMulti::PrepareDownloadSession(MultiPerform& multi, size_t sessions_index, const WriteCallback& write) {
    multi.PrepareDownloadSessions(sessions_index, write);
}
} // namespace cpr


================================================
FILE: cpr/multipart.cpp
================================================
#include "cpr/multipart.h"
#include <initializer_list>
#include <vector>

namespace cpr {
Multipart::Multipart(const std::initializer_list<Part>& p_parts) : parts{p_parts} {}
Multipart::Multipart(const std::vector<Part>& p_parts) : parts{p_parts} {}
Multipart::Multipart(const std::vector<Part>&& p_parts) : parts{p_parts} {}
} // namespace cpr


================================================
FILE: cpr/multiperform.cpp
================================================
#include "cpr/multiperform.h"

#include "cpr/callback.h"
#include "cpr/curlmultiholder.h"
#include "cpr/interceptor.h"
#include "cpr/response.h"
#include "cpr/session.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <curl/curl.h>
#include <curl/curlver.h>
#include <curl/multi.h>
#include <functional>
#include <iosfwd>
#include <iostream>
#include <memory>
#include <optional>
#include <stdexcept>
#include <utility>
#include <vector>

namespace cpr {

MultiPerform::MultiPerform() : multicurl_(new CurlMultiHolder()) {
    current_interceptor_ = interceptors_.end();
    first_interceptor_ = interceptors_.end();
}

MultiPerform::MultiPerform(MultiPerform&& old) noexcept {
    *this = std::move(old);
}

MultiPerform& MultiPerform::operator=(MultiPerform&& old) noexcept {
    sessions_ = std::move(old.sessions_);
    multicurl_ = std::move(old.multicurl_);
    interceptors_ = std::move(old.interceptors_);
    current_interceptor_ = interceptors_.end();
    first_interceptor_ = interceptors_.end();
    return *this;
}

MultiPerform::~MultiPerform() {
    // Unlock all sessions
    for (const auto& [session, method] : sessions_) {
        session->isUsedInMultiPerform = false;

        // Remove easy handle from multi handle
        const CURLMcode error_code = curl_multi_remove_handle(multicurl_->handle, session->curl_->handle);
        if (error_code) {
            std::cerr << "curl_multi_remove_handle() failed, code " << static_cast<int>(error_code) << '\n';
        }
    }
}

void MultiPerform::AddSession(std::shared_ptr<Session>& session, HttpMethod method) {
    // Check if this multiperform is download only
    if (((method != HttpMethod::DOWNLOAD_REQUEST && is_download_multi_perform) && method != HttpMethod::UNDEFINED) || (method == HttpMethod::DOWNLOAD_REQUEST && !is_download_multi_perform && !sessions_.empty())) {
        // Currently it is not possible to mix download and non-download methods, as download needs additional parameters
        throw std::invalid_argument("Failed to add session: Cannot mix download and non-download methods!");
    }

    // Set download only if neccessary
    if (method == HttpMethod::DOWNLOAD_REQUEST) {
        is_download_multi_perform = true;
    }

    // Lock session to the multihandle
    session->isUsedInMultiPerform = true;

    // Add session to sessions_
    sessions_.emplace_back(session, method);
}

void MultiPerform::RemoveSession(const std::shared_ptr<Session>& session) {
    if (sessions_.empty()) {
        throw std::invalid_argument("Failed to find session!");
    }

    // Unlock session
    session->isUsedInMultiPerform = false;

    // Remove session from sessions_
    auto it = std::find_if(sessions_.begin(), sessions_.end(), [&session](const std::pair<std::shared_ptr<Session>, HttpMethod>& pair) { return session->curl_->handle == pair.first->curl_->handle; });
    if (it == sessions_.end()) {
        throw std::invalid_argument("Failed to find session!");
    }
    sessions_.erase(it);

    // Reset download only if empty
    if (sessions_.empty()) {
        is_download_multi_perform = false;
    }
}

std::vector<std::pair<std::shared_ptr<Session>, MultiPerform::HttpMethod>>& MultiPerform::GetSessions() {
    return sessions_;
}

const std::vector<std::pair<std::shared_ptr<Session>, MultiPerform::HttpMethod>>& MultiPerform::GetSessions() const {
    return sessions_;
}

void MultiPerform::DoMultiPerform() {
    // Do multi perform until every handle has finished
    int still_running{0};
    for (const auto& [session, _] : sessions_) {
        const CURLMcode error_code = curl_multi_add_handle(multicurl_->handle, session->curl_->handle);
        if (error_code && error_code != CURLM_ADDED_ALREADY) {
            std::cerr << "curl_multi_add_handle() failed, code " << static_cast<int>(error_code) << '\n';
        }
    }
    do {
        CURLMcode error_code = curl_multi_perform(multicurl_->handle, &still_running);
        if (error_code) {
            std::cerr << "curl_multi_perform() failed, code " << static_cast<int>(error_code) << '\n';
            break;
        }

        if (still_running) {
            const int timeout_ms{250};
#if LIBCURL_VERSION_NUM >= 0x074200 // 7.66.0
            error_code = curl_multi_poll(multicurl_->handle, nullptr, 0, timeout_ms, nullptr);
            if (error_code) {
                std::cerr << "curl_multi_poll() failed, code " << static_cast<int>(error_code) << '\n';
#else
            error_code = curl_multi_wait(multicurl_->handle, nullptr, 0, timeout_ms, nullptr);
            if (error_code) {
                std::cerr << "curl_multi_wait() failed, code " << static_cast<int>(error_code) << '\n';

#endif
                break;
            }
        }
    } while (still_running);
}

std::vector<Response> MultiPerform::ReadMultiInfo(const std::function<Response(Session&, CURLcode)>& complete_function) {
    // Get infos and create Response objects
    std::vector<Response> responses;
    struct CURLMsg* info{nullptr};
    do {
        int msgq = 0;

        // Read info from multihandle
        info = curl_multi_info_read(multicurl_->handle, &msgq);

        if (info) {
            // Find current session
            auto it = std::find_if(sessions_.begin(), sessions_.end(), [&info](const std::pair<std::shared_ptr<Session>, HttpMethod>& pair) { return pair.first->curl_->handle == info->easy_handle; });
            if (it == sessions_.end()) {
                std::cerr << "Failed to find current session!" << '\n';
                break;
            }
            const std::shared_ptr<Session> current_session = (*it).first;

            // Add response object
            // NOLINTNEXTLINE (cppcoreguidelines-pro-type-union-access)
            responses.push_back(complete_function(*current_session, info->data.result));
        }
    } while (info);

    for (const auto& [session, _] : sessions_) {
        const CURLMcode error_code = curl_multi_remove_handle(multicurl_->handle, session->curl_->handle);
        if (error_code) {
            std::cerr << "curl_multi_remove_handle() failed, code " << static_cast<int>(error_code) << '\n';
        }
    }

    // Sort response objects to match order of added sessions
    std::vector<Response> sorted_responses;
    for (const auto& [session, _] : sessions_) {
        Session& current_session = *session;
        auto it = std::find_if(responses.begin(), responses.end(), [&current_session](const Response& response) { return current_session.curl_->handle == response.curl_->handle; });
        const Response current_response = *it; // NOLINT (performance-unnecessary-copy-initialization) False positive
        // Erase response from original vector to increase future search speed
        responses.erase(it);
        sorted_responses.push_back(current_response);
    }
    return sorted_responses;
}

std::vector<Response> MultiPerform::MakeRequest() {
    const std::optional<std::vector<Response>> r = intercept();
    if (r.has_value()) {
        return r.value();
    }

    DoMultiPerform();
    return ReadMultiInfo([](Session& session, CURLcode curl_error) -> Response { return session.Complete(curl_error); });
}

std::vector<Response> MultiPerform::MakeDownloadRequest() {
    const std::optional<std::vector<Response>> r = intercept();
    if (r.has_value()) {
        return r.value();
    }

    DoMultiPerform();
    return ReadMultiInfo([](Session& session, CURLcode curl_error) -> Response { return session.CompleteDownload(curl_error); });
}

void MultiPerform::PrepareSessions() {
    for (const auto& [session, method] : sessions_) {
        switch (method) {
            case HttpMethod::GET_REQUEST:
                session->PrepareGet();
                break;
            case HttpMethod::POST_REQUEST:
                session->PreparePost();
                break;
            case HttpMethod::PUT_REQUEST:
                session->PreparePut();
                break;
            case HttpMethod::DELETE_REQUEST:
                session->PrepareDelete();
                break;
            case HttpMethod::PATCH_REQUEST:
                session->PreparePatch();
                break;
            case HttpMethod::HEAD_REQUEST:
                session->PrepareHead();
                break;
            case HttpMethod::OPTIONS_REQUEST:
                session->PrepareOptions();
                break;
            default:
                std::cerr << "PrepareSessions failed: Undefined HttpMethod or download without arguments!" << '\n';
                return;
        }
    }
}

void MultiPerform::PrepareDownloadSession(size_t sessions_index, const WriteCallback& write) {
    const auto& [session, method] = sessions_[sessions_index];
    switch (method) {
        case HttpMethod::DOWNLOAD_REQUEST:
            session->PrepareDownload(write);
            break;
        default:
            std::cerr << "PrepareSessions failed: Undefined HttpMethod or non download method with arguments!" << '\n';
            return;
    }
}

void MultiPerform::PrepareDownloadSession(size_t sessions_index, std::ofstream& file) {
    const auto& [session, method] = sessions_[sessions_index];
    switch (method) {
        case HttpMethod::DOWNLOAD_REQUEST:
            session->PrepareDownload(file);
            break;
        default:
            std::cerr << "PrepareSessions failed: Undefined HttpMethod or non download method with arguments!" << '\n';
            return;
    }
}

void MultiPerform::SetHttpMethod(HttpMethod method) {
    for (auto& [_, session_method] : sessions_) {
        session_method = method;
    }
}

void MultiPerform::PrepareGet() {
    SetHttpMethod(HttpMethod::GET_REQUEST);
    PrepareSessions();
}

void MultiPerform::PrepareDelete() {
    SetHttpMethod(HttpMethod::DELETE_REQUEST);
    PrepareSessions();
}

void MultiPerform::PreparePut() {
    SetHttpMethod(HttpMethod::PUT_REQUEST);
    PrepareSessions();
}

void MultiPerform::PreparePatch() {
    SetHttpMethod(HttpMethod::PATCH_REQUEST);
    PrepareSessions();
}

void MultiPerform::PrepareHead() {
    SetHttpMethod(HttpMethod::HEAD_REQUEST);
    PrepareSessions();
}

void MultiPerform::PrepareOptions() {
    SetHttpMethod(HttpMethod::OPTIONS_REQUEST);
    PrepareSessions();
}

void MultiPerform::PreparePost() {
    SetHttpMethod(HttpMethod::POST_REQUEST);
    PrepareSessions();
}

std::vector<Response> MultiPerform::Get() {
    PrepareGet();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Delete() {
    PrepareDelete();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Put() {
    PreparePut();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Head() {
    PrepareHead();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Options() {
    PrepareOptions();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Patch() {
    PreparePatch();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Post() {
    PreparePost();
    return MakeRequest();
}

std::vector<Response> MultiPerform::Perform() {
    PrepareSessions();
    return MakeRequest();
}

std::vector<Response> MultiPerform::proceed() {
    // Check if this multiperform mixes download and non download requests
    if (!sessions_.empty()) {
        const bool new_is_download_multi_perform = sessions_.front().second == HttpMethod::DOWNLOAD_REQUEST;

        for (const auto& [_, method] : sessions_) {
            if ((new_is_download_multi_perform && method != HttpMethod::DOWNLOAD_REQUEST) || (!new_is_download_multi_perform && method == HttpMethod::DOWNLOAD_REQUEST)) {
                throw std::invalid_argument("Failed to proceed with session: Cannot mix download and non-download methods!");
            }
        }
        is_download_multi_perform = new_is_download_multi_perform;
    }

    PrepareSessions();
    return MakeRequest();
}

const std::optional<std::vector<Response>> MultiPerform::intercept() {
    if (current_interceptor_ == interceptors_.end()) {
        current_interceptor_ = first_interceptor_;
    } else {
        current_interceptor_++;
    }

    if (current_interceptor_ != interceptors_.end()) {
        auto icpt = current_interceptor_;
        // Nested makeRequest() start at first_interceptor_, thus excluding previous interceptors.
        first_interceptor_ = current_interceptor_;
        ++first_interceptor_;

        const std::optional<std::vector<Response>> r = (*current_interceptor_)->intercept(*this);

        first_interceptor_ = icpt;

        return r;
    }
    return std::nullopt;
}

void MultiPerform::AddInterceptor(const std::shared_ptr<InterceptorMulti>& pinterceptor) {
    // Shall only add before first interceptor run
    assert(current_interceptor_ == interceptors_.end());
    interceptors_.push_back(pinterceptor);
    first_interceptor_ = interceptors_.begin();
}

} // namespace cpr


================================================
FILE: cpr/parameters.cpp
================================================
// NOLINTNEXTLINE(misc-include-cleaner) Ignored since it's for the future
#include "cpr/parameters.h"

namespace cpr {} // namespace cpr


================================================
FILE: cpr/payload.cpp
================================================
// NOLINTNEXTLINE(misc-include-cleaner) Ignored since it's for the future
#include "cpr/payload.h"

namespace cpr {} // namespace cpr


================================================
FILE: cpr/proxies.cpp
================================================
#include "cpr/proxies.h"

#include <initializer_list>
#include <map>
#include <string>
#include <utility>

namespace cpr {

Proxies::Proxies(const std::initializer_list<std::pair<const std::string, std::string>>& hosts) : hosts_{hosts} {}
Proxies::Proxies(const std::map<std::string, std::string>& hosts) : hosts_{hosts} {}

bool Proxies::has(const std::string& protocol) const {
    return hosts_.count(protocol) > 0;
}

const std::string& Proxies::operator[](const std::string& protocol) {
    return hosts_[protocol];
}

} // namespace cpr


================================================
FILE: cpr/proxyauth.cpp
================================================
#include "cpr/proxyauth.h"
#include "cpr/secure_string.h"
#include <string>
#include <string_view>

namespace cpr {

std::string_view EncodedAuthentication::GetUsername() const {
    return username;
}

std::string_view EncodedAuthentication::GetPassword() const {
    return password;
}

const util::SecureString& EncodedAuthentication::GetUsernameUnderlying() const {
    return username;
}

const util::SecureString& EncodedAuthentication::GetPasswordUnderlying() const {
    return password;
}

bool ProxyAuthentication::has(const std::string& protocol) const {
    return proxyAuth_.count(protocol) > 0;
}

std::string_view ProxyAuthentication::GetUsername(const std::string& protocol) {
    return proxyAuth_[protocol].GetUsername();
}

std::string_view ProxyAuthentication::GetPassword(const std::string& protocol) {
    return proxyAuth_[protocol].GetPassword();
}

const util::SecureString& ProxyAuthentication::GetUsernameUnderlying(const std::string& protocol) const {
    return proxyAuth_.at(protocol).GetUsernameUnderlying();
}

const util::SecureString& ProxyAuthentication::GetPasswordUnderlying(const std::string& protocol) const {
    return proxyAuth_.at(protocol).GetPasswordUnderlying();
}

} // namespace cpr


================================================
FILE: cpr/redirect.cpp
================================================
#include "cpr/redirect.h"
#include <cstdint>

namespace cpr {
PostRedirectFlags operator|(PostRedirectFlags lhs, PostRedirectFlags rhs) {
    return static_cast<PostRedirectFlags>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
}

PostRedirectFlags operator&(PostRedirectFlags lhs, PostRedirectFlags rhs) {
    return static_cast<PostRedirectFlags>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
}

PostRedirectFlags operator^(PostRedirectFlags lhs, PostRedirectFlags rhs) {
    return static_cast<PostRedirectFlags>(static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs));
}

PostRedirectFlags operator~(PostRedirectFlags flag) {
    return static_cast<PostRedirectFlags>(~static_cast<uint8_t>(flag));
}

PostRedirectFlags& operator|=(PostRedirectFlags& lhs, PostRedirectFlags rhs) {
    lhs = static_cast<PostRedirectFlags>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
    const uint8_t tmp = static_cast<uint8_t>(lhs);
    lhs = static_cast<PostRedirectFlags>(tmp);
    return lhs;
}

PostRedirectFlags& operator&=(PostRedirectFlags& lhs, PostRedirectFlags rhs) {
    lhs = static_cast<PostRedirectFlags>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
    return lhs;
}

PostRedirectFlags& operator^=(PostRedirectFlags& lhs, PostRedirectFlags rhs) {
    lhs = static_cast<PostRedirectFlags>(static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs));
    return lhs;
}

bool any(PostRedirectFlags flag) {
    return flag != PostRedirectFlags::NONE;
}
} // namespace cpr


================================================
FILE: cpr/response.cpp
================================================
#include "cpr/response.h"
#include <cassert>
#include <cpr/cert_info.h>
#include <cpr/cookies.h>
#include <cpr/cprtypes.h>
#include <cpr/curlholder.h>
#include <cpr/error.h>
#include <cpr/util.h>
#include <curl/curl.h>
#include <curl/curlver.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace cpr {

Response::Response(std::shared_ptr<CurlHolder> curl, std::string&& p_text, std::string&& p_header_string, Cookies&& p_cookies = Cookies{}, Error&& p_error = Error{}) : curl_(std::move(curl)), text(std::move(p_text)), cookies(std::move(p_cookies)), error(std::move(p_error)), raw_header(std::move(p_header_string)) {
    header = cpr::util::parseHeader(raw_header, &status_line, &reason);
    assert(curl_);
    assert(curl_->handle);
    curl_easy_getinfo(curl_->handle, CURLINFO_RESPONSE_CODE, &status_code);
    curl_easy_getinfo(curl_->handle, CURLINFO_TOTAL_TIME, &elapsed);
    const char* url_string{nullptr};
    curl_easy_getinfo(curl_->handle, CURLINFO_EFFECTIVE_URL, &url_string);
    url = Url(url_string);
#if LIBCURL_VERSION_NUM >= 0x073700 // 7.55.0
    curl_easy_getinfo(curl_->handle, CURLINFO_SIZE_DOWNLOAD_T, &downloaded_bytes);
    curl_easy_getinfo(curl_->handle, CURLINFO_SIZE_UPLOAD_T, &uploaded_bytes);
#else
    double downloaded_bytes_double, uploaded_bytes_double;
    curl_easy_getinfo(curl_->handle, CURLINFO_SIZE_DOWNLOAD, &downloaded_bytes_double);
    curl_easy_getinfo(curl_->handle, CURLINFO_SIZE_UPLOAD, &uploaded_bytes_double);
    downloaded_bytes = downloaded_bytes_double;
    uploaded_bytes = uploaded_bytes_double;
#endif
    curl_easy_getinfo(curl_->handle, CURLINFO_REDIRECT_COUNT, &redirect_count);
#if LIBCURL_VERSION_NUM >= 0x071300 // 7.19.0
    const char* ip_ptr{nullptr};
    if (curl_easy_getinfo(curl_->handle, CURLINFO_PRIMARY_IP, &ip_ptr) == CURLE_OK && ip_ptr) {
        primary_ip = ip_ptr;
    }
#endif
#if LIBCURL_VERSION_NUM >= 0x071500 // 7.21.0
    // Ignored here since libcurl uses a long for this.
    // NOLINTNEXTLINE(google-runtime-int)
    long port = 0;
    if (curl_easy_getinfo(curl_->handle, CURLINFO_PRIMARY_PORT, &port) == CURLE_OK) {
        primary_port = port;
    }
#endif
}

std::vector<CertInfo> Response::GetCertInfos() const {
    assert(curl_);
    assert(curl_->handle);
    const curl_certinfo* ci{nullptr};
    curl_easy_getinfo(curl_->handle, CURLINFO_CERTINFO, &ci);

    std::vector<CertInfo> cert_infos;
    for (int i = 0; i < ci->num_of_certs; i++) {
        CertInfo cert_info;
        // NOLINTNEXTLINE (cppcoreguidelines-pro-bounds-pointer-arithmetic)
        for (curl_slist* slist = ci->certinfo[i]; slist; slist = slist->next) {
            cert_info.emplace_back(std::string{slist->data});
        }
        cert_infos.emplace_back(cert_info);
    }
    return cert_infos;
}
} // namespace cpr


================================================
FILE: cpr/session.cpp
================================================
#include "cpr/session.h"

#include <array>
#include <atomic>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>

#include <curl/curl.h>
#include <curl/curlver.h>
#include <curl/easy.h>
#include <curl/system.h>

#include "cpr/accept_encoding.h"
#include "cpr/async.h"
#include "cpr/auth.h"
#include "cpr/bearer.h"
#include "cpr/body.h"
#include "cpr/body_view.h"
#include "cpr/callback.h"
#include "cpr/connect_timeout.h"
#include "cpr/connection_pool.h"
#include "cpr/cookies.h"
#include "cpr/cprtypes.h"
#include "cpr/curlholder.h"
#include "cpr/error.h"
#include "cpr/file.h"
#include "cpr/filesystem.h" // IWYU pragma: keep
#include "cpr/http_version.h"
#include "cpr/interceptor.h"
#include "cpr/interface.h"
#include "cpr/limit_rate.h"
#include "cpr/local_port.h"
#include "cpr/local_port_range.h"
#include "cpr/low_speed.h"
#include "cpr/multipart.h"
#include "cpr/parameters.h"
#include "cpr/payload.h"
#include "cpr/proxies.h"
#include "cpr/proxyauth.h"
#include "cpr/range.h"
#include "cpr/redirect.h"
#include "cpr/reserve_size.h"
#include "cpr/resolve.h"
#include "cpr/response.h"
#include "cpr/ssl_options.h"
#include "cpr/timeout.h"
#include "cpr/unix_socket.h"
#include "cpr/user_agent.h"
#include "cpr/util.h"
#include "cpr/verbose.h"

#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
#include "cpr/ssl_ctx.h"
#endif


namespace cpr {
// Ignored here since libcurl reqires a long:
// NOLINTNEXTLINE(google-runtime-int)
constexpr long ON = 1L;
// Ignored here since libcurl reqires a long:
// NOLINTNEXTLINE(google-runtime-int)
constexpr long OFF = 0L;

CURLcode Session::DoEasyPerform() {
    if (isUsedInMultiPerform) {
        std::cerr << "curl_easy_perform cannot be executed if the CURL handle is used in a MultiPerform.\n";
        return CURLcode::CURLE_FAILED_INIT;
    }
    return curl_easy_perform(curl_->handle);
}

void Session::prepareHeader() {
    curl_slist* chunk = nullptr;
    for (const std::pair<const std::string, std::string>& item : header_) {
        std::string header_string = item.first;
        if (item.second.empty()) {
            header_string += ";";
        } else {
            header_string += ": " + item.second;
        }

        curl_slist* temp = curl_slist_append(chunk, header_string.c_str());
        if (temp) {
            chunk = temp;
        }
    }

    // Set the chunked transfer encoding in case it does not already exist:
    if (chunkedTransferEncoding_ && header_.find("Transfer-Encoding") == header_.end()) {
        curl_slist* temp = curl_slist_append(chunk, "Transfer-Encoding:chunked");
        if (temp) {
            chunk = temp;
        }
    }

    // libcurl would prepare the header "Expect: 100-continue" by default when uploading files larger than 1 MB.
    // Here we would like to disable this feature:
    curl_slist* temp = curl_slist_append(chunk, "Expect:");
    if (temp) {
        chunk = temp;
    }

    curl_easy_setopt(curl_->handle, CURLOPT_HTTPHEADER, chunk);

    curl_slist_free_all(curl_->chunk);
    curl_->chunk = chunk;
}

void Session::prepareProxy() {
    const std::string protocol = url_.str().substr(0, url_.str().find(':'));
    if (proxies_.has(protocol)) {
        curl_easy_setopt(curl_->handle, CURLOPT_PROXY, proxies_[protocol].c_str());
        if (proxyAuth_.has(protocol)) {
            curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERNAME, proxyAuth_.GetUsernameUnderlying(protocol).c_str());
            curl_easy_setopt(curl_->handle, CURLOPT_PROXYPASSWORD, proxyAuth_.GetPasswordUnderlying(protocol).c_str());
        }
    }
}

// Only supported with libcurl >= 7.61.0.
// As an alternative use SetHeader and add the token manually.
#if LIBCURL_VERSION_NUM >= 0x073D00
void Session::SetBearer(const Bearer& token) {
    // Ignore here since this has been defined by libcurl.
    curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
    curl_easy_setopt(curl_->handle, CURLOPT_XOAUTH2_BEARER, token.GetToken());
}
#endif

Session::Session() : curl_(new CurlHolder()) {
    // Set up some sensible defaults
    const curl_version_info_data* version_info = curl_version_info(CURLVERSION_NOW);
    const std::string version = "curl/" + std::string{version_info->version};
    curl_easy_setopt(curl_->handle, CURLOPT_USERAGENT, version.c_str());
    SetRedirect(Redirect());
    curl_easy_setopt(curl_->handle, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(curl_->handle, CURLOPT_ERRORBUFFER, curl_->error.data());
    curl_easy_setopt(curl_->handle, CURLOPT_COOKIEFILE, "");
#ifdef CPR_CURL_NOSIGNAL
    curl_easy_setopt(curl_->handle, CURLOPT_NOSIGNAL, 1L);
#endif

#if LIBCURL_VERSION_NUM >= 0x071900 // 7.25.0
    curl_easy_setopt(curl_->handle, CURLOPT_TCP_KEEPALIVE, 1L);
#endif
    current_interceptor_ = interceptors_.end();
    first_interceptor_ = interceptors_.end();
}

Response Session::makeDownloadRequest() {
    const std::optional<Response> r = intercept();
    if (r.has_value()) {
        return r.value();
    }

    const CURLcode curl_error = DoEasyPerform();

    return CompleteDownload(curl_error);
}

void Session::prepareCommonShared() {
    assert(curl_->handle);

    // Set Header:
    prepareHeader();

    // URL parameter:
    const std::string parametersContent = parameters_.GetContent(*curl_);
    if (!parametersContent.empty()) {
        const Url new_url{url_ + "?" + parametersContent};
        curl_easy_setopt(curl_->handle, CURLOPT_URL, new_url.c_str());
    } else {
        curl_easy_setopt(curl_->handle, CURLOPT_URL, url_.c_str());
    }

    // Proxy:
    prepareProxy();

    // handle NO_PROXY override passed through Proxies object
    // Example: Proxies{"no_proxy": ""} will override environment variable definition with an empty list
    const std::array<std::string, 2> no_proxy{"no_proxy", "NO_PROXY"};
    for (const auto& item : no_proxy) { // cppcheck-suppress useStlAlgorithm
        if (proxies_.has(item)) {       // cppcheck-suppress useStlAlgorithm
            curl_easy_setopt(curl_->handle, CURLOPT_NOPROXY, proxies_[item].c_str());
            break;
        }
    }

#if LIBCURL_VERSION_NUM >= 0x071506 // 7.21.6
    if (acceptEncoding_.empty()) {
        // Enable all supported built-in compressions
        curl_easy_setopt(curl_->handle, CURLOPT_ACCEPT_ENCODING, "");
    } else if (acceptEncoding_.disabled()) {
        // Disable curl adding the 'Accept-Encoding' header
        curl_easy_setopt(curl_->handle, CURLOPT_ACCEPT_ENCODING, nullptr);
    } else {
        curl_easy_setopt(curl_->handle, CURLOPT_ACCEPT_ENCODING, acceptEncoding_.getString().c_str());
    }
#endif

    curl_->error[0] = '\0';

    // Clear the response
    response_string_.clear();
    if (response_string_reserve_size_ > 0) {
        response_string_.reserve(response_string_reserve_size_);
    }

    // Enable so we are able to retrieve certificate information:
    curl_easy_setopt(curl_->handle, CURLOPT_CERTINFO, 1L);
}

void Session::prepareCommon() {
    assert(curl_->handle);

    // Everything else:
    prepareCommonShared();

    // Set Content:
    prepareBodyPayloadOrMultipart();

    if (!cbs_->writecb_.callback && !cbs_->ssecb_.callback) {
        curl_easy_setopt(curl_->handle, CURLOPT_WRITEFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl_->handle, CURLOPT_WRITEDATA, &response_string_);
    }

    header_string_.clear();
    if (!cbs_->headercb_.callback) {
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERDATA, &header_string_);
    }
}

void Session::prepareCommonDownload() {
    assert(curl_->handle);

    // Everything else:
    prepareCommonShared();

    header_string_.clear();
    if (cbs_->headercb_.callback) {
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERFUNCTION, cpr::util::headerUserFunction);
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERDATA, &cbs_->headercb_);
    } else {
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERFUNCTION, cpr::util::writeFunction);
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERDATA, &header_string_);
    }
}

Response Session::makeRequest() {
    const std::optional<Response> r = intercept();
    if (r.has_value()) {
        return r.value();
    }

    const CURLcode curl_error = DoEasyPerform();

    return Complete(curl_error);
}

void Session::SetLimitRate(const LimitRate& limit_rate) {
    curl_easy_setopt(curl_->handle, CURLOPT_MAX_RECV_SPEED_LARGE, limit_rate.downrate);
    curl_easy_setopt(curl_->handle, CURLOPT_MAX_SEND_SPEED_LARGE, limit_rate.uprate);
}

const Content& Session::GetContent() const {
    return content_;
}

void Session::RemoveContent() {
    // inverse function to prepareBodyPayloadOrMultipart()
    if (std::holds_alternative<cpr::Payload>(content_) || std::holds_alternative<cpr::Body>(content_)) {
        // set default values, so curl does not send a body in subsequent requests
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, -1);
        curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, nullptr);
    } else if (std::holds_alternative<cpr::Multipart>(content_)) {
        if (curl_->multipart) {
            // remove multipart data
            curl_mime_free(curl_->multipart);
            curl_->multipart = nullptr;
        }
    } else if (std::holds_alternative<cpr::BodyView>(content_)) {
        // set default values, so curl does not send a body in subsequent requests
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, -1);
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, nullptr);
    }
    content_ = std::monostate{};
}

void Session::SetReadCallback(const ReadCallback& read) {
    cbs_->readcb_ = read;
    curl_easy_setopt(curl_->handle, CURLOPT_INFILESIZE_LARGE, read.size);
    curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, read.size);
    curl_easy_setopt(curl_->handle, CURLOPT_READFUNCTION, cpr::util::readUserFunction);
    curl_easy_setopt(curl_->handle, CURLOPT_READDATA, &cbs_->readcb_);
    chunkedTransferEncoding_ = read.size == -1;
}

void Session::SetHeaderCallback(const HeaderCallback& header) {
    curl_easy_setopt(curl_->handle, CURLOPT_HEADERFUNCTION, cpr::util::headerUserFunction);
    cbs_->headercb_ = header;
    curl_easy_setopt(curl_->handle, CURLOPT_HEADERDATA, &cbs_->headercb_);
}

void Session::SetWriteCallback(const WriteCallback& write) {
    curl_easy_setopt(curl_->handle, CURLOPT_WRITEFUNCTION, cpr::util::writeUserFunction);
    cbs_->writecb_ = write;
    curl_easy_setopt(curl_->handle, CURLOPT_WRITEDATA, &cbs_->writecb_);
}

void Session::SetServerSentEventCallback(const ServerSentEventCallback& sse) {
    curl_easy_setopt(curl_->handle, CURLOPT_WRITEFUNCTION, cpr::util::writeSSEFunction);
    cbs_->ssecb_ = sse;
    curl_easy_setopt(curl_->handle, CURLOPT_WRITEDATA, &cbs_->ssecb_);
}

void Session::SetProgressCallback(const ProgressCallback& progress) {
    cbs_->progresscb_ = progress;
    if (isCancellable) {
        cbs_->cancellationcb_.SetProgressCallback(cbs_->progresscb_);
        return;
    }
#if LIBCURL_VERSION_NUM < 0x072000 // 7.32.0
    curl_easy_setopt(curl_->handle, CURLOPT_PROGRESSFUNCTION, cpr::util::progressUserFunction<ProgressCallback>);
    curl_easy_setopt(curl_->handle, CURLOPT_PROGRESSDATA, &cbs_->progresscb_);
#else
    curl_easy_setopt(curl_->handle, CURLOPT_XFERINFOFUNCTION, cpr::util::progressUserFunction<ProgressCallback>);
    curl_easy_setopt(curl_->handle, CURLOPT_XFERINFODATA, &cbs_->progresscb_);
#endif
    curl_easy_setopt(curl_->handle, CURLOPT_NOPROGRESS, 0L);
}

void Session::SetDebugCallback(const DebugCallback& debug) {
    curl_easy_setopt(curl_->handle, CURLOPT_DEBUGFUNCTION, cpr::util::debugUserFunction);
    cbs_->debugcb_ = debug;
    curl_easy_setopt(curl_->handle, CURLOPT_DEBUGDATA, &cbs_->debugcb_);
    curl_easy_setopt(curl_->handle, CURLOPT_VERBOSE, 1L);
}

void Session::SetUrl(const Url& url) {
    url_ = url;
}

void Session::SetResolve(const Resolve& resolve) {
    SetResolves({resolve});
}

void Session::SetResolves(const std::vector<Resolve>& resolves) {
    curl_slist_free_all(curl_->resolveCurlList);
    curl_->resolveCurlList = nullptr;
    for (const Resolve& resolve : resolves) {
        for (const uint16_t port : resolve.ports) {
            curl_->resolveCurlList = curl_slist_append(curl_->resolveCurlList, (resolve.host + ":" + std::to_string(port) + ":" + resolve.addr).c_str());
        }
    }
    curl_easy_setopt(curl_->handle, CURLOPT_RESOLVE, curl_->resolveCurlList);
}

void Session::SetParameters(const Parameters& parameters) {
    parameters_ = parameters;
}

void Session::SetParameters(Parameters&& parameters) {
    parameters_ = std::move(parameters);
}

void Session::SetHeader(const Header& header) {
    header_ = header;
}

void Session::UpdateHeader(const Header& header) {
    for (const std::pair<const std::string, std::string>& item : header) {
        header_[item.first] = item.second;
    }
}

Header& Session::GetHeader() {
    return header_;
}

const Header& Session::GetHeader() const {
    return header_;
}

void Session::SetTimeout(const Timeout& timeout) {
    curl_easy_setopt(curl_->handle, CURLOPT_TIMEOUT_MS, timeout.Milliseconds());
}

void Session::SetConnectTimeout(const ConnectTimeout& timeout) {
    curl_easy_setopt(curl_->handle, CURLOPT_CONNECTTIMEOUT_MS, timeout.Milliseconds());
}

void Session::SetConnectionPool(const ConnectionPool& pool) {
    CURL* curl = curl_->handle;
    pool.SetupHandler(curl);
}

void Session::SetAuth(const Authentication& auth) {
    // Ignore here since this has been defined by libcurl.
    switch (auth.GetAuthMode()) {
        case AuthMode::BASIC:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString());
            break;
        case AuthMode::DIGEST:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
            curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString());
            break;
        case AuthMode::NTLM:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
            curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString());
            break;
        case AuthMode::NEGOTIATE:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_NEGOTIATE);
            curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString());
            break;
        case AuthMode::ANY:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
            curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString());
            break;
        case AuthMode::ANYSAFE:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
            curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString());
            break;
    }
}

void Session::SetUserAgent(const UserAgent& ua) {
    curl_easy_setopt(curl_->handle, CURLOPT_USERAGENT, ua.c_str());
}

void Session::SetPayload(const Payload& payload) {
    content_ = payload;
}

void Session::SetPayload(Payload&& payload) {
    content_ = std::move(payload);
}

void Session::SetProxies(const Proxies& proxies) {
    proxies_ = proxies;
}

void Session::SetProxies(Proxies&& proxies) {
    proxies_ = std::move(proxies);
}

void Session::SetProxyAuth(ProxyAuthentication&& proxy_auth) {
    proxyAuth_ = std::move(proxy_auth);
}

void Session::SetProxyAuth(const ProxyAuthentication& proxy_auth) {
    proxyAuth_ = proxy_auth;
}

void Session::SetMultipart(const Multipart& multipart) {
    content_ = multipart;
}

void Session::SetMultipart(Multipart&& multipart) {
    content_ = std::move(multipart);
}

void Session::SetRedirect(const Redirect& redirect) {
    curl_easy_setopt(curl_->handle, CURLOPT_FOLLOWLOCATION, redirect.follow ? 1L : 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_MAXREDIRS, redirect.maximum);
    curl_easy_setopt(curl_->handle, CURLOPT_UNRESTRICTED_AUTH, redirect.cont_send_cred ? 1L : 0L);

    // NOLINTNEXTLINE (google-runtime-int)
    long mask = 0;
    if (any(redirect.post_flags & PostRedirectFlags::POST_301)) {
        mask |= CURL_REDIR_POST_301;
    }
    if (any(redirect.post_flags & PostRedirectFlags::POST_302)) {
        mask |= CURL_REDIR_POST_302;
    }
    if (any(redirect.post_flags & PostRedirectFlags::POST_303)) {
        mask |= CURL_REDIR_POST_303;
    }
    curl_easy_setopt(curl_->handle, CURLOPT_POSTREDIR, mask);
}

void Session::SetCookies(const Cookies& cookies) {
    curl_easy_setopt(curl_->handle, CURLOPT_COOKIELIST, "ALL");
    curl_easy_setopt(curl_->handle, CURLOPT_COOKIE, cookies.GetEncoded(*curl_).c_str());
}

void Session::SetBody(const Body& body) {
    content_ = body;
}

void Session::SetBody(Body&& body) {
    content_ = std::move(body);
}

// cppcheck-suppress passedByValue
void Session::SetBodyView(BodyView body) {
    static_assert(std::is_trivially_copyable_v<BodyView>, "BodyView expected to be trivially copyable otherwise will need some std::move across codebase");
    content_ = body;
}

void Session::SetLowSpeed(const LowSpeed& low_speed) {
    curl_easy_setopt(curl_->handle, CURLOPT_LOW_SPEED_LIMIT, static_cast<long>(low_speed.limit));
    curl_easy_setopt(curl_->handle, CURLOPT_LOW_SPEED_TIME, static_cast<long>(low_speed.time.count())); // cppcheck-suppress y2038-unsafe-call
}

void Session::SetVerifySsl(const VerifySsl& verify) {
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_VERIFYPEER, verify ? ON : OFF);
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_VERIFYHOST, verify ? 2L : 0L);
}

void Session::SetUnixSocket(const UnixSocket& unix_socket) {
    curl_easy_setopt(curl_->handle, CURLOPT_UNIX_SOCKET_PATH, unix_socket.GetUnixSocketString());
}

void Session::SetSslOptions(const SslOptions& options) {
    if (!options.cert_file.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_SSLCERT, options.cert_file.c_str());
        if (!options.cert_type.empty()) {
            curl_easy_setopt(curl_->handle, CURLOPT_SSLCERTTYPE, options.cert_type.c_str());
        }
    }
#if SUPPORT_CURLOPT_SSLCERT_BLOB
    else if (!options.cert_blob.empty()) {
        std::string cert_blob(options.cert_blob);
        curl_blob blob{};
        // NOLINTNEXTLINE (readability-container-data-pointer)
        blob.data = &cert_blob[0];
        blob.len = cert_blob.length();
        blob.flags = CURL_BLOB_COPY;
        curl_easy_setopt(curl_->handle, CURLOPT_SSLCERT_BLOB, &blob);
        if (!options.cert_type.empty()) {
            curl_easy_setopt(curl_->handle, CURLOPT_SSLCERTTYPE, options.cert_type.c_str());
        }
    }
#endif
    if (!options.key_file.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_SSLKEY, options.key_file.c_str());
        if (!options.key_type.empty()) {
            curl_easy_setopt(curl_->handle, CURLOPT_SSLKEYTYPE, options.key_type.c_str());
        }
        if (!options.key_pass.empty()) {
            curl_easy_setopt(curl_->handle, CURLOPT_KEYPASSWD, options.key_pass.c_str());
        }
#if SUPPORT_CURLOPT_SSLKEY_BLOB
    } else if (!options.key_blob.empty()) {
        std::string key_blob(options.key_blob);
        curl_blob blob{};
        // NOLINTNEXTLINE (readability-container-data-pointer)
        blob.data = &key_blob[0];
        blob.len = key_blob.length();
        blob.flags = CURL_BLOB_COPY;
        curl_easy_setopt(curl_->handle, CURLOPT_SSLKEY_BLOB, &blob);
        if (!options.key_type.empty()) {
            curl_easy_setopt(curl_->handle, CURLOPT_SSLKEYTYPE, options.key_type.c_str());
        }
        if (!options.key_pass.empty()) {
            curl_easy_setopt(curl_->handle, CURLOPT_KEYPASSWD, options.key_pass.c_str());
        }
#endif
    }
    if (!options.pinned_public_key.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_PINNEDPUBLICKEY, options.pinned_public_key.c_str());
    }
#if SUPPORT_ALPN
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_ENABLE_ALPN, options.enable_alpn ? ON : OFF);
#endif
#if SUPPORT_NPN
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_ENABLE_NPN, options.enable_npn ? ON : OFF);
#endif
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_VERIFYPEER, options.verify_peer ? ON : OFF);
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_VERIFYHOST, options.verify_host ? 2L : 0L);
#if LIBCURL_VERSION_NUM >= 0x072900 // 7.41.0
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_VERIFYSTATUS, options.verify_status ? ON : OFF);
#endif

    int maxTlsVersion = options.ssl_version;
#if SUPPORT_MAX_TLS_VERSION
    maxTlsVersion |= options.max_version;
#endif

    curl_easy_setopt(curl_->handle, CURLOPT_SSLVERSION,
                     // Ignore here since this has been defined by libcurl.
                     maxTlsVersion);

    // NOLINTNEXTLINE (google-runtime-int)
    long curlSslOptions = 0;
#if SUPPORT_SSL_NO_REVOKE
    sslNoRevoke_ = options.ssl_no_revoke;
    if (options.ssl_no_revoke) {
        curlSslOptions |= CURLSSLOPT_NO_REVOKE;
    }
#endif
#if LIBCURL_VERSION_NUM >= 0x074700 // 7.71.0
    // Fix loading certs from Windows cert store when using OpenSSL:
    curlSslOptions |= CURLSSLOPT_NATIVE_CA;
#endif
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_OPTIONS, curlSslOptions);

    if (!options.ca_info.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_CAINFO, options.ca_info.c_str());
    }
#if SUPPORT_CURLOPT_CAINFO_BLOB
    if (!options.ca_info_blob.empty()) {
        std::string cainfo_blob(options.ca_info_blob);
        curl_blob blob{};
        blob.data = cainfo_blob.data();
        blob.len = cainfo_blob.length();
        blob.flags = CURL_BLOB_COPY;
        curl_easy_setopt(curl_->handle, CURLOPT_CAINFO_BLOB, &blob);
    }
#endif
    if (!options.ca_path.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_CAPATH, options.ca_path.c_str());
    }
#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
#ifdef OPENSSL_BACKEND_USED
    if (!options.ca_buffer.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_SSL_CTX_FUNCTION, sslctx_function_load_ca_cert_from_buffer);
        curl_easy_setopt(curl_->handle, CURLOPT_SSL_CTX_DATA, options.ca_buffer.c_str());
    }
#endif
#endif
    if (!options.crl_file.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_CRLFILE, options.crl_file.c_str());
    }
    if (!options.ciphers.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_SSL_CIPHER_LIST, options.ciphers.c_str());
    }
#if SUPPORT_TLSv13_CIPHERS
    if (!options.tls13_ciphers.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_TLS13_CIPHERS, options.tls13_ciphers.c_str());
    }
#endif
#if SUPPORT_SESSIONID_CACHE
    curl_easy_setopt(curl_->handle, CURLOPT_SSL_SESSIONID_CACHE, options.session_id_cache ? ON : OFF);
#endif
}

void Session::SetVerbose(const Verbose& verbose) {
    curl_easy_setopt(curl_->handle, CURLOPT_VERBOSE, verbose.verbose ? ON : OFF);
}

void Session::SetInterface(const Interface& iface) {
    if (iface.str().empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_INTERFACE, nullptr);
    } else {
        curl_easy_setopt(curl_->handle, CURLOPT_INTERFACE, iface.c_str());
    }
}

void Session::SetLocalPort(const LocalPort& local_port) {
    curl_easy_setopt(curl_->handle, CURLOPT_LOCALPORT, static_cast<long>(static_cast<uint16_t>(local_port)));
}

void Session::SetLocalPortRange(const LocalPortRange& local_port_range) {
    curl_easy_setopt(curl_->handle, CURLOPT_LOCALPORTRANGE, static_cast<long>(static_cast<uint16_t>(local_port_range)));
}

void Session::SetHttpVersion(const HttpVersion& version) {
    switch (version.code) {
        case HttpVersionCode::VERSION_NONE:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE);
            break;

        case HttpVersionCode::VERSION_1_0:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
            break;

        case HttpVersionCode::VERSION_1_1:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            break;

#if LIBCURL_VERSION_NUM >= 0x072100 // 7.33.0
        case HttpVersionCode::VERSION_2_0:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
            break;
#endif

#if LIBCURL_VERSION_NUM >= 0x072F00 // 7.47.0
        case HttpVersionCode::VERSION_2_0_TLS:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
            break;
#endif

#if LIBCURL_VERSION_NUM >= 0x073100 // 7.49.0
        case HttpVersionCode::VERSION_2_0_PRIOR_KNOWLEDGE:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
            break;
#endif

#if LIBCURL_VERSION_NUM >= 0x074200 // 7.66.0
        case HttpVersionCode::VERSION_3_0:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
            break;
#endif
#if LIBCURL_VERSION_NUM >= 0x075701 // 7.87.1, but corresponds to 7.88.0 tag
        case HttpVersionCode::VERSION_3_0_ONLY:
            curl_easy_setopt(curl_->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY);
            break;
#endif

        default: // Should not happen
            throw std::invalid_argument("Invalid/Unknown HTTP version type.");
    }
}

void Session::SetRange(const Range& range) {
    const std::string range_str = range.str();
    curl_easy_setopt(curl_->handle, CURLOPT_RANGE, range_str.c_str());
}

void Session::SetMultiRange(const MultiRange& multi_range) {
    const std::string multi_range_str = multi_range.str();
    curl_easy_setopt(curl_->handle, CURLOPT_RANGE, multi_range_str.c_str());
}

void Session::SetReserveSize(const ReserveSize& reserve_size) {
    ResponseStringReserve(reserve_size.size);
}

void Session::SetAcceptEncoding(const AcceptEncoding& accept_encoding) {
    acceptEncoding_ = accept_encoding;
}

void Session::SetAcceptEncoding(AcceptEncoding&& accept_encoding) {
    acceptEncoding_ = std::move(accept_encoding);
}

cpr_off_t Session::GetDownloadFileLength() {
    cpr_off_t downloadFileLength = -1;
    curl_easy_setopt(curl_->handle, CURLOPT_URL, url_.c_str());

    prepareProxy();

    curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1);
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 1);
    if (DoEasyPerform() == CURLE_OK) {
        // NOLINTNEXTLINE (google-runtime-int)
        long status_code{};
        curl_easy_getinfo(curl_->handle, CURLINFO_RESPONSE_CODE, &status_code);
        if (200 == status_code) {
            curl_easy_getinfo(curl_->handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &downloadFileLength);
        }
    }
    return downloadFileLength;
}

void Session::ResponseStringReserve(size_t size) {
    response_string_reserve_size_ = size;
}

Response Session::Delete() {
    PrepareDelete();
    return makeRequest();
}

Response Session::Download(const WriteCallback& write) {
    PrepareDownload(write);
    return makeDownloadRequest();
}

Response Session::Download(std::ofstream& file) {
    PrepareDownload(file);
    return makeDownloadRequest();
}

Response Session::Get() {
    PrepareGet();
    return makeRequest();
}

Response Session::Head() {
    PrepareHead();
    return makeRequest();
}

Response Session::Options() {
    PrepareOptions();
    return makeRequest();
}

Response Session::Patch() {
    PreparePatch();
    return makeRequest();
}

Response Session::Post() {
    PreparePost();
    return makeRequest();
}

Response Session::Put() {
    PreparePut();
    return makeRequest();
}

std::shared_ptr<Session> Session::GetSharedPtrFromThis() {
    try {
        return shared_from_this();
    } catch (std::bad_weak_ptr&) {
        throw std::runtime_error("Failed to get a shared pointer from this. The reason is probably that the session object is not managed by a shared pointer, which is required to use this functionality.");
    }
}

AsyncResponse Session::GetAsync() {
    auto shared_this = shared_from_this();
    return async([shared_this]() { return shared_this->Get(); });
}

AsyncResponse Session::DeleteAsync() {
    return async([shared_this = GetSharedPtrFromThis()]() { return shared_this->Delete(); });
}

AsyncResponse Session::DownloadAsync(const WriteCallback& write) {
    return async([shared_this = GetSharedPtrFromThis(), write]() { return shared_this->Download(write); });
}

AsyncResponse Session::DownloadAsync(std::ofstream& file) {
    return async([shared_this = GetSharedPtrFromThis(), &file]() { return shared_this->Download(file); });
}

AsyncResponse Session::HeadAsync() {
    return async([shared_this = GetSharedPtrFromThis()]() { return shared_this->Head(); });
}

AsyncResponse Session::OptionsAsync() {
    return async([shared_this = GetSharedPtrFromThis()]() { return shared_this->Options(); });
}

AsyncResponse Session::PatchAsync() {
    return async([shared_this = GetSharedPtrFromThis()]() { return shared_this->Patch(); });
}

AsyncResponse Session::PostAsync() {
    return async([shared_this = GetSharedPtrFromThis()]() { return shared_this->Post(); });
}

AsyncResponse Session::PutAsync() {
    return async([shared_this = GetSharedPtrFromThis()]() { return shared_this->Put(); });
}

std::shared_ptr<CurlHolder> Session::GetCurlHolder() {
    return curl_;
}

std::string Session::GetFullRequestUrl() {
    const std::string parametersContent = parameters_.GetContent(*curl_);
    return url_.str() + (parametersContent.empty() ? "" : "?") + parametersContent;
}

void Session::PrepareDelete() {
    curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "DELETE");
    prepareCommon();
}

void Session::PrepareGet() {
    // In case there is a body or payload for this request, we create a custom GET-Request since a
    // GET-Request with body is based on the HTTP RFC **not** a leagal request.
    if (hasBodyOrPayload()) {
        curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
        curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "GET");
    } else {
        curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
        curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr);
        curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1L);
    }
    prepareCommon();
}

void Session::PrepareHead() {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 1L);
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr);
    prepareCommon();
}

void Session::PrepareOptions() {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "OPTIONS");
    prepareCommon();
}

void Session::PreparePatch() {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "PATCH");
    prepareCommon();
}

void Session::PreparePost() {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);

    // In case there is no body or payload set it to an empty post:
    if (hasBodyOrPayload()) {
        curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr);
    } else {
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, cbs_->readcb_.callback ? nullptr : "");
        curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "POST");
    }
    prepareCommon();
}

void Session::PreparePut() {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
    if (!hasBodyOrPayload() && cbs_->readcb_.callback) {
        /**
         * Yes, this one has to be CURLOPT_POSTFIELDS even if we are performing a PUT request.
         * In case we don't set this one, performing a POST-request with PUT won't work.
         * It in theory this only enforces the usage of the readcallback for POST requests, but works here as well.
         **/
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, nullptr);
    }
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "PUT");
    curl_easy_setopt(curl_->handle, CURLOPT_RANGE, nullptr);
    prepareCommon();
}

void Session::PrepareDownload(std::ofstream& file) {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1);
    curl_easy_setopt(curl_->handle, CURLOPT_WRITEFUNCTION, cpr::util::writeFileFunction);
    curl_easy_setopt(curl_->handle, CURLOPT_WRITEDATA, &file);
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr);

    prepareCommonDownload();
}

void Session::PrepareDownload(const WriteCallback& write) {
    curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
    curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1);
    curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr);

    SetWriteCallback(write);

    prepareCommonDownload();
}

Response Session::Complete(CURLcode curl_error) {
    curl_slist* raw_cookies{nullptr};
    curl_easy_getinfo(curl_->handle, CURLINFO_COOKIELIST, &raw_cookies);
    Cookies cookies = util::parseCookies(raw_cookies);
    curl_slist_free_all(raw_cookies);

    std::string errorMsg = curl_->error.data();
    return Response(curl_, std::move(response_string_), std::move(header_string_), std::move(cookies), Error(curl_error, std::move(errorMsg)));
}

Response Session::CompleteDownload(CURLcode curl_error) {
    if (!cbs_->headercb_.callback) {
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERFUNCTION, nullptr);
        curl_easy_setopt(curl_->handle, CURLOPT_HEADERDATA, 0);
    }

    curl_slist* raw_cookies{nullptr};
    curl_easy_getinfo(curl_->handle, CURLINFO_COOKIELIST, &raw_cookies);
    Cookies cookies = util::parseCookies(raw_cookies);
    curl_slist_free_all(raw_cookies);
    std::string errorMsg = curl_->error.data();

    return Response(curl_, "", std::move(header_string_), std::move(cookies), Error(curl_error, std::move(errorMsg)));
}

void Session::AddInterceptor(const std::shared_ptr<Interceptor>& pinterceptor) {
    // Shall only add before first interceptor run
    assert(current_interceptor_ == interceptors_.end());
    interceptors_.push_back(pinterceptor);
    first_interceptor_ = interceptors_.begin();
}

Response Session::proceed() {
    prepareCommon();
    return makeRequest();
}

const std::optional<Response> Session::intercept() {
    if (current_interceptor_ == interceptors_.end()) {
        current_interceptor_ = first_interceptor_;
    } else {
        ++current_interceptor_;
    }

    if (current_interceptor_ != interceptors_.end()) {
        auto icpt = current_interceptor_;
        // Nested makeRequest() start at first_interceptor_, thus excluding previous interceptors.
        first_interceptor_ = current_interceptor_;
        ++first_interceptor_;

        const std::optional<Response> r = (*current_interceptor_)->intercept(*this);

        first_interceptor_ = icpt;

        return r;
    }
    return std::nullopt;
}

void Session::prepareBodyPayloadOrMultipart() const {
    // Either a body, multipart or a payload is allowed. Inverse function to RemoveContent()

    if (std::holds_alternative<cpr::Payload>(content_)) {
        const std::string payload = std::get<cpr::Payload>(content_).GetContent(*curl_);
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(payload.length()));
        curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, payload.c_str());
    } else if (std::holds_alternative<cpr::Body>(content_)) {
        const std::string& body = std::get<cpr::Body>(content_).str();
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(body.length()));
        curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, body.c_str());
    } else if (std::holds_alternative<cpr::BodyView>(content_)) {
        const std::string_view body = std::get<cpr::BodyView>(content_).str();
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(body.length()));
        // NOLINTNEXTLINE (bugprone-suspicious-stringview-data-usage)
        curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, body.data());
    } else if (std::holds_alternative<cpr::Multipart>(content_)) {
        // Make sure, we have a empty multipart to start with:
        if (curl_->multipart) {
            curl_mime_free(curl_->multipart);
        }
        curl_->multipart = curl_mime_init(curl_->handle);

        // Add all multipart pieces:
        const cpr::Multipart& multipart = std::get<cpr::Multipart>(content_);
        for (const Part& part : multipart.parts) {
            if (part.is_file) {
                for (const File& file : part.files) {
                    curl_mimepart* mimePart = curl_mime_addpart(curl_->multipart);
                    if (!part.content_type.empty()) {
                        curl_mime_type(mimePart, part.content_type.c_str());
                    }

                    curl_mime_filedata(mimePart, file.filepath.c_str());
                    curl_mime_name(mimePart, part.name.c_str());

                    if (file.hasOverridenFilename()) {
                        curl_mime_filename(mimePart, file.overriden_filename.c_str());
                    } else {
                        // NOLINTNEXTLINE (misc-include-cleaner)
                        curl_mime_filename(mimePart, fs::path(file.filepath).filename().string().c_str());
                    }
                }
            } else {
                curl_mimepart* mimePart = curl_mime_addpart(curl_->multipart);
                if (!part.content_type.empty()) {
                    curl_mime_type(mimePart, part.content_type.c_str());
                }
                if (part.is_buffer) {
                    // Do not use formdata, to prevent having to use reinterpreter_cast:
                    curl_mime_name(mimePart, part.name.c_str());
                    curl_mime_data(mimePart, part.data, part.datalen);
                    curl_mime_filename(mimePart, part.value.c_str());
                } else {
                    curl_mime_name(mimePart, part.name.c_str());
                    curl_mime_data(mimePart, part.value.c_str(), CURL_ZERO_TERMINATED);
                }
            }
        }

        curl_easy_setopt(curl_->handle, CURLOPT_MIMEPOST, curl_->multipart);
    }
}

[[nodiscard]] bool Session::hasBodyOrPayload() const {
    return std::holds_alternative<cpr::Body>(content_) || std::holds_alternative<cpr::BodyView>(content_) || std::holds_alternative<cpr::Payload>(content_);
}

// clang-format off
void Session::SetOption(const Resolve& resolve) { SetResolve(resolve); }
void Session::SetOption(const std::vector<Resolve>& resolves) { SetResolves(resolves); }
void Session::SetOption(const ReadCallback& read) { SetReadCallback(read); }
void Session::SetOption(const HeaderCallback& header) { SetHeaderCallback(header); }
void Session::SetOption(const WriteCallback& write) { SetWriteCallback(write); }
void Session::SetOption(const ProgressCallback& progress) { SetProgressCallback(progress); }
void Session::SetOption(const DebugCallback& debug) { SetDebugCallback(debug); }
void Session::SetOption(const ServerSentEventCallback& sse) { SetServerSentEventCallback(sse); }
void Session::SetOption(const Url& url) { SetUrl(url); }
void Session::SetOption(const Parameters& parameters) { SetParameters(parameters); }
void Session::SetOption(Parameters&& parameters) { SetParameters(std::move(parameters)); }
void Session::SetOption(const Header& header) { SetHeader(header); }
void Session::SetOption(const Timeout& timeout) { SetTimeout(timeout); }
void Session::SetOption(const ConnectTimeout& timeout) { SetConnectTimeout(timeout); }
void Session::SetOption(const Authentication& auth) { SetAuth(auth); }
void Session::SetOption(const LimitRate& limit_rate) { SetLimitRate(limit_rate); }
// Only supported with libcurl >= 7.61.0.
// As an alternative use SetHeader and add the token manually.
#if LIBCURL_VERSION_NUM >= 0x073D00
void Session::SetOption(const Bearer& auth) { SetBearer(auth); }
#endif
void Session::SetOption(const UserAgent& ua) { SetUserAgent(ua); }
void Session::SetOption(const Payload& payload) { SetPayload(payload); }
void Session::SetOption(Payload&& payload) { SetPayload(std::move(payload)); }
void Session::SetOption(const Proxies& proxies) { SetProxies(proxies); }
void Session::SetOption(Proxies&& proxies) { SetProxies(std::move(proxies)); }
void Session::SetOption(ProxyAuthentication&& proxy_auth) { SetProxyAuth(std::move(proxy_auth)); }
void Session::SetOption(const ProxyAuthentication& proxy_auth) { SetProxyAuth(proxy_auth); }
void Session::SetOption(const Multipart& multipart) { SetMultipart(multipart); }
void Session::SetOption(Multipart&& multipart) { SetMultipart(std::move(multipart)); }
void Session::SetOption(const Redirect& redirect) { SetRedirect(redirect); }
void Session::SetOption(const Cookies& cookies) { SetCookies(cookies); }
void Session::SetOption(const Body& body) { SetBody(body); }
void Session::SetOption(Body&& body) { SetBody(std::move(body)); }
// cppcheck-suppress passedByValue
void Session::SetOption(BodyView body) { SetBodyView(body); }
void Session::SetOption(const LowSpeed& low_speed) { SetLowSpeed(low_speed); }
void Session::SetOption(const VerifySsl& verify) { SetVerifySsl(verify); }
void Session::SetOption(const Verbose& verbose) { SetVerbose(verbose); }
void Session::SetOption(const UnixSocket& unix_socket) { SetUnixSocket(unix_socket); }
void Session::SetOption(const SslOptions& options) { SetSslOptions(options); }
void Session::SetOption(const Interface& iface) { SetInterface(iface); }
void Session::SetOption(const LocalPort& local_port) { SetLocalPort(local_port); }
void Session::SetOption(const LocalPortRange& local_port_range) { SetLocalPortRange(local_port_range); }
void Session::SetOption(const HttpVersion& version) { SetHttpVersion(version); }
void Session::SetOption(const Range& range) { SetRange(range); }
void Session::SetOption(const MultiRange& multi_range) { SetMultiRange(multi_range); }
void Session::SetOption(const ReserveSize& reserve_size) { SetReserveSize(reserve_size); }
void Session::SetOption(const AcceptEncoding& accept_encoding) { SetAcceptEncoding(accept_encoding); }
void Session::SetOption(AcceptEncoding&& accept_encoding) { SetAcceptEncoding(std::move(accept_encoding)); }
void Session::SetOption(const ConnectionPool& pool) { SetConnectionPool(pool); }
// clang-format on

void Session::SetCancellationParam(std::shared_ptr<std::atomic_bool> param) {
    cbs_->cancellationcb_ = CancellationCallback{std::move(param)};
    isCancellable = true;
#if LIBCURL_VERSION_NUM < 0x072000 // 7.32.0
    curl_easy_setopt(curl_->handle, CURLOPT_PROGRESSFUNCTION, cpr::util::progressUserFunction<CancellationCallback>);
    curl_easy_setopt(curl_->handle, CURLOPT_PROGRESSDATA, &cbs_->cancellationcb_);
#else
    curl_easy_setopt(curl_->handle, CURLOPT_XFERINFOFUNCTION, cpr::util::progressUserFunction<CancellationCallback>);
    curl_easy_setopt(curl_->handle, CURLOPT_XFERINFODATA, &cbs_->cancellationcb_);
#endif
    curl_easy_setopt(curl_->handle, CURLOPT_NOPROGRESS, 0L);
}
} // namespace cpr


================================================
FILE: cpr/sse.cpp
================================================
#include "cpr/sse.h"

#include <charconv>
#include <cstddef>
#include <functional>
#include <string>
#include <string_view>
#include <system_error>
#include <utility>

namespace cpr {

bool ServerSentEventParser::parse(std::string_view data, const std::function<bool(ServerSentEvent&&)>& callback) {
    // Append incoming data to buffer
    buffer_.append(data);

    // Process complete lines
    size_t pos = 0;
    while ((pos = buffer_.find('\n')) != std::string::npos) {
        std::string line = buffer_.substr(0, pos);
        buffer_.erase(0, pos + 1);

        // Remove trailing \r if present (handles both \n and \r\n)
        if (!line.empty() && line.back() == '\r') {
            line.pop_back();
        }

        if (!processLine(line, callback)) {
            return false;
        }
    }

    return true;
}

void ServerSentEventParser::reset() {
    buffer_.clear();
    current_event_ = ServerSentEvent();
}

bool ServerSentEventParser::processLine(const std::string& line, const std::function<bool(ServerSentEvent&&)>& callback) {
    // Empty line means end of event
    if (line.empty()) {
        return dispatchEvent(callback);
    }

    // Lines starting with ':' are comments, ignore them
    if (line[0] == ':') {
        return true;
    }

    // Find the colon separator
    const size_t colon_pos = line.find(':');

    std::string field;
    std::string value;

    if (colon_pos == std::string::npos) {
        // No colon, entire line is the field name
        field = line;
        value = "";
    } else {
        field = line.substr(0, colon_pos);
        // Skip the colon and optional leading space
        size_t value_start = colon_pos + 1;
        if (value_start < line.size() && line[value_start] == ' ') {
            value_start++;
        }
        value = line.substr(value_start);
    }

    // Process the field
    if (field == "event") {
        current_event_.event = value;
    } else if (field == "data") {
        // Multiple data fields are concatenated with newlines
        if (!current_event_.data.empty()) {
            current_event_.data += '\n';
        }
        current_event_.data += value;
    } else if (field == "id") {
        // Only set id if the value doesn't contain null character
        if (value.find('\0') == std::string::npos) {
            current_event_.id = value;
        }
    } else if (field == "retry") {
        // Parse retry value as integer
        size_t retry_value = 0;
        const std::string_view sv(value);
        const char* begin = sv.data();
        const char* end = begin + sv.size(); // NOLINT (cppcoreguidelines-pro-bounds-pointer-arithmetic) Required here since Windows and Clang/GCC have different std::string_view iterator implementations
        auto [ptr, ec] = std::from_chars(begin, end, retry_value);
        if (ec == std::errc()) {
            current_event_.retry = retry_value;
        }
    }
    // Unknown fields are ignored per spec

    return true;
}

bool ServerSentEventParser::dispatchEvent(const std::function<bool(ServerSentEvent&&)>& callback) {
    // Don't dispatch if data is empty
    if (current_event_.data.empty()) {
        current_event_ = ServerSentEvent();
        return true;
    }

    // Invoke callback with the current event
    const bool continue_parsing = callback(std::move(current_event_));

    // Reset for next event (but keep event type as "message")
    current_event_ = ServerSentEvent();

    return continue_parsing;
}

bool ServerSentEventCallback::handleData(std::string_view data) {
    return parser_.parse(data, [this](ServerSentEvent&& event) { return (*this)(std::move(event)); });
}

} // namespace cpr


================================================
FILE: cpr/ssl_ctx.cpp
================================================

#include "cpr/ssl_ctx.h"
#include "cpr/ssl_options.h"
#include <cstddef>
#include <curl/curl.h>
#include <iostream>
#include <memory>

#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION

#ifdef OPENSSL_BACKEND_USED

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>

// openssl/types.h was added in later version of openssl (starting from 3.0.0) and is therefore not always available.
// This is for example the case on Ubuntu 20.04 or Centos 7.
// We try to include it if available to satisfy clang-tidy.
// Ref: https://github.com/openssl/openssl/commit/50cd4768c6b89c757645f28519236bb989216f8d
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/types.h>
#else
#include <openssl/ossl_typ.h>
#endif

// openssl/pemerr.h was added in 1.1.1a, but not in BoringSSL
// Ref https://github.com/libcpr/cpr/issues/333#issuecomment-2425104338
#if OPENSSL_VERSION_NUMBER >= 0x1010101fL && !defined(OPENSSL_IS_BORINGSSL)
#include <openssl/pemerr.h>
#endif

namespace cpr {

/**
 * The ssl_ctx parameter is actually a pointer to the SSL library's SSL_CTX for OpenSSL.
 * If an error is returned from the callback no attempt to establish a connection is made and
 * the perform operation will return the callback's error code.
 *
 * Sources: https://curl.se/libcurl/c/CURLOPT_SSL_CTX_FUNCTION.html
 *          https://curl.se/libcurl/c/CURLOPT_SSL_CTX_DATA.html
 */

template <auto fn>
struct deleter_from_fn {
    template <typename T>
    constexpr void operator()(T* arg) const {
        fn(arg);
    }
};

template <typename T, auto fn>
using custom_unique_ptr = std::unique_ptr<T, deleter_from_fn<fn>>;
using x509_ptr = custom_unique_ptr<X509, X509_free>;
using bio_ptr = custom_unique_ptr<BIO, BIO_free>;

CURLcode sslctx_function_load_ca_cert_from_buffer(CURL* /*curl*/, void* sslctx, void* raw_cert_buf) {
    // Check arguments
    if (raw_cert_buf == nullptr || sslctx == nullptr) {
        std::cerr << "Invalid callback arguments!\n";
        return CURLE_ABORTED_BY_CALLBACK;
    }

    // Create a memory BIO using the data of cert_buf
    // Note: It is assumed, that cert_buf is nul terminated and its length is determined by strlen
    const char* cert_buf = static_cast<char*>(raw_cert_buf);
    BIO* bio = BIO_new_mem_buf(cert_buf, -1);

    // Get a pointer to the current certificate verification storage
    X509_STORE* store = SSL_CTX_get_cert_store(static_cast<SSL_CTX*>(sslctx));
    if (store == nullptr) {
        std::cerr << "SSL_CTX_get_cert_store failed!\n";
        ERR_print_errors_fp(stderr);
        BIO_free(bio);
        return CURLE_ABORTED_BY_CALLBACK;
    }

    // Load the PEM formatted certicifate into an X509 structure which OpenSSL can use
    // PEM_read_bio_X509 can read multiple certificates from the same buffer in a loop.
    // The buffer should be in PEM format, which is a base64 encoded format
    // with header and footer lines like
    //
    //    CA 1
    //    ============
    //    -----BEGIN CERTIFICATE-----
    //    ... base64 data ...
    //    -----END CERTIFICATE-----
    //
    //    CA 2
    //    ============
    //    -----BEGIN CERTIFICATE-----
    //    ... base64 data ...
    //    -----END CERTIFICATE-----
    //
    size_t certs_loaded = 0;
    X509* cert = nullptr;
    while ((cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr)) != nullptr) {
        const int status = X509_STORE_add_cert(store, cert);
        // Fail if any loaded cert is invalid
        if (status == 0) {
            std::cerr << "[CPR] while adding certificate to store\n";
            ERR_print_errors_fp(stderr);
            BIO_free(bio);
            return CURLE_ABORTED_BY_CALLBACK;
        }
        certs_loaded++;
        // Free cert so we can load another one
        X509_free(cert);
        cert = nullptr;
    }

    // NOLINTNEXTLINE(google-runtime-int) Ignored here since it is an API return value
    const unsigned long err = ERR_peek_last_error();
    if (certs_loaded == 0 && err != 0) {
        // Check if the error is just EOF or an actual parsing error
        if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
            // This is expected if the buffer was empty or contains no valid
            // PEM certs
            std::cerr << "No PEM certificates found or end of stream\n";
        } else {
            std::cerr << "PEM_read_bio_X509 failed after loading " << certs_loaded << " certificates\n";
            ERR_print_errors_fp(stderr);
            BIO_free(bio);
            return CURLE_ABORTED_BY_CALLBACK;
        }
    }

    // Free the entire bio chain
    BIO_free(bio);

    // The CA certificate was loaded successfully into the verification storage
    return CURLE_OK;
}

} // namespace cpr

#endif // OPENSSL_BACKEND_USED

#endif // SUPPORT_CURLOPT_SSL_CTX_FUNCTION


================================================
FILE: cpr/threadpool.cpp
================================================
#include "cpr/threadpool.h"
#include <algorithm>
#include <chrono>
#include <cstddef>
#include <memory>
#include <mutex>
#include <thread>
#include <utility>

namespace cpr {

ThreadPool::ThreadPool(size_t min_threads, size_t max_threads, std::chrono::milliseconds max_idle_ms) : min_thread_num(min_threads), max_thread_num(max_threads), max_idle_time(max_idle_ms) {}

ThreadPool::~ThreadPool() {
    Stop();
}

int ThreadPool::Start(size_t start_threads) {
    if (status != Status::STOP) {
        return -1;
    }
    status = Status::RUNNING;
    start_threads = std::clamp(start_threads, min_thread_num, max_thread_num);
    for (size_t i = 0; i < start_threads; ++i) {
        CreateThread();
    }
    return 0;
}

int ThreadPool::Stop() {
    const std::unique_lock status_lock(status_wait_mutex);
    if (status == Status::STOP) {
        return -1;
    }

    status = Status::STOP;
    status_wait_cond.notify_all();
    task_cond.notify_all();

    for (auto& i : threads) {
        if (i.thread->joinable()) {
            i.thread->join();
        }
    }

    threads.clear();
    cur_thread_num = 0;
    idle_thread_num = 0;
    return 0;
}

int ThreadPool::Pause() {
    if (status == Status::RUNNING) {
        status = Status::PAUSE;
    }
    return 0;
}

int ThreadPool::Resume() {
    const std::unique_lock status_lock(status_wait_mutex);
    if (status == Status::PAUSE) {
        status = Status::RUNNING;
        status_wait_cond.notify_all();
    }
    return 0;
}

void ThreadPool::Wait() {
    while (true) {
        if (status == Status::STOP || (tasks.empty() && idle_thread_num == cur_thread_num)) {
            break;
        }
        std::this_thread::yield();
    }
}

bool ThreadPool::CreateThread() {
    if (cur_thread_num >= max_thread_num) {
        return false;
    }
    auto thread = std::make_shared<std::thread>([this] {
        bool initialRun = true;
        while (status != Status::STOP) {
            {
                std::unique_lock status_lock(status_wait_mutex);
                status_wait_cond.wait(status_lock, [this]() { return status != Status::PAUSE; });
            }

            Task task;
            {
                std::unique_lock<std::mutex> locker(task_mutex);
                task_cond.wait_for(locker, std::chrono::milliseconds(max_idle_time), [this]() { return status == Status::STOP || !tasks.empty(); });
                if (status == Status::STOP) {
                    return;
                }
                if (tasks.empty()) {
                    if (cur_thread_num > min_thread_num) {
                        DelThread(std::this_thread::get_id());
                        return;
                    }
                    continue;
                }
                if (!initialRun) {
                    --idle_thread_num;
                }
                task = std::move(tasks.front());
                tasks.pop();
            }
            if (task) {
                task();
                ++idle_thread_num;
                initialRun = false;
            }
        }
    });
    AddThread(thread);
    return true;
}

void ThreadPool::AddThread(const std::shared_ptr<std::thread>& thread) {
    thread_mutex.lock();
    ++cur_thread_num;
    ThreadData data;
    data.thread = thread;
    data.id = thread->get_id();
    data.status = Status::RUNNING;
    data.start_time = std::chrono::steady_clock::now();
    data.stop_time = std::chrono::steady_clock::time_point::max();
    threads.emplace_back(data);
    thread_mutex.unlock();
}

void ThreadPool::DelThread(std::thread::id id) {
    const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();

    thread_mutex.lock();
    --cur_thread_num;
    --idle_thread_num;
    auto iter = threads.begin();
    while (iter != threads.end()) {
        if (iter->status == Status::STOP && now > iter->stop_time) {
            if (iter->thread->joinable()) {
                iter->th
Download .txt
gitextract_di3av8n9/

├── .clang-format
├── .clang-tidy
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   └── feature-request.yml
│   ├── dependabot.yml
│   └── workflows/
│       ├── build-deb.yml
│       ├── build-nuget.yml
│       ├── ci.yml
│       ├── clang-format.yml
│       ├── clang-tidy.yml
│       ├── cppcheck.yml
│       └── readme-updater.yml
├── .gitignore
├── .vscode/
│   └── tasks.json
├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── cmake/
│   ├── FindMbedTLS.cmake
│   ├── clang-tidy.cmake
│   ├── clear_variable.cmake
│   ├── code_coverage.cmake
│   ├── cppcheck.cmake
│   ├── cprConfig-ssl.cmake.in
│   ├── cprConfig.cmake.in
│   ├── cprver.h.in
│   ├── libpsl.cmake
│   ├── mongoose.CMakeLists.txt
│   ├── sanitizer.cmake
│   ├── std_fs_support_test.cpp
│   └── zlib_external.cmake
├── cppcheck-suppressions.xml
├── cpr/
│   ├── CMakeLists.txt
│   ├── accept_encoding.cpp
│   ├── async.cpp
│   ├── auth.cpp
│   ├── callback.cpp
│   ├── cert_info.cpp
│   ├── connection_pool.cpp
│   ├── cookies.cpp
│   ├── cprtypes.cpp
│   ├── curl_container.cpp
│   ├── curlholder.cpp
│   ├── curlmultiholder.cpp
│   ├── error.cpp
│   ├── file.cpp
│   ├── interceptor.cpp
│   ├── multipart.cpp
│   ├── multiperform.cpp
│   ├── parameters.cpp
│   ├── payload.cpp
│   ├── proxies.cpp
│   ├── proxyauth.cpp
│   ├── redirect.cpp
│   ├── response.cpp
│   ├── session.cpp
│   ├── sse.cpp
│   ├── ssl_ctx.cpp
│   ├── threadpool.cpp
│   ├── timeout.cpp
│   ├── unix_socket.cpp
│   └── util.cpp
├── cpr-config.cmake
├── include/
│   ├── CMakeLists.txt
│   └── cpr/
│       ├── accept_encoding.h
│       ├── api.h
│       ├── async.h
│       ├── async_wrapper.h
│       ├── auth.h
│       ├── bearer.h
│       ├── body.h
│       ├── body_view.h
│       ├── buffer.h
│       ├── callback.h
│       ├── cert_info.h
│       ├── connect_timeout.h
│       ├── connection_pool.h
│       ├── cookies.h
│       ├── cpr.h
│       ├── cprtypes.h
│       ├── curl_container.h
│       ├── curlholder.h
│       ├── curlmultiholder.h
│       ├── error.h
│       ├── file.h
│       ├── filesystem.h
│       ├── http_version.h
│       ├── interceptor.h
│       ├── interface.h
│       ├── limit_rate.h
│       ├── local_port.h
│       ├── local_port_range.h
│       ├── low_speed.h
│       ├── multipart.h
│       ├── multiperform.h
│       ├── parameters.h
│       ├── payload.h
│       ├── proxies.h
│       ├── proxyauth.h
│       ├── range.h
│       ├── redirect.h
│       ├── reserve_size.h
│       ├── resolve.h
│       ├── response.h
│       ├── secure_string.h
│       ├── session.h
│       ├── singleton.h
│       ├── sse.h
│       ├── ssl_ctx.h
│       ├── ssl_options.h
│       ├── status_codes.h
│       ├── threadpool.h
│       ├── timeout.h
│       ├── unix_socket.h
│       ├── user_agent.h
│       ├── util.h
│       └── verbose.h
├── nuget/
│   ├── build/
│   │   └── native/
│   │       ├── libcpr.props
│   │       └── libcpr.targets
│   └── libcpr.nuspec
├── package-build/
│   ├── build-package.sh
│   └── debian-libcpr/
│       ├── README.Debian
│       ├── changelog
│       ├── control
│       ├── copyright
│       ├── libcpr-dev.install
│       ├── libcpr1.install
│       ├── rules
│       └── source/
│           └── format
├── scripts/
│   ├── check_clang_format.sh
│   ├── delete_build_dir.sh
│   └── run_clang_format.sh
└── test/
    ├── CMakeLists.txt
    ├── LICENSE
    ├── abstractServer.cpp
    ├── abstractServer.hpp
    ├── alternating_tests.cpp
    ├── async_tests.cpp
    ├── callback_tests.cpp
    ├── connection_pool_tests.cpp
    ├── curlholder_tests.cpp
    ├── data/
    │   ├── certificates/
    │   │   ├── ca-bundle.crt
    │   │   ├── client.crt
    │   │   ├── root-ca.crt
    │   │   ├── server.crt
    │   │   └── sub-ca.crt
    │   ├── client.cnf
    │   ├── generate-certificates.sh
    │   ├── keys/
    │   │   ├── client.key
    │   │   ├── root-ca.key
    │   │   ├── server.key
    │   │   ├── server.pub
    │   │   └── sub-ca.key
    │   ├── root-ca.cnf
    │   ├── server.cnf
    │   ├── sub-ca.cnf
    │   ├── test_file.txt
    │   ├── test_file_hello_äüöp_2585.txt
    │   └── test_file_hello_äüöp_2585_你好.txt
    ├── delete_tests.cpp
    ├── download_tests.cpp
    ├── encoded_auth_tests.cpp
    ├── error_tests.cpp
    ├── file_upload_tests.cpp
    ├── get_tests.cpp
    ├── head_tests.cpp
    ├── httpServer.cpp
    ├── httpServer.hpp
    ├── httpsServer.cpp
    ├── httpsServer.hpp
    ├── interceptor_multi_tests.cpp
    ├── interceptor_tests.cpp
    ├── multiasync_tests.cpp
    ├── multiasync_tests.hpp
    ├── multiperform_tests.cpp
    ├── options_tests.cpp
    ├── patch_tests.cpp
    ├── post_tests.cpp
    ├── prepare_tests.cpp
    ├── proxy_auth_tests.cpp
    ├── proxy_tests.cpp
    ├── put_tests.cpp
    ├── raw_body_tests.cpp
    ├── resolve_tests.cpp
    ├── session_tests.cpp
    ├── singleton_tests.cpp
    ├── singleton_tests.hpp
    ├── sse_tests.cpp
    ├── ssl_tests.cpp
    ├── structures_tests.cpp
    ├── testUtils.cpp
    ├── testUtils.hpp
    ├── testUtils_tests.cpp
    ├── threadpool_tests.cpp
    ├── util_tests.cpp
    └── version_tests.cpp
Download .txt
SYMBOL INDEX (882 symbols across 125 files)

FILE: cmake/std_fs_support_test.cpp
  function main (line 9) | int main() {

FILE: cpr/accept_encoding.cpp
  type cpr (line 11) | namespace cpr {

FILE: cpr/async.cpp
  type cpr (line 3) | namespace cpr {

FILE: cpr/auth.cpp
  type cpr (line 5) | namespace cpr {
    function AuthMode (line 18) | AuthMode Authentication::GetAuthMode() const noexcept {

FILE: cpr/callback.cpp
  type cpr (line 5) | namespace cpr {

FILE: cpr/cert_info.cpp
  type cpr (line 5) | namespace cpr {

FILE: cpr/connection_pool.cpp
  type cpr (line 6) | namespace cpr {

FILE: cpr/cookies.cpp
  type cpr (line 10) | namespace cpr {

FILE: cpr/cprtypes.cpp
  type cpr (line 7) | namespace cpr {

FILE: cpr/curl_container.cpp
  type cpr (line 8) | namespace cpr {
    class CurlContainer<Pair> (line 89) | class CurlContainer<Pair>
    class CurlContainer<Parameter> (line 90) | class CurlContainer<Parameter>

FILE: cpr/curlholder.cpp
  type cpr (line 8) | namespace cpr {
    function CurlHolder (line 40) | CurlHolder& CurlHolder::operator=(CurlHolder&& old) noexcept {

FILE: cpr/curlmultiholder.cpp
  type cpr (line 5) | namespace cpr {

FILE: cpr/error.cpp
  type cpr (line 6) | namespace cpr {
    function ErrorCode (line 8) | ErrorCode Error::getErrorCodeForCurlError(std::int32_t curl_code) {

FILE: cpr/file.cpp
  type cpr (line 6) | namespace cpr {
    function Files (line 46) | Files& Files::operator=(const Files& other) {
    function Files (line 53) | Files& Files::operator=(Files&& old) noexcept {

FILE: cpr/interceptor.cpp
  type cpr (line 11) | namespace cpr {
    function Response (line 13) | Response Interceptor::proceed(Session& session) {
    function Response (line 17) | Response Interceptor::proceed(Session& session, ProceedHttpMethod http...
    function Response (line 38) | Response Interceptor::proceed(Session& session, ProceedHttpMethod http...
    function Response (line 45) | Response Interceptor::proceed(Session& session, ProceedHttpMethod http...

FILE: cpr/multipart.cpp
  type cpr (line 5) | namespace cpr {

FILE: cpr/multiperform.cpp
  type cpr (line 23) | namespace cpr {
    function MultiPerform (line 34) | MultiPerform& MultiPerform::operator=(MultiPerform&& old) noexcept {
    type CURLMsg (line 141) | struct CURLMsg

FILE: cpr/parameters.cpp
  type cpr (line 4) | namespace cpr {}

FILE: cpr/payload.cpp
  type cpr (line 4) | namespace cpr {}

FILE: cpr/proxies.cpp
  type cpr (line 8) | namespace cpr {

FILE: cpr/proxyauth.cpp
  type cpr (line 6) | namespace cpr {

FILE: cpr/redirect.cpp
  type cpr (line 4) | namespace cpr {
    function PostRedirectFlags (line 5) | PostRedirectFlags operator|(PostRedirectFlags lhs, PostRedirectFlags r...
    function PostRedirectFlags (line 9) | PostRedirectFlags operator&(PostRedirectFlags lhs, PostRedirectFlags r...
    function PostRedirectFlags (line 13) | PostRedirectFlags operator^(PostRedirectFlags lhs, PostRedirectFlags r...
    function PostRedirectFlags (line 17) | PostRedirectFlags operator~(PostRedirectFlags flag) {
    function PostRedirectFlags (line 21) | PostRedirectFlags& operator|=(PostRedirectFlags& lhs, PostRedirectFlag...
    function PostRedirectFlags (line 28) | PostRedirectFlags& operator&=(PostRedirectFlags& lhs, PostRedirectFlag...
    function PostRedirectFlags (line 33) | PostRedirectFlags& operator^=(PostRedirectFlags& lhs, PostRedirectFlag...
    function any (line 38) | bool any(PostRedirectFlags flag) {

FILE: cpr/response.cpp
  type cpr (line 16) | namespace cpr {

FILE: cpr/session.cpp
  type cpr (line 70) | namespace cpr {
    function CURLcode (line 78) | CURLcode Session::DoEasyPerform() {
    function Response (line 164) | Response Session::makeDownloadRequest() {
    function Response (line 264) | Response Session::makeRequest() {
    function Content (line 280) | const Content& Session::GetContent() const {
    function Header (line 391) | Header& Session::GetHeader() {
    function Header (line 395) | const Header& Session::GetHeader() const {
    function cpr_off_t (line 744) | cpr_off_t Session::GetDownloadFileLength() {
    function Response (line 767) | Response Session::Delete() {
    function Response (line 772) | Response Session::Download(const WriteCallback& write) {
    function Response (line 777) | Response Session::Download(std::ofstream& file) {
    function Response (line 782) | Response Session::Get() {
    function Response (line 787) | Response Session::Head() {
    function Response (line 792) | Response Session::Options() {
    function Response (line 797) | Response Session::Patch() {
    function Response (line 802) | Response Session::Post() {
    function Response (line 807) | Response Session::Put() {
    function AsyncResponse (line 820) | AsyncResponse Session::GetAsync() {
    function AsyncResponse (line 825) | AsyncResponse Session::DeleteAsync() {
    function AsyncResponse (line 829) | AsyncResponse Session::DownloadAsync(const WriteCallback& write) {
    function AsyncResponse (line 833) | AsyncResponse Session::DownloadAsync(std::ofstream& file) {
    function AsyncResponse (line 837) | AsyncResponse Session::HeadAsync() {
    function AsyncResponse (line 841) | AsyncResponse Session::OptionsAsync() {
    function AsyncResponse (line 845) | AsyncResponse Session::PatchAsync() {
    function AsyncResponse (line 849) | AsyncResponse Session::PostAsync() {
    function AsyncResponse (line 853) | AsyncResponse Session::PutAsync() {
    function Response (line 953) | Response Session::Complete(CURLcode curl_error) {
    function Response (line 963) | Response Session::CompleteDownload(CURLcode curl_error) {
    function Response (line 985) | Response Session::proceed() {

FILE: cpr/sse.cpp
  type cpr (line 11) | namespace cpr {

FILE: cpr/ssl_ctx.cpp
  type cpr (line 37) | namespace cpr {
    type deleter_from_fn (line 49) | struct deleter_from_fn {
    function CURLcode (line 61) | CURLcode sslctx_function_load_ca_cert_from_buffer(CURL* /*curl*/, void...

FILE: cpr/threadpool.cpp
  type cpr (line 10) | namespace cpr {

FILE: cpr/timeout.cpp
  type cpr (line 9) | namespace cpr {

FILE: cpr/unix_socket.cpp
  type cpr (line 4) | namespace cpr {

FILE: cpr/util.cpp
  type cpr::util (line 40) | namespace cpr::util {
    type CurlHTTPCookieField (line 42) | enum class CurlHTTPCookieField : uint8_t {
    function Cookies (line 52) | Cookies parseCookies(curl_slist* raw_cookies) {
    function Header (line 74) | Header parseHeader(const std::string& headers, std::string* status_lin...
    function split (line 117) | std::vector<std::string> split(const std::string& to_split, char delim...
    function readUserFunction (line 129) | size_t readUserFunction(char* ptr, size_t size, size_t nitems, const R...
    function headerUserFunction (line 134) | size_t headerUserFunction(char* ptr, size_t size, size_t nmemb, const ...
    function writeFunction (line 139) | size_t writeFunction(char* ptr, size_t size, size_t nmemb, void* data) {
    function writeFileFunction (line 145) | size_t writeFileFunction(char* ptr, size_t size, size_t nmemb, std::of...
    function writeUserFunction (line 151) | size_t writeUserFunction(char* ptr, size_t size, size_t nmemb, const W...
    function writeSSEFunction (line 156) | size_t writeSSEFunction(char* ptr, size_t size, size_t nmemb, ServerSe...
    function debugUserFunction (line 161) | int debugUserFunction(CURL* /*handle*/, curl_infotype type, char* data...
    function urlEncode (line 176) | util::SecureString urlEncode(std::string_view s) {
    function urlDecode (line 191) | util::SecureString urlDecode(std::string_view s) {
    function isTrue (line 196) | bool isTrue(const std::string& s) {
    function time_t (line 202) | time_t sTimestampToT(const std::string& st) {

FILE: include/cpr/accept_encoding.h
  function AcceptEncodingMethods (line 14) | enum class AcceptEncodingMethods : uint8_t {

FILE: include/cpr/api.h
  function namespace (line 22) | namespace cpr {

FILE: include/cpr/async.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/async_wrapper.h
  type class (line 9) | enum class
  function throw (line 28) | throw std::logic_error{error};
  function explicit (line 35) | explicit AsyncWrapper(std::future<T>&& f) : future{std::move(f)} {}
  function throw (line 88) | throw std::logic_error{error};
  function T (line 111) | [[nodiscard]] T get() {
  function future_status (line 126) | future_status wait_for(const std::chrono::duration<Rep, Period>& timeout...
  function future_status (line 132) | future_status wait_until(const std::chrono::time_point<Clock, Duration>&...
  function CancellationResult (line 138) | CancellationResult Cancel() {

FILE: include/cpr/auth.h
  function AuthMode (line 12) | enum class AuthMode : uint8_t { BASIC, DIGEST, NTLM, NEGOTIATE, ANY, ANY...

FILE: include/cpr/bearer.h
  function namespace (line 11) | namespace cpr {

FILE: include/cpr/body.h
  function body (line 20) | Body(const char* body) : StringHolder<Body>(body) {}

FILE: include/cpr/body_view.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/buffer.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/callback.h
  function const (line 20) | bool operator()(char* buffer, size_t& buffer_size) const {
  function userdata (line 27) | intptr_t userdata{}
  function cpr_off_t (line 28) | cpr_off_t size{}
  function class (line 32) | class HeaderCallback {
  function class (line 47) | class WriteCallback {
  function class (line 62) | class ProgressCallback {
  function class (line 77) | class DebugCallback {

FILE: include/cpr/cert_info.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/connect_timeout.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/connection_pool.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/cookies.h
  function namespace (line 10) | namespace cpr {

FILE: include/cpr/cprtypes.h
  function namespace (line 12) | namespace cpr {
  function url (line 153) | Url(const char* url) : StringHolder<Url>(url) {}
  type CaseInsensitiveCompare (line 164) | struct CaseInsensitiveCompare {

FILE: include/cpr/curl_container.h
  function namespace (line 12) | namespace cpr {

FILE: include/cpr/curlholder.h
  type CurlHolder (line 12) | struct CurlHolder {
  type curl_slist (line 30) | struct curl_slist
  type curl_slist (line 31) | struct curl_slist
  function curl_mime (line 32) | curl_mime* multipart{nullptr};

FILE: include/cpr/curlmultiholder.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/error.h
  function ErrorCode (line 17) | enum class ErrorCode : uint16_t {
  function namespace (line 182) | namespace std {

FILE: include/cpr/file.h
  function namespace (line 10) | namespace cpr {

FILE: include/cpr/filesystem.h
  function namespace (line 8) | namespace cpr {
  function namespace (line 14) | namespace cpr {
  function namespace (line 19) | namespace cpr {

FILE: include/cpr/http_version.h
  function namespace (line 7) | namespace cpr {

FILE: include/cpr/interceptor.h
  function namespace (line 9) | namespace cpr {

FILE: include/cpr/interface.h
  function namespace (line 9) | namespace cpr {

FILE: include/cpr/limit_rate.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/local_port.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/local_port_range.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/low_speed.h
  function namespace (line 7) | namespace cpr {

FILE: include/cpr/multipart.h
  function namespace (line 13) | namespace cpr {

FILE: include/cpr/multiperform.h
  function namespace (line 13) | namespace cpr {

FILE: include/cpr/parameters.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/payload.h
  function namespace (line 9) | namespace cpr {

FILE: include/cpr/proxies.h
  function namespace (line 8) | namespace cpr {

FILE: include/cpr/proxyauth.h
  function namespace (line 12) | namespace cpr {

FILE: include/cpr/range.h
  function namespace (line 7) | namespace cpr {
  function class (line 26) | class MultiRange {

FILE: include/cpr/redirect.h
  type class (line 7) | enum class
  function PostRedirectFlags (line 71) | PostRedirectFlags post_flags{PostRedirectFlags::NONE};

FILE: include/cpr/reserve_size.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/resolve.h
  function namespace (line 7) | namespace cpr {

FILE: include/cpr/response.h
  function class (line 22) | class Response {

FILE: include/cpr/secure_string.h
  function namespace (line 8) | namespace cpr::util {

FILE: include/cpr/session.h
  function class (line 57) | class Session : public std::enable_shared_from_this<Session> {
  type Callbacks (line 271) | struct Callbacks {
  function response_string_reserve_size_ (line 287) | size_t response_string_reserve_size_{0}
  function sslNoRevoke_ (line 301) | bool sslNoRevoke_{false};

FILE: include/cpr/sse.h
  function namespace (line 11) | namespace cpr {
  function class (line 45) | class ServerSentEventParser {
  function class (line 74) | class ServerSentEventCallback {

FILE: include/cpr/ssl_ctx.h
  function namespace (line 9) | namespace cpr {

FILE: include/cpr/ssl_options.h
  function namespace (line 77) | namespace cpr {
  function namespace (line 628) | namespace priv {

FILE: include/cpr/status_codes.h
  function namespace (line 3) | namespace cpr {

FILE: include/cpr/threadpool.h
  function std (line 20) | constexpr std::chrono::milliseconds CPR_DEFAULT_THREAD_POOL_MAX_IDLE_TIM...

FILE: include/cpr/timeout.h
  function Timeout (line 15) | Timeout(const std::int32_t& milliseconds) : Timeout{std::chrono::millise...

FILE: include/cpr/unix_socket.h
  function namespace (line 6) | namespace cpr {

FILE: include/cpr/user_agent.h
  function namespace (line 9) | namespace cpr {

FILE: include/cpr/util.h
  function namespace (line 15) | namespace cpr::util {

FILE: include/cpr/verbose.h
  function namespace (line 4) | namespace cpr {

FILE: test/abstractServer.cpp
  type cpr (line 3) | namespace cpr {
    function EventHandler (line 26) | static void EventHandler(mg_connection* conn, int event, void* event_d...

FILE: test/abstractServer.hpp
  type cpr (line 15) | namespace cpr {
    type TimerArg (line 18) | struct TimerArg {
      method TimerArg (line 25) | explicit TimerArg(mg_mgr* m, mg_connection* c, mg_timer&& t) : mgr{m...
    class AbstractServer (line 32) | class AbstractServer : public testing::Environment {

FILE: test/alternating_tests.cpp
  function TEST (line 13) | TEST(AlternatingTests, PutGetTest) {
  function TEST (line 38) | TEST(AlternatingTests, PutGetPutGetTest) {
  function TEST (line 82) | TEST(AlternatingTests, HeadGetTest) {
  function TEST (line 107) | TEST(AlternatingTests, PutHeadTest) {
  function TEST (line 133) | TEST(AlternatingTests, PutPostTest) {
  function main (line 159) | int main(int argc, char** argv) {

FILE: test/async_tests.cpp
  function write_data (line 17) | bool write_data(std::string_view /*data*/, intptr_t /*userdata*/) {
  function TEST (line 21) | TEST(AsyncTests, AsyncGetTest) {
  function TEST (line 34) | TEST(AsyncTests, AsyncGetMultipleTest) {
  function TEST (line 50) | TEST(AsyncTests, AsyncGetMultipleReflectTest) {
  function TEST (line 70) | TEST(AsyncTests, AsyncDownloadTest) {
  function main (line 79) | int main(int argc, char** argv) {

FILE: test/callback_tests.cpp
  function status_callback (line 20) | int status_callback(int& status_code, Response r) {
  function status_callback_ref (line 25) | int status_callback_ref(int& status_code, const Response& r) {
  function text_callback (line 30) | std::string text_callback(std::string& expected_text, Response r) {
  function text_callback_ref (line 35) | std::string text_callback_ref(std::string& expected_text, const Response...
  function TEST (line 40) | TEST(CallbackGetTests, CallbackGetLambdaStatusTest) {
  function TEST (line 54) | TEST(CallbackGetTests, CallbackGetLambdaTextTest) {
  function TEST (line 68) | TEST(CallbackGetTests, CallbackGetLambdaStatusReferenceTest) {
  function TEST (line 82) | TEST(CallbackGetTests, CallbackGetLambdaTextReferenceTest) {
  function TEST (line 96) | TEST(CallbackGetTests, CallbackGetFunctionStatusTest) {
  function TEST (line 106) | TEST(CallbackGetTests, CallbackGetFunctionTextTest) {
  function TEST (line 116) | TEST(CallbackGetTests, CallbackGetFunctionStatusReferenceTest) {
  function TEST (line 126) | TEST(CallbackGetTests, CallbackGetFunctionTextReferenceTest) {
  function TEST (line 136) | TEST(CallbackDeleteTests, CallbackDeleteLambdaStatusTest) {
  function TEST (line 150) | TEST(CallbackDeleteTests, CallbackDeleteLambdaTextTest) {
  function TEST (line 164) | TEST(CallbackDeleteTests, CallbackDeleteLambdaStatusReferenceTest) {
  function TEST (line 178) | TEST(CallbackDeleteTests, CallbackDeleteLambdaTextReferenceTest) {
  function TEST (line 192) | TEST(CallbackDeleteTests, CallbackDeleteFunctionStatusTest) {
  function TEST (line 202) | TEST(CallbackDeleteTests, CallbackDeleteFunctionTextTest) {
  function TEST (line 212) | TEST(CallbackDeleteTests, CallbackDeleteFunctionStatusReferenceTest) {
  function TEST (line 222) | TEST(CallbackDeleteTests, CallbackDeleteFunctionTextReferenceTest) {
  function TEST (line 232) | TEST(CallbackHeadTests, CallbackHeadLambdaStatusTest) {
  function TEST (line 246) | TEST(CallbackHeadTests, CallbackHeadLambdaTextTest) {
  function TEST (line 260) | TEST(CallbackHeadTests, CallbackHeadLambdaStatusReferenceTest) {
  function TEST (line 274) | TEST(CallbackHeadTests, CallbackHeadLambdaTextReferenceTest) {
  function TEST (line 288) | TEST(CallbackHeadTests, CallbackHeadFunctionStatusTest) {
  function TEST (line 298) | TEST(CallbackHeadTests, CallbackHeadFunctionTextTest) {
  function TEST (line 308) | TEST(CallbackHeadTests, CallbackHeadFunctionStatusReferenceTest) {
  function TEST (line 318) | TEST(CallbackHeadTests, CallbackHeadFunctionTextReferenceTest) {
  function TEST (line 328) | TEST(CallbackPostTests, CallbackPostLambdaStatusTest) {
  function TEST (line 344) | TEST(CallbackPostTests, CallbackPostLambdaTextTest) {
  function TEST (line 359) | TEST(CallbackPostTests, CallbackPostLambdaStatusReferenceTest) {
  function TEST (line 375) | TEST(CallbackPostTests, CallbackPostLambdaTextReferenceTest) {
  function TEST (line 390) | TEST(CallbackPostTests, CallbackPostFunctionStatusTest) {
  function TEST (line 401) | TEST(CallbackPostTests, CallbackPostFunctionTextTest) {
  function TEST (line 412) | TEST(CallbackPostTests, CallbackPostFunctionStatusReferenceTest) {
  function TEST (line 423) | TEST(CallbackPostTests, CallbackPostFunctionTextReferenceTest) {
  function TEST (line 434) | TEST(CallbackPutTests, CallbackPutLambdaStatusTest) {
  function TEST (line 449) | TEST(CallbackPutTests, CallbackPutLambdaTextTest) {
  function TEST (line 464) | TEST(CallbackPutTests, CallbackPutLambdaStatusReferenceTest) {
  function TEST (line 479) | TEST(CallbackPutTests, CallbackPutLambdaTextReferenceTest) {
  function TEST (line 494) | TEST(CallbackPutTests, CallbackPutFunctionStatusTest) {
  function TEST (line 505) | TEST(CallbackPutTests, CallbackPutFunctionTextTest) {
  function TEST (line 516) | TEST(CallbackPutTests, CallbackPutFunctionStatusReferenceTest) {
  function TEST (line 527) | TEST(CallbackPutTests, CallbackPutFunctionTextReferenceTest) {
  function TEST (line 538) | TEST(CallbackOptionsTests, CallbackOptionsLambdaStatusTest) {
  function TEST (line 552) | TEST(CallbackOptionsTests, CallbackOptionsLambdaTextTest) {
  function TEST (line 566) | TEST(CallbackOptionsTests, CallbackOptionsLambdaStatusReferenceTest) {
  function TEST (line 580) | TEST(CallbackOptionsTests, CallbackOptionsLambdaTextReferenceTest) {
  function TEST (line 594) | TEST(CallbackOptionsTests, CallbackOptionsFunctionStatusTest) {
  function TEST (line 604) | TEST(CallbackOptionsTests, CallbackOptionsFunctionTextTest) {
  function TEST (line 614) | TEST(CallbackOptionsTests, CallbackOptionsFunctionStatusReferenceTest) {
  function TEST (line 624) | TEST(CallbackOptionsTests, CallbackOptionsFunctionTextReferenceTest) {
  function TEST (line 634) | TEST(CallbackPatchTests, CallbackPatchLambdaStatusTest) {
  function TEST (line 649) | TEST(CallbackPatchTests, CallbackPatchLambdaTextTest) {
  function TEST (line 664) | TEST(CallbackPatchTests, CallbackPatchLambdaStatusReferenceTest) {
  function TEST (line 679) | TEST(CallbackPatchTests, CallbackPatchLambdaTextReferenceTest) {
  function TEST (line 694) | TEST(CallbackPatchTests, CallbackPatchFunctionStatusTest) {
  function TEST (line 705) | TEST(CallbackPatchTests, CallbackPatchFunctionTextTest) {
  function TEST (line 716) | TEST(CallbackPatchTests, CallbackPatchFunctionStatusReferenceTest) {
  function TEST (line 727) | TEST(CallbackPatchTests, CallbackPatchFunctionTextReferenceTest) {
  function TEST (line 738) | TEST(CallbackDataTests, CallbackReadFunctionCancelTest) {
  function TEST (line 744) | TEST(CallbackDataTests, CallbackReadFunctionTextTest) {
  function TEST (line 772) | TEST(CallbackDataTests, CallbackReadFunctionTextTestPut) {
  function TEST (line 807) | TEST(CallbackDataTests, CallbackReadFunctionHeaderTest) {
  function TEST (line 858) | TEST(CallbackDataTests, CallbackHeaderFunctionCancelTest) {
  function TEST (line 864) | TEST(CallbackDataTests, CallbackHeaderFunctionTextTest) {
  function TEST (line 878) | TEST(CallbackDataTests, CallbackWriteFunctionCancelTest) {
  function TEST (line 884) | TEST(CallbackDataTests, CallbackWriteFunctionTextTest) {
  function TEST (line 898) | TEST(CallbackDataTests, CallbackProgressFunctionCancelTest) {
  function TEST (line 904) | TEST(CallbackDataTests, CallbackProgressFunctionTotalTest) {
  function TEST (line 918) | TEST(CallbackDataTests, CallbackDebugFunctionTextTest) {
  function main (line 930) | int main(int argc, char** argv) {

FILE: test/connection_pool_tests.cpp
  function TEST (line 17) | TEST(MultipleGetTests, PoolBasicMultipleGetTest) {
  function TEST (line 44) | TEST(MultipleGetTests, PoolAsyncGetMultipleTest) {
  function main (line 106) | int main(int argc, char** argv) {

FILE: test/curlholder_tests.cpp
  function TEST (line 10) | TEST(CurlholderTests, MoveOperator) {
  function main (line 17) | int main(int argc, char** argv) {

FILE: test/delete_tests.cpp
  function TEST (line 13) | TEST(DeleteTests, DeleteTest) {
  function TEST (line 24) | TEST(DeleteTests, DeleteUnallowedTest) {
  function TEST (line 35) | TEST(DeleteTests, DeleteJsonBodyTest) {
  function TEST (line 46) | TEST(DeleteTests, SessionDeleteTest) {
  function TEST (line 59) | TEST(DeleteTests, SessionDeleteUnallowedTest) {
  function TEST (line 72) | TEST(DeleteTests, SessionDeleteJsonBodyTest) {
  function TEST (line 87) | TEST(DeleteTests, SessionDeleteAfterGetTest) {
  function TEST (line 105) | TEST(DeleteTests, SessionDeleteUnallowedAfterGetTest) {
  function TEST (line 123) | TEST(DeleteTests, SessionDeleteAfterHeadTest) {
  function TEST (line 141) | TEST(DeleteTests, SessionDeleteUnallowedAfterHeadTest) {
  function TEST (line 159) | TEST(DeleteTests, SessionDeleteAfterPostTest) {
  function TEST (line 178) | TEST(DeleteTests, SessionDeleteUnallowedAfterPostTest) {
  function TEST (line 197) | TEST(DeleteTests, AsyncDeleteTest) {
  function TEST (line 209) | TEST(DeleteTests, AsyncDeleteUnallowedTest) {
  function TEST (line 221) | TEST(DeleteTests, AsyncMultipleDeleteTest) {
  function TEST (line 238) | TEST(DeleteTests, AsyncMultipleDeleteUnallowedTest) {
  function main (line 255) | int main(int argc, char** argv) {

FILE: test/download_tests.cpp
  function write_data (line 18) | bool write_data(std::string_view /*data*/, intptr_t /*userdata*/) {
  function TEST (line 22) | TEST(DownloadTests, DownloadHeaderGzip) {
  function TEST (line 33) | TEST(DownloadTests, DownloadAcceptEncodingGzip) {
  function TEST (line 44) | TEST(DownloadTests, RangeTestWholeFile) {
  function TEST (line 57) | TEST(DownloadTests, RangeTestLowerLimit) {
  function TEST (line 70) | TEST(DownloadTests, RangeTestUpperLimit) {
  function TEST (line 83) | TEST(DownloadTests, RangeTestLowerAndUpperLimit) {
  function TEST (line 98) | TEST(DownloadTests, RangeTestMultipleRangesSet) {
  function TEST (line 112) | TEST(DownloadTests, RangeTestMultipleRangesOption) {
  function real_write_data (line 126) | bool real_write_data(std::string_view data, intptr_t userdata) {
  function TEST (line 133) | TEST(DownloadTests, GetDownloadFileLength) {
  function main (line 148) | int main(int argc, char** argv) {

FILE: test/encoded_auth_tests.cpp
  function TEST (line 9) | TEST(EncodedAuthenticationTests, UnicodeEncoderTest) {
  function main (line 17) | int main(int argc, char** argv) {

FILE: test/error_tests.cpp
  function TEST (line 16) | TEST(ErrorTests, UnsupportedProtocolFailure) {
  function TEST (line 23) | TEST(ErrorTests, InvalidURLFailure) {
  function TEST (line 30) | TEST(ErrorTests, TimeoutFailure) {
  function TEST (line 37) | TEST(ErrorTests, ChronoTimeoutFailure) {
  function TEST (line 44) | TEST(ErrorTests, ConnectTimeoutFailure) {
  function TEST (line 52) | TEST(ErrorTests, ChronoConnectTimeoutFailure) {
  function TEST (line 60) | TEST(ErrorTests, LowSpeedTimeFailure) {
  function TEST (line 67) | TEST(ErrorTests, LowSpeedBytesFailure) {
  function TEST (line 74) | TEST(ErrorTests, ProxyFailure) {
  function TEST (line 83) | TEST(ErrorTests, BoolFalseTest) {
  function TEST (line 88) | TEST(ErrorTests, BoolTrueTest) {
  function TEST (line 94) | TEST(ErrorTests, StringReprTest) {
  function TEST (line 100) | TEST(ErrorTests, StringReprUnknownTest) {
  function main (line 107) | int main(int argc, char** argv) {

FILE: test/file_upload_tests.cpp
  function GetBasePath (line 22) | cpr::fs::path GetBasePath(const std::string& execPath) {
  function TEST (line 27) | TEST(FileUploadTests, AsciiFileName) {
  function TEST (line 49) | TEST(FileUploadTests, NonAsciiFileName) {
  function TEST (line 71) | TEST(FileUploadTests, ChineseFileName) {
  function main (line 93) | int main(int argc, char** argv) {

FILE: test/get_tests.cpp
  function TEST (line 18) | TEST(BasicTests, HelloWorldTest) {
  function TEST (line 29) | TEST(BasicTests, HelloWorldStringViewUrlTest) {
  function TEST (line 40) | TEST(BasicTests, HelloWorldNoInterfaceTest) {
  function TEST (line 52) | TEST(BasicTests, HelloWorldNoInterfaceStringViewTest) {
  function TEST (line 64) | TEST(BasicTests, TimeoutTest) {
  function TEST (line 75) | TEST(BasicTests, BasicJsonTest) {
  function TEST (line 92) | TEST(BasicTests, ResourceNotFoundTest) {
  function TEST (line 103) | TEST(BasicTests, BadHostTest) {
  function TEST (line 113) | TEST(CookiesTests, BasicCookiesTest) {
  function TEST (line 138) | TEST(CookiesTests, EmptyCookieTest) {
  function TEST (line 163) | TEST(CookiesTests, ClientSetCookiesTest) {
  function TEST (line 178) | TEST(CookiesTests, UnencodedCookiesTest) {
  function TEST (line 194) | TEST(ParameterTests, SingleParameterTest) {
  function TEST (line 206) | TEST(ParameterTests, SingleParameterOnlyKeyTest) {
  function TEST (line 217) | TEST(ParameterTests, MultipleParametersTest) {
  function TEST (line 228) | TEST(ParameterTests, MultipleDynamicParametersTest) {
  function TEST (line 242) | TEST(BasicAuthenticationTests, BasicAuthenticationSuccessTest) {
  function TEST (line 253) | TEST(BasicAuthenticationTests, BasicBearerSuccessTest) {
  function TEST (line 268) | TEST(BasicAuthenticationTests, BasicDigestSuccessTest) {
  function TEST (line 279) | TEST(BasicAthenticationParameterTests, BasicAuthenticationSuccessSingleP...
  function TEST (line 290) | TEST(BasicAuthenticationParameterTests, BasicAuthenticationSuccessMultip...
  function TEST (line 301) | TEST(BasicAuthenticationParameterTests, BasicAuthenticationSuccessSingle...
  function TEST (line 312) | TEST(BasicAuthenticationParameterTests, BasicAuthenticationSuccessMultip...
  function TEST (line 324) | TEST(BasicAuthenticationHeaderTests, BasicAuthenticationSuccessSingleHea...
  function TEST (line 336) | TEST(BasicAuthenticationHeaderTests, BasicAuthenticationSuccessMultipleH...
  function TEST (line 350) | TEST(BasicAuthenticationHeaderTests, BasicAuthenticationSuccessSingleHea...
  function TEST (line 362) | TEST(BasicAuthenticationHeaderTests, BasicAuthenticationSuccessMultipleH...
  function TEST (line 376) | TEST(BasicAuthenticationTests, BasicAuthenticationNullFailureTest) {
  function TEST (line 386) | TEST(BasicAuthenticationTests, BasicAuthenticationFailureTest) {
  function TEST (line 396) | TEST(BasicAuthenticationParameterTests, BasicAuthenticationFailureSingle...
  function TEST (line 406) | TEST(BasicAuthenticationParameterTests, BasicAuthenticationFailureMultip...
  function TEST (line 416) | TEST(HeaderTests, HeaderJsonTest) {
  function TEST (line 433) | TEST(HeaderTests, HeaderReflectNoneTest) {
  function TEST (line 445) | TEST(HeaderTests, HeaderReflectUpdateHeaderAddSessionTest) {
  function TEST (line 473) | TEST(HeaderTests, SessionHeaderReflectTest) {
  function TEST (line 485) | TEST(HeaderTests, HeaderReflectUpdateHeaderUpdateSessionTest) {
  function TEST (line 509) | TEST(HeaderTests, HeaderReflectEmptyTest) {
  function TEST (line 521) | TEST(HeaderTests, HeaderReflectSingleTest) {
  function TEST (line 533) | TEST(HeaderTests, HeaderReflectMultipleTest) {
  function TEST (line 547) | TEST(HeaderTests, HeaderReflectCaseInsensitiveTest) {
  function TEST (line 561) | TEST(HeaderTests, SetEmptyHeaderTest) {
  function TEST (line 573) | TEST(ParameterHeaderTests, HeaderReflectNoneParametersTest) {
  function TEST (line 585) | TEST(ParameterHeaderTests, HeaderReflectEmptyParametersTest) {
  function TEST (line 597) | TEST(ParameterHeaderTests, HeaderReflectSingleParametersTest) {
  function TEST (line 609) | TEST(ParameterHeaderTests, HeaderReflectMultipleParametersTest) {
  function TEST (line 623) | TEST(ParameterHeaderTests, HeaderReflectCaseInsensitiveParametersTest) {
  function TEST (line 637) | TEST(ParameterHeaderTests, HeaderReflectEmptyParametersReverseTest) {
  function TEST (line 649) | TEST(ParameterHeaderTests, HeaderReflectSingleParametersReverseTest) {
  function TEST (line 661) | TEST(ParameterHeaderTests, HeaderReflectMultipleParametersReverseTest) {
  function TEST (line 675) | TEST(ParameterHeaderTests, HeaderReflectCaseInsensitiveParametersReverse...
  function TEST (line 689) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 701) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 712) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 724) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 735) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 747) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 758) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 770) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 781) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 793) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 804) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 816) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 827) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 839) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 850) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 862) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 873) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 885) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 896) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 908) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 919) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 931) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 942) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 954) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 965) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 977) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 988) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1000) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1011) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1023) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1034) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1046) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1057) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1069) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1080) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1092) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1103) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1115) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1126) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1138) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1149) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1161) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1172) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1184) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1195) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1207) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1218) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1230) | TEST(BasicAuthenticationParameterHeaderTests, BasicAuthenticationParamet...
  function TEST (line 1241) | TEST(GetRedirectTests, RedirectTest) {
  function TEST (line 1252) | TEST(GetRedirectTests, ZeroMaxRedirectsSuccessTest) {
  function TEST (line 1263) | TEST(GetRedirectTests, ZeroMaxRedirectsFailureTest) {
  function TEST (line 1273) | TEST(GetRedirectTests, BasicAuthenticationRedirectSuccessTest) {
  function TEST (line 1285) | TEST(BasicTests, RequestBodyTest) {
  function TEST (line 1297) | TEST(BasicTests, RequestBodyStringViewTest) {
  function TEST (line 1309) | TEST(LimitRateTests, HelloWorldTest) {
  function main (line 1320) | int main(int argc, char** argv) {

FILE: test/head_tests.cpp
  function TEST (line 14) | TEST(HeadTests, BasicHeadTest) {
  function TEST (line 24) | TEST(HeadTests, ComplexHeadTest) {
  function TEST (line 34) | TEST(HeadTests, ResourceNotFoundHeadTest) {
  function TEST (line 44) | TEST(HeadTests, BadHostHeadTest) {
  function TEST (line 54) | TEST(HeadTests, CookieHeadTest) {
  function TEST (line 78) | TEST(HeadTests, ParameterHeadTest) {
  function TEST (line 89) | TEST(HeadTests, AuthenticationSuccessHeadTest) {
  function TEST (line 99) | TEST(HeadTests, AuthenticationNullFailureHeadTest) {
  function TEST (line 109) | TEST(HeadTests, AuthenticationFailureHeadTest) {
  function TEST (line 119) | TEST(HeadTests, BearerSuccessHeadTest) {
  function TEST (line 133) | TEST(HeadTests, DigestSuccessHeadTest) {
  function TEST (line 143) | TEST(HeadTests, HeaderReflectNoneHeadTest) {
  function TEST (line 154) | TEST(HeadTests, HeaderReflectEmptyHeadTest) {
  function TEST (line 165) | TEST(HeadTests, HeaderReflectHeadTest) {
  function TEST (line 176) | TEST(HeadTests, SetEmptyHeaderHeadTest) {
  function TEST (line 187) | TEST(HeadTests, RedirectHeadTest) {
  function TEST (line 197) | TEST(HeadTests, ZeroMaxRedirectsHeadTest) {
  function TEST (line 207) | TEST(HeadTests, BasicHeadAsyncTest) {
  function main (line 223) | int main(int argc, char** argv) {

FILE: test/httpServer.cpp
  type cpr (line 11) | namespace cpr {
    function mg_connection (line 22) | mg_connection* HttpServer::initServer(mg_mgr* mgr, mg_event_handler_t ...

FILE: test/httpServer.hpp
  type cpr (line 9) | namespace cpr {
    class HttpServer (line 10) | class HttpServer : public AbstractServer {

FILE: test/httpsServer.cpp
  type cpr (line 4) | namespace cpr {
    function mg_connection (line 21) | mg_connection* HttpsServer::initServer(mg_mgr* mgr, mg_event_handler_t...

FILE: test/httpsServer.hpp
  type cpr (line 12) | namespace cpr {
    class HttpsServer (line 13) | class HttpsServer : public AbstractServer {
      type mg_tls_opts (line 19) | struct mg_tls_opts

FILE: test/interceptor_multi_tests.cpp
  class HiddenHelloWorldRedirectInterceptorMulti (line 15) | class HiddenHelloWorldRedirectInterceptorMulti : public InterceptorMulti {
    method intercept (line 17) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeStatusCodeInterceptorMulti (line 38) | class ChangeStatusCodeInterceptorMulti : public InterceptorMulti {
    method intercept (line 40) | std::vector<Response> intercept(MultiPerform& multi) override {
  class SetBasicAuthInterceptorMulti (line 54) | class SetBasicAuthInterceptorMulti : public InterceptorMulti {
    method intercept (line 56) | std::vector<Response> intercept(MultiPerform& multi) override {
  class SetUnsupportedProtocolErrorInterceptorMulti (line 68) | class SetUnsupportedProtocolErrorInterceptorMulti : public InterceptorMu...
    method intercept (line 70) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToGetInterceptorMulti (line 86) | class ChangeRequestMethodToGetInterceptorMulti : public InterceptorMulti {
    method intercept (line 88) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToPostInterceptorMulti (line 96) | class ChangeRequestMethodToPostInterceptorMulti : public InterceptorMulti {
    method intercept (line 98) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToPutInterceptorMulti (line 106) | class ChangeRequestMethodToPutInterceptorMulti : public InterceptorMulti {
    method intercept (line 108) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToDeleteInterceptorMulti (line 116) | class ChangeRequestMethodToDeleteInterceptorMulti : public InterceptorMu...
    method intercept (line 118) | std::vector<Response> intercept(MultiPerform& multi) override {
  function write_data (line 125) | bool write_data(std::string_view /*data*/, intptr_t /*userdata*/) {
  class ChangeRequestMethodToDownloadCallbackInterceptorMulti (line 129) | class ChangeRequestMethodToDownloadCallbackInterceptorMulti : public Int...
    method intercept (line 131) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToHeadInterceptorMulti (line 139) | class ChangeRequestMethodToHeadInterceptorMulti : public InterceptorMulti {
    method intercept (line 141) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToOptionsInterceptorMulti (line 148) | class ChangeRequestMethodToOptionsInterceptorMulti : public InterceptorM...
    method intercept (line 150) | std::vector<Response> intercept(MultiPerform& multi) override {
  class ChangeRequestMethodToPatchInterceptorMulti (line 157) | class ChangeRequestMethodToPatchInterceptorMulti : public InterceptorMul...
    method intercept (line 159) | std::vector<Response> intercept(MultiPerform& multi) override {
  function TEST (line 167) | TEST(InterceptorMultiTest, HiddenUrlRewriteInterceptorMultiTest) {
  function TEST (line 183) | TEST(InterceptorMultiTest, ChangeStatusCodeInterceptorMultiTest) {
  function TEST (line 199) | TEST(InterceptorMultiTest, DownloadChangeStatusCodeInterceptorMultiTest) {
  function TEST (line 216) | TEST(InterceptorMultiTest, SetBasicAuthInterceptorMultiTest) {
  function TEST (line 234) | TEST(InterceptorMultiTest, SetUnsupportedProtocolErrorInterceptorMultiTe...
  function TEST (line 253) | TEST(InterceptorMultiTest, ChangeRequestMethodToGetInterceptorMultiTest) {
  function TEST (line 271) | TEST(InterceptorMultiTest, ChangeRequestMethodToPostInterceptorMultiTest) {
  function TEST (line 292) | TEST(InterceptorMultiTest, ChangeRequestMethodToPutInterceptorMultiTest) {
  function TEST (line 313) | TEST(InterceptorMultiTest, ChangeRequestMethodToPatchInterceptorMultiTes...
  function TEST (line 334) | TEST(InterceptorMultiTest, ChangeRequestMethodToOptionsInterceptorMultiT...
  function TEST (line 352) | TEST(InterceptorMultiTest, ChangeRequestMethodToHeadInterceptorMultiTest) {
  function TEST (line 369) | TEST(InterceptorMultiTest, ChangeRequestMethodToDownloadCallbackIntercep...
  function TEST (line 386) | TEST(InterceptorMultiTest, ChangeRequestMethodToDownloadCallbackIntercep...
  function TEST (line 406) | TEST(InterceptorMultiTest, ChangeRequestMethodToDeleteInterceptorMultiTe...
  function TEST (line 424) | TEST(InterceptorMultiTest, TwoInterceptorMultisTest) {
  function TEST (line 443) | TEST(InterceptorMultiTest, ThreeInterceptorMultisTest) {
  function main (line 466) | int main(int argc, char** argv) {

FILE: test/interceptor_tests.cpp
  class HiddenHelloWorldRedirectInterceptor (line 11) | class HiddenHelloWorldRedirectInterceptor : public Interceptor {
    method Response (line 13) | Response intercept(Session& session) override {
  class ChangeStatusCodeInterceptor (line 30) | class ChangeStatusCodeInterceptor : public Interceptor {
    method Response (line 32) | Response intercept(Session& session) override {
  class SetBasicAuthInterceptor (line 42) | class SetBasicAuthInterceptor : public Interceptor {
    method Response (line 44) | Response intercept(Session& session) override {
  class SetUnsupportedProtocolErrorInterceptor (line 53) | class SetUnsupportedProtocolErrorInterceptor : public Interceptor {
    method Response (line 55) | Response intercept(Session& session) override {
  class ChangeRequestMethodToGetInterceptor (line 67) | class ChangeRequestMethodToGetInterceptor : public Interceptor {
    method Response (line 69) | Response intercept(Session& session) override {
  class ChangeRequestMethodToPostInterceptor (line 74) | class ChangeRequestMethodToPostInterceptor : public Interceptor {
    method Response (line 76) | Response intercept(Session& session) override {
  class ChangeRequestMethodToPutInterceptor (line 82) | class ChangeRequestMethodToPutInterceptor : public Interceptor {
    method Response (line 84) | Response intercept(Session& session) override {
  class ChangeRequestMethodToDeleteInterceptor (line 90) | class ChangeRequestMethodToDeleteInterceptor : public Interceptor {
    method Response (line 92) | Response intercept(Session& session) override {
  function write_data (line 97) | bool write_data(std::string_view /*data*/, intptr_t /*userdata*/) {
  class ChangeRequestMethodToDownloadCallbackInterceptor (line 101) | class ChangeRequestMethodToDownloadCallbackInterceptor : public Intercep...
    method Response (line 103) | Response intercept(Session& session) override {
  class ChangeRequestMethodToHeadInterceptor (line 108) | class ChangeRequestMethodToHeadInterceptor : public Interceptor {
    method Response (line 110) | Response intercept(Session& session) override {
  class ChangeRequestMethodToOptionsInterceptor (line 115) | class ChangeRequestMethodToOptionsInterceptor : public Interceptor {
    method Response (line 117) | Response intercept(Session& session) override {
  class ChangeRequestMethodToPatchInterceptor (line 122) | class ChangeRequestMethodToPatchInterceptor : public Interceptor {
    method Response (line 124) | Response intercept(Session& session) override {
  class RetryInterceptor (line 130) | class RetryInterceptor : public Interceptor {
    method Response (line 132) | Response intercept(Session& session) override {
  function TEST (line 143) | TEST(InterceptorTest, HiddenUrlRewriteInterceptorTest) {
  function TEST (line 156) | TEST(InterceptorTest, ChangeStatusCodeInterceptorTest) {
  function TEST (line 175) | TEST(InterceptorTest, RetryInterceptorTest) {
  function TEST (line 195) | TEST(InterceptorTest, DownloadChangeStatusCodeInterceptorTest) {
  function TEST (line 209) | TEST(InterceptorTest, SetBasicAuthInterceptorTest) {
  function TEST (line 224) | TEST(InterceptorTest, SetUnsupportedProtocolErrorInterceptorTest) {
  function TEST (line 240) | TEST(InterceptorTest, ChangeRequestMethodToGetInterceptorTest) {
  function TEST (line 255) | TEST(InterceptorTest, ChangeRequestMethodToPostInterceptorTest) {
  function TEST (line 273) | TEST(InterceptorTest, ChangeRequestMethodToPutInterceptorTest) {
  function TEST (line 291) | TEST(InterceptorTest, ChangeRequestMethodToPatchInterceptorTest) {
  function TEST (line 309) | TEST(InterceptorTest, ChangeRequestMethodToOptionsInterceptorTest) {
  function TEST (line 324) | TEST(InterceptorTest, ChangeRequestMethodToHeadInterceptorTest) {
  function TEST (line 338) | TEST(InterceptorTest, ChangeRequestMethodToDownloadCallbackInterceptorTe...
  function TEST (line 352) | TEST(InterceptorTest, ChangeRequestMethodToDeleteInterceptorTest) {
  function TEST (line 368) | TEST(InterceptorTest, TwoInterceptorsTest) {
  function TEST (line 384) | TEST(InterceptorTest, ThreeInterceptorsTest) {
  function main (line 404) | int main(int argc, char** argv) {

FILE: test/multiasync_tests.cpp
  function TEST (line 19) | TEST(AsyncWrapperTests, TestConstructorDeductions) {
  function TEST (line 32) | TEST(AsyncWrapperNonCancellableTests, TestGetNoError) {
  function TEST (line 39) | TEST(AsyncWrapperNonCancellableTests, TestExceptionsNoSharedState) {
  function TEST (line 55) | TEST(AsyncWrapperCancellableTests, TestExceptionsNoSharedState) {
  function TEST (line 72) | TEST(AsyncWrapperCancellableTests, TestExceptionsCancelledRequest) {
  function TEST (line 88) | TEST(AsyncWrapperCancellableTests, TestWaitFor) {
  function TEST (line 108) | TEST(MultiAsyncBasicTests, MultiAsyncGetTest) {
  function TEST (line 118) | TEST(MultiAsyncBasicTests, MultiAsyncDeleteTest) {
  function TEST (line 152) | TEST(MultiAsyncBasicTests, MultiAsyncHeadTest) {
  function TEST (line 191) | TEST(MultiAsyncBasicTests, MultiAsyncOptionsTest) {
  function TEST (line 214) | TEST(MultiAsyncBasicTests, MultiAsyncPatchTest) {
  function TEST (line 238) | TEST(MultiAsyncBasicTests, MultiAsyncPostTest) {
  function TEST (line 275) | TEST(MultiAsyncBasicTests, MultiAsyncPutTest) {
  function TEST (line 311) | TEST(MultiAsyncCancelTests, CancellationOnQueue) {
  function TEST (line 337) | TEST(MultiAsyncCancelTests, TestCancellationInTransit) {
  function TEST (line 371) | TEST(MultiAsyncCancelTests, TestCancellationOnResponseWrapperDestruction) {
  function TEST (line 408) | TEST(MultiAsyncCancelTests, TestIntervalOfProgressCallsLowSpeed) {
  function main (line 430) | int main(int argc, char** argv) {

FILE: test/multiasync_tests.hpp
  class TestSynchronizationEnv (line 7) | class TestSynchronizationEnv : public testing::Environment {
    method Reset (line 14) | void Reset() {

FILE: test/multiperform_tests.cpp
  function write_data (line 18) | bool write_data(std::string_view /*data*/, intptr_t /*userdata*/) {
  function TEST (line 22) | TEST(MultiperformAddSessionTests, MultiperformAddSingleSessionTest) {
  function TEST (line 30) | TEST(MultiperformAddSessionTests, MultiperformAddMultipleSessionsTest) {
  function TEST (line 39) | TEST(MultiperformAddSessionTests, MultiperformAddMultipleNonDownloadSess...
  function TEST (line 48) | TEST(MultiperformAddSessionTests, MultiperformAddMultipleDownloadSession...
  function TEST (line 57) | TEST(MultiperformAddSessionTests, MultiperformAddTwoMixedTypeSessionsTes...
  function TEST (line 66) | TEST(MultiperformAddSessionTests, MultiperformAddTwoMixedTypeSessionsRev...
  function TEST (line 75) | TEST(MultiperformRemoveSessionTests, MultiperformRemoveSingleSessionTest) {
  function TEST (line 84) | TEST(MultiperformRemoveSessionTests, MultiperformRemoveMultipleSessionsT...
  function TEST (line 95) | TEST(MultiperformRemoveSessionTests, MultiperformRemoveNonExistingSessio...
  function TEST (line 101) | TEST(MultiperformRemoveSessionTests, MultiperformRemoveNonExistingSessio...
  function TEST (line 110) | TEST(MultiperformGetTests, MultiperformSingleSessionGetTest) {
  function TEST (line 127) | TEST(MultiperformGetTests, MultiperformTwoSessionsGetTest) {
  function TEST (line 167) | TEST(MultiperformGetTests, MultiperformRemoveSessionGetTest) {
  function TEST (line 195) | TEST(MultiperformGetTests, MultiperformSingleSessionMultiGetTest) {
  function TEST (line 220) | TEST(MultiperformGetTests, MultiperformAssignAfterUseTest) {
  function TEST (line 263) | TEST(MultiperformGetTests, MultiperformTenSessionsGetTest) {
  function TEST (line 287) | TEST(MultiperformDeleteTests, MultiperformSingleSessionDeleteTest) {
  function TEST (line 304) | TEST(MultiperformDownloadTests, MultiperformSingleSessionDownloadTest) {
  function TEST (line 319) | TEST(MultiperformDownloadTests, MultiperformSingleSessionDownloadNonMatc...
  function TEST (line 326) | TEST(MultiperformDownloadTests, MultiperformTwoSessionsDownloadTest) {
  function TEST (line 354) | TEST(MultiperformPutTests, MultiperformSingleSessionPutTest) {
  function TEST (line 375) | TEST(MultiperformHeadTests, MultiperformSingleSessionHeadTest) {
  function TEST (line 392) | TEST(MultiperformOptionsTests, MultiperformSingleSessionOptionsTest) {
  function TEST (line 409) | TEST(MultiperformPatchTests, MultiperformSingleSessionPatchTest) {
  function TEST (line 430) | TEST(MultiperformPostTests, MultiperformSingleSessionPostTest) {
  function TEST (line 451) | TEST(MultiperformPerformTests, MultiperformSingleGetPerformTest) {
  function TEST (line 468) | TEST(MultiperformPerformTests, MultiperformTwoGetPerformTest) {
  function TEST (line 508) | TEST(MultiperformPerformTests, MultiperformMixedMethodsPerformTest) {
  function TEST (line 570) | TEST(MultiperformPerformDownloadTests, MultiperformSinglePerformDownload...
  function TEST (line 585) | TEST(MultiperformDownloadTests, MultiperformSinglePerformDownloadNonMatc...
  function TEST (line 592) | TEST(MultiperformPerformDownloadTests, MultiperformTwoPerformDownloadTes...
  function TEST (line 620) | TEST(MultiperformAPITests, MultiperformApiSingleGetTest) {
  function TEST (line 631) | TEST(MultiperformAPITests, MultiperformApiTwoGetsTest) {
  function TEST (line 664) | TEST(MultiperformAPITests, MultiperformApiSingleDeleteTest) {
  function TEST (line 675) | TEST(MultiperformAPITests, MultiperformApiSinglePutTest) {
  function TEST (line 689) | TEST(MultiperformAPITests, MultiperformApiSingleHeadTest) {
  function TEST (line 700) | TEST(MultiperformAPITests, MultiperformApiSingleOptionsTest) {
  function TEST (line 711) | TEST(MultiperformAPITests, MultiperformApiSinglePatchTest) {
  function TEST (line 725) | TEST(MultiperformAPITests, MultiperformApiSinglePostTest) {
  function main (line 739) | int main(int argc, char** argv) {

FILE: test/options_tests.cpp
  function TEST (line 13) | TEST(OptionsTests, BaseUrlTest) {
  function TEST (line 24) | TEST(OptionsTests, SpecificUrlTest) {
  function TEST (line 35) | TEST(OptionsTests, AsyncBaseUrlTest) {
  function TEST (line 52) | TEST(OptionsTests, AsyncSpecificUrlTest) {
  function main (line 69) | int main(int argc, char** argv) {

FILE: test/patch_tests.cpp
  function TEST (line 13) | TEST(PatchTests, PatchTest) {
  function TEST (line 28) | TEST(PatchTests, PatchUnallowedTest) {
  function TEST (line 40) | TEST(PatchTests, SessionPatchTest) {
  function TEST (line 58) | TEST(PatchTests, SessionPatchUnallowedTest) {
  function TEST (line 73) | TEST(PatchTests, SessionPatchAfterGetTest) {
  function TEST (line 96) | TEST(PatchTests, SessionPatchUnallowedAfterGetTest) {
  function TEST (line 116) | TEST(PatchTests, SessionPatchAfterHeadTest) {
  function TEST (line 139) | TEST(PatchTests, SessionPatchUnallowedAfterHeadTest) {
  function TEST (line 159) | TEST(PatchTests, SessionPatchAfterPostTest) {
  function TEST (line 183) | TEST(PatchTests, SessionPatchUnallowedAfterPostTest) {
  function TEST (line 204) | TEST(PatchTests, AsyncPatchTest) {
  function TEST (line 220) | TEST(PatchTests, AsyncPatchUnallowedTest) {
  function TEST (line 233) | TEST(PatchTests, AsyncMultiplePatchTest) {
  function TEST (line 254) | TEST(PatchTests, AsyncMultiplePatchUnallowedTest) {
  function main (line 272) | int main(int argc, char** argv) {

FILE: test/post_tests.cpp
  function TEST (line 20) | TEST(UrlEncodedPostTests, UrlPostSingleTest) {
  function TEST (line 34) | TEST(UrlEncodedPostTests, UrlPostAddPayloadPair) {
  function TEST (line 51) | TEST(UrlEncodedPostTests, UrlPostPayloadIteratorTest) {
  function TEST (line 69) | TEST(UrlEncodedPostTests, UrlPostEncodeTest) {
  function TEST (line 83) | TEST(UrlEncodedPostTests, UrlPostEncodeNoCopyTest) {
  function TEST (line 99) | TEST(UrlEncodedPostTests, UrlPostManyTest) {
  function TEST (line 115) | TEST(UrlEncodedPostTests, UrlPostBadHostTest) {
  function TEST (line 126) | TEST(UrlEncodedPostTests, FormPostSingleTest) {
  function TEST (line 140) | TEST(UrlEncodedPostTests, FormPostFileTest) {
  function TEST (line 163) | TEST(UrlEncodedPostTests, FormPostMultipleFilesTestLvalue) {
  function TEST (line 242) | TEST(UrlEncodedPostTests, FormPostMultipleFilesTestRvalue) {
  function TEST (line 317) | TEST(UrlEncodedPostTests, FormPostFileTestWithOverridenFilename) {
  function TEST (line 342) | TEST(UrlEncodedPostTests, FormPostFileNoCopyTest) {
  function TEST (line 366) | TEST(UrlEncodedPostTests, FormPostFileNoCopyTestWithOverridenFilename) {
  function TEST (line 391) | TEST(UrlEncodedPostTests, TimeoutPostTest) {
  function TEST (line 403) | TEST(UrlEncodedPostTests, FormPostFileBufferTest) {
  function TEST (line 420) | TEST(UrlEncodedPostTests, FormPostFileBufferNoCopyTest) {
  function TEST (line 438) | TEST(UrlEncodedPostTests, FormPostFileBufferPointerTest) {
  function TEST (line 455) | TEST(UrlEncodedPostTests, FormPostFileBufferArrayTest) {
  function TEST (line 473) | TEST(UrlEncodedPostTests, FormPostFileBufferVectorTest) {
  function TEST (line 488) | TEST(UrlEncodedPostTests, FormPostFileBufferStdArrayTest) {
  function TEST (line 503) | TEST(UrlEncodedPostTests, FormPostBufferRvalueTest) {
  function TEST (line 518) | TEST(UrlEncodedPostTests, ReflectPostBufferLvalueTest) {
  function TEST (line 534) | TEST(UrlEncodedPostTests, FormPostManyTest) {
  function TEST (line 549) | TEST(UrlEncodedPostTests, FormPostManyNoCopyTest) {
  function TEST (line 565) | TEST(UrlEncodedPostTests, FormPostContentTypeTest) {
  function TEST (line 579) | TEST(UrlEncodedPostTests, FormPostContentTypeLValueTest) {
  function TEST (line 594) | TEST(UrlEncodedPostTests, UrlPostAsyncSingleTest) {
  function TEST (line 615) | TEST(UrlEncodedPostTests, UrlReflectTest) {
  function TEST (line 625) | TEST(UrlEncodedPostTests, PostWithNoBodyTest) {
  function getTimestamp (line 636) | static std::string getTimestamp() {
  function TEST (line 651) | TEST(UrlEncodedPostTests, PostReflectTest) {
  function TEST (line 669) | TEST(UrlEncodedPostTests, PostReflectPayloadTest) {
  function TEST (line 678) | TEST(UrlEncodedPostTests, InjectMultipleHeadersTest) {
  function TEST (line 692) | TEST(UrlEncodedPostTests, PostBodyWithFile) {
  function TEST (line 708) | TEST(UrlEncodedPostTests, PostBodyWithBuffer) {
  function TEST (line 719) | TEST(PostRedirectTests, TempRedirectTest) {
  function TEST (line 733) | TEST(PostRedirectTests, TempRedirectNoneTest) {
  function TEST (line 741) | TEST(PostRedirectTests, PermRedirectTest) {
  function TEST (line 755) | TEST(PostRedirectTests, PermRedirectNoneTest) {
  function TEST (line 763) | TEST(PostRedirectTests, TempRedirectDefaultTest) {
  function TEST (line 772) | TEST(PostRedirectTests, PermRedirectDefaultTest) {
  function main (line 781) | int main(int argc, char** argv) {

FILE: test/prepare_tests.cpp
  function TEST (line 14) | TEST(PrepareTests, GetTest) {
  function TEST (line 29) | TEST(PrepareTests, OptionsTests) {
  function TEST (line 44) | TEST(PrepareTests, PatchTest) {
  function TEST (line 64) | TEST(PrepareTests, MultipleDeleteHeadPutGetPostTest) {
  function main (line 137) | int main(int argc, char** argv) {

FILE: test/proxy_auth_tests.cpp
  function TEST (line 20) | TEST(ProxyAuthTests, SetProxyCredentials) {
  function TEST (line 32) | TEST(ProxyAuthTests, SingleProxyTest) {
  function TEST (line 43) | TEST(ProxyAuthTests, MultipleProxyHttpTest) {
  function TEST (line 54) | TEST(ProxyAuthTests, CopyProxyTest) {
  function TEST (line 67) | TEST(ProxyAuthTests, ProxySessionTest) {
  function TEST (line 82) | TEST(ProxyAuthTests, ReferenceProxySessionTest) {
  function main (line 100) | int main(int argc, char** argv) {

FILE: test/proxy_tests.cpp
  function TEST (line 23) | TEST(ProxyTests, SingleProxyTest) {
  function TEST (line 32) | TEST(ProxyTests, MultipleProxyHttpTest) {
  function TEST (line 43) | TEST(ProxyTests, ProxyHttpsTest) {
  function TEST (line 52) | TEST(ProxyTests, MultipleProxyHttpsTest) {
  function TEST (line 62) | TEST(ProxyTests, CopyProxyTest) {
  function TEST (line 72) | TEST(ProxyTests, ProxySessionTest) {
  function TEST (line 84) | TEST(ProxyTests, ReferenceProxySessionTest) {
  function TEST (line 98) | TEST(ProxyTests, NoProxyTest) {
  function main (line 141) | int main(int argc, char** argv) {

FILE: test/put_tests.cpp
  function TEST (line 13) | TEST(PutTests, PutTest) {
  function TEST (line 28) | TEST(PutTests, PutUnallowedTest) {
  function TEST (line 40) | TEST(PutTests, SessionPutTest) {
  function TEST (line 58) | TEST(PutTests, SessionPutUnallowedTest) {
  function TEST (line 73) | TEST(PutTests, SessionPutAfterGetTest) {
  function TEST (line 96) | TEST(PutTests, SessionPutUnallowedAfterGetTest) {
  function TEST (line 116) | TEST(PutTests, SessionPutAfterHeadTest) {
  function TEST (line 139) | TEST(PutTests, SessionPutUnallowedAfterHeadTest) {
  function TEST (line 159) | TEST(PutTests, SessionPutAfterPostTest) {
  function TEST (line 183) | TEST(PutTests, SessionPutUnallowedAfterPostTest) {
  function TEST (line 204) | TEST(PutTests, AsyncPutTest) {
  function TEST (line 220) | TEST(PutTests, AsyncPutUnallowedTest) {
  function TEST (line 233) | TEST(PutTests, AsyncMultiplePutTest) {
  function TEST (line 254) | TEST(PutTests, AsyncMultiplePutUnallowedTest) {
  function main (line 272) | int main(int argc, char** argv) {

FILE: test/raw_body_tests.cpp
  function TEST (line 16) | TEST(BodyPostTests, DefaultUrlEncodedPostTest) {
  function TEST (line 27) | TEST(BodyPostTests, TextUrlEncodedPostTest) {
  function TEST (line 41) | TEST(BodyPostTests, TextUrlEncodedNoCopyPostTest) {
  function TEST (line 57) | TEST(BodyPostTests, UrlEncodedManyPostTest) {
  function TEST (line 73) | TEST(BodyPostTests, CustomHeaderNumberPostTest) {
  function TEST (line 84) | TEST(BodyPostTests, CustomHeaderTextPostTest) {
  function TEST (line 95) | TEST(BodyPostTests, CustomWrongHeaderPostTest) {
  function TEST (line 106) | TEST(BodyPostTests, UrlPostBadHostTest) {
  function TEST (line 117) | TEST(BodyPostTests, StringMoveBodyTest) {
  function TEST (line 131) | TEST(BodyPostTests, BodyViewTest) {
  function main (line 145) | int main(int argc, char** argv) {

FILE: test/resolve_tests.cpp
  function TEST (line 12) | TEST(ResolveTests, HelloWorldTest) {
  function TEST (line 24) | TEST(ResolveTests, RedirectMultiple) {
  function main (line 40) | int main(int argc, char** argv) {

FILE: test/session_tests.cpp
  function write_data (line 25) | bool write_data(std::string_view /*data*/, intptr_t /*userdata*/) {
  function TEST (line 29) | TEST(SessionGetTests, GetMultipleTimes) {
  function TEST (line 45) | TEST(SessionPostTests, PostMultipleTimes) {
  function TEST (line 65) | TEST(RedirectTests, TemporaryDefaultRedirectTest) {
  function TEST (line 78) | TEST(RedirectTests, NoTemporaryRedirectTest) {
  function TEST (line 92) | TEST(RedirectTests, PermanentDefaultRedirectTest) {
  function TEST (line 105) | TEST(RedirectTests, NoPermanentRedirectTest) {
  function TEST (line 119) | TEST(MaxRedirectsTests, ZeroMaxRedirectsSuccessTest) {
  function TEST (line 133) | TEST(MaxRedirectsTests, ZeroMaxRedirectsFailureTest) {
  function TEST (line 146) | TEST(MaxRedirectsTests, OneMaxRedirectsSuccessTest) {
  function TEST (line 160) | TEST(MaxRedirectsTests, OneMaxRedirectsFailureTest) {
  function TEST (line 173) | TEST(MaxRedirectsTests, TwoMaxRedirectsSuccessTest) {
  function TEST (line 187) | TEST(MultipleGetTests, BasicMultipleGetTest) {
  function TEST (line 202) | TEST(MultipleGetTests, UrlChangeMultipleGetTest) {
  function TEST (line 234) | TEST(MultipleGetTests, HeaderMultipleGetTest) {
  function TEST (line 251) | TEST(MultipleGetTests, HeaderChangeMultipleGetTest) {
  function TEST (line 292) | TEST(MultipleGetTests, ParameterMultipleGetTest) {
  function TEST (line 308) | TEST(MultipleGetTests, ParameterChangeMultipleGetTest) {
  function TEST (line 335) | TEST(MultipleGetTests, BasicAuthenticationMultipleGetTest) {
  function TEST (line 351) | TEST(MultipleGetTests, BasicAuthenticationChangeMultipleGetTest) {
  function TEST (line 385) | TEST(ParameterTests, ParameterSingleTest) {
  function TEST (line 400) | TEST(ParameterTests, ParameterMultipleTest) {
  function TEST (line 415) | TEST(FullRequestUrlTest, GetFullRequestUrlNoParametersTest) {
  function TEST (line 423) | TEST(FullRequestUrlTest, GetFullRequestUrlOneParameterTest) {
  function TEST (line 433) | TEST(FullRequestUrlTest, GetFullRequestUrlMultipleParametersTest) {
  function TEST (line 443) | TEST(TimeoutTests, SetTimeoutTest) {
  function TEST (line 457) | TEST(TimeoutTests, SetTimeoutLongTest) {
  function TEST (line 471) | TEST(TimeoutTests, SetTimeoutLowSpeed) {
  function TEST (line 482) | TEST(TimeoutTests, SetChronoTimeoutTest) {
  function TEST (line 496) | TEST(TimeoutTests, SetChronoTimeoutLongTest) {
  function TEST (line 510) | TEST(TimeoutTests, SetChronoLiteralTimeoutTest) {
  function TEST (line 524) | TEST(TimeoutTests, SetChronoLiteralTimeoutLowSpeed) {
  function TEST (line 535) | TEST(ConnectTimeoutTests, SetConnectTimeoutTest) {
  function TEST (line 549) | TEST(ConnectTimeoutTests, SetConnectTimeoutLongTest) {
  function TEST (line 563) | TEST(ConnectTimeoutTests, SetChronoConnectTimeoutTest) {
  function TEST (line 577) | TEST(ConnectTimeoutTests, SetChronoConnectTimeoutLongTest) {
  function TEST (line 591) | TEST(LowSpeedTests, SetLowSpeedTest) {
  function TEST (line 605) | TEST(PayloadTests, SetPayloadTest) {
  function TEST (line 622) | TEST(PayloadTests, SetPayloadLValueTest) {
  function TEST (line 640) | TEST(MultipartTests, SetMultipartTest) {
  function TEST (line 657) | TEST(MultipartTests, SetMultipartValueTest) {
  function TEST (line 675) | TEST(MultipartTests, SetMultipartVectorPartsTest) {
  function TEST (line 693) | TEST(BodyTests, SetBodyTest) {
  function TEST (line 710) | TEST(BodyTests, SetBodyValueTest) {
  function TEST (line 728) | TEST(BodyTests, SetBodyViewTest) {
  function TEST (line 745) | TEST(DigestTests, SetDigestTest) {
  function TEST (line 759) | TEST(AnyAuthTests, SetAnyTest) {
  function TEST (line 773) | TEST(AnyAuthTests, SetAnySafeTest) {
  function TEST (line 802) | TEST(UserAgentTests, SetUserAgentTest) {
  function TEST (line 818) | TEST(UserAgentTests, SetUserAgentStringViewTest) {
  function TEST (line 834) | TEST(CookiesTests, BasicCookiesTest) {
  function TEST (line 860) | TEST(CookiesTests, ClientSetCookiesTest) {
  function TEST (line 893) | TEST(CookiesTests, RedirectionWithChangingCookiesTest) {
  function TEST (line 937) | TEST(DifferentMethodTests, GetPostTest) {
  function TEST (line 959) | TEST(DifferentMethodTests, PostGetTest) {
  function TEST (line 981) | TEST(DifferentMethodTests, GetPostGetTest) {
  function TEST (line 1011) | TEST(DifferentMethodTests, PostGetPostTest) {
  function TEST (line 1041) | TEST(DifferentMethodTests, MultipleGetPostTest) {
  function TEST (line 1065) | TEST(DifferentMethodTests, MultipleDeleteHeadPutGetPostTest) {
  function TEST (line 1151) | TEST(CurlHolderManipulateTests, CustomOptionTest) {
  function TEST (line 1174) | TEST(LocalPortTests, SetLocalPortTest) {
  function TEST (line 1201) | TEST(LocalPortTests, SetOptionTest) {
  function TEST (line 1234) | TEST(LocalPortTests, SetLocalPortTestOccupied) {
  function TEST (line 1244) | TEST(LocalPortTests, SetOptionTestOccupied) {
  function TEST (line 1255) | TEST(BasicTests, ReserveResponseString) {
  function Split (line 1270) | std::vector<std::string> Split(const std::string& s) {
  function CompareEncodings (line 1283) | void CompareEncodings(const std::string& response, const std::vector<std...
  function TEST (line 1292) | TEST(BasicTests, AcceptEncodingTestWithMethodsStringMap) {
  function TEST (line 1306) | TEST(BasicTests, AcceptEncodingTestWithMethodsStringMapLValue) {
  function TEST (line 1321) | TEST(BasicTests, AcceptEncodingTestWithCostomizedString) {
  function TEST (line 1335) | TEST(BasicTests, AcceptEncodingTestWithCostomizedStringLValue) {
  function TEST (line 1350) | TEST(BasicTests, AcceptEncodingTestDisabled) {
  function TEST (line 1364) | TEST(BasicTests, AcceptEncodingTestDisabledMultipleThrow) {
  function TEST (line 1372) | TEST(BasicTests, DisableHeaderExpect100ContinueTest) {
  function TEST (line 1391) | TEST(AsyncRequestsTests, AsyncGetTest) {
  function TEST (line 1404) | TEST(AsyncRequestsTests, AsyncGetMultipleTest) {
  function TEST (line 1426) | TEST(AsyncRequestsTests, AsyncGetMultipleTemporarySessionTest) {
  function TEST (line 1446) | TEST(AsyncRequestsTests, AsyncGetMultipleReflectTest) {
  function TEST (line 1468) | TEST(AsyncRequestsTests, AsyncWritebackDownloadTest) {
  function TEST (line 1480) | TEST(AsyncRequestsTests, AsyncPostTest) {
  function TEST (line 1498) | TEST(AsyncRequestsTests, AsyncPutTest) {
  function TEST (line 1516) | TEST(AsyncRequestsTests, AsyncHeadTest) {
  function TEST (line 1529) | TEST(AsyncRequestsTests, AsyncDeleteTest) {
  function TEST (line 1542) | TEST(AsyncRequestsTests, AsyncOptionsTest) {
  function TEST (line 1555) | TEST(AsyncRequestsTests, AsyncPatchTest) {
  function TEST (line 1568) | TEST(CallbackTests, GetCallbackTest) {
  function TEST (line 1582) | TEST(CallbackTests, PostCallbackTest) {
  function TEST (line 1596) | TEST(CallbackTests, PutCallbackTest) {
  function TEST (line 1615) | TEST(CallbackTests, HeadCallbackTest) {
  function TEST (line 1629) | TEST(CallbackTests, DeleteCallbackTest) {
  function TEST (line 1643) | TEST(CallbackTests, OptionsCallbackTest) {
  function TEST (line 1657) | TEST(CallbackTests, PatchCallbackTest) {
  function TEST (line 1671) | TEST(CallbackTests, Move) {
  function main (line 1683) | int main(int argc, char** argv) {

FILE: test/singleton_tests.cpp
  function TEST (line 8) | TEST(SingletonTests, GetInstanceTest) {
  function TEST (line 13) | TEST(SingletonTests, ExitInstanceTest) {
  function main (line 20) | int main(int argc, char** argv) {

FILE: test/singleton_tests.hpp
  class TestSingleton (line 5) | class TestSingleton {

FILE: test/sse_tests.cpp
  function TEST (line 16) | TEST(SSETests, SSEParserBasicTest) {
  function TEST (line 34) | TEST(SSETests, SSEParserMultilineDataTest) {
  function TEST (line 50) | TEST(SSETests, SSEParserWithEventTypeTest) {
  function TEST (line 66) | TEST(SSETests, SSEParserWithIdTest) {
  function TEST (line 84) | TEST(SSETests, SSEParserWithRetryTest) {
  function TEST (line 101) | TEST(SSETests, SSEParserCompleteEventTest) {
  function TEST (line 126) | TEST(SSETests, SSEParserMultipleEventsTest) {
  function TEST (line 146) | TEST(SSETests, SSEParserIgnoreCommentsTest) {
  function TEST (line 165) | TEST(SSETests, SSEParserIgnoreEmptyDataTest) {
  function TEST (line 181) | TEST(SSETests, SSEParserChunkedDataTest) {
  function TEST (line 202) | TEST(SSETests, SSEParserCRLFTest) {
  function TEST (line 217) | TEST(SSETests, SSEParserFieldWithoutColonTest) {
  function TEST (line 235) | TEST(SSETests, SSECallbackTest) {
  function TEST (line 247) | TEST(SSETests, SSECallbackHandleDataTest) {
  function TEST (line 263) | TEST(SSETests, SSECallbackAbortTest) {
  function main (line 286) | int main(int argc, char** argv) {

FILE: test/ssl_tests.cpp
  function loadFileContent (line 24) | std::string loadFileContent(const std::string filePath) {
  function TEST (line 31) | TEST(SslTests, HelloWorldTestSimpel) {
  function TEST (line 49) | TEST(SslTests, HelloWorldTestFull) {
  function TEST (line 71) | TEST(SslTests, GetCertInfos) {
  function TEST (line 142) | TEST(SslTests, LoadCertFromBufferTestSimpel) {
  function TEST (line 163) | TEST(SslTests, LoadCertFromBlobTestSimpel) {
  function TEST (line 184) | TEST(SslTests, LoadKeyFromBlobTestSimpel) {
  function TEST (line 205) | TEST(SslTests, CaInfoBlobTestSimpel) {
  function GetBasePath (line 224) | fs::path GetBasePath(const std::string& execPath) {
  function main (line 228) | int main(int argc, char** argv) {

FILE: test/structures_tests.cpp
  function TEST (line 11) | TEST(PayloadTests, UseStringVariableTest) {
  function TEST (line 20) | TEST(PayloadTests, DisableEncodingTest) {
  function TEST (line 32) | TEST(ParametersTests, UseStringVariableTest) {
  function TEST (line 41) | TEST(ParametersTests, DisableEncodingTest) {
  function TEST (line 53) | TEST(ParametersTests, NoCurlHolderTest) {
  function TEST (line 63) | TEST(UrlToAndFromString, UrlTests) {
  function main (line 69) | int main(int argc, char** argv) {

FILE: test/testUtils.cpp
  type cpr::test (line 18) | namespace cpr::test {
    function get_free_port (line 20) | std::uint16_t get_free_port() {

FILE: test/testUtils.hpp
  type cpr::test (line 12) | namespace cpr::test {
    type WSAInit (line 18) | struct WSAInit {
      method WSAInit (line 19) | WSAInit() {

FILE: test/testUtils_tests.cpp
  function TEST (line 6) | TEST(TestUtils, GetUnusedPort) {
  function main (line 13) | int main(int argc, char** argv) {

FILE: test/threadpool_tests.cpp
  function TEST (line 8) | TEST(ThreadPoolTests, DISABLED_BasicWorkOneThread) {
  function TEST (line 29) | TEST(ThreadPoolTests, DISABLED_BasicWorkMultipleThreads) {
  function TEST (line 50) | TEST(ThreadPoolTests, DISABLED_PauseResumeSingleThread) {
  function TEST (line 76) | TEST(ThreadPoolTests, DISABLED_PauseResumeMultipleThreads) {
  function main (line 103) | int main(int argc, char** argv) {

FILE: test/util_tests.cpp
  function TEST (line 10) | TEST(UtilParseCookiesTests, BasicParseTest) {
  function TEST (line 33) | TEST(UtilParseHeaderTests, BasicParseTest) {
  function TEST (line 54) | TEST(UtilParseHeaderTests, NewlineTest) {
  function TEST (line 65) | TEST(UtilParseHeaderTests, SpaceNewlineTest) {
  function TEST (line 76) | TEST(UtilParseHeaderTests, CarriageReturnNewlineTest) {
  function TEST (line 87) | TEST(UtilParseHeaderTests, SpaceCarriageReturnNewlineTest) {
  function TEST (line 98) | TEST(UtilParseHeaderTests, BasicStatusLineTest) {
  function TEST (line 113) | TEST(UtilParseHeaderTests, NewlineStatusLineTest) {
  function TEST (line 128) | TEST(UtilParseHeaderTests, NoReasonSpaceTest) {
  function TEST (line 143) | TEST(UtilParseHeaderTests, NoReasonTest) {
  function TEST (line 158) | TEST(UtilUrlEncodeTests, UnicodeEncoderTest) {
  function TEST (line 165) | TEST(UtilUrlEncodeTests, AsciiEncoderTest) {
  function TEST (line 172) | TEST(UtilUrlDecodeTests, UnicodeDecoderTest) {
  function TEST (line 179) | TEST(UtilUrlDecodeTests, AsciiDecoderTest) {
  function TEST (line 186) | TEST(UtilIsTrueTests, TrueTest) {
  function TEST (line 204) | TEST(UtilIsTrueTests, FalseTest) {
  function main (line 222) | int main(int argc, char** argv) {

FILE: test/version_tests.cpp
  function TEST (line 8) | TEST(VersionTests, StringVersionExists) {
  function TEST (line 14) | TEST(VersionTests, StringVersionValid) {
  function TEST (line 37) | TEST(VersionTests, VersionMajorExists) {
  function TEST (line 43) | TEST(VersionTests, VersionMinorExists) {
  function TEST (line 49) | TEST(VersionTests, VersionPatchExists) {
  function TEST (line 55) | TEST(VersionTests, VersionNumExists) {
  function main (line 62) | int main(int argc, char** argv) {
Condensed preview — 197 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (910K chars).
[
  {
    "path": ".clang-format",
    "chars": 1801,
    "preview": "---\nLanguage:        Cpp\n# BasedOnStyle:  Google\nAccessModifierOffset: -2\nAlignAfterOpenBracket: true\nAlignEscapedNewlin"
  },
  {
    "path": ".clang-tidy",
    "chars": 1642,
    "preview": "---\nChecks: '*,\n-cppcoreguidelines-pro-type-static-cast-downcast,\n-fuchsia-default-arguments-calls,\n-fuchsia-default-arg"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "chars": 2349,
    "preview": "name: \"🐛 Bug report\"\ndescription: Something in cpr is not working as expected? Create a report to help us improve.\nlabel"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "chars": 1911,
    "preview": "name: \"✨ Feature request\"\ndescription: Suggest an idea for this project.\nlabels: [\"Needs Investigation :mag:\", \"Feature "
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 117,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/workflows/build-deb.yml",
    "chars": 1682,
    "preview": "name: Build Debian Package\non:\n  push:\n    tags: [ '[0-9]+.[0-9]+.[0-9]+' ]\n  workflow_dispatch:\n    inputs:\n      versi"
  },
  {
    "path": ".github/workflows/build-nuget.yml",
    "chars": 4238,
    "preview": "name: Build NuGet Package\non:\n  push:\n    tags: [ '[0-9]+.[0-9]+.[0-9]+' ]\n  workflow_dispatch:\n    inputs:\n      versio"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 12460,
    "preview": "name: CI\non: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull request. Yes, th"
  },
  {
    "path": ".github/workflows/clang-format.yml",
    "chars": 675,
    "preview": "name: \"Test Clang Format\"\n\non: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pul"
  },
  {
    "path": ".github/workflows/clang-tidy.yml",
    "chars": 1102,
    "preview": "name: \"Test Clang Tidy\"\n\non: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull "
  },
  {
    "path": ".github/workflows/cppcheck.yml",
    "chars": 1173,
    "preview": "name: \"Test cppcheck\"\n\non: [push, workflow_dispatch, pull_request] # Trigger for every push as well as for every pull re"
  },
  {
    "path": ".github/workflows/readme-updater.yml",
    "chars": 660,
    "preview": "name: Update GIT_TAG In Readme\non:\n  release:\n    types: [published]\n\n# Workflow configuration\nenv:\n  OUTPUT_BRANCH: \"ma"
  },
  {
    "path": ".gitignore",
    "chars": 643,
    "preview": "# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic libraries\n*.so\n*.dyl"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 1671,
    "preview": "{\n    // See https://go.microsoft.com/fwlink/?LinkId=733558\n    // for the documentation about the tasks.json format\n   "
  },
  {
    "path": "CMakeLists.txt",
    "chars": 21420,
    "preview": "cmake_minimum_required(VERSION 3.18)\nproject(cpr VERSION 1.15.0 LANGUAGES CXX)\n\nmath(EXPR cpr_VERSION_NUM \"${cpr_VERSION"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5215,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1276,
    "preview": "# Contributing to C++ Requests\n\nPlease fork this repository and contribute back using [pull requests](https://github.com"
  },
  {
    "path": "LICENSE",
    "chars": 1229,
    "preview": "This license applies to everything except the contents of the \"test\"\ndirectory and its subdirectories.\n\nMIT License\n\nCop"
  },
  {
    "path": "README.md",
    "chars": 10673,
    "preview": "# C++ Requests: Curl for People <img align=\"right\" height=\"40\" src=\"http://i.imgur.com/d9Xtyts.png\">\n\n[![Documentation]("
  },
  {
    "path": "cmake/FindMbedTLS.cmake",
    "chars": 604,
    "preview": "# Source: https://github.com/curl/curl/blob/curl-7_82_0/CMake/FindMbedTLS.cmake\nfind_path(MBEDTLS_INCLUDE_DIRS mbedtls/s"
  },
  {
    "path": "cmake/clang-tidy.cmake",
    "chars": 755,
    "preview": "# Include this file if and only if you want to use clang-tidy linter.\n\nif (NOT ${CMAKE_SYSTEM_NAME} STREQUAL \"Windows\")\n"
  },
  {
    "path": "cmake/clear_variable.cmake",
    "chars": 421,
    "preview": "macro(clear_variable)\n    cmake_parse_arguments(CLEAR_VAR \"\" \"DESTINATION;BACKUP;REPLACE\" \"\" ${ARGN})\n    set(${CLEAR_VA"
  },
  {
    "path": "cmake/code_coverage.cmake",
    "chars": 1148,
    "preview": "# Code coverage\nif(CPR_BUILD_TESTS AND CPR_GENERATE_COVERAGE)\n    set(CMAKE_BUILD_TYPE COVERAGE CACHE INTERNAL \"Coverage"
  },
  {
    "path": "cmake/cppcheck.cmake",
    "chars": 872,
    "preview": "# Include this file if and only if you want to use cppcheck.\n\nif (NOT ${CPR_CPPCHECK_PATH} STREQUAL \"\")\n    get_filename"
  },
  {
    "path": "cmake/cprConfig-ssl.cmake.in",
    "chars": 199,
    "preview": "include(CMakeFindDependencyMacro)\n@PACKAGE_INIT@\n\nfind_dependency(CURL REQUIRED)\nfind_dependency(OpenSSL REQUIRED)\n\nincl"
  },
  {
    "path": "cmake/cprConfig.cmake.in",
    "chars": 165,
    "preview": "include(CMakeFindDependencyMacro)\n@PACKAGE_INIT@\n\nfind_dependency(CURL REQUIRED)\n\ninclude(${CMAKE_CURRENT_LIST_DIR}/cprT"
  },
  {
    "path": "cmake/cprver.h.in",
    "chars": 754,
    "preview": "#ifndef CPR_CPRVER_H\n#define CPR_CPRVER_H\n\n/**\n * CPR version as a string.\n **/\n#define CPR_VERSION \"${cpr_VERSION}\"\n\n/*"
  },
  {
    "path": "cmake/libpsl.cmake",
    "chars": 4536,
    "preview": "# Builds libpsl which is especially necessary on Windows since there it is not available via e.g. a package manager.\n\nin"
  },
  {
    "path": "cmake/mongoose.CMakeLists.txt",
    "chars": 480,
    "preview": "cmake_minimum_required(VERSION 3.15)\nproject(mongoose C)\n\n\nadd_library(mongoose STATIC mongoose.c)\ntarget_include_direct"
  },
  {
    "path": "cmake/sanitizer.cmake",
    "chars": 5771,
    "preview": "include(CheckCXXSourceCompiles)\n\nset(ALL_ACTIVE_SAN_FLAGS \"\")\n\n # No sanitizers when cross compiling to prevent stuff li"
  },
  {
    "path": "cmake/std_fs_support_test.cpp",
    "chars": 231,
    "preview": "#if __has_include(<filesystem>)\n#include <filesystem>\nnamespace fs = std::filesystem;\n#else\n#include <experimental/files"
  },
  {
    "path": "cmake/zlib_external.cmake",
    "chars": 804,
    "preview": "# ZLIB\n\n# Fix Windows missing \"zlib.dll\":\nif(WIN32 AND (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}))\n    set(CMAKE_R"
  },
  {
    "path": "cppcheck-suppressions.xml",
    "chars": 1270,
    "preview": "<?xml version=\"1.0\"?>\n<suppressions>\n    <!-- Exclude Paths -->\n    <suppress>\n        <id>*</id>\n        <fileName>*/bu"
  },
  {
    "path": "cpr/CMakeLists.txt",
    "chars": 2854,
    "preview": "cmake_minimum_required(VERSION 3.15)\n\nadd_library(cpr\n        accept_encoding.cpp\n        async.cpp\n        auth.cpp\n   "
  },
  {
    "path": "cpr/accept_encoding.cpp",
    "chars": 1388,
    "preview": "#include \"cpr/accept_encoding.h\"\n\n#include <algorithm>\n#include <initializer_list>\n#include <iterator>\n#include <numeric"
  },
  {
    "path": "cpr/async.cpp",
    "chars": 170,
    "preview": "#include \"cpr/async.h\"\n\nnamespace cpr {\n\n// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)\nCPR_SING"
  },
  {
    "path": "cpr/auth.cpp",
    "chars": 545,
    "preview": "#include \"cpr/auth.h\"\n\n#include <string_view>\n\nnamespace cpr {\n\nAuthentication::Authentication(std::string_view username"
  },
  {
    "path": "cpr/callback.cpp",
    "chars": 537,
    "preview": "#include \"cpr/callback.h\"\n#include \"cpr/cprtypes.h\"\n#include <functional>\n\nnamespace cpr {\nvoid CancellationCallback::Se"
  },
  {
    "path": "cpr/cert_info.cpp",
    "chars": 897,
    "preview": "#include \"cpr/cert_info.h\"\n#include <cstddef>\n#include <string>\n\nnamespace cpr {\n\nstd::string& CertInfo::operator[](cons"
  },
  {
    "path": "cpr/connection_pool.cpp",
    "chars": 1584,
    "preview": "#include \"cpr/connection_pool.h\"\n#include <curl/curl.h>\n#include <memory>\n#include <mutex>\n\nnamespace cpr {\nConnectionPo"
  },
  {
    "path": "cpr/cookies.cpp",
    "chars": 2866,
    "preview": "#include \"cpr/cookies.h\"\n#include \"cpr/curlholder.h\"\n#include <chrono>\n#include <ctime>\n#include <iomanip>\n#include <sst"
  },
  {
    "path": "cpr/cprtypes.cpp",
    "chars": 392,
    "preview": "#include \"cpr/cprtypes.h\"\n#include <algorithm>\n#include <cctype>\n#include <string>\n\n\nnamespace cpr {\nbool CaseInsensitiv"
  },
  {
    "path": "cpr/curl_container.cpp",
    "chars": 2641,
    "preview": "#include \"cpr/curl_container.h\"\n#include \"cpr/curlholder.h\"\n#include <algorithm>\n#include <initializer_list>\n#include <i"
  },
  {
    "path": "cpr/curlholder.cpp",
    "chars": 2375,
    "preview": "#include \"cpr/curlholder.h\"\n#include \"cpr/secure_string.h\"\n#include <cassert>\n#include <curl/curl.h>\n#include <curl/easy"
  },
  {
    "path": "cpr/curlmultiholder.cpp",
    "chars": 274,
    "preview": "#include \"cpr/curlmultiholder.h\"\n#include <cassert>\n#include <curl/multi.h>\n\nnamespace cpr {\n\nCurlMultiHolder::CurlMulti"
  },
  {
    "path": "cpr/error.cpp",
    "chars": 7120,
    "preview": "#include \"cpr/error.h\"\n#include <cstdint>\n#include <curl/curl.h>\n#include <curl/curlver.h>\n\nnamespace cpr {\n// NOLINTBEG"
  },
  {
    "path": "cpr/file.cpp",
    "chars": 1120,
    "preview": "#include \"cpr/file.h\"\n#include <initializer_list>\n#include <string>\n#include <utility>\n\nnamespace cpr {\n\nFiles::Files(co"
  },
  {
    "path": "cpr/interceptor.cpp",
    "chars": 2090,
    "preview": "#include \"cpr/interceptor.h\"\n#include \"cpr/callback.h\"\n#include \"cpr/multiperform.h\"\n#include \"cpr/response.h\"\n#include "
  },
  {
    "path": "cpr/multipart.cpp",
    "chars": 345,
    "preview": "#include \"cpr/multipart.h\"\n#include <initializer_list>\n#include <vector>\n\nnamespace cpr {\nMultipart::Multipart(const std"
  },
  {
    "path": "cpr/multiperform.cpp",
    "chars": 12905,
    "preview": "#include \"cpr/multiperform.h\"\n\n#include \"cpr/callback.h\"\n#include \"cpr/curlmultiholder.h\"\n#include \"cpr/interceptor.h\"\n#"
  },
  {
    "path": "cpr/parameters.cpp",
    "chars": 137,
    "preview": "// NOLINTNEXTLINE(misc-include-cleaner) Ignored since it's for the future\n#include \"cpr/parameters.h\"\n\nnamespace cpr {} "
  },
  {
    "path": "cpr/payload.cpp",
    "chars": 134,
    "preview": "// NOLINTNEXTLINE(misc-include-cleaner) Ignored since it's for the future\n#include \"cpr/payload.h\"\n\nnamespace cpr {} // "
  },
  {
    "path": "cpr/proxies.cpp",
    "chars": 543,
    "preview": "#include \"cpr/proxies.h\"\n\n#include <initializer_list>\n#include <map>\n#include <string>\n#include <utility>\n\nnamespace cpr"
  },
  {
    "path": "cpr/proxyauth.cpp",
    "chars": 1231,
    "preview": "#include \"cpr/proxyauth.h\"\n#include \"cpr/secure_string.h\"\n#include <string>\n#include <string_view>\n\nnamespace cpr {\n\nstd"
  },
  {
    "path": "cpr/redirect.cpp",
    "chars": 1505,
    "preview": "#include \"cpr/redirect.h\"\n#include <cstdint>\n\nnamespace cpr {\nPostRedirectFlags operator|(PostRedirectFlags lhs, PostRed"
  },
  {
    "path": "cpr/response.cpp",
    "chars": 2828,
    "preview": "#include \"cpr/response.h\"\n#include <cassert>\n#include <cpr/cert_info.h>\n#include <cpr/cookies.h>\n#include <cpr/cprtypes."
  },
  {
    "path": "cpr/session.cpp",
    "chars": 43372,
    "preview": "#include \"cpr/session.h\"\n\n#include <array>\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n#include <cstdlib>\n#i"
  },
  {
    "path": "cpr/sse.cpp",
    "chars": 3680,
    "preview": "#include \"cpr/sse.h\"\n\n#include <charconv>\n#include <cstddef>\n#include <functional>\n#include <string>\n#include <string_vi"
  },
  {
    "path": "cpr/ssl_ctx.cpp",
    "chars": 4934,
    "preview": "\n#include \"cpr/ssl_ctx.h\"\n#include \"cpr/ssl_options.h\"\n#include <cstddef>\n#include <curl/curl.h>\n#include <iostream>\n#in"
  },
  {
    "path": "cpr/threadpool.cpp",
    "chars": 4268,
    "preview": "#include \"cpr/threadpool.h\"\n#include <algorithm>\n#include <chrono>\n#include <cstddef>\n#include <memory>\n#include <mutex>"
  },
  {
    "path": "cpr/timeout.cpp",
    "chars": 1172,
    "preview": "#include \"cpr/timeout.h\"\n\n#include <chrono>\n#include <limits>\n#include <stdexcept>\n#include <string>\n#include <type_trai"
  },
  {
    "path": "cpr/unix_socket.cpp",
    "chars": 163,
    "preview": "\n#include \"cpr/unix_socket.h\"\n\nnamespace cpr {\nconst char* UnixSocket::GetUnixSocketString() const noexcept {\n    return"
  },
  {
    "path": "cpr/util.cpp",
    "chars": 7490,
    "preview": "#include \"cpr/util.h\"\n#include \"cpr/callback.h\"\n#include \"cpr/cookies.h\"\n#include \"cpr/cprtypes.h\"\n#include \"cpr/curlhol"
  },
  {
    "path": "cpr-config.cmake",
    "chars": 903,
    "preview": "# - C++ Requests, Curl for People\n# This module is a libcurl wrapper written in modern C++.\n# It provides an easy, intui"
  },
  {
    "path": "include/CMakeLists.txt",
    "chars": 2808,
    "preview": "cmake_minimum_required(VERSION 3.15)\n\ntarget_include_directories(cpr PUBLIC\n    $<INSTALL_INTERFACE:include>\n    $<BUILD"
  },
  {
    "path": "include/cpr/accept_encoding.h",
    "chars": 1135,
    "preview": "#ifndef CPR_ACCEPT_ENCODING_H\n#define CPR_ACCEPT_ENCODING_H\n\n#include <cstdint>\n#include <curl/curlver.h>\n#include <init"
  },
  {
    "path": "include/cpr/api.h",
    "chars": 12990,
    "preview": "#ifndef CPR_API_H\n#define CPR_API_H\n\n#include <fstream>\n#include <functional>\n#include <future>\n#include <string>\n#inclu"
  },
  {
    "path": "include/cpr/async.h",
    "chars": 1693,
    "preview": "#ifndef CPR_ASYNC_H\n#define CPR_ASYNC_H\n\n#include \"async_wrapper.h\"\n#include \"singleton.h\"\n#include \"threadpool.h\"\n\nname"
  },
  {
    "path": "include/cpr/async_wrapper.h",
    "chars": 5023,
    "preview": "#ifndef CPR_ASYNC_WRAPPER_H\n#define CPR_ASYNC_WRAPPER_H\n\n#include <atomic>\n#include <future>\n#include <memory>\n\nnamespac"
  },
  {
    "path": "include/cpr/auth.h",
    "chars": 573,
    "preview": "#ifndef CPR_AUTH_H\n#define CPR_AUTH_H\n\n#include <cstdint>\n#include <string>\n#include <string_view>\n\n#include \"cpr/util.h"
  },
  {
    "path": "include/cpr/bearer.h",
    "chars": 817,
    "preview": "#ifndef CPR_BEARER_H\n#define CPR_BEARER_H\n\n#include <curl/curlver.h>\n#include <string>\n\n#include <utility>\n\n#include \"cp"
  },
  {
    "path": "include/cpr/body.h",
    "chars": 1575,
    "preview": "#ifndef CPR_BODY_H\n#define CPR_BODY_H\n\n#include <exception>\n#include <fstream>\n#include <initializer_list>\n#include <str"
  },
  {
    "path": "include/cpr/body_view.h",
    "chars": 930,
    "preview": "#ifndef CPR_BODY_VIEW_H\n#define CPR_BODY_VIEW_H\n\n#include <string_view>\n\n#include \"cpr/buffer.h\"\n\nnamespace cpr {\n\nclass"
  },
  {
    "path": "include/cpr/buffer.h",
    "chars": 1091,
    "preview": "#ifndef CPR_BUFFER_H\n#define CPR_BUFFER_H\n\n#include <string>\n\n#include \"cpr/filesystem.h\"\n\nnamespace cpr {\n\nstruct Buffe"
  },
  {
    "path": "include/cpr/callback.h",
    "chars": 4343,
    "preview": "#ifndef CPR_CALLBACK_H\n#define CPR_CALLBACK_H\n\n#include \"cprtypes.h\"\n\n#include <atomic>\n#include <cstdint>\n#include <fun"
  },
  {
    "path": "include/cpr/cert_info.h",
    "chars": 995,
    "preview": "#ifndef CPR_CERT_INFO_H\n#define CPR_CERT_INFO_H\n\n#include <initializer_list>\n#include <string>\n#include <vector>\n\nnamesp"
  },
  {
    "path": "include/cpr/connect_timeout.h",
    "chars": 350,
    "preview": "#ifndef CPR_CONNECT_TIMEOUT_H\n#define CPR_CONNECT_TIMEOUT_H\n\n#include \"cpr/timeout.h\"\n\nnamespace cpr {\n\nclass ConnectTim"
  },
  {
    "path": "include/cpr/connection_pool.h",
    "chars": 3075,
    "preview": "#ifndef CPR_CONNECTION_POOL_H\n#define CPR_CONNECTION_POOL_H\n\n#include <curl/curl.h>\n#include <memory>\n#include <mutex>\n\n"
  },
  {
    "path": "include/cpr/cookies.h",
    "chars": 3488,
    "preview": "#ifndef CPR_COOKIES_H\n#define CPR_COOKIES_H\n\n#include \"cpr/curlholder.h\"\n#include <chrono>\n#include <initializer_list>\n#"
  },
  {
    "path": "include/cpr/cpr.h",
    "chars": 1196,
    "preview": "#ifndef CPR_CPR_H\n#define CPR_CPR_H\n\n#include \"cpr/api.h\"\n#include \"cpr/auth.h\"\n#include \"cpr/bearer.h\"\n#include \"cpr/ca"
  },
  {
    "path": "include/cpr/cprtypes.h",
    "chars": 3969,
    "preview": "#ifndef CPR_CPRTYPES_H\n#define CPR_CPRTYPES_H\n\n#include <curl/curl.h>\n#include <curl/system.h>\n#include <initializer_lis"
  },
  {
    "path": "include/cpr/curl_container.h",
    "chars": 1418,
    "preview": "#ifndef CPR_CURL_CONTAINER_H\n#define CPR_CURL_CONTAINER_H\n\n#include <initializer_list>\n#include <memory>\n#include <strin"
  },
  {
    "path": "include/cpr/curlholder.h",
    "chars": 1423,
    "preview": "#ifndef CPR_CURLHOLDER_H\n#define CPR_CURLHOLDER_H\n\n#include <array>\n#include <curl/curl.h>\n#include <mutex>\n\n#include \"c"
  },
  {
    "path": "include/cpr/curlmultiholder.h",
    "chars": 243,
    "preview": "#ifndef CPR_CURLMULTIHOLDER_H\n#define CPR_CURLMULTIHOLDER_H\n\n#include <curl/curl.h>\n\nnamespace cpr {\n\nclass CurlMultiHol"
  },
  {
    "path": "include/cpr/error.h",
    "chars": 11068,
    "preview": "#ifndef CPR_ERROR_H\n#define CPR_ERROR_H\n\n#include <cstdint>\n#include <string>\n#include <unordered_map>\n\n#include \"cpr/cp"
  },
  {
    "path": "include/cpr/file.h",
    "chars": 1473,
    "preview": "#ifndef CPR_FILE_H\n#define CPR_FILE_H\n\n#include <initializer_list>\n#include <string>\n#include <vector>\n\n#include \"cpr/fi"
  },
  {
    "path": "include/cpr/filesystem.h",
    "chars": 775,
    "preview": "#ifndef CPR_FILESYSTEM_H\n#define CPR_FILESYSTEM_H\n\n// Include filesystem into the namespace \"fs\" from either \"filesystem"
  },
  {
    "path": "include/cpr/http_version.h",
    "chars": 2020,
    "preview": "#ifndef CPR_HTTP_VERSION_H\n#define CPR_HTTP_VERSION_H\n\n#include <cstdint>\n#include <curl/curlver.h>\n\nnamespace cpr {\nenu"
  },
  {
    "path": "include/cpr/interceptor.h",
    "chars": 2115,
    "preview": "#ifndef CPR_INTERCEPTOR_H\n#define CPR_INTERCEPTOR_H\n\n#include \"cpr/multiperform.h\"\n#include \"cpr/response.h\"\n#include \"c"
  },
  {
    "path": "include/cpr/interface.h",
    "chars": 920,
    "preview": "#ifndef CPR_INTERFACE_H\n#define CPR_INTERFACE_H\n\n#include <initializer_list>\n#include <string>\n\n#include \"cpr/cprtypes.h"
  },
  {
    "path": "include/cpr/limit_rate.h",
    "chars": 326,
    "preview": "#ifndef CPR_LIMIT_RATE_H\n#define CPR_LIMIT_RATE_H\n\n#include <cstdint>\n\nnamespace cpr {\n\nclass LimitRate {\n  public:\n    "
  },
  {
    "path": "include/cpr/local_port.h",
    "chars": 340,
    "preview": "#ifndef CPR_LOCAL_PORT_H\n#define CPR_LOCAL_PORT_H\n\n#include <cstdint>\n\nnamespace cpr {\n\nclass LocalPort {\n  public:\n    "
  },
  {
    "path": "include/cpr/local_port_range.h",
    "chars": 387,
    "preview": "#ifndef CPR_LOCAL_PORT_RANGE_H\n#define CPR_LOCAL_PORT_RANGE_H\n\n#include <cstdint>\n\nnamespace cpr {\n\nclass LocalPortRange"
  },
  {
    "path": "include/cpr/low_speed.h",
    "chars": 586,
    "preview": "#ifndef CPR_LOW_SPEED_H\n#define CPR_LOW_SPEED_H\n\n#include <chrono>\n#include <cstdint>\n\nnamespace cpr {\n\nclass LowSpeed {"
  },
  {
    "path": "include/cpr/multipart.h",
    "chars": 1826,
    "preview": "#ifndef CPR_MULTIPART_H\n#define CPR_MULTIPART_H\n\n#include <cstdint>\n#include <initializer_list>\n#include <string>\n#inclu"
  },
  {
    "path": "include/cpr/multiperform.h",
    "chars": 5175,
    "preview": "#ifndef CPR_MULTIPERFORM_H\n#define CPR_MULTIPERFORM_H\n\n#include \"cpr/curlmultiholder.h\"\n#include \"cpr/response.h\"\n#inclu"
  },
  {
    "path": "include/cpr/parameters.h",
    "chars": 361,
    "preview": "#ifndef CPR_PARAMETERS_H\n#define CPR_PARAMETERS_H\n\n#include <initializer_list>\n\n#include \"cpr/curl_container.h\"\n\nnamespa"
  },
  {
    "path": "include/cpr/payload.h",
    "chars": 457,
    "preview": "#ifndef CPR_PAYLOAD_H\n#define CPR_PAYLOAD_H\n\n#include <initializer_list>\n\n#include \"cpr/curl_container.h\"\n\n\nnamespace cp"
  },
  {
    "path": "include/cpr/proxies.h",
    "chars": 554,
    "preview": "#ifndef CPR_PROXIES_H\n#define CPR_PROXIES_H\n\n#include <initializer_list>\n#include <map>\n#include <string>\n\nnamespace cpr"
  },
  {
    "path": "include/cpr/proxyauth.h",
    "chars": 2074,
    "preview": "#ifndef CPR_PROXYAUTH_H\n#define CPR_PROXYAUTH_H\n\n#include <initializer_list>\n#include <map>\n#include <string>\n#include <"
  },
  {
    "path": "include/cpr/range.h",
    "chars": 1171,
    "preview": "#ifndef CPR_RANGE_H\n#define CPR_RANGE_H\n\n#include <cstdint>\n#include <optional>\n\nnamespace cpr {\n\nclass Range {\n  public"
  },
  {
    "path": "include/cpr/redirect.h",
    "chars": 3086,
    "preview": "#ifndef CPR_REDIRECT_H\n#define CPR_REDIRECT_H\n\n#include <cstdint>\n\nnamespace cpr {\nenum class PostRedirectFlags : uint8_"
  },
  {
    "path": "include/cpr/reserve_size.h",
    "chars": 238,
    "preview": "#ifndef CPR_RESERVE_SIZE_H\n#define CPR_RESERVE_SIZE_H\n\n#include <cstdint>\n\nnamespace cpr {\n\nclass ReserveSize {\n  public"
  },
  {
    "path": "include/cpr/resolve.h",
    "chars": 556,
    "preview": "#ifndef CPR_RESOLVE_H\n#define CPR_RESOLVE_H\n\n#include <set>\n#include <string>\n\nnamespace cpr {\nclass Resolve {\n  public:"
  },
  {
    "path": "include/cpr/response.h",
    "chars": 1541,
    "preview": "#ifndef CPR_RESPONSE_H\n#define CPR_RESPONSE_H\n\n#include <cassert>\n#include <cstdint>\n#include <memory>\n#include <string>"
  },
  {
    "path": "include/cpr/secure_string.h",
    "chars": 2287,
    "preview": "#ifndef CPR_SECURE_STRING_H\n#define CPR_SECURE_STRING_H\n\n#include <memory>\n#include <string>\n#include <string_view>\n\nnam"
  },
  {
    "path": "include/cpr/session.h",
    "chars": 13198,
    "preview": "#ifndef CPR_SESSION_H\n#define CPR_SESSION_H\n\n#include <cstdint>\n#include <fstream>\n#include <functional>\n#include <futur"
  },
  {
    "path": "include/cpr/singleton.h",
    "chars": 1961,
    "preview": "#ifndef CPR_SINGLETON_H\n#define CPR_SINGLETON_H\n\n#include <cassert>\n#include <mutex>\n\n// NOLINTBEGIN(cppcoreguidelines-m"
  },
  {
    "path": "include/cpr/sse.h",
    "chars": 2780,
    "preview": "#ifndef CPR_SSE_H\n#define CPR_SSE_H\n\n#include <cstdint>\n#include <functional>\n#include <optional>\n#include <string>\n#inc"
  },
  {
    "path": "include/cpr/ssl_ctx.h",
    "chars": 693,
    "preview": "#ifndef CPR_SSL_CTX_H\n#define CPR_SSL_CTX_H\n\n#include \"cpr/ssl_options.h\"\n#include <curl/curl.h>\n\n#if SUPPORT_CURLOPT_SS"
  },
  {
    "path": "include/cpr/ssl_options.h",
    "chars": 16414,
    "preview": "#ifndef CPR_SSL_OPTIONS_H\n#define CPR_SSL_OPTIONS_H\n\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"cp"
  },
  {
    "path": "include/cpr/status_codes.h",
    "chars": 3866,
    "preview": "#ifndef CPR_STATUS_CODES\n#define CPR_STATUS_CODES\nnamespace cpr {\nnamespace status {\n// Information responses\nconstexpr "
  },
  {
    "path": "include/cpr/threadpool.h",
    "chars": 3710,
    "preview": "#ifndef CPR_THREADPOOL_H\n#define CPR_THREADPOOL_H\n\n#include <atomic>\n#include <chrono>\n#include <condition_variable>\n#in"
  },
  {
    "path": "include/cpr/timeout.h",
    "chars": 707,
    "preview": "#ifndef CPR_TIMEOUT_H\n#define CPR_TIMEOUT_H\n\n#include <chrono>\n#include <cstdint>\n\nnamespace cpr {\n\nclass Timeout {\n  pu"
  },
  {
    "path": "include/cpr/unix_socket.h",
    "chars": 348,
    "preview": "#ifndef CPR_UNIX_SOCKET_H\n#define CPR_UNIX_SOCKET_H\n\n#include <string>\n\nnamespace cpr {\n\nclass UnixSocket {\n  public:\n  "
  },
  {
    "path": "include/cpr/user_agent.h",
    "chars": 945,
    "preview": "#ifndef CPR_USER_AGENT_H\n#define CPR_USER_AGENT_H\n\n#include <initializer_list>\n#include <string>\n\n#include \"cpr/cprtypes"
  },
  {
    "path": "include/cpr/util.h",
    "chars": 2034,
    "preview": "#ifndef CPR_UTIL_H\n#define CPR_UTIL_H\n\n#include <fstream>\n#include <memory>\n#include <string>\n#include <vector>\n\n#includ"
  },
  {
    "path": "include/cpr/verbose.h",
    "chars": 252,
    "preview": "#ifndef CPR_VERBOSE_H_\n#define CPR_VERBOSE_H_\n\nnamespace cpr {\n\nclass Verbose {\n  public:\n    Verbose() = default;\n    V"
  },
  {
    "path": "nuget/build/native/libcpr.props",
    "chars": 991,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" ToolsVersion"
  },
  {
    "path": "nuget/build/native/libcpr.targets",
    "chars": 671,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\"\n  xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "nuget/libcpr.nuspec",
    "chars": 870,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<package xmlns=\"http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd\">\n  <me"
  },
  {
    "path": "package-build/build-package.sh",
    "chars": 546,
    "preview": "#!/bin/bash\n\nSRC_DIR=$1\n\nLIB='libcpr'\n\nLIB_DIR=\"${LIB}_${VERSION}\"\nDEBIAN_DIR=\"${LIB_DIR}/debian\"\n\nARCHIVE_NAME=\"$LIB_DI"
  },
  {
    "path": "package-build/debian-libcpr/README.Debian",
    "chars": 132,
    "preview": "libcpr for Debian\n\nA package of the libcpr library.\n\n -- Philip Saendig <philip.saendig@gmail.com>  Tue, 24 May 2022 10:"
  },
  {
    "path": "package-build/debian-libcpr/changelog",
    "chars": 159,
    "preview": "libcpr (%VERSION-1) UNRELEASED; urgency=low\n\n  [ Philip Saendig ]\n  * First package of libcpr %VERSION for debian.\n\n -- "
  },
  {
    "path": "package-build/debian-libcpr/control",
    "chars": 1220,
    "preview": "Source: libcpr\nSection: libs\nPriority: optional\nMaintainer: Philip Saendig <philip.saendig@gmail.com>\nBuild-Depends:\n de"
  },
  {
    "path": "package-build/debian-libcpr/copyright",
    "chars": 1977,
    "preview": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: libcpr\nSource: https://github."
  },
  {
    "path": "package-build/debian-libcpr/libcpr-dev.install",
    "chars": 43,
    "preview": "usr/include\nusr/lib/*/*.so\nusr/lib/*/cmake\n"
  },
  {
    "path": "package-build/debian-libcpr/libcpr1.install",
    "chars": 17,
    "preview": "usr/lib/*/*.so.*\n"
  },
  {
    "path": "package-build/debian-libcpr/rules",
    "chars": 406,
    "preview": "#!/usr/bin/make -f\nexport DH_VERBOSE = 1\nexport DEB_BUILD_MAINT_OPTIONS = hardening=+all\nexport DEB_CFLAGS_MAINT_APPEND "
  },
  {
    "path": "package-build/debian-libcpr/source/format",
    "chars": 12,
    "preview": "3.0 (quilt)\n"
  },
  {
    "path": "scripts/check_clang_format.sh",
    "chars": 1144,
    "preview": "#!/bin/bash\n\n# Based on: https://gist.github.com/leilee/1d0915a583f8f29414cc21cd86e7151b\n# Checks if all files are forma"
  },
  {
    "path": "scripts/delete_build_dir.sh",
    "chars": 166,
    "preview": "#!/bin/bash\n\nprintf \"🗑️  Clearing your build directory...\\n\"\nrm -rf build/*\n\nGREEN='\\033[0;32m'\nNC='\\033[0m'\n\nprintf \"✅ "
  },
  {
    "path": "scripts/run_clang_format.sh",
    "chars": 776,
    "preview": "#!/bin/bash\n\n# Based on: https://gist.github.com/leilee/1d0915a583f8f29414cc21cd86e7151b\n# Run from the project root dir"
  },
  {
    "path": "test/CMakeLists.txt",
    "chars": 5277,
    "preview": "cmake_minimum_required(VERSION 3.15)\n\nfind_package(Threads REQUIRED)\n\nif (ENABLE_SSL_TESTS)\n    add_library(test_server "
  },
  {
    "path": "test/LICENSE",
    "chars": 35231,
    "preview": "This license applies to everything inside this directory and all\nsubdirectories.\n\n                     GNU GENERAL PUBLI"
  },
  {
    "path": "test/abstractServer.cpp",
    "chars": 4735,
    "preview": "#include \"abstractServer.hpp\"\n\nnamespace cpr {\nvoid AbstractServer::SetUp() {\n    Start();\n}\n\nvoid AbstractServer::TearD"
  },
  {
    "path": "test/abstractServer.hpp",
    "chars": 2056,
    "preview": "#ifndef CPR_TEST_ABSTRACT_SERVER_SERVER_H\n#define CPR_TEST_ABSTRACT_SERVER_SERVER_H\n\n#include <atomic>\n#include <conditi"
  },
  {
    "path": "test/alternating_tests.cpp",
    "chars": 4995,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstat"
  },
  {
    "path": "test/async_tests.cpp",
    "chars": 2834,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n#include <vector>\n\n#include \"cpr/cpr.h\"\n#include \"cpr/filesystem.h\"\n\n#includ"
  },
  {
    "path": "test/callback_tests.cpp",
    "chars": 38886,
    "preview": "#include <cstddef>\n#include <gtest/gtest.h>\n\n#include <chrono>\n#include <string>\n#include <thread>\n#include <vector>\n\n#i"
  },
  {
    "path": "test/connection_pool_tests.cpp",
    "chars": 3721,
    "preview": "#include <gtest/gtest.h>\n\n#include <chrono>\n#include <string>\n#include <thread>\n#include <vector>\n\n#include <cpr/cpr.h>\n"
  },
  {
    "path": "test/curlholder_tests.cpp",
    "chars": 459,
    "preview": "#include <gtest/gtest.h>\n\n#include <utility>\n\n#include \"cpr/curlholder.h\"\n\n// Check if there is a double free in curl ho"
  },
  {
    "path": "test/data/certificates/ca-bundle.crt",
    "chars": 1288,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBrjCCAWCgAwIBAgIRAKy+/CzeW5ALVVSDllVnZdMwBQYDK2VwMDExCzAJBgNV\nBAYTAkdCMRAwDgYDVQQKDAdFeGF"
  },
  {
    "path": "test/data/certificates/client.crt",
    "chars": 574,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBejCCASygAwIBAgIRAKy+/CzeW5ALVVSDllVnZdUwBQYDK2VwMDAxCzAJBgNV\nBAYTAkdCMRAwDgYDVQQKDAdFeGF"
  },
  {
    "path": "test/data/certificates/root-ca.crt",
    "chars": 644,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBrzCCAWGgAwIBAgIRAKy+/CzeW5ALVVSDllVnZdIwBQYDK2VwMDExCzAJBgNV\nBAYTAkdCMRAwDgYDVQQKDAdFeGF"
  },
  {
    "path": "test/data/certificates/server.crt",
    "chars": 652,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBtDCCAWagAwIBAgIRAKy+/CzeW5ALVVSDllVnZdQwBQYDK2VwMDAxCzAJBgNV\nBAYTAkdCMRAwDgYDVQQKDAdFeGF"
  },
  {
    "path": "test/data/certificates/sub-ca.crt",
    "chars": 644,
    "preview": "-----BEGIN CERTIFICATE-----\nMIIBrjCCAWCgAwIBAgIRAKy+/CzeW5ALVVSDllVnZdMwBQYDK2VwMDExCzAJBgNV\nBAYTAkdCMRAwDgYDVQQKDAdFeGF"
  },
  {
    "path": "test/data/client.cnf",
    "chars": 192,
    "preview": "# Based on https://www.feistyduck.com/library/openssl-cookbook/online/openssl-command-line/private-ca-create-subordinate"
  },
  {
    "path": "test/data/generate-certificates.sh",
    "chars": 2831,
    "preview": "#!/bin/sh\n\n# Generate a CA with a self-signed root certificate that then signs the server certificate\n# Based on the Ope"
  },
  {
    "path": "test/data/keys/client.key",
    "chars": 119,
    "preview": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIIK4CYIlr3jGta1aSNICikX8V4CXv/i6IJTmj68CUQOU\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/data/keys/root-ca.key",
    "chars": 119,
    "preview": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEICJbx2nPwG8L2S/EKvCHI2q4InmAFAaNVBqdVq13ZpJz\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/data/keys/server.key",
    "chars": 119,
    "preview": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIGqt/stoQYkwb24d3EUC0LpH2QwKuh+0tftML+wk/N1P\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/data/keys/server.pub",
    "chars": 113,
    "preview": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAJ0tSokVLKymAYomJc2Wc4tTZ079MtX5vxohk0BfsS5U=\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "test/data/keys/sub-ca.key",
    "chars": 119,
    "preview": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIASqWiXeb8UOEbwjVVq/2j49JvbBX2aLAiqjUtHQK2qV\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/data/root-ca.cnf",
    "chars": 2821,
    "preview": "# Based on: https://www.feistyduck.com/library/openssl-cookbook/online/openssl-command-line/private-ca-creating-root.htm"
  },
  {
    "path": "test/data/server.cnf",
    "chars": 271,
    "preview": "# Based on https://www.feistyduck.com/library/openssl-cookbook/online/openssl-command-line/private-ca-create-subordinate"
  },
  {
    "path": "test/data/sub-ca.cnf",
    "chars": 701,
    "preview": "[req]\ndefault_bits            = 4096\nencrypt_key             = yes\ndefault_md              = sha256\nutf8                "
  },
  {
    "path": "test/data/test_file.txt",
    "chars": 32,
    "preview": "test content: hello_äüöp_2585_你好"
  },
  {
    "path": "test/data/test_file_hello_äüöp_2585.txt",
    "chars": 32,
    "preview": "test content: hello_äüöp_2585_你好"
  },
  {
    "path": "test/data/test_file_hello_äüöp_2585_你好.txt",
    "chars": 32,
    "preview": "test content: hello_äüöp_2585_你好"
  },
  {
    "path": "test/delete_tests.cpp",
    "chars": 9624,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstat"
  },
  {
    "path": "test/download_tests.cpp",
    "chars": 6093,
    "preview": "#include <cstddef>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/accept_encoding.h\"\n#include \"cpr/cpr.h\"\n\n#"
  },
  {
    "path": "test/encoded_auth_tests.cpp",
    "chars": 483,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\nusing namespace cpr;\n\nTEST(EncodedAuthenticationTests"
  },
  {
    "path": "test/error_tests.cpp",
    "chars": 3962,
    "preview": "#include <gtest/gtest.h>\n\n#include <chrono>\n#include <string>\n\n#include \"cpr/cpr.h\"\n#include <curl/curl.h>\n\n#include \"ht"
  },
  {
    "path": "test/file_upload_tests.cpp",
    "chars": 4113,
    "preview": "#include <gtest/gtest.h>\n\n#include <fstream>\n#include <optional>\n#include <string>\n\n#include <cpr/cpr.h>\n#include <cpr/f"
  },
  {
    "path": "test/get_tests.cpp",
    "chars": 66158,
    "preview": "#include <chrono>\n#include <cpr/error.h>\n#include <gtest/gtest.h>\n\n#include <memory>\n#include <string>\n\n#include \"cpr/cp"
  },
  {
    "path": "test/head_tests.cpp",
    "chars": 9372,
    "preview": "#include <chrono>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing na"
  },
  {
    "path": "test/httpServer.cpp",
    "chars": 39520,
    "preview": "#include \"httpServer.hpp\"\n#include <array>\n#include <chrono>\n#include <ctime>\n#include <iomanip>\n#include <sstream>\n#inc"
  },
  {
    "path": "test/httpServer.hpp",
    "chars": 4256,
    "preview": "#ifndef CPR_TEST_HTTP_SERVER_H\n#define CPR_TEST_HTTP_SERVER_H\n\n#include <string>\n\n#include \"abstractServer.hpp\"\n#include"
  },
  {
    "path": "test/httpsServer.cpp",
    "chars": 2104,
    "preview": "#include \"httpsServer.hpp\"\n#include <system_error>\n\nnamespace cpr {\nHttpsServer::HttpsServer(fs::path&& baseDirPath, fs:"
  },
  {
    "path": "test/httpsServer.hpp",
    "chars": 1285,
    "preview": "#ifndef CPR_TEST_HTTPS_SERVER_H\n#define CPR_TEST_HTTPS_SERVER_H\n\n#include <memory>\n#include <string>\n\n#include \"abstract"
  },
  {
    "path": "test/interceptor_multi_tests.cpp",
    "chars": 18787,
    "preview": "#include <gtest/gtest.h>\n#include <iostream>\n#include <memory>\n\n#include \"cpr/cpr.h\"\n#include \"cpr/interceptor.h\"\n#inclu"
  },
  {
    "path": "test/interceptor_tests.cpp",
    "chars": 14140,
    "preview": "#include <gtest/gtest.h>\n#include <iostream>\n\n#include \"cpr/cpr.h\"\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstat"
  },
  {
    "path": "test/multiasync_tests.cpp",
    "chars": 19963,
    "preview": "#include <functional>\n#include <string>\n#include <vector>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n#include \"mul"
  },
  {
    "path": "test/multiasync_tests.hpp",
    "chars": 381,
    "preview": "#pragma once\n\n#include <atomic>\n#include <condition_variable>\n#include <gtest/gtest.h>\n\nclass TestSynchronizationEnv : p"
  },
  {
    "path": "test/multiperform_tests.cpp",
    "chars": 30518,
    "preview": "#include <cstdint>\n#include <gtest/gtest.h>\n\n#include <memory>\n#include <string>\n\n#include \"cpr/api.h\"\n#include \"cpr/cpr"
  },
  {
    "path": "test/options_tests.cpp",
    "chars": 2636,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstat"
  },
  {
    "path": "test/patch_tests.cpp",
    "chars": 9584,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstat"
  },
  {
    "path": "test/post_tests.cpp",
    "chars": 31687,
    "preview": "#include <chrono>\n#include <cstddef>\n#include <gtest/gtest.h>\n\n#include <array>\n#include <cstdio>\n#include <fstream>\n#in"
  },
  {
    "path": "test/prepare_tests.cpp",
    "chars": 5365,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n#include <vector>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing na"
  },
  {
    "path": "test/proxy_auth_tests.cpp",
    "chars": 4139,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n#include \"httpServer.hpp\"\n\n// TODO: This requires a lo"
  },
  {
    "path": "test/proxy_tests.cpp",
    "chars": 5141,
    "preview": "#include <gtest/gtest.h>\n\n#include <chrono>\n#include <sstream>\n#include <stdlib.h>\n#include <string>\n\n#include \"cpr/cpr."
  },
  {
    "path": "test/put_tests.cpp",
    "chars": 9472,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstat"
  },
  {
    "path": "test/raw_body_tests.cpp",
    "chars": 5721,
    "preview": "#include <gtest/gtest.h>\n\n#include <cstdio>\n#include <fstream>\n#include <string>\n\n#include \"cpr/cpr.h\"\n#include \"cpr/mul"
  },
  {
    "path": "test/resolve_tests.cpp",
    "chars": 1689,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cpr.h\"\n#include \"httpServer.hpp\"\n\nusing namespace cpr;\n\nstati"
  },
  {
    "path": "test/session_tests.cpp",
    "chars": 65528,
    "preview": "#include <algorithm>\n#include <chrono>\n#include <cstdint>\n#include <cstdlib>\n#include <gtest/gtest.h>\n\n#include <stdexce"
  },
  {
    "path": "test/singleton_tests.cpp",
    "chars": 638,
    "preview": "#include <gtest/gtest.h>\n\n#include \"singleton_tests.hpp\"\n\n// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-va"
  },
  {
    "path": "test/singleton_tests.hpp",
    "chars": 141,
    "preview": "#pragma once\n\n#include \"cpr/cpr.h\"\n\nclass TestSingleton {\n    CPR_SINGLETON_DECL(TestSingleton)\n  private:\n    TestSingl"
  },
  {
    "path": "test/sse_tests.cpp",
    "chars": 8098,
    "preview": "#include <gtest/gtest.h>\n\n#include <chrono>\n#include <string>\n#include <thread>\n#include <vector>\n\n#include \"cpr/cpr.h\"\n"
  },
  {
    "path": "test/ssl_tests.cpp",
    "chars": 11592,
    "preview": "#include <gtest/gtest.h>\n\n#include <chrono>\n#include <string>\n#include <thread>\n#include <vector>\n\n#include \"cpr/cprtype"
  },
  {
    "path": "test/structures_tests.cpp",
    "chars": 2163,
    "preview": "#include \"cpr/cprtypes.h\"\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/parameters.h\"\n#include \"cpr/payload"
  },
  {
    "path": "test/testUtils.cpp",
    "chars": 1689,
    "preview": "#include \"testUtils.hpp\"\n\n#include <cstdint>\n#include <stdexcept>\n\n#ifdef _WIN32\n#define NOMINMAX\n#include <winsock2.h>\n"
  },
  {
    "path": "test/testUtils.hpp",
    "chars": 756,
    "preview": "#ifndef CPR_TEST_UTILS_H\n#define CPR_TEST_UTILS_H\n#include <cstdint>\n#include <stdexcept>\n\n#ifdef _WIN32\n#define NOMINMA"
  },
  {
    "path": "test/testUtils_tests.cpp",
    "chars": 318,
    "preview": "#include <cstdint>\n#include <gtest/gtest.h>\n\n#include \"testUtils.hpp\"\n\nTEST(TestUtils, GetUnusedPort) {\n    uint16_t por"
  },
  {
    "path": "test/threadpool_tests.cpp",
    "chars": 2512,
    "preview": "#include <atomic>\n#include <cstddef>\n#include <gtest/gtest.h>\n\n\n#include \"cpr/threadpool.h\"\n\nTEST(ThreadPoolTests, DISAB"
  },
  {
    "path": "test/util_tests.cpp",
    "chars": 8230,
    "preview": "#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"cpr/cprtypes.h\"\n#include \"cpr/util.h\"\n\nusing namespace cpr;\n\nTEST"
  },
  {
    "path": "test/version_tests.cpp",
    "chars": 1433,
    "preview": "#include \"cpr/cpr.h\"\n#include <cctype>\n#include <cstddef>\n#include <gtest/gtest.h>\n#include <string>\n\n\nTEST(VersionTests"
  }
]

About this extraction

This page contains the full source code of the libcpr/cpr GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 197 files (845.4 KB), approximately 215.4k tokens, and a symbol index with 882 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!