libzeep-6.1.1/0000755000175000017500000000000014752105534013017 5ustar maartenmaartenlibzeep-6.1.1/.github/0000755000175000017500000000000014752105534014357 5ustar maartenmaartenlibzeep-6.1.1/.github/workflows/0000755000175000017500000000000014752105534016414 5ustar maartenmaartenlibzeep-6.1.1/.github/workflows/build-documentation.yml0000644000175000017500000000320414752105534023104 0ustar maartenmaarten# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml name: publish docs on: push: branches: [ "trunk" ] permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Set reusable strings id: strings shell: bash run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Install dependencies Ubuntu run: sudo apt-get update && sudo apt-get install cmake doxygen - uses: actions/setup-python@v4 with: python-version: '3.9' cache: 'pip' # caching pip dependencies - run: pip install -r docs/requirements.txt - name: Configure CMake run: > cmake -S . -B build -DZEEP_BUILD_DOCUMENTATION=ON -DZEEP_BUILD_LIBRARY=OFF -DZEEP_BUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF - name: Run Sphinx run: cmake --build build --target Sphinx-libzeep - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ${{ steps.strings.outputs.build-output-dir }}/docs/sphinx deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: docs steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 libzeep-6.1.1/.github/workflows/cmake-multi-platform.yml0000644000175000017500000000377114752105534023201 0ustar maartenmaarten# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml name: multi platform test on: push: branches: [ "trunk", "develop" ] pull_request: branches: [ "trunk" ] jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] build_type: [ Release ] include: - os: windows-latest cpp_compiler: cl - os: ubuntu-latest cpp_compiler: g++ - os: macos-latest cpp_compiler: clang++ steps: - uses: actions/checkout@v3 - name: Set reusable strings id: strings shell: bash run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Install dependencies Ubuntu if: matrix.os == 'ubuntu-latest' run: > sudo apt-get update && sudo apt-get install libboost-dev mrc - name: Install Boost Windows if: matrix.os == 'windows-latest' uses: MarkusJx/install-boost@v2.4.4 id: install-boost with: boost_version: 1.82.0 platform_version: 2019 toolset: msvc - name: Install Boost macOS if: matrix.os == 'macos-latest' run: > brew install boost - name: Configure CMake env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} run: > cmake -B ${{ steps.strings.outputs.build-output-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -S ${{ github.workspace }} - name: Build run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} run: ctest --build-config ${{ matrix.build_type }} --output-on-failure libzeep-6.1.1/.gitignore0000644000175000017500000000033414752105534015007 0ustar maartenmaartentest/xml/XML-Test-Suite/ tests/ .vs/ .vscode build/ Testing/Temporary CMakeSettings.json include/zeep/config.hpp **/.gdb_history include/zeep/http/asio.hpp lib-xml/src/revision.hpp docs/api docs/conf.py src/revision.hpp libzeep-6.1.1/.gitmodules0000644000175000017500000000024514752105534015175 0ustar maartenmaarten[submodule "date"] path = date url = https://github.com/HowardHinnant/date.git [submodule "libmcfp"] path = libmcfp url = https://github.com/mhekkel/libmcfp.git libzeep-6.1.1/.readthedocs.yaml0000644000175000017500000000075714752105534016257 0ustar maartenmaartenversion: 2 build: os: "ubuntu-22.04" tools: python: "3.11" apt_packages: - "doxygen" - "cmake" jobs: pre_build: - "cmake -S . -B build -DZEEP_BUILD_DOCUMENTATION=ON -DZEEP_BUILD_LIBRARY=OFF -DBUILD_TESTING=OFF" - "cmake --build build --target Doxygen" # Build from the docs/ directory with Sphinx sphinx: configuration: docs/conf.py # Explicitly set the version of Python and its requirements python: install: - requirements: docs/requirements.txt libzeep-6.1.1/CMakeLists.txt0000644000175000017500000002744714752105534015575 0ustar maartenmaarten# Copyright Maarten L. Hekkelman, 2023 # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) cmake_minimum_required(VERSION 3.22) project(libzeep VERSION 6.1.0 LANGUAGES CXX) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) include(GNUInstallDirs) include(CheckFunctionExists) include(CheckIncludeFiles) include(FindFilesystem) include(CheckLibraryExists) include(CMakePackageConfigHelpers) include(GenerateExportHeader) include(VersionString) include(CTest) include(CMakeDependentOption) option(ZEEP_BUILD_LIBRARY "Build the library from source code, should be off when configuring on ReadTheDocs" ON) option(ZEEP_BUILD_DOCUMENTATION "Build documentation" OFF) option(ZEEP_USE_BOOST_ASIO "Use the asio library from Boost instead of the non-boost version" ON) option(ZEEP_ALLOW_FETCH_CONTENT "Use cmake's FetchContent to retrieve missing packages" ON) cmake_dependent_option(ZEEP_BUILD_EXAMPLES "Build the example applications" ON "ZEEP_BUILD_LIBRARY" OFF) # New policy for Boost, set it here if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.30) cmake_policy(SET CMP0167 NEW) endif() if(ZEEP_BUILD_LIBRARY) set(CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # When building with ninja-multiconfig, build both debug and release by default if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") set(CMAKE_CROSS_CONFIGS "Debug;Release") set(CMAKE_DEFAULT_CONFIGS "Debug;Release") endif() find_package(Filesystem REQUIRED) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter") elseif(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") endif() # Build shared libraries by default (not my cup of tea, but hey) option(BUILD_SHARED_LIBS "Build a shared library instead of a static one" OFF) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) if(WIN32) if(${CMAKE_SYSTEM_VERSION} GREATER_EQUAL 10) # Windows 10 add_definitions(-D _WIN32_WINNT=0x0A00) elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.3) # Windows 8.1 add_definitions(-D _WIN32_WINNT=0x0603) elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.2) # Windows 8 add_definitions(-D _WIN32_WINNT=0x0602) elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.1) # Windows 7 add_definitions(-D _WIN32_WINNT=0x0601) elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.0) # Windows Vista add_definitions(-D _WIN32_WINNT=0x0600) else() # Windows XP (5.1) add_definitions(-D _WIN32_WINNT=0x0501) endif() add_definitions(-DNOMINMAX) endif() if(MSVC) # make msvc standards compliant... add_compile_options(/permissive-) endif() # Optionally use mrc to create resources if(WIN32 AND BUILD_SHARED_LIBS) message("Not using resources when building shared libraries for Windows") else() find_package(Mrc QUIET) if(MRC_FOUND) option(USE_RSRC "Use mrc to create resources" ON) if(USE_RSRC) message("Using resources compiled with ${MRC_EXECUTABLE} version ${MRC_VERSION_STRING}") set(WEBAPP_USES_RESOURCES 1) endif() else() message(STATUS "Not using resources since mrc was not found") endif() endif() set(CMAKE_THREAD_PREFER_PTHREAD) set(THREADS_PREFER_PTHREAD_FLAG) find_package(Threads REQUIRED) if(ZEEP_USE_BOOST_ASIO) find_package(Boost 1.74 REQUIRED) message(STATUS "Using asio from boost") configure_file(${PROJECT_SOURCE_DIR}/cmake/asio-boost.hpp.in ${PROJECT_SOURCE_DIR}/include/zeep/http/asio.hpp @ONLY) set(FIND_DEPENDENCY_BOOST "find_dependency(Boost REQUIRED)") else() find_path(ASIO_INCLUDE_DIR asio.hpp REQUIRED) message(STATUS "Using standalone asio") configure_file(${PROJECT_SOURCE_DIR}/cmake/asio.hpp.in ${PROJECT_SOURCE_DIR}/include/zeep/http/asio.hpp @ONLY) endif() if(NOT (TARGET date OR date_FOUND)) find_package(date 3.0.1 QUIET NAMES date libhowardhinnant-date) if(NOT date_FOUND) if(ZEEP_ALLOW_FETCH_CONTENT) include(FetchContent) FetchContent_Declare(date GIT_REPOSITORY https://github.com/HowardHinnant/date.git GIT_TAG v3.0.1) FetchContent_MakeAvailable(date) else() message(FATAL_ERROR "The date package was not found, please install https://github.com/HowardHinnant/date and try again") endif() endif() endif() if(UNIX) set(HTTP_HAS_UNIX_DAEMON 1) find_file(HAVE_SYS_WAIT_H "sys/wait.h") if(HAVE_SYS_WAIT_H) set(HTTP_SERVER_HAS_PREFORK 1) endif() endif() # Generate the revision.hpp file write_version_header("${PROJECT_SOURCE_DIR}/lib-xml/src" LIB_NAME "libzeep") list(APPEND ZEEP_HEADERS ${PROJECT_SOURCE_DIR}/include/zeep/crypto.hpp ${PROJECT_SOURCE_DIR}/include/zeep/streambuf.hpp ${PROJECT_SOURCE_DIR}/include/zeep/value-serializer.hpp ${PROJECT_SOURCE_DIR}/include/zeep/config.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/document.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/parser.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/xpath.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/node.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/character-classification.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/serialize.hpp ${PROJECT_SOURCE_DIR}/include/zeep/xml/doctype.hpp ${PROJECT_SOURCE_DIR}/include/zeep/type-traits.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/to_element.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/element.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/factory.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/serializer.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/parser.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/type_traits.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/from_element.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/element_fwd.hpp ${PROJECT_SOURCE_DIR}/include/zeep/json/iterator.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/asio.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/access-control.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/controller.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/message-parser.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/tag-processor.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/connection.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/server.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/daemon.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/error-handler.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/reply.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/template-processor.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/header.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/request.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/rest-controller.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/soap-controller.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/html-controller.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/security.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/uri.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/el-processing.hpp ${PROJECT_SOURCE_DIR}/include/zeep/http/login-controller.hpp ${PROJECT_SOURCE_DIR}/include/zeep/unicode-support.hpp ${PROJECT_SOURCE_DIR}/include/zeep/nvp.hpp ${PROJECT_SOURCE_DIR}/include/zeep/exception.hpp ) list(APPEND ZEEP_SRC ${PROJECT_SOURCE_DIR}/lib-http/src/access-control.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/connection.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/controller.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/crypto.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/daemon.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/el-processing.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/error-handler.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/format.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/glob.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/html-controller.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/login-controller.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/message-parser.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/reply.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/request.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/rest-controller.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/security.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/server.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/uri.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/soap-controller.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/tag-processor-v2.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/tag-processor.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/template-processor.cpp ${PROJECT_SOURCE_DIR}/lib-http/src/signals.cpp ${PROJECT_SOURCE_DIR}/lib-json/src/element.cpp ${PROJECT_SOURCE_DIR}/lib-json/src/json-parser.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/character-classification.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/doctype.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/document.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/html-named-characters.hpp ${PROJECT_SOURCE_DIR}/lib-xml/src/html-named-characters.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/node.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/xml-parser.cpp ${PROJECT_SOURCE_DIR}/lib-xml/src/xpath.cpp ) if(USE_RSRC) list(APPEND ZEEP_SRC ${PROJECT_SOURCE_DIR}/lib-http/src/controller-rsrc.cpp) endif() if(HTTP_SERVER_HAS_PREFORK) list(APPEND ZEEP_HEADERS ${PROJECT_SOURCE_DIR}/include/zeep/http/preforked-server.hpp) list(APPEND ZEEP_SRC ${PROJECT_SOURCE_DIR}/lib-http/src/preforked-server.cpp) endif() add_library(zeep ${ZEEP_SRC} ${ZEEP_HEADERS}) add_library(zeep::zeep ALIAS zeep) set_target_properties(zeep PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories(zeep PUBLIC "$" "$" ) target_link_libraries(zeep PUBLIC Threads::Threads date::date ${STDCPPFS_LIBRARY}) if(ZEEP_USE_BOOST_ASIO) target_link_libraries(zeep PUBLIC Boost::boost) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") target_link_options(zeep PRIVATE -undefined dynamic_lookup) endif() # # Build debug library with d postfix # set(CMAKE_DEBUG_POSTFIX d) # set_target_properties(zeep PROPERTIES DEBUG_POSTFIX "d") # Install rules install(TARGETS zeep EXPORT zeep-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(EXPORT zeep-targets NAMESPACE zeep:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zeep ) install( DIRECTORY include/zeep DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT Devel PATTERN "config.hpp.in" EXCLUDE ) configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/zeep-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/zeep/zeep-config.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zeep ) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/zeep/zeep-config-version.cmake" COMPATIBILITY AnyNewerVersion ) file(GLOB OLD_CONFIG_FILES ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/zeep/zeepConfig*.cmake ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/zeep/zeepTargets*.cmake) if(OLD_CONFIG_FILES) message(STATUS "Installation will remove old config files: ${OLD_CONFIG_FILES}") install(CODE "file(REMOVE ${OLD_CONFIG_FILES})") endif() install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zeep/zeep-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/zeep/zeep-config-version.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/zeep COMPONENT Devel ) set(zeep_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}) set_target_properties(zeep PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} INTERFACE_zeep_MAJOR_VERSION ${PROJECT_VERSION_MAJOR} COMPATIBLE_INTERFACE_STRING zeep_MAJOR_VERSION ) # Config file set(LIBZEEP_VERSION ${PROJECT_VERSION}) set(LIBZEEP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set(LIBZEEP_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(LIBZEEP_VERSION_PATCH ${PROJECT_VERSION_PATCH}) configure_file("${PROJECT_SOURCE_DIR}/include/zeep/config.hpp.in" "${PROJECT_SOURCE_DIR}/include/zeep/config.hpp" @ONLY) endif(ZEEP_BUILD_LIBRARY) # Documentation if(ZEEP_BUILD_DOCUMENTATION) add_subdirectory(docs) endif() # Examples if(ZEEP_BUILD_EXAMPLES) add_subdirectory(examples) endif() # Tests if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL) add_subdirectory(test) endif() libzeep-6.1.1/LICENSE_1_0.txt0000644000175000017500000000247214752105534015306 0ustar maartenmaartenBoost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libzeep-6.1.1/README.md0000644000175000017500000001347514752105534014310 0ustar maartenmaartenlibzeep ======= [![DOI](https://zenodo.org/badge/44161414.svg)](https://zenodo.org/badge/latestdoi/44161414) [![github CI](https://github.com/mhekkel/libzeep/actions/workflows/cmake-multi-platform.yml/badge.svg)](https://github.com/mhekkel/libzeep/actions) [![github CI](https://github.com/mhekkel/libzeep/actions/workflows/build-documentation.yml/badge.svg)](https://github.com/mhekkel/libzeep/actions) TL;DR ----- Libzeep is a web application framework written in C++. To see a starter project visit the [libzeep-webapp-starter](https://github.com/mhekkel/libzeep-webapp-starter.git) page. About ----- Libzeep was originally developed to make it easy to create SOAP servers. And since working with SOAP means working with XML and no decent C++ XML library existed on my radar I created a full XML library as well. Unfortunately (well, considering the work I did), REST proved to be more popular than SOAP, and so I added a better JSON implementation to version 4 of libzeep as well as a way to create REST servers more easily. But then I had to use Spring for some time and was impressed by the simplicity of building interactive web applications and thought I should bring that simplicity to the C++ world. After all, my applications need raw speed and no, Java is not fast. The current incarnation of libzeep, version 6.0, is a completely refactored set of libraries. One for manipulating XML, one for handling JSON and one for building web applications. The XML part of libzeep consists of a validating parser, a DOM(-like) node implementation, an XPath search engine and a XML writer/formatter. The validation works based on DOCTYPE definitions. Please note that libzeep aims to provide a fully compliant XML processor as specified by the W3 organisation (see: [www.w3.org/TR/xml](https://www.w3.org/TR/xml) ). This means it is as strict as the standard requires and it stops processing a file when a validation of the well-formedness is encountered, or when a document appears to be invalid when it is in validating mode. Error reporting is done in this case. The JSON library in itself is fairly simple. There are much better alternatives if you're looking for just JSON. But this implementation is required by the web application part. And then we have a web application library. This one makes it very easy to build a HTTP server that serves HTML but also speaks REST and SOAP. The current implementation consists of a HTTP server class to which you can add controllers. Each controller has a path prefix and handles requests for some entries in this uri path. The base class controller is simple and in fact is just a base class. The HTML controller can be used as a base class so you can add methods that will be called for certain URI paths. In combination with the available tag processors you can then create and return dynamic XHTML pages. The REST and SOAP controllers likewise can be used as base classes to export methods that take simple or complex named parameters and return JSON and SOAP enveloped data structures respectively. Full documentation can be found at: [www.hekkelman.com/libzeep-doc/](https://www.hekkelman.com/libzeep-doc/) Building libzeep ---------------- To build libzeep you have to have [cmake](https://cmake.org/) installed. You also need to have installed [Howard Hinnants date library](https://github.com/HowardHinnant/date) as well as [libmcfp](https://github.com/mhekkel/libmcf). And, unless you are using macOS, it is recommended to install [mrc](https://github.com/mhekkel/mrc) in order to have resources support in libzeep. The commands to build libzeep from the command line are e.g.: ```bash git clone https://github.com/mhekkel/libzeep cd libzeep cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build ctest --test-dir build cmake --install build ``` Creating a simple web application --------------------------------- Create a template in xhtml first, store this as `hello.xhtml` in a directory called `docroot`: ```xml Hello

Hello, !

``` Then create a source file called `http-server.cpp` with the following content: ```c++ #define WEBAPP_USES_RESOURCES 0 #include #include #include class hello_controller : public zeep::http::html_controller { public: hello_controller() { map_get("", &hello_controller::handle_index, "name"); map_get("index.html", &hello_controller::handle_index, "name"); map_get("hello/{name}", &hello_controller::handle_index, "name"); } zeep::http::reply handle_index(const zeep::http::scope& scope, std::optional user) { zeep::http::scope sub(scope); sub.put("name", user.value_or("world")); return get_template_processor().create_reply_from_template("hello.xhtml", sub); } }; int main() { zeep::http::server srv(std::filesystem::canonical("docroot")); srv.add_controller(new hello_controller()); srv.bind("::", 8080); srv.run(2); return 0; } ``` Create a `CMakeLists.txt` file: ```cmake cmake_minimum_required(VERSION 3.16) project(http-server LANGUAGES CXX) set(CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(zeep REQUIRED) add_executable(http-server http-server.cpp) target_link_libraries(http-server zeep::zeep) ``` And configure and build the app: ```bash cmake . cmake --build . ``` And then run it: ```bash ./http-server ``` Now you can access the result using the following URL's: * * * libzeep-6.1.1/changelog0000644000175000017500000002314614752105534014677 0ustar maartenmaartenVersion 6.1.1 - Fixed copyright on named characters files Version 6.1.0 - Better login handling - Do not specify BOOST_ASIO_STANDALONE by default Version 6.0.16 - Fix the reload of daemons without preforking Version 6.0.15 - Changed the way parsers convert a string to a float, now use std::from_chars for a final conversion to avoid rounding errors. - Fix test on macOS (no /proc filesystem there) - Removed using codecvt_utf8 since it is deprecated - Removed asio::ip::tcp::resolver::query usage - Refactored daemon to no longer expose code that requires POSIX calls like fork/exec on Windows Version 6.0.14 - Fix URI parser, some paths were not absolute - Added variant of http::daemon with forking a daemon but no preforked children. Simply a single instance with multiple threads. Version 6.0.13 - Flush access log after each request. (replacing all instances of std::endl was a bit too drastic). - Better handling of not_found - Don't test when included in other project - Fix redirects after login/logout (this time for real, I hope) Version 6.0.12 - Catch URI parse error in connection Version 6.0.11 - Builds on macOS again, I hope Version 6.0.10 - Fix html_controller and rest_controller to pass path parameters decoded. - No longer use the date library to write out localised date/time formats since the installed date library might contain ONLY_C_LOCALE defined. - Do not read PID file when running the foreground - Renamed the cmake config files for libzeep from CamelCase to kebab-case. The install rules should remove older config files. Version 6.0.9 - Fix writing encoded path segments for URI's Version 6.0.8 - Security fix: redirect to relative URI's only on login - Added a new HTTP status code: 422 Unprocessable Entity Version 6.0.7 - various cmake related fixes - new version string module Version 6.0.6 - Dropped support for GNU autotools, pkgconfig Version 6.0.5 - Fix SONAME (should have been updated to 6 of course) - Changed code in format to no longer use std::codecvt_utf8 - support for building with stand alone ASIO Version 6.0.4.1 - Do not try to build examples, that only works after installing Version 6.0.4 - Fix message parser to accept HTTP messages without a content-length but with a content-type header. - Include at more locations - Include version string code (https://github.com/mhekkel/version-string.cmake) Version 6.0.3 - Fixes in login controller logic. Again. Version 6.0.2 - When processing tags in a HTML5 environment, replace CDATA sections with plain text. CDATA is not supported in HTML5. - Better resource linking Version 6.0.1 - Fixed some issues in serializing and detection templates to enable serializing std::optional. - Added option to timeout JWT access tokens - handle_file of template-processor now uses chunked transfer encoding - Avoid crash when loading a non-regular file - complete rewrite of uri class - Fix formatDecimal for negative numbers Version 6.0.0 - Dropped boost::date_time and other boost libraries - Fix daemon::reload - New html_controller routines that mimic the rest_controller mapping - Added access control object, for CORS handling - Changed serialising of std::chrono time_point values. - Redesigned login_controller Version 5.1.8 - Fix bug in parsing binary multipart/form-data parameters Version 5.1.7 - Fix dependency on std::filesystem library Version 5.1.6 - Fix the visibility of types in zeep::json::detail::iterator_impl - Reintroduced resolving of bind addresses, using "localhost" is easier than only numerical addresses. - Return correct status code in case of catching an exception in rest controllers. - Fix dependency in .cmake config file for Threads - Generate config.hpp file. Version 5.1.5 - update zeepConfig.cmake to include required link file - fix infinite loop in processing incorrect :inline constructs Version 5.1.4 - Update cmakefile to work more reliably Version 5.1.3 - Update SONAME to 5.1 - Create reproducible builds of documentation (and thus whole package) Version 5.1.2 - Fix glob code to match empty path specifications for controllers - Change CMakeLists file to generate only shared or static libs, but not both - Generate pkgconfig file again Version 5.1.1 - Removed uriparser again. URI implementation is now regex based. - Replaced GNU configure with cmake Version 5.1.0 - Added base32 encoding/decoding - Various REST controller fixes, mainly in accepting parameters - The library is now always compiled with PIC - Requred boost version is now 71 - Ignore SIGCHLD in foreground mode, signals are now handled by cross platform implementation - reintroduced a Windows version - Fixed a couple of security issues, all caused by incorrectly parsing uri's. Switched to using liburiparser for now. Version 5.0.2 - Add support for building shared libraries - Decoupled example code from rest, should now be build after installation, or use the STAGE=1 option to make. - rest controller can now return a reply object, adding flexibility Version 5.0.1 - Update makefile to include changes made for the Debian package - Fix writing HTML, proper empty elements - Added some workarounds to build on macOS - Fixed endianness issue in sha implementation Version 5.0.0 - Total rewrite of about everything - Controllers are now the main handlers of requests, three major variants for HTML, REST and SOAP. - Implemented some cryptographic routines in order to drop dependency on libcrypto++ - Redesigned authentication, dropped HTTP digest and opted for JWT, added security_context class for managing all of this - Code now requires a c++17 compiler - Lots of test code added - Added some real world examples - Tested with boost 1.65.1 up to 1.73 - Refactored request, it is now a class and credentials are always stored if a valid access-token was detected. - A bunch of fixes to make web application work behind a reverse proxy. Version 4.0.0 - Major rewrite, may break code. - Added a JSON parser and compatible internal object, is analogous to the version of nlohmann. Replaces the old element class in webapp. - Removed parameter_map, get request parameters from request itself. - Reorganized code, separate folder for lib and examples. - Refactored webapp and move the tag processing into a separate class. Added a second tag processor that mimics thymeleaf. Version 3.0.2 - Change in zeep/xml/serialize.hpp for gcc 4.7 compiler Version 3.0.1 - added cast to uint32 in webapp-el to allow compilation on s390 Version 3.0 - Support for non-intrusive serialization. The call to serialize is now done by the templated struct zeep::xml::struct_serializer. You can create a specialization for this struct to do something else than calling MyClass::serialize. - xml::document now has serialize and deserialize members. - A streaming input added, process_document_elements calls the callback for all elements that match a given xpath. - ISO8859-1 support (finally) - some xpath additions (matches e.g.) - changed signature of various find routines to work with const char* - changed authentication mechanism in webapp to allow multiple realms - some small changes in writing out XML documents/xml::writer - added line number to validation error messages - process value tag of mrs:option tag - el processing returns original string if it does not contain an expression - in expression language, support var1[var2] constructs - fix in writing doctype declaration - insert/erase implementations of zeep::xml::node... - fixed bug in el implementation (dividing numbers) - extended log format of HTTP server to allow better awstat logs (using the extra fields for SOAP calls). Also writes the X-Forwarded-For client if any. - Patches provided by Patrick Rotsaert: serializer for xsd:time and optional data types based on boost::optional. - Split out log_request as a virtual method in http::server - Added quick and dirty test for requests from mobile clients - Added virtual destructors to all base classes. - OPTIONS and HEAD support in web server Version 2.9.0 - Added some calls to xml::writer to write e.g. xml-decl and doctypes Version 2.8.2 - Fix in unicode support code - Preliminary support for handling authentication Version 2.8.1 - removed boost::ptr_vector/ptr_list. - work around a crashing bug in el::object[string] when compiling with icpc Version 2.8.0 - write_content added. - nullptr instead of nil, added a stub for old compilers. - fix in el::object (mixing up uint64 and size_t) Version 2.6.3 - Fix for stack overflow in delete large XML documents Version 2.6.2 - Apparently the word size has changed on amd64/GNUC targets. I've switched to a more robust template selection algorithm for WSDL generation. Version 2.6.1 - Fix in keep-alive (clear reply object after each served reply) - Implemented missing at() virtual method for el::vector - Writing comments now validates output - check mounted paths instead of only the root for handlers - optimization flags in makefile Version 2.6.0 - Changed parameter_map (for webapp) into a multimap Version 2.5.2 - Throw exception when attempting to write null character. Version 2.5.1 - Removed the use of split_iterator from webapp since it generated crashes when built as a shared library... Version 2.5.0 - added webapp, a base class used to create web applications, it uses XHTML templates to fill in. It uses a script language to enable interaction with the C++ code. Version 2.1.0 - support for HTTP/1.1 - added multiplication in xpath expression language... oops - revised interface for container::iterator, now it is possible to use more STL and boost functions on a container directly, like: xml::container cnt = ...; foreach (node* n, cnt) { cout << n->name() << endl; } libzeep-6.1.1/cmake/0000755000175000017500000000000014752105534014077 5ustar maartenmaartenlibzeep-6.1.1/cmake/FindFilesystem.cmake0000644000175000017500000000442614752105534020034 0ustar maartenmaarten# Simplistic reimplementation of https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake if(TARGET std::filesystem) return() endif() cmake_minimum_required(VERSION 3.10) include(CMakePushCheckState) include(CheckIncludeFileCXX) include(CheckCXXSourceCompiles) cmake_push_check_state() set(CMAKE_CXX_STANDARD 17) check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER) mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER) set(code [[ #include #include int main() { auto cwd = std::filesystem::current_path(); return EXIT_SUCCESS; } ]]) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 8.4.0) # >> https://stackoverflow.com/questions/63902528/program-crashes-when-filesystempath-is-destroyed set(CXX_FILESYSTEM_NO_LINK_NEEDED 0) else() # Check a simple filesystem program without any linker flags check_cxx_source_compiles("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED) endif() if(CXX_FILESYSTEM_NO_LINK_NEEDED) set(_found 1) else() set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES}) # Add the libstdc++ flag set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs) check_cxx_source_compiles("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED) set(_found ${CXX_FILESYSTEM_STDCPPFS_NEEDED}) if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED) # Try the libc++ flag set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs) check_cxx_source_compiles("${code}" CXX_FILESYSTEM_CPPFS_NEEDED) set(_found ${CXX_FILESYSTEM_CPPFS_NEEDED}) endif() endif() if(_found) add_library(std::filesystem INTERFACE IMPORTED) set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17) if(CXX_FILESYSTEM_NO_LINK_NEEDED) # Nothing to add... elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED) set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME stdc++fs) set(STDCPPFS_LIBRARY stdc++fs) elseif(CXX_FILESYSTEM_CPPFS_NEEDED) set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME c++fs) set(STDCPPFS_LIBRARY c++fs) endif() endif() cmake_pop_check_state() set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE) if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND) message(FATAL_ERROR "Cannot run simple program using std::filesystem") endif() libzeep-6.1.1/cmake/FindSphinx.cmake0000644000175000017500000000053414752105534017155 0ustar maartenmaarten# Look for an executable called sphinx-build find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable") include(FindPackageHandleStandardArgs) # Handle standard arguments to find_package like REQUIRED and QUIET find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE) libzeep-6.1.1/cmake/VersionString.cmake0000644000175000017500000002273714752105534017730 0ustar maartenmaarten# SPDX-License-Identifier: BSD-2-Clause # Copyright (c) 2021-2023 Maarten L. Hekkelman # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # This cmake extension writes out a revision.hpp file in a specified directory. # The file will contain a C++ inline function that can be used to write out # version information. cmake_minimum_required(VERSION 3.15) # We want the revision.hpp file to be updated whenever the status of the # git repository changes. Use the same technique as in GetGitRevisionDescription.cmake # from https://github.com/rpavlik/cmake-modules #[=======================================================================[.rst: .. command:: write_version_header Write a file named revision.hpp containing version info:: write_version_header( [FILE_NAME ] [LIB_NAME ] ) This command will generate the code to write a file name revision.hpp in the directory ````. ``FILE_NAME`` Specify the name of the file to create, default is ``revision.hpp``. ``LIB_NAME`` Specify the library name which will be used as a prefix part for the variables contained in the revision file. #]=======================================================================] # Record the location of this module now, not at the time the CMakeLists.txt # is being processed get_filename_component(_current_cmake_module_dir ${CMAKE_CURRENT_LIST_FILE} PATH) # First locate a .git file or directory. function(_get_git_dir _start_dir _variable) set(cur_dir "${_start_dir}") set(git_dir "${_start_dir}/.git") while(NOT EXISTS "${git_dir}") # .git dir not found, search parent directories set(prev_dir "${cur_dir}") get_filename_component(cur_dir "${cur_dir}" DIRECTORY) if(cur_dir STREQUAL prev_dir OR cur_dir STREQUAL ${_start_dir}) # we are not in git since we either hit root or # the ${_start_dir} which should be the top set(${_variable} "" PARENT_SCOPE) return() endif() set(git_dir "${cur_dir}/.git") endwhile() set(${_variable} "${git_dir}" PARENT_SCOPE) endfunction() # Locate the git refspec hash and load the hash # This code locates the file containing the git refspec/hash # and loads it. Doing it this way assures that each time the git # repository changes the revision.hpp file gets out of date. function(_get_git_hash _data_dir _variable) # Be pessimistic set(_variable "" PARENT_SCOPE) # Load git package if needed if(NOT GIT_FOUND) find_package(Git QUIET) endif() # And fail if not found if(NOT GIT_FOUND) return() endif() # Locate the nearest .git file or directory _get_git_dir(${CMAKE_CURRENT_SOURCE_DIR} GIT_DIR) # And fail if not found if("${GIT_DIR}" STREQUAL "") return() endif() # Check if the current source dir is a git submodule or a worktree. # In both cases .git is a file instead of a directory. # if(IS_DIRECTORY ${GIT_DIR}) set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") else() # The following git command will return a non empty string that # points to the super project working tree if the current # source dir is inside a git submodule. # Otherwise the command will return an empty string. # execute_process( COMMAND "${GIT_EXECUTABLE}" rev-parse --show-superproject-working-tree WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE out ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT "${out}" STREQUAL "") # If out is not empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule file(READ ${GIT_DIR} submodule) string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE ${submodule}) string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE) get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") else() # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree file(READ ${GIT_DIR} worktree_ref) # The .git directory contains a path to the worktree information directory # inside the parent git repo of the worktree. # string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir ${worktree_ref}) string(STRIP ${git_worktree_dir} git_worktree_dir) _get_git_dir("${git_worktree_dir}" GIT_DIR) set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD") endif() endif() # Fail if the 'head' file was not found if(NOT EXISTS "${HEAD_SOURCE_FILE}") return() endif() # Make a copy of the head file set(HEAD_FILE "${_data_dir}/HEAD") configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY) # Now we create a cmake file that will read the contents of this # head file in the appropriate way file(WRITE "${_data_dir}/grab-ref.cmake.in" [[ set(HEAD_HASH) file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) if(HEAD_CONTENTS MATCHES "ref") # named branch string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") if(EXISTS "@GIT_DIR@/${HEAD_REF}") configure_file("@GIT_DIR@/${HEAD_REF}" "@VERSION_STRING_DATA@/head-ref" COPYONLY) else() configure_file("@GIT_DIR@/packed-refs" "@VERSION_STRING_DATA@/packed-refs" COPYONLY) file(READ "@VERSION_STRING_DATA@/packed-refs" PACKED_REFS) if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") set(HEAD_HASH "${CMAKE_MATCH_1}") endif() endif() else() # detached HEAD configure_file("@GIT_DIR@/HEAD" "@VERSION_STRING_DATA@/head-ref" COPYONLY) endif() if(NOT HEAD_HASH) file(READ "@VERSION_STRING_DATA@/head-ref" HEAD_HASH LIMIT 1024) string(STRIP "${HEAD_HASH}" HEAD_HASH) endif() ]]) configure_file("${VERSION_STRING_DATA}/grab-ref.cmake.in" "${VERSION_STRING_DATA}/grab-ref.cmake" @ONLY) # Include the aforementioned file, this will define # the HEAD_HASH variable we're looking for include("${VERSION_STRING_DATA}/grab-ref.cmake") set(${_variable} "${HEAD_HASH}" PARENT_SCOPE) endfunction() # Create a revision file, containing the current git version info, if any function(write_version_header dir) set(flags ) set(options LIB_NAME FILE_NAME) set(sources ) cmake_parse_arguments(VERSION_STRING_OPTION "${flags}" "${options}" "${sources}" ${ARGN}) # parameter check if(NOT IS_DIRECTORY ${dir}) message(FATAL_ERROR "First parameter to write_version_header should be a directory where the final revision.hpp file will be placed") endif() if(VERSION_STRING_OPTION_FILE_NAME) set(file_name "${VERSION_STRING_OPTION_FILE_NAME}") else() set(file_name "revision.hpp") endif() # Where to store intermediate files set(VERSION_STRING_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/VersionString") if(NOT EXISTS "${VERSION_STRING_DATA}") file(MAKE_DIRECTORY "${VERSION_STRING_DATA}") endif() # Load the git hash using the wizzard-like code above. _get_git_hash("${VERSION_STRING_DATA}" GIT_HASH) # If git was found, fetch the git description string if(GIT_HASH) execute_process( COMMAND "${GIT_EXECUTABLE}" describe --dirty --match=build WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" RESULT_VARIABLE res OUTPUT_VARIABLE out ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(res EQUAL 0) set(REVISION_STRING "${out}") endif() endif() # Check the revision string, if it matches we fill in the required info if(REVISION_STRING MATCHES "build-([0-9]+)-g([0-9a-f]+)(-dirty)?") set(BUILD_NUMBER ${CMAKE_MATCH_1}) if(CMAKE_MATCH_3) set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}*") else() set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}") endif() string(TIMESTAMP REVISION_DATE_TIME "%Y-%m-%dT%H:%M:%SZ" UTC) else() set(REVISION_GIT_TAGREF "") set(BUILD_NUMBER 0) set(REVISION_DATE_TIME "") endif() if(VERSION_STRING_OPTION_LIB_NAME) set(VAR_PREFIX "${VERSION_STRING_OPTION_LIB_NAME}") set(IDENT_PREFIX "${VERSION_STRING_OPTION_LIB_NAME}_") set(BOOL_IS_MAIN "false") else() set(VAR_PREFIX "") set(IDENT_PREFIX "") set(BOOL_IS_MAIN "true") endif() configure_file("${_current_cmake_module_dir}/revision.hpp.in" "${dir}/${file_name}" @ONLY) endfunction() libzeep-6.1.1/cmake/asio-boost.hpp.in0000644000175000017500000000066014752105534017276 0ustar maartenmaarten// Copyright Maarten L. Hekkelman, 2023 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #pragma once #if ZEEP_BOOST_ASIO_STANDALONE #define BOOST_ASIO_STANDALONE 1 #endif #include #include namespace asio_ns = ::boost::asio; namespace asio_system_ns = ::boost::system; libzeep-6.1.1/cmake/asio.hpp.in0000644000175000017500000000047714752105534016160 0ustar maartenmaarten// Copyright Maarten L. Hekkelman, 2023 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #pragma once #include namespace asio_ns = ::asio; namespace asio_system_ns = ::std; libzeep-6.1.1/cmake/revision.hpp.in0000644000175000017500000000634514752105534017063 0ustar maartenmaarten// This file was generated by VersionString.cmake #pragma once #include constexpr const char k@VAR_PREFIX@ProjectName[] = "@PROJECT_NAME@"; constexpr const char k@VAR_PREFIX@VersionNumber[] = "@PROJECT_VERSION@"; constexpr int k@VAR_PREFIX@BuildNumber = @BUILD_NUMBER@; constexpr const char k@VAR_PREFIX@RevisionGitTag[] = "@REVISION_GIT_TAGREF@"; constexpr const char k@VAR_PREFIX@RevisionDate[] = "@REVISION_DATE_TIME@"; #ifndef VERSION_INFO_DEFINED #define VERSION_INFO_DEFINED 1 namespace version_info_v1_1 { class version_info_base { public: static void write_version_string(std::ostream &os, bool verbose) { auto s_main = registered_main(); if (s_main != nullptr) s_main->write(os, verbose); if (verbose) { for (auto lib = registered_libraries(); lib != nullptr; lib = lib->m_next) { os << "-\n"; lib->write(os, verbose); } } } protected: version_info_base(const char *name, const char *version, int build_number, const char *git_tag, const char *revision_date, bool is_main) : m_name(name) , m_version(version) , m_build_number(build_number) , m_git_tag(git_tag) , m_revision_date(revision_date) { if (is_main) registered_main() = this; else { auto &s_head = registered_libraries(); m_next = s_head; s_head = this; } } void write(std::ostream &os, bool verbose) { os << m_name << " version " << m_version << '\n'; if (verbose) { if (m_build_number != 0) { os << "build: " << m_build_number << ' ' << m_revision_date << '\n'; if (m_git_tag[0] != 0) os << "git tag: " << m_git_tag << '\n'; } } } using version_info_ptr = version_info_base *; static version_info_ptr ®istered_main() { static version_info_ptr s_main = nullptr; return s_main; } static version_info_ptr ®istered_libraries() { static version_info_ptr s_head = nullptr; return s_head; } const char *m_name; const char *m_version; int m_build_number; const char *m_git_tag; const char *m_revision_date; version_info_base *m_next = nullptr; }; template class version_info : public version_info_base { public: using implementation_type = T; version_info(const char *name, const char *version, int build_number, const char *git_tag, const char *revision_date, bool is_main) : version_info_base(name, version, build_number, git_tag, revision_date, is_main) { } struct register_object { register_object() { static implementation_type s_instance; } }; template struct reference_object; static register_object s_registered_object; static reference_object s_referenced_object; }; template typename version_info::register_object version_info::s_registered_object; } // namespace version_info_v1_1 inline void write_version_string(std::ostream &os, bool verbose) { version_info_v1_1::version_info_base::write_version_string(os, verbose); } #endif class version_info_@IDENT_PREFIX@impl : public version_info_v1_1::version_info { public: version_info_@IDENT_PREFIX@impl() : version_info(k@VAR_PREFIX@ProjectName, k@VAR_PREFIX@VersionNumber, k@VAR_PREFIX@BuildNumber, k@VAR_PREFIX@RevisionGitTag, k@VAR_PREFIX@RevisionDate, @BOOL_IS_MAIN@) { } };libzeep-6.1.1/cmake/zeep-config.cmake.in0000644000175000017500000000033414752105534017714 0ustar maartenmaarten@PACKAGE_INIT@ include(CMakeFindDependencyMacro) find_dependency(Threads) @FIND_DEPENDENCY_BOOST@ find_dependency(date REQUIRED) include("${CMAKE_CURRENT_LIST_DIR}/zeep-targets.cmake") check_required_components(zeep) libzeep-6.1.1/docs/0000755000175000017500000000000014752105534013747 5ustar maartenmaartenlibzeep-6.1.1/docs/CMakeLists.txt0000644000175000017500000000366414752105534016520 0ustar maartenmaartenfind_package(Doxygen REQUIRED) find_package(Sphinx REQUIRED) # Find all the public headers # get_target_property(ZEEP_PUBLIC_HEADER_DIR libzeep INTERFACE_INCLUDE_DIRECTORIES) set(ZEEP_PUBLIC_HEADER_DIR ${PROJECT_SOURCE_DIR}/include/zeep) file(GLOB_RECURSE ZEEP_PUBLIC_HEADERS ${ZEEP_PUBLIC_HEADER_DIR}/*.hpp) set(DOXYGEN_INPUT_DIR ${ZEEP_PUBLIC_HEADER_DIR}) set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/xml) set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/index.xml) set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) #Replace variables inside @@ with the current values configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) add_custom_command( OUTPUT ${DOXYGEN_OUTPUT_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR}) add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} BYPRODUCTS ${DOXYGEN_OUTPUT_DIR} DEPENDS ${ZEEP_PUBLIC_HEADERS} ${DOXYGEN_OUTPUT_DIR} ${DOXYFILE_OUT} COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} COMMENT "Generating docs") add_custom_target("Doxygen-libzeep" ALL DEPENDS ${DOXYGEN_INDEX_FILE}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_SOURCE_DIR}/conf.py @ONLY) set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx) add_custom_target("Sphinx-libzeep" ALL COMMAND ${SPHINX_EXECUTABLE} -b html -Dbreathe_projects.libzeep=${DOXYGEN_OUTPUT_DIR} ${SPHINX_SOURCE} ${SPHINX_BUILD} DEPENDS ${DOXYGEN_INDEX_FILE} BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/api WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating documentation with Sphinx") install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/sphinx/ DESTINATION ${CMAKE_INSTALL_DOCDIR} PATTERN .doctrees EXCLUDE) libzeep-6.1.1/docs/Doxyfile.in0000644000175000017500000000043514752105534016064 0ustar maartenmaartenEXCLUDE_SYMBOLS = std*, zeep::json::detail* FILE_PATTERNS = *.hpp PREDEFINED += and=&& or=|| not=! GENERATE_XML = YES GENERATE_HTML = NO GENERATE_LATEX = NO GENERATE_TODOLIST = NO INPUT = @DOXYGEN_INPUT_DIR@ libzeep-6.1.1/docs/_static/0000755000175000017500000000000014752105534015375 5ustar maartenmaartenlibzeep-6.1.1/docs/_static/logo.png0000644000175000017500000000552014752105534017045 0ustar maartenmaartenPNG  IHDRd25~bKGD pHYs  tIME -4Ab#iTXtCommentCreated with GIMPd.e IDATx[aLSW~jR(*BqJ9]’-G5(.5%e X5dc2'lC3 |?~PD}9==s$ L@6 Addx"z=bcc$߅"Jǎg+DV>Ӕ1~B1j/ރy? <9~'NX4 ztdy?T fۈU*<'"7Ȕ)Si#k" 2|IkCdR[[ BΜ93v< j54 ^|EDgϞjj}V#Fq?i2Dxnqi<ذa|޳^pL̛bOP;2Niiibv*ݍ1H6.٧̟?_}z|A:ܟ|VىAVnׯG}}=`֭())_z%m;wXk ,#~NןO:gE?m2$-[P]] G}:fBpp0ʕ+hn͆[nFl(߿{OwލÇVX*qGB9sJ+W_ػwFG_|߆lڴiC<(%@LLLdCC޽KK.l6 mNNkYߋ/--%Ɗ ]zz:/_~ǹiӦҐdFFМ>}]]]t\y&7o,xM,kՓ4 InxxJRdggt d2ywxhͪU[bb"'dw R__B.]f͢J̙3i4yf^|YRA/_.www?^A-qoڍr ;z$?** mmmL/!AdLywP(;v)NΠ#$$=<>޽{j8vze0{oJJJ/-@سg$xdqqסF&%%Q155$oaNN͛={KUV`0Pղ$Cx"hn4n``9s-Y1ݿ?bj,//Nc^^D˰0޼y+]Gdhܘ׭['b555l6YYYr o߾Ht\t I^cMM hġdq^\JJ |MjZFh6988H^xgrss_Mb~^?{,.]:N; 2!fh4AXp!N8kh4oEAAΝ >** +WDPPT*p 8đLϣNѠC``X BCCQZZ ͆F N'~[Vܹj]]]=pAqڵkBƍGƳxƤ$^~$o0==$#IܹcCC$oݺEq?'|}st뫑8Ɂ677_}4DFOk׮155UR… G!ӧOG{{;ZZZp8w bV,[ gFGGSN`nGAAoƽ{vc$&&t:Eݻغu+m+))sh"dee9кAW^o0$f3fΜ-[n\.֮]ȗy)Ν;˗/je~~>cq첷t,d``LL ˽h-[F^ϣGr͚5j寿@FGGKtq4lll2MRŋUUUngaa!,X@Ns߾}CO}u%^I磀jg?1 ~'qld"ʐ ?U}MJIENDB`libzeep-6.1.1/docs/conf.py.in0000644000175000017500000000347314752105534015662 0ustar maartenmaartenproject = 'libzeep-doc' copyright = '2023, Maarten L. Hekkelman' author = 'Maarten L. Hekkelman' release = '@PROJECT_VERSION@' # -- General configuration --------------------------------------------------- extensions = [ "breathe", "exhale", "myst_parser" ] breathe_projects = { "libzeep": "../build/docs/xml" } myst_enable_extensions = [ "colon_fence" ] breathe_default_project = "libzeep" # Setup the exhale extension exhale_args = { # These arguments are required "containmentFolder": "./api", "rootFileName": "library_root.rst", "doxygenStripFromPath": "../include/", # Heavily encouraged optional argument (see docs) "rootFileTitle": "API Reference", # Suggested optional arguments # "createTreeView": True, # TIP: if using the sphinx-bootstrap-theme, you need # "treeViewIsBootstrap": True, "exhaleExecutesDoxygen": False, "contentsDirectives" : False, "verboseBuild": False } # Tell sphinx what the primary language being documented is. primary_domain = 'cpp' # Tell sphinx what the pygments highlight language should be. highlight_language = 'cpp' templates_path = ['_templates'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] html_theme_options = { } cpp_index_common_prefix = [ 'zeep::', 'zeep::http::', 'zeep::xml::', 'zeep::json::' ] libzeep-6.1.1/docs/genindex.rst0000644000175000017500000000001414752105534016275 0ustar maartenmaartenIndex ===== libzeep-6.1.1/docs/index.rst0000644000175000017500000000521114752105534015607 0ustar maartenmaartenIntroduction ============ Libzeep started as a spin-off of `MRS `_ which is a tool to index and search large text-based bioinformatics databanks. The code that generates a SOAP server in compile time in MRS was needed in another project and this is how libzeep started. BTW, zeep is the dutch word for soap. One of the major parts of libzeep used to be the XML library. It contains a full validating parser with support for XML 1.0 and 1.1 as well as a DOM API for manipulating XML based data structures in memory. The current implementation of libzeep goes much further. It is by now a swissarmy knife for building web applications in C++ including a web server implementation, a JSON library, SOAP and REST controller support and a templating engine looking suspisciously like `Thymeleaf `_. Lots of the concepts used in libzeep are inspired by the Java based `Spring framework `_. xml --- A feature complete XML library containing a validating parser as well as a modern C++ API for the data structures. It also supports serializing data structures using a boost-like serialization interface. json ---- This is an implementation of a JSON library. I've attempted to make it source code compatible with the very good `JSON library by Niels Lohmann `_. There are some major differences though, my library has a very different parser as well as support for serializing using the same technique as libzeep-xml. On the other hand mine lacks many of the advanced cool features found in Niels library. http ---- This library contains a web server implementation. There's also code to create daemon processes and run a preforked webserver. The design follows a bit the one from Spring and so there's a HTTP server class that delegates requests to controllers. A security context class helps in limiting access to authorized users only. Three specialized controller classes provide HTML templates, REST and SOAP services. The template language implementation attempts to be source code compatible with Thymeleaf. The REST controller maps member function calls to the HTTP URI space and translates HTTP parameters and HTTP form content into function variables and it provides transparent and automatic translation of result types into JSON. The SOAP controller is like the REST controller, but now digests requests wrapped in SOAP envelopes, delegates them to handler functions and returns the result back wrapped in SOAP envelopes. .. toctree:: :maxdepth: 2 :caption: Contents self lib-xml lib-json lib-http lib-generic api/library_root.rst genindex libzeep-6.1.1/docs/lib-generic.rst0000644000175000017500000000354214752105534016665 0ustar maartenmaartenGeneric ======= Introduction ------------ Originally libzeep came as a single library. But if you only need the XML functionality it might not be very useful to include all the networking code for the HTTP server. And so the libraries were split into modules that can be used independently from each other. There are some files that are shared by all libraries though The configuration file ^^^^^^^^^^^^^^^^^^^^^^ In :ref:`file_zeep_config.hpp` you can find a couple of flags that influence what parts of libzeep should be left out. The first is to enable building a :cpp:class:`zeep::http::preforked_server` class, probably only useful in a UNIX context. The other flag allows the compilation of code that uses resources. Resources in a libzeep context are a bit different from their counterparts in MacOS and Windows. Libzeep uses *mrc* to bundle resources in an executable. Especially for small web applications this makes installation very easy at the cost of configurability. See `github pages for mrc `_ for more information. character array streambuf ^^^^^^^^^^^^^^^^^^^^^^^^^ Sometimes it is very convenient to have a `std::istream` reading from a `const char*` buffer, the class :cpp:class:`zeep::char_streambuf` allows you to do just that. .. code-block:: cpp auto sb = zeep::char_streambuf("Hello, world!"); auto is = std::istream(&sb); std::string line; std::getline(is, line); Unicode/text support ^^^^^^^^^^^^^^^^^^^^ Various simple routines used when working with UTF-8 encoded Unicode text. Routines that are so common, you really ask yourself why these are not part of the standard yet. Serialization support ^^^^^^^^^^^^^^^^^^^^^ Originally, libzeep could only serialize XML. Later, with the addition of a JSON library with its own serialization ideas, the two were merged somewhat and the overlapping code ended up here. libzeep-6.1.1/docs/lib-http.rst0000644000175000017500000024240114752105534016227 0ustar maartenmaartenHTTP ==== Introduction -------------------------------------- The goal of libzeep is to provide a library that makes creating web applications as easy as possible. A lot of frameworks already exist to help building these interactive web apps written in languages ranging from Java to Python to more exotic stuff like Ruby and Laravel. The `Spring `_ version stands out between these since it is well designed and offers tons of features and still is fairly easy to work with. But all of these have one flaw in common, they're not written in C++ and thus lack the raw performance. Libzeep tries to implement some of the design patterns found in Spring. There is a very basic HTTP server class with some additional classes that help in creating daemon processes when running a UNIX or lookalike. This HTTP server class delegates requests to controller classes that each process requests in their own corner of the URI space occupied by your server. There are three main controller classes, each targeted at a different task. The first, :cpp:class:`zeep::http::html_controller` maps requests to functions that take a :cpp:class:`zeep::http::request` and :cpp:class:`zeep::http::scope` and return a :cpp:class:`zeep::http::reply`. Various routines are available to help constructing XHTML based replies based on XHTML template files. These files can contain special tags that will be processed and the values can be expressed in *expression language*. The second controller class is the :cpp:class:`zeep::http::rest_controller`. This one also maps requests to functions, but this time the parameters in the request are automatically translated into function parameters and the result of the function is converted back into JSON automatically. Named parameters can be passed in the payload of a POST request, as query parameters in a GET request or as parts of the URI path, as in ``GET /book/1234/title`` where you request the title of book number 1234. The third controller is the :cpp:class:`zeep::http::soap_controller`. Similar to the REST controller, but this time the translation is between SOAP XML messages and parameters and vice versa. HTTP server -------------------------------------- threads to run simultaneously. Something like this: .. literalinclude:: ../examples/http-server-0.cpp :start-after: //[ most_simple_http_server :end-before: //] :language: cpp Running this code will create a server that listens to port 8080 on localhost and will return ``NOT FOUND`` for all requests. Not particularly useful of course. It is possible to derive a class Controllers -------------------------------------- that handles any request, since it has a prefix that is effectively the same as the root. It returns a simple reply. .. literalinclude:: ../examples/http-server-1.cpp :start-after: //[ simple_http_server :end-before: //] :language: c++ Still a not so useful example. Fortunately there are several implementations of :cpp:class:`zeep::http::controller` that we can use. HTML Controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :cpp:class:`zeep::http::html_controller` class allows you to *mount* a request handler on a URI path, the result is that this request handler, which is a method of your controller class, will be called whenever a HTTP request with a matching URI comes in. The handler method has next to the :cpp:class:`zeep::http::request` and :cpp:class:`zeep::http::reply` parameter an additional :cpp:class:`zeep::http::scope` parameter. This scope is a kind of nested map of variable names and values. The scope is *const*, if you want to add data to the scope you should create your own sub scope and pass the original in the constructor. A handler can of course create simple replies, just as in the previous example. But you can also use templates. Note that the constructor of :cpp:class:`zeep::http::html_controller` takes a second parameter that is called docroot. This should contain the path to the directory containing the templates. .. note:: The docroot parameter is ignored when you create a html controller based on resources, see section on resources further in this documentation. Our :cpp:class:`zeep::http::html_controller` indirectly inherits :cpp:type:`zeep::http::template_processor` and this is the class that uses the `docroot` parameter. This class takes care of processing template files. It loads them and uses the registered tag processors and the `scope` to fill in the blanks and process the constructs found in the template. .. literalinclude:: ../examples/http-server-2.cpp :language: c++ :start-after: //[ simple_http_server_2 :end-before: //] This example uses the file docroot/hello.xhtml which should contain: .. code-block:: xml Hello

Hello, !

Now build and run this code, and you can access your welcome page at [If you want to see another name, use e.g. instead. Several remarks here. The server object is created with a ``docroot`` parameter. That parameter tells the server to create a default :cpp:type:`zeep::http::template_processor` for use by the :cpp:class:`zeep::http::html_controller` objects. As you can see in the handler code, a check is made for a parameter called ``name``. When present, its value is stored in the newly created sub-scope object. The template file contains a construct in the ```` element that tests for the availability of this variable and uses the default ``'world'`` otherwise. For more information on templates see the section on :ref:`xhtml-template`. The path specified in `mount` is `{,index,index.html}` which is a glob pattern, this pattern can accept the following constructs: +--------------------+-------------------------------------------------------+ | path | matches | +====================+=======================================================+ | `**/*.js` | matches `x.js`, `a/b/c.js`, etc | +--------------------+-------------------------------------------------------+ | `{css,scripts}/` | matches e.g. `css/1/first.css` and `scripts/index.js` | +--------------------+-------------------------------------------------------+ | `a;b;c` | matches either `a`, `b` or `c` | +--------------------+-------------------------------------------------------+ The way _mount_ works in the :cpp:class:`zeep::http::html_controller` class was a bit oldfashioned and inflexible. Especially compared to the :cpp:class:`zeep::http::rest_controller` class. So version 6 of libzeep brings a new way of *mounting*, to avoid conflicts now called *mapping*. The signature of handlers is now changed to take a couple of arguments, using std::optional if they are not required. Conversion of types is done automatically. The handler also takes a :cpp:class:`zeep::http::scope` as first parameter and returns the :cpp:class:`zeep::http::reply` object. How this works in practice is what you can see here: .. literalinclude:: ../examples/http-server-3.cpp :start-after: //[ simple_http_server_3 :end-before: //] :language: c++ Request and Reply -------------------------------------- An implementation of the HTTP standard will need various data types. There are :cpp:class:`zeep::http::request` and :cpp:class:`zeep::http::reply`. And these contain :cpp:class:`zeep::http::header` but the `method` specifier (which was changed to a `std::string` in a recent update to libzeep). The HTTP specification for :cpp:class:`zeep::http::request` and :cpp:class:`zeep::http::reply` are sufficiently similar to allow for a common `:cpp:class:`zeep::http::parser`. The parser for requests supports `chunked transfer encoding `_. request ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :cpp:class:`zeep::http::request` encapsulates what was received. The standard HTTP request contains a method, like ``GET`` or ``POST``. In this version of libzeep only a limited subset of methods are supported. The next part is the ``uri`` that was requested. Then we have the version, usually 1.0 or 1.1. Libzeep does not currently support anything else. When 1.1 was used, libzeep will honour the keep-alive flag. Headers are stored in an array and can be accessed using :cpp:func:`zeep::http::request::get_header`. Cookies stored in the headers can be accessed using :cpp:func:`zeep::http::request::get_cookie`. A :cpp:class:`zeep::http::request` may also contain a payload, usually only in case of a ``POST`` or ``PUT``. Requests can have parameters. These can be passed url-encoded in the uri, or they can be encoded in the payload using ``application/x-www-form-urlencoded`` or ``multipart/form-data`` encoding. The various :cpp:func:`zeep::http::request::get_parameter` members allow retrieving these parameters by name, optinally passing in a default value in case the parameter was not part of the request. A special case are file parameters, these are retrieved using :cpp:func:`zeep::http::request::get_file_parameter`. This returns a :cpp:class:`zeep::http::file_param` struct that contains information about the uploaded file. Using the [{ref}`zeep:cpp:class:`::char_streambuf `char_streambuf`] class`` you can efficiently read the contents of such a file: .. code-block:: cpp zeep::file_param f = req.get_file_parameter("upoad"); zeep::char_streambuf sb(f.data, f.length); std::istream is(&sb); Many other convenience accessors are available but data is also directly accessible since this is a `struct`. There are some functions to set data. Those are probably only useful if you write your own code to send out HTTP requests to other servers. reply ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :cpp:class:`zeep::http::reply` object is the object you need to fill in. Replies contain a status line, headers and optionally a payload. There is a static member called :cpp:func:`zeep::http::reply::stock_reply` that allows you to create a complete reply from a status code and an optional message. The :cpp:func:`zeep::http::reply::set_header` and :cpp:func:`zeep::http::reply::set_cookie` member functions take care of setting headers and cookies respectively. The content of the payload can be set using the various :cpp:func:`zeep::http::reply::set_content` methods. They will set the content type header according to the data passed in. If you specify a `std::istream*` as content, and the version is set to ``1.1`` then the data stream will be sent in chunked transfer-encoding. .. _xhtml-template: XHTML Template Processing -------------------------------------- Many web application frameworks provide a way of templating, write some boilerplate HTML and fill in the details at the moment a page is requested. Apart from that, a page may contains lots of external scripts, stylesheets, images and fonts. For these two tasks libzeep comes with a :cpp:type:`zeep::http::template_processor` class. loading ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Starting with the second task just mentioned, the :cpp:type:`zeep::http::template_processor` takes a ``docroot`` parameter in its constructor. This docroot is the location on disk where files are located. But it is also possible to build libzeep with in-memory resources by using `mrc `_. Have a look at the example code for usage. The :cpp:func:`zeep::http::basic_template_processor::load_file` member of :cpp:type:`zeep::http::template_processor` loads a file from disk (or compiled resources), the :cpp:func:`zeep::http::basic_template_processor::file_time` member can be used to get the file time of a file. This can be used to generate ``304 not modified`` replies instead. The :cpp:func:`zeep::http::basic_template_processor::load_template` member loads a template file from docroot and parses the XML contained in this file into a :cpp:class:`zeep::xml::document`. templates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Since we're using a XML parser/library to load template, they should be strict XMTML. It is possible to make these files somewhat HTML 5 like by adding the doctype .. code-block:: xml The tags inside a template can be processed using a tag_processor. Tag processors are linked to element and attributes in the template using XML namespaces. The method :cpp:func:`zeep::http::basic_template_processor::create_reply_from_template` can be used to convert a template into a reply using the data store in a :cpp:class:`zeep::http::scope`. tag processing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Libzeep comes with two tag_processor implementations, the first :cpp:class:`zeep::http::tag_processor_v1` is a legacy one and should probably not be used in new code. The second, :cpp:class:`zeep::http::tag_processor_v2`, is inspired by [@https://www.thymeleaf.org]. Using ``el`` script -------------------------------------- ``el`` is the abbreviation for *Expression Language*. It is a script language that tries to be like `Unified Expression Language `_. libzeep comes with code to evaluate ``el`` expressions. The language has the concept of variables and these can be created in the C++ code using the :cpp:class:`zeep::json::element` class. Variables created this way are then stored in a :cpp:class:`zeep::http::scope` object and passed along to the processing code. To give an example: .. literalinclude:: ../examples/synopsis-el-1.cpp :language: c++ :start-after: //[ fill_scope :end-before: //] And then you can process some ``expression language`` construct like this: .. literalinclude:: ../examples/synopsis-el-1.cpp :language: c++ :start-after: //[ evaluate_el :end-before: //] And if you then print out the result it should give you something like: "1: 1, 2: 2" ``el`` syntax ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Most often you will use simple expressions: +--------------+------------------------------------------------------------------------------------------------------------------------+ | expression | evaluates to | +==============+========================================================================================================================+ | ``${ ... }`` | variable | +--------------+------------------------------------------------------------------------------------------------------------------------+ | ``*{ ... }`` | selection variable (lookup is done in the scope of variables that were selected with ``z:select``, v2 processor only ) | +--------------+------------------------------------------------------------------------------------------------------------------------+ | ``@{ ... }`` | link URL | +--------------+------------------------------------------------------------------------------------------------------------------------+ | ``~{ ... }`` | fragment | +--------------+------------------------------------------------------------------------------------------------------------------------+ | ``#{ ... }`` | message (not supported yet in libzeep) | +--------------+------------------------------------------------------------------------------------------------------------------------+ The language has literals: +---------------------+----------------------------------------------------------------------------------------------------------------+ | expression | evaluates to | +=====================+================================================================================================================+ | `'my text string'`` | Text literal | +---------------------+----------------------------------------------------------------------------------------------------------------+ | `42`` | Numeric literal | +---------------------+----------------------------------------------------------------------------------------------------------------+ | `3.14`` | Numeric literal, note that scientific notation is not supported | +---------------------+----------------------------------------------------------------------------------------------------------------+ | `true`` | Boolean literal | +---------------------+----------------------------------------------------------------------------------------------------------------+ | `null`` | Null literal | +---------------------+----------------------------------------------------------------------------------------------------------------+ | `user greeting`` | token | +---------------------+----------------------------------------------------------------------------------------------------------------+ Text operations supported are: +---------------------+----------------------------------------------------------------------------------------------------------------+ | construct | description | +=====================+================================================================================================================+ | ``'a' + ' b'`` | concatenation, result is 'a b' | +---------------------+----------------------------------------------------------------------------------------------------------------+ | ``|hello ${user}|`` | literal substitution, if variable user contains 'scott', result is 'hello scott' | +---------------------+----------------------------------------------------------------------------------------------------------------+ Operators: +----------------------------+--------------------------------------------------------+ | operators | type | +============================+========================================================+ | ``+ - * / %`` | binary operators for standard arithmetic operations | +----------------------------+--------------------------------------------------------+ | ``-`` | unary operator, minus sign | +----------------------------+--------------------------------------------------------+ | ``and or`` | binary operators for standard boolean operations | +----------------------------+--------------------------------------------------------+ | ``! not`` | unary operators, negate | +----------------------------+--------------------------------------------------------+ | ``> < >= <= gt lt ge le`` | operators to compare values | +----------------------------+--------------------------------------------------------+ | ``== != eq ne`` | operators to check for equality | +----------------------------+--------------------------------------------------------+ | a ``?`` b | conditional operator: if a then return b else null | +----------------------------+--------------------------------------------------------+ | a ``?`` b ``:`` c | conditional operator: if a then return b else return c | +----------------------------+--------------------------------------------------------+ | a ``?:`` b | conditional operator: if a then return a else return b | +----------------------------+--------------------------------------------------------+ When using variables, accessing their content follows the same rules as in Javascript. Arrays have a member function ``length``. :: _predefined-objects: A few predefined utility objects are predefined. These are ``#dates``, ``#numbers``, ``#request`` and ``#security``. +------------------------------------------------------+------------------------------------------------------------------------------------------+ | object.method | Description | +======================================================+==========================================================================================+ | ``#dates.format(date,format)`` | This method takes two parameters, a preferrably ISO formatted date and a format string. | | | The result will be the output of `std::put_time`_. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ |``#numbers.formatDecimal(number,int_digits,decimals)``| This method takes up to three parameters, a number that needs to be formatted, an | | | int_digits parameter that specifies the minimum number of integral digits to use and | | | a decimals parameter that specifies how many decimals to use. | | | | | | The number is formatted using the locale matching the language specified in the Accept | | | HTTP request header. However, if that locale is not available the default locale is used.| | | | | | Defaults for int_digits is 1 and decimals is 0. | | | | | | Example output: ``${#numbers.formatDecimal(pi,2,4)}`` is **03.1415** when the locale to | | | use is en_US. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ | ``#numbers.formatDiskSize(number,decimals)`` | This method takes up to two parameters, a number that needs to be formatted, | | | and a decimals parameter that specifies how many decimals to use. | | | | | | The number is divided by 1024 until it fits three int digits and the suffix is | | | adjusted accordingly. | | | Default for decimals is 0. | | | | | | Example output: ``${#numbers.formatDiskSize(20480,2)}`` is **2.00K** when the locale to | | | use is en_US. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ | ``#request.getRequestURI()`` | Returns the original URI in the HTTP request. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ | ``#security.authorized()`` | Returns whether the uses has successfully logged in. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ | ``#security.username()`` | Returns the username for the current user. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ | ``#security.hasRole(role)`` | Returns whether the uses has the role as specified by the parameter. | +------------------------------------------------------+------------------------------------------------------------------------------------------+ .. _std::put_time: https://en.cppreference.com/w/cpp/io/manip/put_time tag_processor_v1 -------------------------------------- This tag_processor works on tags, mostly. As opposed to tag_processor_v2 which works on attributes mainly. The tags are in a separate XML namespace. You can change this name space using the `ns` parameter in the constructor, the default is ``http://www.hekkelman.com/libzeep/m1``. There are several predefined processing tags which are summarized below. There used to be also a way to add your own processing tags using an `add_processor` method but that has been dropped. +------------------+-----------------------------------------------------------------------------------------------+ | tag name | Description and Examples | | | | | (without prefix) | | +==================+===============================================================================================+ | include | Takes one parameter named `file` and replaces the tag with the processed content of this file | | | | | | .. code-block:: xml | | | | | | | +------------------+-----------------------------------------------------------------------------------------------+ | if | Takes one parameter named `test` containing an `el` script. This script is evaluated and | | | if the result is not empty, zero or false, the content of the `if` tags is inserted in | | | the output. Otherwise, the content is discarded. | | | | | | .. code-block:: xml | | | | | | | | | Hello ${name} | | | | +------------------+-----------------------------------------------------------------------------------------------+ | iterate | Takes two parameters, `collection` which contains an `el` script that evaluates to an array | | | `el::object` and a name in `var`. The content of the `iterate` tag is included for each value | | | of `collection` and `var` will contain the current value. | | | | | | .. code-block:: xml | | | | | |
    | | | | | |
  • ${name}
  • | | |
    | | |
| +------------------+-----------------------------------------------------------------------------------------------+ | for | Takes three parameters. The parameters `begin` and `end` should evaluate to a number. The | | | parameter `var` contains a name that will be used to hold the current value when inserting | | | the content of the `for` tag in each iteration of the for loop between `begin` and `end`. | | | | | | .. code-block:: xml | | | | | | | | | ${i}, | | | | +------------------+-----------------------------------------------------------------------------------------------+ | number | Format the number in the `n` parameter using the `f` format. This is limited to the formats | | | ``'#.##0'`` and ``'#.##0B'`` for now. The first formats an integer value using thousand | | | separators, the second tries to format the integer value in a power of two multiplier | | | (kibi, mebi, etc.) with a suffix of `B`, `M`, `G`, etc. | | | | | | .. code-block:: xml | | | | | | | | | | | | Will output `1K` | +------------------+-----------------------------------------------------------------------------------------------+ | options | This tag will insert multiple =