Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.16...3.29)

PROJECT(HTTPD C)

set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}../vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "toolchain")

INCLUDE(CheckSymbolExists)
INCLUDE(CheckCSourceCompiles)
INCLUDE("build/build-modules-c.cmake")
Expand Down Expand Up @@ -428,7 +430,13 @@ SET(MODULE_LIST
"modules/test/mod_optional_hook_import+O+example optional hook importer"
"modules/test/mod_policy+I+HTTP protocol compliance filters"
)

IF(BUILD_PYHTTPD_MODULES)
LIST(APPEND MODULE_LIST
"test/pyhttpd/mod_aptest/mod_aptest+A+Test module. Useful only for developers and testing purposes."
"test/modules/http1/mod_h1test/mod_h1test+A+Http/1 Test module. Useful only for developers and testing purposes."
"test/modules/http2/mod_h2test/mod_h2test+A+Http/2 Test module. Useful only for developers and testing purposes."
)
ENDIF()
# Track which modules actually built have APIs to link against.
SET(installed_mod_libs_exps)

Expand Down Expand Up @@ -1065,6 +1073,40 @@ INSTALL(TARGETS ${install_targets}
INSTALL(TARGETS ${install_modules}
RUNTIME DESTINATION modules
)
INSTALL(CODE [[
SET(SERVER_ROOT "${CMAKE_INSTALL_PREFIX}")

CONFIGURE_FILE(
"../support/apachectl.bat.in"
"${CMAKE_CURRENT_BINARY_DIR}/support/apachectl.bat"
@ONLY
)
]])
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/support/apachectl.bat"
DESTINATION bin
)

INSTALL(CODE [[
find_package(Git QUIET)

if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} branch --show-current
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()

SET(SERVER_ROOT "${CMAKE_INSTALL_PREFIX}")

CONFIGURE_FILE(
"../test/pyhttpd/config_win.ini.in"
"../test/pyhttpd/config.ini"
@ONLY
)
]])

IF(INSTALL_PDB)
INSTALL(FILES ${install_bin_pdb}
Expand Down
107 changes: 107 additions & 0 deletions build-win.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
@ECHO off
@REM

@REM -------------------------------------
@REM Variables used in this script
@REM -------------------------------------
SET CWD=%CD%
SET "CWD=%CWD:\=/%"
@REM -------------------------------------
SET ARCH="x64-windows"
SET BUILD_TYPE="Debug"
SET VCPKG_DIRECTORY="vcpkg\installed\x64-windows"
SET VCPKG_DIRECTORY_LIB=%VCPKG_DIRECTORY%
SET GENERATOR="NMake Makefiles"
@REM SET GENERATOR="Ninja"
SET CMAKE_VERSION="4.0"
SET HTTPD_INSTALL_DIRECTORY="C:/Users/%USERNAME%/Projects/http-debug/apache"
@REM -------------------------------------

@REM -------------------------------------
@REM Installs via MS vcpkg manager all the
@REM packages needed to build httpd
@REM -------------------------------------
if NOT EXIST vcpkg\ (
echo "Adding...."
git submodule add --force https://github.com/microsoft/vcpkg.git vcpkg
PUSHD vcpkg\
CALL bootstrap-vcpkg.bat
) else (
echo "Updating...."
git submodule update --remote --merge vcpkg/
PUSHD vcpkg\
)

SET VCPKG_ROOT=%CWD%\vcpkg
@REM For some reason using the manifest doesn't install the default-features
vcpkg.exe install --triplet x64-windows apr[private-headers] apr-util pcre2 openssl nghttp2 curl libxml2 jansson

POPD

@REM -------------------------------------
@REM Setup build env using VS build 2022
@REM It maybe installed somewhere else, if so, the path will need updating to find the batch file
@REM -------------------------------------
call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat"

@REM -------------------------------------
@REM Create a temp dir for cmake files
@REM -------------------------------------
if not EXIST build-asf-win\ (
mkdir build-asf-win\
)

PUSHD build-asf-win\

@REM -------------------------------------
@REM Run cmake so that it configures the
@REM and creates the needed makefiles
@REM -------------------------------------
cmake .. -B . ^
-G %GENERATOR% ^
-DCMAKE_BUILD_TYPE=%BUILD_TYPE% ^
-DCMAKE_TOOLCHAIN_FILE=%CWD%/vcpkg/scripts/buildsystems/vcpkg.cmake ^
-DVCPKG_TARGET_TRIPLET=%ARCH% ^
-DNGHTTP2_INCLUDE_DIR=%CWD%/vcpkg/installed/x64-windows/include ^
-DAPR_INCLUDE_DIR=%CWD%/vcpkg/installed/x64-windows/include ^
"-DAPR_LIBRARIES=%CWD%/vcpkg/installed/x64-windows/lib/libapr-1.lib;%CWD%/vcpkg/installed/x64-windows/lib/libaprutil-1.lib" ^
-DNGHTTP2_LIBRARIES=%CWD%/vcpkg/installed/x64-windows/lib/nghttp2.lib ^
-DBUILD_PYHTTPD_MODULES=true ^
-DCMAKE_POLICY_VERSION_MINIMUM=%CMAKE_VERSION% ^
--install-prefix %HTTPD_INSTALL_DIRECTORY%

@REM -------------------------------------
@REM Build httpd
@REM -------------------------------------
cmake --build .

@REM -------------------------------------
@REM Install httpd only
@REM -------------------------------------
cmake --install . --config %BUILD_TYPE%
POPD

@REM -------------------------------------
@REM Copy the dependencies.
@REM -------------------------------------
if %BUILD_TYPE% == "Debug" (
SET VCPKG_DIRECTORY_LIB=%VCPKG_DIRECTORY_LIB%\debug
)

@REM -------------------------------------
@REM Copy the libraries needed to run httpd
@REM -------------------------------------
xcopy %VCPKG_DIRECTORY_LIB%\bin\* %HTTPD_INSTALL_DIRECTORY%\bin /y /f /i

@REM -------------------------------------
@REM Run the pyHttpd tests
@REM -------------------------------------
PUSHD test\
python.exe -m pip install --upgrade pip
python.exe -m venv .venv
call .venv\Scripts\activate
call python.exe -m pip install websockets filelock cryptography pyopenssl python-multipart pebble pytest-html pytest==8.4.2 cffi
call python.exe -m pytest -vvv --ignore="modules/md" --ignore="modules/http2" -k "not test_cgi_003_01 and not test_800_websockets and not test_02_unix and not test_003_get and not test_004_post and not test_002_restarts and not test_005_trailers" --junitxml="reports/pytest-results.xml" --html="reports/Results" --self-contained-html
deactivate

POPD
71 changes: 71 additions & 0 deletions support/apachectl.bat.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
echo off
SETLOCAL EnableDelayedExpansion
set "BIN_INSTALL_DIR=@SERVER_ROOT@/bin"

:: -----------------------------------------------------------------------------
:: Apache Control Script for Windows
:: By Paul Lodge
:: March 2026
:: Version 0.0.1
:: -----------------------------------------------------------------------------

set "APACHE24=Apache2.x"
set "HTTPD=%BIN_INSTALL_DIR%\httpd.exe"
set "ACMD=%~1"

:: Check if a command was provided
if "%ACMD%"=="" goto DEFAULT

:: Switch Logic
if /I "%ACMD%"=="install" goto INSTALL
if /I "%ACMD%"=="uninstall" goto UNINSTALL
if /I "%ACMD%"=="start" goto START
if /I "%ACMD%"=="stop" goto STOP
if /I "%ACMD%"=="restart" goto RESTART
if /I "%ACMD%"=="graceful" goto RESTART
if /I "%ACMD%"=="startssl" goto SSL_ERROR
if /I "%ACMD%"=="sslstart" goto SSL_ERROR
if /I "%ACMD%"=="start-SSL" goto SSL_ERROR
if /I "%ACMD%"=="configtest" goto NOT_SUPPORTED
if /I "%ACMD%"=="status" goto NOT_SUPPORTED
if /I "%ACMD%"=="fullstatus" goto NOT_SUPPORTED

goto DEFAULT

:INSTALL
"%HTTPD%" -k install
goto END

:UNINSTALL
"%HTTPD%" -k uninstall -n %APACHE24%
goto END

:START
net start %APACHE24%
goto END

:STOP
net stop %APACHE24%
goto END

:RESTART
net stop %APACHE24%
net start %APACHE24%
goto END

:SSL_ERROR
echo The startssl option is no longer supported.
echo Please edit httpd.conf to include the SSL configuration settings
echo and then use 'apachectl start'.
goto END

:NOT_SUPPORTED
echo Not supported!
goto END

:DEFAULT
"%HTTPD%" %*
goto END

:END
ENDLOCAL
3 changes: 2 additions & 1 deletion test/modules/core/htdocs/ssi/exec.shtml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
<!--#exec cmd="echo SSI_OK" -->
<!--#set var="SSI" value="SSI_OK" -->
<!--#echo var="SSI" -->
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/bin/sh
echo "Content-Type: text/plain"
echo
echo "OK"
7 changes: 3 additions & 4 deletions test/modules/core/test_002_restarts.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,11 @@ def _rtime(self, s: str) -> timedelta:
delta = d - self._start
return f"{delta.seconds:+02d}.{delta.microseconds:06d}"



@pytest.mark.skipif(condition='STRESS_TEST' not in os.environ,
reason="STRESS_TEST not set in env")
@pytest.mark.skipif(condition=not CoreTestEnv().h2load_is_at_least('1.41.0'),
reason="h2load unavailable or misses --connect-to option")
@pytest.mark.skipif(condition=CoreTestEnv().isWindows or not CoreTestEnv().h2load_is_at_least('1.41.0'),
reason="h2load unavailable or misses --connect-to option")

class TestRestarts:

def test_core_002_01(self, env):
Expand Down
23 changes: 14 additions & 9 deletions test/modules/http1/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,24 @@ def make(self):
self._setup_data_1k_1m()

def _add_h1test(self):
local_dir = os.path.dirname(inspect.getfile(H1TestSetup))
p = subprocess.run([self.env.apxs, '-c', 'mod_h1test.c'],
capture_output=True,
cwd=os.path.join(local_dir, 'mod_h1test'))
rv = p.returncode
if rv != 0:
log.error(f"compiling md_h1test failed: {p.stderr}")
raise Exception(f"compiling md_h1test failed: {p.stderr}")
module_dir = self.env.test_modules_dir
if not self.env.isWindows:
local_dir = os.path.dirname(inspect.getfile(H1TestSetup))
p = subprocess.run([self.env.apxs, '-c', 'mod_h1test.c'],
capture_output=True,
cwd=os.path.join(local_dir, 'mod_h1test'))

rv = p.returncode
if rv != 0:
log.error(f"compiling md_h1test failed: {p.stderr}")
raise Exception(f"compiling md_h1test failed: {p.stderr}")

module_dir = f"{local_dir}/mod_h1test/.libs"

modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf')
with open(modules_conf, 'a') as fd:
# load our test module which is not installed
fd.write(f"LoadModule h1test_module \"{local_dir}/mod_h1test/.libs/mod_h1test.so\"\n")
fd.write(f"LoadModule h1test_module \"{module_dir}/mod_h1test.so\"\n")

def _setup_data_1k_1m(self):
s90 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n"
Expand Down
23 changes: 14 additions & 9 deletions test/modules/http2/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,24 @@ def make(self):
self._setup_data_1k_1m()

def _add_h2test(self):
local_dir = os.path.dirname(inspect.getfile(H2TestSetup))
p = subprocess.run([self.env.apxs, '-c', 'mod_h2test.c'],
capture_output=True,
cwd=os.path.join(local_dir, 'mod_h2test'))
rv = p.returncode
if rv != 0:
log.error(f"compiling md_h2test failed: {p.stderr}")
raise Exception(f"compiling md_h2test failed: {p.stderr}")
module_dir = self.env.test_modules_dir
if not self.env.isWindows:
local_dir = os.path.dirname(inspect.getfile(H2TestSetup))
p = subprocess.run([self.env.apxs, '-c', 'mod_h2test.c'],
capture_output=True,
cwd=os.path.join(local_dir, 'mod_h2test'))

rv = p.returncode
if rv != 0:
log.error(f"compiling md_h2test failed: {p.stderr}")
raise Exception(f"compiling md_h2test failed: {p.stderr}")

module_dir = f"{local_dir}/mod_h2test/.libs"

modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf')
with open(modules_conf, 'a') as fd:
# load our test module which is not installed
fd.write(f"LoadModule h2test_module \"{local_dir}/mod_h2test/.libs/mod_h2test.so\"\n")
fd.write(f"LoadModule h2test_module \"{module_dir}/mod_h2test.so\"\n")

def _setup_data_1k_1m(self):
s90 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n"
Expand Down
Loading