2
0
Fork 0

Compare commits

...

57 Commits

Author SHA1 Message Date
Stefan Bühler 1735f5524f [core] fix GError leak
Change-Id: I581d34880a4a592a6f81c49c21e95c7fb0061db6
2024-02-06 16:52:13 +01:00
Stefan Bühler 2b4e6d3a4d [build] add .github workflow
Change-Id: I8377f42da3d28ae1d2593ac5ab9ba1c1f1d97074
2024-01-13 20:25:34 +01:00
Stefan Bühler d9e4b2e4d7 [tests] try to use shorter socket filenames
Change-Id: I7f59268078f2178910de3425a0b68a8e5113b071
2024-01-13 19:35:30 +01:00
Stefan Bühler 643514a9c7 [core] recent g_module_open handles lib prefix and suffixes better; try that first
Change-Id: Ieecd1234e5cc81a11e43172d4563d43bca6658be
2024-01-13 18:55:49 +01:00
Stefan Bühler 7c2d19ed24 [core] add proper error handling to li_module_load
Change-Id: I4b11b93cee06ea5d983712158b39b5a8542460e4
2024-01-13 18:55:49 +01:00
Stefan Bühler b0ffa8417c [meson] install lua files only if lua was enabled (fixes #3227)
Change-Id: Ie186e2f8742cd3c2a0deb328b246e53db3100a76
2023-10-03 00:04:06 +02:00
Stefan Bühler 14679eedb7 [meson] fix module dependencies (must be a list)
Also only check module dependencies (not main_deps) to determine whether
to enable a module.

Change-Id: Ic5e3ec3189131b3d17cf8b8770ab047726ec6a0c
2023-10-02 18:50:14 +02:00
Stefan Bühler a9725af5f3 [meson] fix building without unwind (optional dependency)
Change-Id: I601232d50cfa1761bfa8aa4cb8e6650c9213547e
2023-10-02 18:39:20 +02:00
Stefan Bühler c673e5b638 [plugin_core] always enforce directory handling of aliases
Example: `alias "/foo" => "/some/dir/";`
* old behavior: would resolve "/foo../" to "/some/dir/../".
* new behavior: prefix doesn't match.

Note: `alias "/foo/" => "/some/dir"`, as shown in the doc examples,
always did the right thing.

Change-Id: Icf506d2f39ee57217799f9c68da74e172c92c09e
2023-09-14 13:33:59 +02:00
Stefan Bühler 7c926c9245 [meson] compiler.has_type requires meson 1.0 to use array for prefix - join manually to support meson 0.61
Change-Id: I0e18a39d7915fd5fafe2846d4908f35965565061
2023-09-14 12:21:22 +02:00
Stefan Bühler f1bf458341 [meson] rename shared libs to what autobuild created
Change-Id: I6f94f6300b7f2fac67cd74fc17151b8ea41dba0f
2023-09-11 20:45:59 +02:00
Stefan Bühler 727ec90417 [autobuild] drop autobuild
Change-Id: I3c0a3e153c85afad469e982a6db39ee5ff6fa0f0
2023-09-11 18:12:55 +02:00
Stefan Bühler 1fffbd1a9e [automake] include meson files
Change-Id: I1eddded1bc72b0299936893fa784a68a993bb279
2023-09-11 17:34:24 +02:00
Stefan Bühler 7f843c75a6 [cmake] drop cmake support - use meson instead
Change-Id: I484cc78c8c5db3da6f30fafecff4384a3b7ff291
2023-09-11 17:20:35 +02:00
Stefan Bühler 232e1837bd [mod_openssl] drop support for openssl1.0 and older (probably includes libressl)
Change-Id: I3d1e807ec09d159344bba0d59b8c48c81539b27e
2023-09-11 17:16:33 +02:00
Stefan Bühler c60df4f141 [mod_openssl] support openssl3 ECDH curve selection
Change-Id: I99f4367c6c01308f0251dcf0011cafc85a39baac
2023-09-11 17:07:02 +02:00
Stefan Bühler ec60ea02fd [mod_openssl] support openssl3 DH parameter loading
Change-Id: I3db0952581b1f50985e0f89d16db27d20af7bdb9
2023-09-11 17:06:56 +02:00
Stefan Bühler 10f54c2d83 [core] don't release mainaction before stopping workers
This reverts commit f2ade38923.

Running workers will try to handle connections, and thus changing
mainaction without locking is a race condition, and also we don't handle
a NULL mainaction properly and segfault.

Given running connections will keep mainaction alive anyway, it is
unclear what the purpose of releasing it early was in the first place.

Change-Id: I2266958520c3cfca28c5c19574abdf44ddf6b0bc
2023-09-08 15:53:41 +02:00
Stefan Bühler dca280076b [angel] improve instance related logging
Change-Id: Ie58d07ae441100299c75aeb657000fdcf828036d
2023-09-08 15:24:51 +02:00
Stefan Bühler 522a9e221b [angel] improve startup/stop logging
Change-Id: I71666d8f37edf1246a58daa880b3fa64316d801f
2023-09-08 15:14:49 +02:00
Stefan Bühler a19d73ecd5 [angel] server_module not shared anymore, drop refcount handling
Change-Id: I65cd3cb1409238537299e0654fb681ab5286b43f
2023-09-08 15:14:49 +02:00
Stefan Bühler 0ced2aa60a [angel] remove config reload handling, don't unload plugins while instance is running
* config reload wasn't actually available; but internal code existed
  trying to handle it:
  * it would load new plugins and unload old plugins
  * state of old plugins might be in use by running instances
* server stop was implemented as "loading empty config" (without core
  plugin)
* NULL-derefs/segfaults on exit when instances tried to access plugin
  data that was already gone

As we only load a single config: drop this completely, and replace
"cleanup pending config" (to handle config reload errors) with "stop"
callback in plugins.

Change-Id: I204441fb9f54e22d2b0d31ed18d0c188fe7150ac
2023-09-08 15:14:49 +02:00
Stefan Bühler b4102fed4c [angel] move plugin core types to implementation
Change-Id: I912934be6e0d20b2c12c17bf7e007198b49bfb0c
2023-09-08 15:14:49 +02:00
Stefan Bühler 87a7339b49 [angel] fix small memory leak from config loading
Change-Id: I2aa174c220543a7bcc011118eaaf4b0925b4aa19
2023-09-08 15:14:45 +02:00
Stefan Bühler 23164d557f [mod_progress] accept any 2xx status codes as success (fixes #2357)
Change-Id: I0d6b8b53679316a3df5f439e55e664f8127c4f6f
2023-07-23 02:03:44 +02:00
Stefan Bühler 184efd18f7 [doc] fix typo in email address
Change-Id: Idf435b3fc1d632fc14ae61bc0371e03ab3661f80
2023-07-16 19:02:50 +02:00
Stefan Bühler bb473ed334 [mimetypes.conf] adding new mimetypes
Change-Id: Ib4becbcb6989866b1b1eb610571ca783bc7e7448
2023-07-13 01:37:30 +02:00
Stefan Bühler 3a34f793cd [mimetypes.conf] dropping some mimetypes
Change-Id: I6311bc1ba72bf6c3f09788a2c4d850270184d3de
2023-07-13 01:37:24 +02:00
Stefan Bühler b9efcc316e [mimetypes.conf] changing various mimetypes (text/javascript and others)
Change-Id: I8ad45572a911933328d36f98d4aff2abbca60cba
2023-07-13 01:36:23 +02:00
Stefan Bühler 698c1a54ef [doc] update my email address
Change-Id: If05298c4d7779000d800710e06134fc65b395db6
2023-07-13 01:00:01 +02:00
Stefan Bühler 6d7d0b784c [doc] convert http:// to https:// links if valid
Change-Id: I07cd924121f00e9682071cbfcc2c135b22428a41
2023-07-13 00:59:18 +02:00
Stefan Bühler 29d4a1543d [doc] convert from textile to markdown; don't allow simple text in section/description anymore
Change-Id: Ic6ee47465b934ba00cb92f2ab68a3a9d6ff01235
2023-07-13 00:14:37 +02:00
Stefan Bühler 7472bb4b18 [tests] fix cleanup if prepare fails
Change-Id: I6a7a8b2f3b0573256cc3ce12cfaf6355dd958c80
2023-07-12 17:00:07 +02:00
Stefan Bühler 69ca252e48 [tests] chmod -x tests/pylt/run.py
Change-Id: I2850413df92643066eda4e87635883484593853a
2023-07-12 16:58:35 +02:00
Stefan Bühler 77f9f06c2a [tests] disable non-prefix crypt auth (deprecated, not available on all platforms)
Change-Id: I6918c2041737ca228b16b776030f03eff2f9cf23
2023-07-12 16:56:21 +02:00
Stefan Bühler dd17dcc380 [crypt] some crypt[_r] implementations return NULL instead of a failure token; li_safe_crypt returns FALSE in that case (and clears the buffer)
Change-Id: I74f78b522333023b5d0bfd052ae137895b4b8e2f
2023-07-12 15:51:39 +02:00
Stefan Bühler 52b19412af fix glib g_string_append_len usage (broken with GSTR_LEN macro)
Change-Id: I6e3ba995b6b094f16f49957cf5d1d03099255a61
2023-07-11 00:27:47 +02:00
Stefan Bühler 0c3ee6741d [build] add meson support
drop HAVE_CONFIG_H - we always want #include <lighttpd/config.h> to
work, and HAVE_CONFIG_H is a too generic name anyway.

Change-Id: Ie8dba7dfd82308bd8fc68e36bce6d2584b7a9d96
2023-01-15 19:46:56 +01:00
Stefan Bühler 10586541b5 [tests] remove concept of feature_check - always test everything
Change-Id: Id2d0878263f41e38c2ce4ee57ac34f8f7724c71a
2023-01-15 12:14:15 +01:00
Stefan Bühler c691084b48 [tests] use local fcgi-cgi written in python
Change-Id: I305d1e67d7799d8edd3f9d4516c7412ba4c7db1b
2023-01-15 12:12:37 +01:00
Stefan Bühler 24025686d4 [core] stream plug should forward "abort" to dest (source disconnect before closing)
Change-Id: I7c5691c1aa720ebf66987be0d02919103b4106e3
2023-01-08 14:29:17 +01:00
Stefan Bühler 0ff166282f [core] stream plug should stop when source disconnects too
Change-Id: Iedf508275ab39ac5b98dfe3a76873140a0dfa333
2023-01-08 01:25:37 +01:00
Stefan Bühler 56aae45f6d [mod_debug] support repeating output of pending events on stop
Change-Id: I6f4d79323e53d2e2084a0db9fa4dda6e4acd2e10
2023-01-07 19:54:11 +01:00
Stefan Bühler 42d554bd3e [angel] fix use-after-free of cached listening sockets
On stop the cached listenings sockets were freed through the hashtable;
but they are actually refcounted, and the hashtable only has a "weak"
reference (which gets cleared once all strong references are dropped).

Change-Id: I5f9c14f1c1e28f3a2b73955e69e36e1f9dae5780
2023-01-07 15:49:46 +01:00
Stefan Bühler 6791ccbaec [angel] fix handling of notifications on worker stop
* fix handling of "simple calls" (notifications)
  when plugin/action can't be found (must not send
  an error response, as id == -1)
* server stop clears all plugins; don't log error in
  that stage

Change-Id: If5167a3bd6d069c4cfc6dad13e205ce18b724509
2023-01-07 15:49:46 +01:00
Stefan Bühler 87e125bffa [tests] package moved python files
Change-Id: I0dbb2248b6001f47c5284edb26e5a38d33326b23
2023-01-07 13:59:00 +01:00
Stefan Bühler cbcc2e48a9 [core] use union of sockaddr_* pointers instead of pointer to storage union
We didn't allocate the full storage, which the compiler complained
about.
Keep using a storage type when we actually allocate / use the full
type.

Change-Id: I25dba8af09f772852eabbd113f101c200491e44b
2023-01-07 13:38:08 +01:00
Stefan Bühler 5a02032485 [tests] refactor python tests
* try to adapt a more modern python style
* add flake8 linting and mypy type checking
  * add many type hints
  * dataclasses
  * various refactorings to make proper type hints possible
* use f-strings for formatting instead of `%` and `.format`
* get rid of `Env` global; pass it explicitly or use a ContextVar
* use metaclass to automatically register test cases

Change-Id: I19d6223157b769cb6491c032d3ec9eb2cd70ef44
2023-01-06 20:25:34 +01:00
Stefan Bühler a5e8c80bf8 [tests] reorganize python tests
Change-Id: I7127b0e1cd16f713bca7310c04bd049aa2f74570
2023-01-05 14:00:23 +01:00
Stefan Bühler f046f4fac1 [core] improve comments
Change-Id: If1d107d3a2534197be213246c7b3e4d5e7af6de8
2023-01-05 12:52:27 +00:00
Stefan Bühler a615411747 fix spelling
Taken from https://github.com/lighttpd/lighttpd2/pull/12 by Josh Soref

Change-Id: I28ebf617e6fd4ae71671130af622f56f055bb578
2023-01-05 12:52:13 +00:00
Stefan Bühler b96d2495f4 [core] remove HEDLEY_FALL_THROUGH from empty case
Change-Id: Ie406c9719ce24f85c9220ee9b1fa0775ec986c04
2023-01-05 12:48:52 +00:00
Stefan Bühler 2879d7ccc2 [tests] use raw tcp for bad url request test
curl doesn't allow urls with spaces anymore (which is a good thing)

Change-Id: Id735a6e5d37a19a5ad4efc46830f8ec63a427415
2023-01-05 12:39:36 +00:00
Stefan Bühler 29e57d3005 [core] re-enable listening sockets
make sure to check once a second whether we can re-enable the listening
sockets.

Change-Id: Ib9844c183de2b8a8bd00bafebdca348b88f71314
2021-09-15 12:19:01 +02:00
Stefan Bühler 2ae359b04a [doc] fix ino/dev field in lua stat, add lighty.path_simplify to global methods
Change-Id: I76ad8233d0ea1a934d0812c9a8c93fa97317344d
2021-08-12 17:12:04 +02:00
Stefan Bühler f25bc4106f [core] fix li_path_simplify comment: always operating in-place
Change-Id: Idb657f798516b0d2ed53fb0b2cfecbcbbe801c00
2021-08-12 17:11:28 +02:00
Stefan Bühler ad66680e62 [core] put HEDLEY_NO_RETURN at front of declaration
Change-Id: I5fa705453e33567df6ab75b5fe3eb6ae2221895b
2021-08-08 16:26:52 +02:00
244 changed files with 7692 additions and 8146 deletions

8
.flake8 Normal file
View File

@ -0,0 +1,8 @@
[flake8]
# E266 too many leading '#' for block comment [ I like marking disabled code blocks with '### ' ]
# E402 module level import not at top of file [ usually on purpose. might use individual overrides instead? ]
# E713 test for membership should be not in [ disagree: want `not a in x` ]
# E714 test for object identity should be 'is not' [ disagree: want `not a is x` ]
# W503 line break before binary operator [ gotta pick one way ]
extend-ignore = E266,E402,E713,E714,W503
max-line-length = 120

50
.github/workflows/ci-alpine.yml vendored Normal file
View File

@ -0,0 +1,50 @@
name: "Checks (alpine, many platforms)"
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
jobs:
linux-alpine:
runs-on: ubuntu-latest
name: linux-alpine-${{ matrix.platform }}
# abort if x86_64 fails
continue-on-error: ${{ matrix.platform != 'x86_64' }}
strategy:
fail-fast: true
matrix:
platform: ['x86_64','x86','armhf','armv7','aarch64','ppc64le','riscv64','s390x']
steps:
- uses: actions/checkout@v4
- uses: jirutka/setup-alpine@v1
with:
# riscv64 currently requires 'edge'
branch: edge
arch: ${{ matrix.platform }}
packages: >
build-base
meson
libev-dev
ragel
glib-dev
lua5.1-dev
zlib-dev
bzip2-dev
pkgconf
openssl-dev
gnutls-dev
libidn-dev
libunwind-dev
python3
py3-curl
- name: meson setup
shell: alpine.sh {0}
run: meson setup mesonbuilddir
- name: meson compile
shell: alpine.sh {0}
run: meson compile -C mesonbuilddir
- name: meson test
shell: alpine.sh {0}
run: meson test -C mesonbuilddir -v

67
.github/workflows/ci-linux.yml vendored Normal file
View File

@ -0,0 +1,67 @@
name: "Checks (Ubuntu: gcc+clang)"
on: [push, pull_request]
concurrency:
group: ${{github.workflow}}-${{github.head_ref}}
cancel-in-progress: true
jobs:
linux-build-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
pkgs=(
ruby
ruby-nokogiri
ruby-kramdown
libxml2-utils
)
sudo apt-get install "${pkgs[@]}"
- name: Build docs
run: |
mkdir -p out
ruby doc/compile.rb out
cp doc/*.css doc/*.js out
- uses: actions/upload-artifact@v4
with:
name: lighttpd2-docs
path: out
linux-ubuntu:
runs-on: ubuntu-latest
name: linux-ubuntu-${{ matrix.compiler }}
strategy:
matrix:
compiler: ['gcc', 'clang']
steps:
- uses: actions/checkout@v4
- if: ${{ matrix.compiler == 'clang' }}
uses: egor-tensin/setup-clang@v1
- name: Install dependencies
run: |
pkgs=(
meson
libev-dev
ragel
libglib2.0-dev
liblua5.1-dev
zlib1g-dev
libbz2-dev
pkg-config
libssl-dev
libgnutls28-dev
libidn-dev
libunwind8-dev
python3
python3-pycurl
)
sudo apt-get install "${pkgs[@]}"
- name: meson setup
run: meson setup mesonbuilddir
- name: meson compile
run: meson compile -C mesonbuilddir
- name: meson test
run: meson test -C mesonbuilddir -v

52
.github/workflows/ci-macos.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: "Checks (macOS)"
on: [push, pull_request]
concurrency:
group: ${{github.workflow}}-${{github.head_ref}}
cancel-in-progress: true
jobs:
macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
pkgs=(
meson
libev
ragel
glib
lua@5.1
zlib
bzip2
openssl@3
gnutls
libidn
python3
python-pycurl
md5sha1sum
)
brew install "${pkgs[@]}"
- name: meson setup
run: meson setup -D unwind=false mesonbuilddir
- name: meson compile
run: meson compile -C mesonbuilddir
- name: prepare environment for tests
run: |
sudo ifconfig lo0 alias 127.0.0.2 up
# try to create a tmpdir with a short relative path (for shorter unix socket paths)
NEWTMPDIR=~/tmp
ln -sf "${TMPDIR}" "${NEWTMPDIR}"
echo "TMPDIR=$NEWTMPDIR" >> "$GITHUB_ENV"
echo "PATH=$(brew --prefix python)/libexec/bin:$PATH" >> "$GITHUB_ENV"
if [ ! -f $(brew --prefix python)/libexec/bin/python3 ]; then
# the brew path only provides "python", not "python3"...
ln -s python $(brew --prefix python)/libexec/bin/python3
fi
- name: meson test
run: |
meson test -C mesonbuilddir -v

18
.gitignore vendored
View File

@ -1,17 +1,3 @@
*build/
autom4te.cache/
m4/
Makefile.in
aclocal.m4
ar-lib
compile
config.guess
config.sub
configure
depcomp
include/lighttpd/config.h.in
include/lighttpd/config.h.in~
install-sh
ltmain.sh
missing
CMakeLists.txt.user
.vscode
.mypy_cache

View File

@ -1,14 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0 FATAL_ERROR)
PROJECT(lighttpd C)
SET(PACKAGE_NAME ${CMAKE_PROJECT_NAME})
SET(PACKAGE_VERSION 2.0.0)
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
#INCLUDE(CTest)
ENABLE_TESTING()
ADD_SUBDIRECTORY(src build)
add_subdirectory(tests)

View File

@ -29,7 +29,7 @@ THE SOFTWARE.
The doc/ directory contains some assets by 3rd parties:
From doc/bootstrap* (Apache License 2.0):
Copyright 2013 Twitter, Inc.
Licensed under http://www.apache.org/licenses/LICENSE-2.0
Licensed under https://www.apache.org/licenses/LICENSE-2.0
From doc/jquery-1.10.1.min.js (MIT License):
(c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license

View File

@ -1,6 +0,0 @@
SUBDIRS=contrib doc src include tests
ACLOCAL_AMFLAGS=-I m4
EXTRA_DIST=autogen.sh CMakeLists.txt cmake build-helpers
DISTCHECK_CONFIGURE_FLAGS=--with-lua --with-openssl --with-kerberos5 --with-gnutls --with-zlib --with-bzip2

View File

@ -1,14 +0,0 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
set -e
if [ ! -f configure.ac -o ! -f COPYING ]; then
echo "Doesn't look like you're in the source directory" >&2
exit 1
fi
# old autoreconf/aclocal versions fail hard if m4 doesn't exist
mkdir -p m4
autoreconf --force --install
echo "Now type './configure ...' and 'make' to compile."

View File

@ -1,136 +0,0 @@
# GLIB - Library of useful C routines
AM_TESTS_ENVIRONMENT= \
G_TEST_SRCDIR="$(abs_srcdir)" \
G_TEST_BUILDDIR="$(abs_builddir)" \
G_DEBUG=gc-friendly \
MALLOC_CHECK_=2 \
MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256))
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/build-helpers/tap-driver.sh
LOG_COMPILER = $(top_srcdir)/build-helpers/tap-test
NULL =
# initialize variables for unconditional += appending
BUILT_SOURCES =
BUILT_EXTRA_DIST =
CLEANFILES = *.log *.trs
DISTCLEANFILES =
MAINTAINERCLEANFILES =
EXTRA_DIST =
TESTS =
installed_test_LTLIBRARIES =
installed_test_PROGRAMS =
installed_test_SCRIPTS =
nobase_installed_test_DATA =
noinst_LTLIBRARIES =
noinst_PROGRAMS =
noinst_SCRIPTS =
noinst_DATA =
check_LTLIBRARIES =
check_PROGRAMS =
check_SCRIPTS =
check_DATA =
# We support a fairly large range of possible variables. It is expected that all types of files in a test suite
# will belong in exactly one of the following variables.
#
# First, we support the usual automake suffixes, but in lowercase, with the customary meaning:
#
# test_programs, test_scripts, test_data, test_ltlibraries
#
# The above are used to list files that are involved in both uninstalled and installed testing. The
# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite.
# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is
# installed in the same way as it appears in the package layout.
#
# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled',
# like so:
#
# installed_test_programs, uninstalled_test_programs
# installed_test_scripts, uninstalled_test_scripts
# installed_test_data, uninstalled_test_data
# installed_test_ltlibraries, uninstalled_test_ltlibraries
#
# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts
# that should not themselves be run as testcases (but exist to be used from other testcases):
#
# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs
# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts
#
# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data
# file automatically end up in the tarball.
#
# dist_test_scripts, dist_test_data, dist_test_extra_scripts
# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts
# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts
#
# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the
# standard automake convention of not disting programs scripts or data by default.
#
# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted
# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under
# gtester. That's a bit strange for scripts, but it's possible.
TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \
$(dist_test_scripts) $(dist_uninstalled_test_scripts)
# Note: build even the installed-only targets during 'make check' to ensure that they still work.
# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to
# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were
# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'.
all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \
$(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs)
all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \
$(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts)
all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \
$(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts)
all_test_scripts += $(all_dist_test_scripts)
EXTRA_DIST += $(all_dist_test_scripts)
all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data)
all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data)
all_test_data += $(all_dist_test_data)
EXTRA_DIST += $(all_dist_test_data)
all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries)
if ENABLE_ALWAYS_BUILD_TESTS
noinst_LTLIBRARIES += $(all_test_ltlibs)
noinst_PROGRAMS += $(all_test_programs)
noinst_SCRIPTS += $(all_test_scripts)
noinst_DATA += $(all_test_data)
else
check_LTLIBRARIES += $(all_test_ltlibs)
check_PROGRAMS += $(all_test_programs)
check_SCRIPTS += $(all_test_scripts)
check_DATA += $(all_test_data)
endif
if ENABLE_INSTALLED_TESTS
installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \
$(test_extra_programs) $(installed_test_extra_programs)
installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \
$(test_extra_scripts) $(installed_test_extra_scripts)
installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \
$(dist_installed_test_scripts) $(dist_installed_test_extra_scripts)
nobase_installed_test_DATA += $(test_data) $(installed_test_data)
nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data)
installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries)
installed_testcases = $(test_programs) $(installed_test_programs) \
$(test_scripts) $(installed_test_scripts) \
$(dist_test_scripts) $(dist_installed_test_scripts)
installed_test_meta_DATA = $(installed_testcases:=.test)
%.test: %$(EXEEXT) Makefile
$(AM_V_GEN) ($(MKDIR_P) $(@D); \
echo '[Test]' > $@.tmp; \
echo 'Type=session' >> $@.tmp; \
echo 'Exec=$(installed_testdir)/$(notdir $<) --tap' >> $@.tmp; \
echo 'Output=TAP' >> $@.tmp; \
mv $@.tmp $@)
CLEANFILES += $(installed_test_meta_DATA)
endif

View File

@ -1,31 +0,0 @@
# Increment this whenever this file is changed.
#serial 1
dnl GLIB_TESTS
dnl
AC_DEFUN([GLIB_TESTS],
[
AC_ARG_ENABLE(installed-tests,
AS_HELP_STRING([--enable-installed-tests],
[Enable installation of some test cases]),
[case ${enableval} in
yes) ENABLE_INSTALLED_TESTS="1" ;;
no) ENABLE_INSTALLED_TESTS="" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;;
esac])
AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1")
AC_ARG_ENABLE(always-build-tests,
AS_HELP_STRING([--enable-always-build-tests],
[Enable always building tests during 'make all']),
[case ${enableval} in
yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;;
no) ENABLE_ALWAYS_BUILD_TESTS="" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;;
esac])
AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1")
if test "$ENABLE_INSTALLED_TESTS" = "1"; then
AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME)
AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME)
fi
])

View File

@ -1,652 +0,0 @@
#! /bin/sh
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
scriptversion=2011-12-27.17; # UTC
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
me=tap-driver.sh
fatal ()
{
echo "$me: fatal: $*" >&2
exit 1
}
usage_error ()
{
echo "$me: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
tap-driver.sh --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--ignore-exit]
[--diagnostic-string=STRING] [--merge|--no-merge]
[--comments|--no-comments] [--] TEST-COMMAND
The \`--test-name', \`--log-file' and \`--trs-file' options are mandatory.
END
}
# TODO: better error handling in option parsing (in particular, ensure
# TODO: $log_file, $trs_file and $test_name are defined).
test_name= # Used for reporting.
log_file= # Where to save the result and output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=0
color_tests=0
merge=0
ignore_exit=0
comments=0
diag_string='#'
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "$me $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) shift;; # No-op.
--merge) merge=1;;
--no-merge) merge=0;;
--ignore-exit) ignore_exit=1;;
--comments) comments=1;;
--no-comments) comments=0;;
--diagnostic-string) diag_string=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
esac
shift
done
test $# -gt 0 || usage_error "missing test command"
case $expect_failure in
yes) expect_failure=1;;
*) expect_failure=0;;
esac
if test $color_tests = yes; then
init_colors='
color_map["red"]="" # Red.
color_map["grn"]="" # Green.
color_map["lgn"]="" # Light green.
color_map["blu"]="" # Blue.
color_map["mgn"]="" # Magenta.
color_map["std"]="" # No color.
color_for_result["ERROR"] = "mgn"
color_for_result["PASS"] = "grn"
color_for_result["XPASS"] = "red"
color_for_result["FAIL"] = "red"
color_for_result["XFAIL"] = "lgn"
color_for_result["SKIP"] = "blu"'
else
init_colors=''
fi
# :; is there to work around a bug in bash 3.2 (and earlier) which
# does not always set '$?' properly on redirection failure.
# See the Autoconf manual for more details.
:;{
(
# Ignore common signals (in this subshell only!), to avoid potential
# problems with Korn shells. Some Korn shells are known to propagate
# to themselves signals that have killed a child process they were
# waiting for; this is done at least for SIGINT (and usually only for
# it, in truth). Without the `trap' below, such a behaviour could
# cause a premature exit in the current subshell, e.g., in case the
# test command it runs gets terminated by a SIGINT. Thus, the awk
# script we are piping into would never seen the exit status it
# expects on its last input line (which is displayed below by the
# last `echo $?' statement), and would thus die reporting an internal
# error.
# For more information, see the Autoconf manual and the threads:
# <http://lists.gnu.org/archive/html/bug-autoconf/2011-09/msg00004.html>
# <http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/004121.html>
trap : 1 3 2 13 15
if test $merge -gt 0; then
exec 2>&1
else
exec 2>&3
fi
"$@"
echo $?
) | LC_ALL=C ${AM_TAP_AWK-awk} \
-v me="$me" \
-v test_script_name="$test_name" \
-v log_file="$log_file" \
-v trs_file="$trs_file" \
-v expect_failure="$expect_failure" \
-v merge="$merge" \
-v ignore_exit="$ignore_exit" \
-v comments="$comments" \
-v diag_string="$diag_string" \
'
# FIXME: the usages of "cat >&3" below could be optimized when using
# FIXME: GNU awk, and/or on systems that supports /dev/fd/.
# Implementation note: in what follows, `result_obj` will be an
# associative array that (partly) simulates a TAP result object
# from the `TAP::Parser` perl module.
## ----------- ##
## FUNCTIONS ##
## ----------- ##
function fatal(msg)
{
print me ": " msg | "cat >&2"
exit 1
}
function abort(where)
{
fatal("internal error " where)
}
# Convert a boolean to a "yes"/"no" string.
function yn(bool)
{
return bool ? "yes" : "no";
}
function add_test_result(result)
{
if (!test_results_index)
test_results_index = 0
test_results_list[test_results_index] = result
test_results_index += 1
test_results_seen[result] = 1;
}
# Whether the test script should be re-run by "make recheck".
function must_recheck()
{
for (k in test_results_seen)
if (k != "XFAIL" && k != "PASS" && k != "SKIP")
return 1
return 0
}
# Whether the content of the log file associated to this test should
# be copied into the "global" test-suite.log.
function copy_in_global_log()
{
for (k in test_results_seen)
if (k != "PASS")
return 1
return 0
}
# FIXME: this can certainly be improved ...
function get_global_test_result()
{
if ("ERROR" in test_results_seen)
return "ERROR"
if ("FAIL" in test_results_seen || "XPASS" in test_results_seen)
return "FAIL"
all_skipped = 1
for (k in test_results_seen)
if (k != "SKIP")
all_skipped = 0
if (all_skipped)
return "SKIP"
return "PASS";
}
function stringify_result_obj(result_obj)
{
if (result_obj["is_unplanned"] || result_obj["number"] != testno)
return "ERROR"
if (plan_seen == LATE_PLAN)
return "ERROR"
if (result_obj["directive"] == "TODO")
return result_obj["is_ok"] ? "XPASS" : "XFAIL"
if (result_obj["directive"] == "SKIP")
return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL;
if (length(result_obj["directive"]))
abort("in function stringify_result_obj()")
return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL
}
function decorate_result(result)
{
color_name = color_for_result[result]
if (color_name)
return color_map[color_name] "" result "" color_map["std"]
# If we are not using colorized output, or if we do not know how
# to colorize the given result, we should return it unchanged.
return result
}
function report(result, details)
{
if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/)
{
msg = ": " test_script_name
add_test_result(result)
}
else if (result == "#")
{
msg = " " test_script_name ":"
}
else
{
abort("in function report()")
}
if (length(details))
msg = msg " " details
# Output on console might be colorized.
print decorate_result(result) msg
# Log the result in the log file too, to help debugging (this is
# especially true when said result is a TAP error or "Bail out!").
print result msg | "cat >&3";
}
function testsuite_error(error_message)
{
report("ERROR", "- " error_message)
}
function handle_tap_result()
{
details = result_obj["number"];
if (length(result_obj["description"]))
details = details " " result_obj["description"]
if (plan_seen == LATE_PLAN)
{
details = details " # AFTER LATE PLAN";
}
else if (result_obj["is_unplanned"])
{
details = details " # UNPLANNED";
}
else if (result_obj["number"] != testno)
{
details = sprintf("%s # OUT-OF-ORDER (expecting %d)",
details, testno);
}
else if (result_obj["directive"])
{
details = details " # " result_obj["directive"];
if (length(result_obj["explanation"]))
details = details " " result_obj["explanation"]
}
report(stringify_result_obj(result_obj), details)
}
# `skip_reason` should be empty whenever planned > 0.
function handle_tap_plan(planned, skip_reason)
{
planned += 0 # Avoid getting confused if, say, `planned` is "00"
if (length(skip_reason) && planned > 0)
abort("in function handle_tap_plan()")
if (plan_seen)
{
# Error, only one plan per stream is acceptable.
testsuite_error("multiple test plans")
return;
}
planned_tests = planned
# The TAP plan can come before or after *all* the TAP results; we speak
# respectively of an "early" or a "late" plan. If we see the plan line
# after at least one TAP result has been seen, assume we have a late
# plan; in this case, any further test result seen after the plan will
# be flagged as an error.
plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN)
# If testno > 0, we have an error ("too many tests run") that will be
# automatically dealt with later, so do not worry about it here. If
# $plan_seen is true, we have an error due to a repeated plan, and that
# has already been dealt with above. Otherwise, we have a valid "plan
# with SKIP" specification, and should report it as a particular kind
# of SKIP result.
if (planned == 0 && testno == 0)
{
if (length(skip_reason))
skip_reason = "- " skip_reason;
report("SKIP", skip_reason);
}
}
function extract_tap_comment(line)
{
if (index(line, diag_string) == 1)
{
# Strip leading `diag_string` from `line`.
line = substr(line, length(diag_string) + 1)
# And strip any leading and trailing whitespace left.
sub("^[ \t]*", "", line)
sub("[ \t]*$", "", line)
# Return what is left (if any).
return line;
}
return "";
}
# When this function is called, we know that line is a TAP result line,
# so that it matches the (perl) RE "^(not )?ok\b".
function setup_result_obj(line)
{
# Get the result, and remove it from the line.
result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0)
sub("^(not )?ok[ \t]*", "", line)
# If the result has an explicit number, get it and strip it; otherwise,
# automatically assing the next progresive number to it.
if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/)
{
match(line, "^[0-9]+")
# The final `+ 0` is to normalize numbers with leading zeros.
result_obj["number"] = substr(line, 1, RLENGTH) + 0
line = substr(line, RLENGTH + 1)
}
else
{
result_obj["number"] = testno
}
if (plan_seen == LATE_PLAN)
# No further test results are acceptable after a "late" TAP plan
# has been seen.
result_obj["is_unplanned"] = 1
else if (plan_seen && testno > planned_tests)
result_obj["is_unplanned"] = 1
else
result_obj["is_unplanned"] = 0
# Strip trailing and leading whitespace.
sub("^[ \t]*", "", line)
sub("[ \t]*$", "", line)
# This will have to be corrected if we have a "TODO"/"SKIP" directive.
result_obj["description"] = line
result_obj["directive"] = ""
result_obj["explanation"] = ""
if (index(line, "#") == 0)
return # No possible directive, nothing more to do.
# Directives are case-insensitive.
rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*"
# See whether we have the directive, and if yes, where.
pos = match(line, rx "$")
if (!pos)
pos = match(line, rx "[^a-zA-Z0-9_]")
# If there was no TAP directive, we have nothing more to do.
if (!pos)
return
# Let`s now see if the TAP directive has been escaped. For example:
# escaped: ok \# SKIP
# not escaped: ok \\# SKIP
# escaped: ok \\\\\# SKIP
# not escaped: ok \ # SKIP
if (substr(line, pos, 1) == "#")
{
bslash_count = 0
for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--)
bslash_count += 1
if (bslash_count % 2)
return # Directive was escaped.
}
# Strip the directive and its explanation (if any) from the test
# description.
result_obj["description"] = substr(line, 1, pos - 1)
# Now remove the test description from the line, that has been dealt
# with already.
line = substr(line, pos)
# Strip the directive, and save its value (normalized to upper case).
sub("^[ \t]*#[ \t]*", "", line)
result_obj["directive"] = toupper(substr(line, 1, 4))
line = substr(line, 5)
# Now get the explanation for the directive (if any), with leading
# and trailing whitespace removed.
sub("^[ \t]*", "", line)
sub("[ \t]*$", "", line)
result_obj["explanation"] = line
}
function get_test_exit_message(status)
{
if (status == 0)
return ""
if (status !~ /^[1-9][0-9]*$/)
abort("getting exit status")
if (status < 127)
exit_details = ""
else if (status == 127)
exit_details = " (command not found?)"
else if (status >= 128 && status <= 255)
exit_details = sprintf(" (terminated by signal %d?)", status - 128)
else if (status > 256 && status <= 384)
# We used to report an "abnormal termination" here, but some Korn
# shells, when a child process die due to signal number n, can leave
# in $? an exit status of 256+n instead of the more standard 128+n.
# Apparently, both behaviours are allowed by POSIX (2008), so be
# prepared to handle them both. See also Austing Group report ID
# 0000051 <http://www.austingroupbugs.net/view.php?id=51>
exit_details = sprintf(" (terminated by signal %d?)", status - 256)
else
# Never seen in practice.
exit_details = " (abnormal termination)"
return sprintf("exited with status %d%s", status, exit_details)
}
function write_test_results()
{
print ":global-test-result: " get_global_test_result() > trs_file
print ":recheck: " yn(must_recheck()) > trs_file
print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file
for (i = 0; i < test_results_index; i += 1)
print ":test-result: " test_results_list[i] > trs_file
close(trs_file);
}
BEGIN {
## ------- ##
## SETUP ##
## ------- ##
'"$init_colors"'
# Properly initialized once the TAP plan is seen.
planned_tests = 0
COOKED_PASS = expect_failure ? "XPASS": "PASS";
COOKED_FAIL = expect_failure ? "XFAIL": "FAIL";
# Enumeration-like constants to remember which kind of plan (if any)
# has been seen. It is important that NO_PLAN evaluates "false" as
# a boolean.
NO_PLAN = 0
EARLY_PLAN = 1
LATE_PLAN = 2
testno = 0 # Number of test results seen so far.
bailed_out = 0 # Whether a "Bail out!" directive has been seen.
# Whether the TAP plan has been seen or not, and if yes, which kind
# it is ("early" is seen before any test result, "late" otherwise).
plan_seen = NO_PLAN
## --------- ##
## PARSING ##
## --------- ##
is_first_read = 1
while (1)
{
# Involutions required so that we are able to read the exit status
# from the last input line.
st = getline
if (st < 0) # I/O error.
fatal("I/O error while reading from input stream")
else if (st == 0) # End-of-input
{
if (is_first_read)
abort("in input loop: only one input line")
break
}
if (is_first_read)
{
is_first_read = 0
nextline = $0
continue
}
else
{
curline = nextline
nextline = $0
$0 = curline
}
# Copy any input line verbatim into the log file.
print | "cat >&3"
# Parsing of TAP input should stop after a "Bail out!" directive.
if (bailed_out)
continue
# TAP test result.
if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/)
{
testno += 1
setup_result_obj($0)
handle_tap_result()
}
# TAP plan (normal or "SKIP" without explanation).
else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/)
{
# The next two lines will put the number of planned tests in $0.
sub("^1\\.\\.", "")
sub("[^0-9]*$", "")
handle_tap_plan($0, "")
continue
}
# TAP "SKIP" plan, with an explanation.
else if ($0 ~ /^1\.\.0+[ \t]*#/)
{
# The next lines will put the skip explanation in $0, stripping
# any leading and trailing whitespace. This is a little more
# tricky in truth, since we want to also strip a potential leading
# "SKIP" string from the message.
sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "")
sub("[ \t]*$", "");
handle_tap_plan(0, $0)
}
# "Bail out!" magic.
# Older versions of prove and TAP::Harness (e.g., 3.17) did not
# recognize a "Bail out!" directive when preceded by leading
# whitespace, but more modern versions (e.g., 3.23) do. So we
# emulate the latter, "more modern" behaviour.
else if ($0 ~ /^[ \t]*Bail out!/)
{
bailed_out = 1
# Get the bailout message (if any), with leading and trailing
# whitespace stripped. The message remains stored in `$0`.
sub("^[ \t]*Bail out![ \t]*", "");
sub("[ \t]*$", "");
# Format the error message for the
bailout_message = "Bail out!"
if (length($0))
bailout_message = bailout_message " " $0
testsuite_error(bailout_message)
}
# Maybe we have too look for dianogtic comments too.
else if (comments != 0)
{
comment = extract_tap_comment($0);
if (length(comment))
report("#", comment);
}
}
## -------- ##
## FINISH ##
## -------- ##
# A "Bail out!" directive should cause us to ignore any following TAP
# error, as well as a non-zero exit status from the TAP producer.
if (!bailed_out)
{
if (!plan_seen)
{
testsuite_error("missing test plan")
}
else if (planned_tests != testno)
{
bad_amount = testno > planned_tests ? "many" : "few"
testsuite_error(sprintf("too %s tests run (expected %d, got %d)",
bad_amount, planned_tests, testno))
}
if (!ignore_exit)
{
# Fetch exit status from the last line.
exit_message = get_test_exit_message(nextline)
if (exit_message)
testsuite_error(exit_message)
}
}
write_test_results()
exit 0
} # End of "BEGIN" block.
'
# TODO: document that we consume the file descriptor 3 :-(
} 3>"$log_file"
test $? -eq 0 || fatal "I/O or internal error"
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,5 +0,0 @@
#! /bin/sh
# run a GTest in tap mode. The test binary is passed as $1
$1 -k --tap

View File

@ -1,75 +0,0 @@
SET(LIBEV_PATH "" CACHE PATH "Base path for include/ev.h and lib/libev*")
SET(LIBEV_INCLUDE_PATH "" CACHE PATH "Include path for ev.h")
SET(LIBEV_LIBDIR "" CACHE PATH "Path containing libev")
IF(LIBEV_PATH)
SET(LIBEV_INCLUDE_PATH "${LIBEV_PATH}/include" CACHE PATH "Include path for ev.h" FORCE)
SET(LIBEV_LIBDIR "${LIBEV_PATH}/lib" CACHE PATH "Path containing libev" FORCE)
ENDIF(LIBEV_PATH)
IF(LIBEV_INCLUDE_PATH)
INCLUDE_DIRECTORIES(${LIBEV_INCLUDE_PATH})
ENDIF(LIBEV_INCLUDE_PATH)
# Use cached result
IF(NOT LIBEV_FOUND)
UNSET(HAVE_EV_H)
UNSET(HAVE_LIBEV)
UNSET(HAVE_EV_H CACHE)
UNSET(HAVE_LIBEV CACHE)
UNSET(LIBEV_CFLAGS)
UNSET(LIBEV_LDFLAGS)
IF(LIBEV_INCLUDE_PATH OR LIBEV_LIBDIR)
SET(CMAKE_REQUIRED_INCLUDES ${LIBEV_INCLUDE_PATH})
# MESSAGE(STATUS "Looking for ev.h in ${CMAKE_REQUIRED_INCLUDES}")
CHECK_INCLUDE_FILES(ev.h HAVE_EV_H)
IF(HAVE_EV_H)
# MESSAGE(STATUS "Looking for lib ev in ${LIBEV_LIBDIR}")
CHECK_LIBRARY_EXISTS(ev ev_time "${LIBEV_LIBDIR}" HAVE_LIBEV)
IF(HAVE_LIBEV)
SET(LIBEV_LIBRARIES ev CACHE INTERNAL "")
SET(LIBEV_CFLAGS "" CACHE INTERNAL "")
SET(LIBEV_CFLAGS_OTHER "" CACHE INTERNAL "")
SET(LIBEV_INCLUDE_DIRS "" CACHE INTERNAL "")
SET(LIBEV_LDFLAGS "-L${LIBEV_LIBDIR} -lev" CACHE INTERNAL "")
SET(LIBEV_FOUND TRUE CACHE INTERNAL "Found libev" FORCE)
ELSE(HAVE_LIBEV)
MESSAGE(STATUS "Couldn't find lib ev in ${LIBEV_LIBDIR}")
ENDIF(HAVE_LIBEV)
ELSE(HAVE_EV_H)
MESSAGE(STATUS "Couldn't find <ev.h> in ${LIBEV_INCLUDE_PATH}")
ENDIF(HAVE_EV_H)
ELSE(LIBEV_INCLUDE_PATH OR LIBEV_LIBDIR)
pkg_check_modules(LIBEV libev)
IF(NOT LIBEV_FOUND)
# MESSAGE(STATUS "Looking for ev.h in ${CMAKE_REQUIRED_INCLUDES}")
CHECK_INCLUDE_FILES(ev.h HAVE_EV_H)
IF(HAVE_EV_H)
# MESSAGE(STATUS "Looking for lib ev")
CHECK_LIBRARY_EXISTS(ev ev_time "" HAVE_LIBEV)
IF(HAVE_LIBEV)
SET(LIBEV_CFLAGS "" CACHE INTERNAL "")
SET(LIBEV_CFLAGS_OTHER "" CACHE INTERNAL "")
SET(LIBEV_INCLUDE_DIRS "" CACHE INTERNAL "")
SET(LIBEV_LDFLAGS "-lev" CACHE INTERNAL "")
SET(LIBEV_FOUND TRUE CACHE INTERNAL "Found libev" FORCE)
ELSE(HAVE_LIBEV)
MESSAGE(STATUS "Couldn't find lib ev")
ENDIF(HAVE_LIBEV)
ELSE(HAVE_EV_H)
MESSAGE(STATUS "Couldn't find <ev.h>")
ENDIF(HAVE_EV_H)
ENDIF(NOT LIBEV_FOUND)
ENDIF(LIBEV_INCLUDE_PATH OR LIBEV_LIBDIR)
ENDIF(NOT LIBEV_FOUND)
IF(NOT LIBEV_FOUND)
IF(LibEV_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find libev")
ENDIF(LibEV_FIND_REQUIRED)
ENDIF(NOT LIBEV_FOUND)
MARK_AS_ADVANCED(LIBEV_PATH LIBEV_INCLUDE_PATH LIBEV_LIBDIR)

View File

@ -1,48 +0,0 @@
IF(NOT RAGEL_EXECUTABLE)
MESSAGE(STATUS "Looking for ragel")
FIND_PROGRAM(RAGEL_EXECUTABLE ragel)
IF(RAGEL_EXECUTABLE)
EXECUTE_PROCESS(COMMAND "${RAGEL_EXECUTABLE}" -v OUTPUT_VARIABLE _version)
STRING(REGEX MATCH "[0-9.]+" RAGEL_VERSION ${_version})
SET(RAGEL_FOUND TRUE)
ENDIF(RAGEL_EXECUTABLE)
ELSE(NOT RAGEL_EXECUTABLE)
EXECUTE_PROCESS(COMMAND "${RAGEL_EXECUTABLE}" -v OUTPUT_VARIABLE _version)
STRING(REGEX MATCH "[0-9.]+" RAGEL_VERSION ${_version})
SET(RAGEL_FOUND TRUE)
ENDIF(NOT RAGEL_EXECUTABLE)
IF(RAGEL_FOUND)
IF (NOT Ragel_FIND_QUIETLY)
MESSAGE(STATUS "Found ragel: ${RAGEL_EXECUTABLE} (${RAGEL_VERSION})")
ENDIF (NOT Ragel_FIND_QUIETLY)
IF(NOT RAGEL_FLAGS)
SET(RAGEL_FLAGS "-T1")
ENDIF(NOT RAGEL_FLAGS)
MACRO(RAGEL_PARSER SRCFILE)
GET_FILENAME_COMPONENT(SRCPATH "${SRCFILE}" PATH)
GET_FILENAME_COMPONENT(SRCBASE "${SRCFILE}" NAME_WE)
SET(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}/${SRCPATH}/${SRCBASE}.c")
FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${SRCPATH}")
SET(INFILE "${CMAKE_CURRENT_SOURCE_DIR}/${SRCFILE}")
SET(_flags ${ARGV1})
IF(NOT _flags)
SET(_flags ${RAGEL_FLAGS})
ENDIF(NOT _flags)
ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILE}
COMMAND "${RAGEL_EXECUTABLE}"
ARGS -C ${_flags} -o "${OUTFILE}" "${INFILE}"
DEPENDS "${INFILE}"
COMMENT "Generating ${SRCBASE}.c from ${SRCFILE}"
)
ENDMACRO(RAGEL_PARSER)
ELSE(RAGEL_FOUND)
IF(Ragel_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find ragel")
ENDIF(Ragel_FIND_REQUIRED)
ENDIF(RAGEL_FOUND)

View File

@ -1,45 +0,0 @@
## our modules are without the "lib" prefix
MACRO(ADD_AND_INSTALL_LIBRARY LIBNAME SRCFILES)
IF(BUILD_STATIC)
ADD_LIBRARY(${LIBNAME} STATIC ${SRCFILES})
TARGET_LINK_LIBRARIES(lighttpd2 ${LIBNAME})
ELSE(BUILD_STATIC)
ADD_LIBRARY(${LIBNAME} MODULE ${SRCFILES})
SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} ${LIBNAME})
ADD_TARGET_PROPERTIES(${LIBNAME} LINK_FLAGS ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(${LIBNAME} COMPILE_FLAGS ${COMMON_CFLAGS})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
TARGET_INCLUDE_DIRECTORIES(${LIBNAME} PRIVATE ${COMMON_INCLUDE_DIRECTORIES})
TARGET_LINK_LIBRARIES(${LIBNAME} lighttpd-${PACKAGE_VERSION}-common lighttpd-${PACKAGE_VERSION}-shared)
IF(APPLE)
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES LINK_FLAGS "-flat_namespace -undefined suppress")
ENDIF(APPLE)
ENDIF(BUILD_STATIC)
ENDMACRO(ADD_AND_INSTALL_LIBRARY)
MACRO(ADD_TARGET_PROPERTIES _target _name)
SET(_properties)
FOREACH(_prop ${ARGN})
SET(_properties "${_properties} ${_prop}")
ENDFOREACH(_prop)
GET_TARGET_PROPERTY(_old_properties ${_target} ${_name})
#MESSAGE(STATUS "adding property to ${_target} ${_name}:" ${_properties})
IF(NOT _old_properties)
# in case it's NOTFOUND
SET(_old_properties)
ENDIF(NOT _old_properties)
SET_TARGET_PROPERTIES(${_target} PROPERTIES ${_name} "${_old_properties} ${_properties}")
ENDMACRO(ADD_TARGET_PROPERTIES)
MACRO(ADD_PREFIX _target _prefix)
SET(_oldtarget ${${_target}})
SET(_newtarget)
FOREACH(_t ${_oldtarget})
SET(_newtarget ${_newtarget} "${_prefix}${_t}")
ENDFOREACH(_t)
SET(${_target} ${_newtarget})
ENDMACRO(ADD_PREFIX)

View File

@ -1,475 +0,0 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([lighttpd],[2.0.0],[],[],[https://redmine.lighttpd.net/projects/lighttpd2/wiki])
AC_CONFIG_SRCDIR([src/main/lighttpd_worker.c])
AC_CONFIG_HEADERS([include/lighttpd/config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([-Wall -Wno-portability -Wno-override -Werror foreign dist-bzip2 tar-ustar] serial-tests)
m4_include([build-helpers/glibtests.m4])
GLIB_TESTS
dnl check environment
AC_USE_SYSTEM_EXTENSIONS
# Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
AC_PROG_INSTALL
# AC_PROG_RANLIB
AM_PROG_AR
AC_PATH_PROG([RAGEL], [ragel])
if test "x$RAGEL" = "x"; then
AC_MSG_ERROR([ragel not found])
fi
AC_SUBST([RAGEL])
m4_ifndef([PKG_PROG_PKG_CONFIG], [m4_fatal([pkg-config not installed])])
m4_ifndef([LT_INIT], [m4_fatal([libtool not installed])])
LT_INIT([shared disable-static])
# Checks for header files.
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([ \
unistd.h \
stddef.h \
sys/mman.h \
sys/resource.h \
sys/sendfile.h \
sys/types.h \
sys/uio.h \
sys/un.h \
execinfo.h \
])
# pkglibdir
AC_ARG_WITH(
[pkglibdir],
AS_HELP_STRING([--with-pkglibdir=dir],
[specify directory for driver files (default LIBDIR/lighttpd-VERSION]),
[pkglibdir=$withval],
[pkglibdir=$libdir/lighttpd-$PACKAGE_VERSION])
AC_SUBST(pkglibdir)
# libexecdir
libexecdir=$libexecdir/lighttpd2
AC_SUBST([libexecdir])
# Checks for libraries.
# glib/gthread (gthread includes glib)
PKG_CHECK_MODULES([GTHREAD], [gthread-2.0 >= 2.16.0], [],[AC_MSG_ERROR("gthread-2.0 >= 2.16.0 not found")])
# gmodule
PKG_CHECK_MODULES([GMODULE], [gmodule-2.0 >= 2.16.0], [],[AC_MSG_ERROR("gmodule-2.0 >= 2.16.0 not found")])
AC_MSG_CHECKING([for libev support])
AC_ARG_WITH([libev],
[AS_HELP_STRING([--with-libev@<:@=PATH@:>@],[Search for libev in PATH/include and PATH/lib])],
[WITH_LIBEV=$withval],[WITH_LIBEV=yes])
LIBEV_CFLAGS=""
LIBEV_LIBS=""
PKG_CHECK_MODULES([LIBEV], [libev], [], [
# no pkg-config for libev, searching manually:
if test "$WITH_LIBEV" != "yes"; then
LIBEV_CFLAGS="-I$WITH_LIBEV/include"
LIBEV_LIBS="-L$WITH_LIBEV/lib -lev"
else
AC_CHECK_HEADERS([ev.h],[
AC_CHECK_LIB([ev], [ev_time], [
LIBEV_LIBS="-lev"
],[
AC_MSG_ERROR([libev not found])
]
)],[
AC_MSG_ERROR([libev not found])
]
)
fi
])
AC_SUBST([LIBEV_CFLAGS])
AC_SUBST([LIBEV_LIBS])
dnl Large File Support
AC_ARG_ENABLE([lfs],
[AS_HELP_STRING([--disable-lfs],[disable large file support])],
[case "${enableval}" in
yes) lfs=true ;;
no) lfs=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-lfs]) ;;
esac],[lfs=true])
if test x$lfs = xtrue; then
CFLAGS="${CFLAGS} -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES"
fi
dnl Check for gnutls
AC_ARG_WITH([gnutls], [AS_HELP_STRING([--with-gnutls],[gnutls library for ssl/tls (default)])],
[WITH_GNUTLS=$withval],[WITH_GNUTLS=yes])
if test "$WITH_GNUTLS" != "no"; then
PKG_CHECK_MODULES([GNUTLS], [gnutls],[],[
AC_MSG_ERROR([gnutls not found])
])
AC_SUBST([GNUTLS_CFLAGS])
AC_SUBST([GNUTLS_LIBS])
USE_GNUTLS=true
fi
AM_CONDITIONAL([USE_GNUTLS], [test "$USE_GNUTLS" = "true"])
dnl Check for libidn, needed to decode SNI names
AC_ARG_WITH([sni], [AS_HELP_STRING([--with-sni],[SNI support for gnutls/openssl, needs libidn (default)])],
[WITH_SNI=$withval],[WITH_SNI=yes])
if test "$WITH_SNI" != "no"; then
PKG_CHECK_MODULES([IDN], [libidn],[],[
AC_MSG_ERROR([libidn not found])
])
AC_SUBST([IDN_CFLAGS])
AC_SUBST([IDN_LIBS])
AC_DEFINE([USE_SNI], [1], [use sni])
USE_SNI=true
fi
AM_CONDITIONAL([USE_SNI], [test "$USE_SNI" = "true"])
dnl Check for lua
AC_MSG_CHECKING([for lua])
AC_ARG_WITH([lua], [AS_HELP_STRING([--with-lua],[lua engine (default)])],
[WITH_LUA=$withval],[WITH_LUA=yes])
AC_MSG_RESULT([$WITH_LUA])
if test "$WITH_LUA" != "no"; then
# try pkgconfig
if test "$WITH_LUA" = "yes"; then
LUAPC=lua
else
LUAPC=$WITH_LUA
fi
PKG_CHECK_MODULES([LUA], [$LUAPC >= 5.1], [
AC_DEFINE([HAVE_LUA], [1], [liblua])
AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
],[
# for debian based systems
PKG_CHECK_MODULES([LUA], [lua5.1 >= 5.1], [
AC_DEFINE([HAVE_LUA], [1], [liblua])
AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
],[
# for freebsd
PKG_CHECK_MODULES([LUA], [lua-5.1 >= 5.1], [
AC_DEFINE([HAVE_LUA], [1], [liblua])
AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
],[
AC_MSG_ERROR([lua not found])
])
])
])
AC_SUBST([LUA_CFLAGS])
AC_SUBST([LUA_LIBS])
USE_LUA=true
fi
AM_CONDITIONAL([USE_LUA], [test "$USE_LUA" = "true"])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_UID_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
## solaris needs -lsocket -lnsl
AC_SEARCH_LIBS([socket],[socket])
AC_SEARCH_LIBS([inet_addr],[nsl socket])
## freebsd: kvm
AC_SEARCH_LIBS([kvm_open],[kvm])
## math functions
AC_SEARCH_LIBS([fmod],[m])
# Checks for library functions.
AC_CHECK_FUNCS([ \
chroot \
getrlimit \
gmtime_r \
inet_aton \
inet_ntop \
localtime_r \
madvise \
mmap \
posix_fadvise \
sendfile \
sendfile64 \
sendfilev \
writev \
accept4 \
])
dnl Check for IPv6 support
AC_ARG_ENABLE([ipv6],
[AS_HELP_STRING([--disable-ipv6],[disable IPv6 support])],
[case "${enableval}" in
yes) ipv6=true ;;
no) ipv6=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ipv6]) ;;
esac],[ipv6=true])
if test x$ipv6 = xtrue; then
AC_CACHE_CHECK([for IPv6 support], [ac_cv_ipv6_support],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>]], [[struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0; ]])],[ac_cv_ipv6_support=yes],[ac_cv_ipv6_support=no])])
if test "$ac_cv_ipv6_support" = yes; then
AC_DEFINE([HAVE_IPV6],[1],[Whether to enable IPv6 support])
else
AC_MSG_ERROR([IPv6 not supported. Use --disable-ipv6 if this is acceptable.])
fi
fi
dnl Check for struct sockaddr_storage
AC_CACHE_CHECK([for struct sockaddr_storage support], [ac_cv_sockaddr_storage_support],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <sys/socket.h> ]], [[struct sockaddr_storage s; ]])],[ac_cv_sockaddr_storage_support=yes],[ac_cv_sockaddr_storage_support=no])])
if test "ac_cv_sockaddr_storage_support" = yes; then
AC_DEFINE([HAVE_SOCKADDR_STORAGE],[1],[Whether we have struct sockaddr_storage])
fi
dnl Checking for libunwind
AC_MSG_CHECKING(for libunwind)
AC_ARG_WITH(libunwind,
AS_HELP_STRING([--with-libunwind],[Include libunwind support for backtraces on assert failures (default)]),
[WITH_LIBUNWIND=$withval],[WITH_LIBUNWIND=yes])
if test "$WITH_LIBUNWIND" != "no"; then
have_libunwind=no
PKG_CHECK_MODULES(LIBUNWIND, libunwind, [have_libunwind=yes], [
# pkg-config failed, search manually
OLDLIBS="$LIBS"
LIBS="$LIBS -lunwind"
AC_CACHE_CHECK([for libunwind support], [ac_cv_libunwind],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[
# define UNW_LOCAL_ONLY
# include <libunwind.h>
]], [[
unw_context_t context;
unw_getcontext(&context);
]])],[ac_cv_libunwind=yes],[ac_cv_libunwind=no])])
LIBS="$OLDLIBS"
if test "$ac_cv_libunwind" = yes; then
LIBUNWIND_CFLAGS=
LIBUNWIND_LIBS=-lunwind
fi
have_libunwind="$ac_cv_libunwind"
])
if test "$have_libunwind" = yes; then
AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
else
AC_MSG_ERROR("couldn't find libunwind")
fi
AC_SUBST([LIBUNWIND_CFLAGS])
AC_SUBST([LIBUNWIND_LIBS])
fi
dnl Check for openssl
AC_MSG_CHECKING([for OpenSSL])
AC_ARG_WITH([openssl],
AS_HELP_STRING([--with-openssl@<:@=DIR@:>@],[Include openssl support (default)]),
[WITH_OPENSSL=$withval],[WITH_OPENSSL=yes])
OPENSSL_CFLAGS=""
OPENSSL_LIBS=""
if test "$WITH_OPENSSL" != "no"; then
use_openssl=yes
if test "$WITH_OPENSSL" != "yes"; then
OPENSSL_CFLAGS="-I$WITH_OPENSSL/include"
OPENSSL_LIBS="-L$WITH_OPENSSL/lib"
fi
else
use_openssl=no
fi
AC_MSG_RESULT([$use_openssl])
AC_ARG_WITH([openssl-includes],
[AS_HELP_STRING([--with-openssl-includes=DIR],[Custom OpenSSL include path])],
[ use_openssl=yes OPENSSL_CFLAGS="-I$withval" ]
)
AC_ARG_WITH([openssl-libs],
[AS_HELP_STRING([--with-openssl-libs=DIR],[Custom OpenSSL library path])],
[ use_openssl=yes OPENSSL_LIBS="-L$withval" ]
)
AC_ARG_WITH([kerberos5],
[AS_HELP_STRING([--with-kerberos5],[use Kerberos5 support with OpenSSL])],
[ use_kerberos=$withval ], [use_kerberos=no]
)
if test "$use_openssl" = "yes"; then
if test "$use_kerberos" = "no"; then
OPENSSL_CFLAGS="$OPENSSL_CFLAGS -DOPENSSL_NO_KRB5"
fi
OLD_LIBS="$LIBS"
OLD_LDFLAGS="$LDFLAGS"
OLD_CPPFLAGS="$CPPFLAGS"
LDFLAGS="$LDFLAGS $OPENSSL_LIBS"
CPPFLAGS="$CPPFLAGS $OPENSSL_CFLAGS"
AC_CHECK_HEADERS([openssl/ssl.h])
AC_CHECK_LIB([crypto], [BIO_f_base64], [
AC_CHECK_LIB([ssl], [SSL_new], [
OPENSSL_LIBS="$OPENSSL_LIBS -lssl -lcrypto"
have_openssl=yes
AC_DEFINE([HAVE_OPENSSL], [], [Have openssl])
], [], [ -lcrypto "$DL_LIB" ])
], [], [])
LIBS="$OLD_LIBS"
LDFLAGS="$OLD_LDFLAGS"
CPPFLAGS="$OLD_CPPFLAGS"
if test "x$have_openssl" != "xyes"; then
AC_MSG_ERROR([Couldn't find openssl])
fi
AC_SUBST([OPENSSL_CFLAGS])
AC_SUBST([OPENSSL_LIBS])
fi
AM_CONDITIONAL([USE_OPENSSL], [test "x$have_openssl" = "xyes"])
# mod-deflate:
use_mod_deflate=no
# check for zlib
AC_MSG_CHECKING([for zlib support])
AC_ARG_WITH([zlib], [AS_HELP_STRING([--with-zlib],[Enable zlib support for mod_deflate (default)])],
[WITH_ZLIB=$withval],[WITH_ZLIB=yes])
AC_MSG_RESULT([$WITH_ZLIB])
if test "$WITH_BZIP2" != "no"; then
AC_CHECK_LIB([z], [deflate], [
AC_CHECK_HEADERS([zlib.h],[
Z_LIB=-lz
use_mod_deflate=yes
AC_DEFINE([HAVE_ZLIB], [1], [with zlib])
])
])
fi
AC_SUBST([Z_LIB])
# check for bzip2
AC_MSG_CHECKING([for bzip2 support])
AC_ARG_WITH([bzip2], [AS_HELP_STRING([--with-bzip2],[Enable bzip2 support for mod_deflate (default)])],
[WITH_BZIP2=$withval],[WITH_BZIP2=yes])
AC_MSG_RESULT([$WITH_BZIP2])
if test "$WITH_BZIP2" != "no"; then
AC_CHECK_LIB([bz2], [BZ2_bzCompress], [
AC_CHECK_HEADERS([bzlib.h],[
BZ_LIB=-lbz2
use_mod_deflate=yes
AC_DEFINE([HAVE_BZIP], [1], [with bzip2])
])
])
fi
AC_SUBST([BZ_LIB])
AM_CONDITIONAL([USE_MOD_DEFLATE], [test "x$use_mod_deflate" = "xyes"])
AC_ARG_ENABLE([profiler],
[AS_HELP_STRING([--enable-profiler],[enable memory profiler support])],[
profiler=yes
AC_DEFINE([WITH_PROFILER], [1], [profiler])
AC_CHECK_HEADERS([execinfo.h])
],[])
AM_CONDITIONAL([WITH_PROFILER], [test "x$profiler" = "xyes"])
dnl search for crypt_r and (fallback) for crypt
save_LIBS=$LIBS
LIBS=
AC_SEARCH_LIBS([crypt_r],[crypt],[
AC_DEFINE([HAVE_CRYPT_R], [1], [crypt_r])
AC_CHECK_HEADERS([crypt.h],[
AC_DEFINE([HAVE_CRYPT_H], [1], [crypt.h])
])
CRYPT_LIB=$LIBS
],[
AC_SEARCH_LIBS([crypt],[crypt],[
AC_CHECK_HEADERS([crypt.h],[
AC_DEFINE([HAVE_CRYPT_H], [1], [crypt.h])
])
CRYPT_LIB=$LIBS
])
])
LIBS=$save_LIBS
AC_SUBST([CRYPT_LIB])
# check for extra compiler options (warning options)
if test "${GCC}" = "yes"; then
CFLAGS="${CFLAGS} -Wall -W -Wshadow -pedantic -std=gnu99"
fi
AC_ARG_ENABLE([extra-warnings],
[AS_HELP_STRING([--enable-extra-warnings],[enable extra warnings (gcc specific)])],
[case "${enableval}" in
yes) extrawarnings=true ;;
no) extrawarnings=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-extra-warnings]) ;;
esac],[extrawarnings=false])
if test x$extrawarnings = xtrue; then
CFLAGS="${CFLAGS} -g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Wsign-compare -Wnested-externs -Wpointer-arith -Wmissing-prototypes -Wshadow -Wno-pointer-sign -Wformat-security -Wl,--as-needed -Wl,--no-undefined"
fi
AC_CONFIG_FILES([Makefile \
contrib/Makefile \
doc/Makefile \
include/Makefile \
include/lighttpd/Makefile \
src/Makefile \
src/common/Makefile \
src/main/Makefile \
src/angel/Makefile \
src/modules/Makefile \
src/unittests/Makefile \
src/lighttpd2.pc \
tests/Makefile \
])
AC_OUTPUT

View File

@ -1,10 +0,0 @@
EXTRA_DIST=angel.conf lighttpd.conf mimetypes.conf service systemd \
default.html create-mimetypes.conf.pl
# see src/modules/Makefile.am
luadir = $(datarootdir)/lighttpd2/lua
dist_lua_DATA = core__cached_html.lua \
core.lua \
core__xsendfile.lua \
secdownload.lua \
secdownload__secdownload.lua

View File

@ -15,7 +15,7 @@ local basepath = filename:gsub("(.*/)(.*)", "%1")
-- core.wsgi:
-- WSGI applications expect the url to be split into SCRIPT_NAME and
-- PATH_INFO; SCRIPT_NAME is their "application root", and PATH_INFO the requsted
-- PATH_INFO; SCRIPT_NAME is their "application root", and PATH_INFO the requested
-- resource in the application.
-- By default, lighttpd uses an empty PATH_INFO (unless you used the "pathinfo;" action,
-- but this doesn't help here as we're not dealing with static files here)
@ -27,7 +27,7 @@ local basepath = filename:gsub("(.*/)(.*)", "%1")
-- core.wsgi ( <url-prefix>, { <backend-actions>; } );
--
-- Example: Trac in "/trac", listening via FastCGI on unix:/tmp/trac.socket
-- You oviously have to load mod_fastcgi for this.
-- You obviously have to load mod_fastcgi for this.
--
-- core.wsgi ( "/trac", { fastcgi "unix:/tmp/trac.socket"; } );

View File

@ -143,7 +143,7 @@ while (<MIMETYPES>) {
}
# missing in /etc/mime.types;
# from http://www.iana.org/assignments/media-types/media-types.xhtml
# from https://www.iana.org/assignments/media-types/media-types.xhtml
add(".dtd", "application/xml-dtd");
@ -153,7 +153,7 @@ print <<EOF;
setup {
mime_types [
# /etc/mime.types
# and from http://www.iana.org/assignments/media-types/media-types.xhtml
# and from https://www.iana.org/assignments/media-types/media-types.xhtml
EOF

View File

@ -28,12 +28,12 @@
</div>
<h3>About this page</h3>
<p>This is a placeholder page installed by the Lighttpd2 package of this servers operating system.</p>
<p>Lighttpd is a webserver. To learn more about it, please visit <a href="http://www.lighttpd.net">http://www.lighttpd.net</a></p>
<p>Lighttpd is a webserver. To learn more about it, please visit <a href="https://www.lighttpd.net">https://www.lighttpd.net</a></p>
<h3>If you are the administrator of this server</h3>
<ul>
<li>Configuration files are most likely located in /etc/lighttpd2/</li>
<li>Logs are usually stored in /var/log/lighttpd2/</li>
<li>Please consult the documenation provided in the <a href="http://redmine.lighttpd.net/projects/lighttpd2/wiki">Lighttpd2 wiki</a></li>
<li>Please consult the documenation provided in the <a href="https://redmine.lighttpd.net/projects/lighttpd2/wiki">Lighttpd2 wiki</a></li>
<li>For discussions about Lighttpd, please join the IRC channel <a href="irc://irc.freenode.org/lighttpd">#lighttpd</a> on irc.freenode.org</li>
</ul>
<div id="logo" style="text-align: center;">

11
contrib/meson.build Normal file
View File

@ -0,0 +1,11 @@
if get_option('lua')
install_data(
'core__cached_html.lua',
'core.lua',
'core__xsendfile.lua',
'secdownload.lua',
'secdownload__secdownload.lua',
install_dir: lua_dir,
install_tag: 'runtime',
)
endif

View File

@ -3,7 +3,7 @@
setup {
mime_types [
# /etc/mime.types
# and from http://www.iana.org/assignments/media-types/media-types.xhtml
# and from https://www.iana.org/assignments/media-types/media-types.xhtml
".a2l" => "application/A2L",
".aml" => "application/AML",
@ -17,6 +17,7 @@ setup {
".dit" => "application/DIT",
".lxf" => "application/LXF",
".mf4" => "application/MF4",
".oda" => "application/ODA",
".odx" => "application/ODX",
".pdx" => "application/PDX",
".ez" => "application/andrew-inset",
@ -30,6 +31,7 @@ setup {
".held" => "application/atsc-held+xml",
".rsat" => "application/atsc-rsat+xml",
".apxml" => "application/auth-policy+xml",
".amlx" => "application/automationml-amlx+zip",
".xdd" => "application/bacnet-xdd+zip",
".lin" => "application/bbolin",
".xcs" => "application/calendar+xml",
@ -44,10 +46,13 @@ setup {
".cdmiq" => "application/cdmi-queue",
".cellml" => "application/cellml+xml",
".cml" => "application/cellml+xml",
".1clr" => "application/clr",
".cmsc" => "application/cms",
".cpl" => "application/cpl+xml",
".csrattrs" => "application/csrattrs",
".cu" => "application/cu-seeme",
".cwl" => "application/cwl",
".cwl.json" => "application/cwl+json",
".mpd" => "application/dash+xml",
".mpdd" => "application/dashdelta",
".davmount" => "application/davmount+xml",
@ -57,13 +62,14 @@ setup {
".dssc" => "application/dssc+der",
".xdssc" => "application/dssc+xml",
".dvc" => "application/dvcs",
".es" => "application/ecmascript",
".efi" => "application/efi",
".emma" => "application/emma+xml",
".emotionml" => "application/emotionml+xml",
".epub" => "application/epub+zip",
".exi" => "application/exi",
".exp" => "application/express",
".finf" => "application/fastinfoset",
".fdf" => "application/fdf",
".fdt" => "application/fdt+xml",
".pfr" => "application/font-tdpfr",
".spl" => "application/futuresplash",
@ -82,8 +88,6 @@ setup {
".jar" => "application/java-archive",
".ser" => "application/java-serialized-object",
".class" => "application/java-vm",
".js" => "application/javascript",
".mjs" => "application/javascript",
".jrd" => "application/jrd+json",
".json" => "application/json",
".json-patch" => "application/json-patch+json",
@ -97,6 +101,7 @@ setup {
".hqx" => "application/mac-binhex40",
".cpt" => "application/mac-compactpro",
".mads" => "application/mads+xml",
".webmanifest" => "application/manifest+json",
".mrc" => "application/marc",
".mrcx" => "application/marcxml+xml",
".ma" => "application/mathematica",
@ -122,7 +127,6 @@ setup {
".deploy" => "application/octet-stream",
".msp" => "application/octet-stream",
".msu" => "application/octet-stream",
".oda" => "application/oda",
".opf" => "application/oebps-package+xml",
".ogx" => "application/ogg",
".one" => "application/onenote",
@ -130,6 +134,10 @@ setup {
".onetmp" => "application/onenote",
".onetoc2" => "application/onenote",
".oxps" => "application/oxps",
".210" => "application/p21",
".ifc" => "application/p21",
".p21" => "application/p21",
".stpnc" => "application/p21",
".relo" => "application/p2p-overlay+xml",
".pdf" => "application/pdf",
".pem" => "application/pem-certificate-chain",
@ -182,6 +190,10 @@ setup {
".mft" => "application/rpki-manifest",
".roa" => "application/rpki-roa",
".rtf" => "application/rtf",
".sarif" => "application/sarif+json",
".sarif.json" => "application/sarif+json",
".sarif-external-properties" => "application/sarif-external-properties+json",
".sarif-external-properties.json" => "application/sarif-external-properties+json",
".scim" => "application/scim+json",
".scq" => "application/scvp-cv-request",
".scs" => "application/scvp-cv-response",
@ -208,12 +220,14 @@ setup {
".sml" => "application/smil+xml",
".rq" => "application/sparql-query",
".srx" => "application/sparql-results+xml",
".spdx.json" => "application/spdx+json",
".sql" => "application/sql",
".gram" => "application/srgs",
".grxml" => "application/srgs+xml",
".sru" => "application/sru+xml",
".ssml" => "application/ssml+xml",
".stix" => "application/stix+json",
".coswid" => "application/swid+cbor",
".swidtag" => "application/swid+xml",
".tau" => "application/tamp-apex-update",
".auc" => "application/tamp-apex-update-confirm",
@ -232,6 +246,9 @@ setup {
".tsq" => "application/timestamp-query",
".tsr" => "application/timestamp-reply",
".tsd" => "application/timestamped-data",
".jsontm" => "application/tm+json",
".tm.json" => "application/tm+json",
".tm.jsonld" => "application/tm+json",
".trig" => "application/trig",
".ttml" => "application/ttml+xml",
".gsheet" => "application/urc-grpsheet+xml",
@ -251,6 +268,7 @@ setup {
".xel" => "application/xcap-el+xml",
".xer" => "application/xcap-error+xml",
".xns" => "application/xcap-ns+xml",
".xfdf" => "application/xfdf",
".xht" => "application/xhtml+xml",
".xhtm" => "application/xhtml+xml",
".xhtml" => "application/xhtml+xml",
@ -310,13 +328,13 @@ setup {
".fxp" => "application/vnd.adobe.fxp",
".fxpl" => "application/vnd.adobe.fxp",
".xdp" => "application/vnd.adobe.xdp+xml",
".xfdf" => "application/vnd.adobe.xfdf",
".afp" => "application/vnd.afpc.modca",
".list3820" => "application/vnd.afpc.modca",
".listafp" => "application/vnd.afpc.modca",
".pseg3820" => "application/vnd.afpc.modca",
".ovl" => "application/vnd.afpc.modca-overlay",
".psg" => "application/vnd.afpc.modca-pagesegment",
".age" => "application/vnd.age",
".ahead" => "application/vnd.ahead.space",
".azf" => "application/vnd.airzip.filesecure.azf",
".azs" => "application/vnd.airzip.filesecure.azs",
@ -328,6 +346,10 @@ setup {
".apkg" => "application/vnd.anki",
".cii" => "application/vnd.anser-web-certificate-issue-initiation",
".fti" => "application/vnd.anser-web-funds-transfer-initiation",
".arrow" => "application/vnd.apache.arrow.file",
".arrows" => "application/vnd.apache.arrow.stream",
".apex" => "application/vnd.apexlang",
".apexlang" => "application/vnd.apexlang",
".dist" => "application/vnd.apple.installer+xml",
".distz" => "application/vnd.apple.installer+xml",
".mpkg" => "application/vnd.apple.installer+xml",
@ -344,6 +366,8 @@ setup {
".bmml" => "application/vnd.balsamiq.bmml+xml",
".bmpr" => "application/vnd.balsamiq.bmpr",
".ac2" => "application/vnd.banana-accounting",
".lhzd" => "application/vnd.belightsoft.lhzd+zip",
".lhzl" => "application/vnd.belightsoft.lhzl+zip",
".mpm" => "application/vnd.blueice.multipass",
".ep" => "application/vnd.bluetooth.ep.oob",
".le" => "application/vnd.bluetooth.le.oob",
@ -397,10 +421,14 @@ setup {
".clkw" => "application/vnd.crick.clicker.wordbank",
".wbs" => "application/vnd.criticaltools.wbs+xml",
".ssvc" => "application/vnd.crypto-shade-file",
".c9r" => "application/vnd.cryptomator.encrypted",
".c9s" => "application/vnd.cryptomator.encrypted",
".cryptomator" => "application/vnd.cryptomator.vault",
".pml" => "application/vnd.ctc-posml",
".ppd" => "application/vnd.cups-ppd",
".dart" => "application/vnd.dart",
".rdz" => "application/vnd.data-vision.rdz",
".dl" => "application/vnd.datalog",
".dbf" => "application/vnd.dbf",
".ddeb" => "application/vnd.debian.binary-package",
".deb" => "application/vnd.debian.binary-package",
@ -429,6 +457,7 @@ setup {
".geo" => "application/vnd.dynageo",
".dzr" => "application/vnd.dzr",
".mag" => "application/vnd.ecowin.chart",
".ELN" => "application/vnd.eln+zip",
".nml" => "application/vnd.enliven",
".esf" => "application/vnd.epson.esf",
".msf" => "application/vnd.epson.msf",
@ -444,6 +473,7 @@ setup {
".sce" => "application/vnd.etsi.asic-e+zip",
".asics" => "application/vnd.etsi.asic-s+zip",
".tst" => "application/vnd.etsi.timestamp-token",
".carjson" => "application/vnd.eu.kasparian.car+json",
".ecigprofile" => "application/vnd.evolv.ecig.profile",
".ecig" => "application/vnd.evolv.ecig.settings",
".ecigtheme" => "application/vnd.evolv.ecig.theme",
@ -451,8 +481,8 @@ setup {
".pub" => "application/vnd.exstream-package",
".ez2" => "application/vnd.ezpix-album",
".ez3" => "application/vnd.ezpix-package",
".gdz" => "application/vnd.familysearch.gedcom+zip",
".dim" => "application/vnd.fastcopy-disk-image",
".fdf" => "application/vnd.fdf",
".msd" => "application/vnd.fdsn.mseed",
".mseed" => "application/vnd.fdsn.mseed",
".dataless" => "application/vnd.fdsn.seed",
@ -474,7 +504,14 @@ setup {
".xct" => "application/vnd.fujixerox.docuworks.container",
".fzs" => "application/vnd.fuzzysheet",
".txd" => "application/vnd.genomatix.tuxedo",
".genozip" => "application/vnd.genozip",
".grd" => "application/vnd.gentics.grd+json",
".ebuild" => "application/vnd.gentoo.ebuild",
".eclass" => "application/vnd.gentoo.eclass",
".gpkg.tar" => "application/vnd.gentoo.gpkg",
".xpak" => "application/vnd.gentoo.xpak",
".ggb" => "application/vnd.geogebra.file",
".ggs" => "application/vnd.geogebra.slides",
".ggt" => "application/vnd.geogebra.tool",
".gex" => "application/vnd.geometry-explorer",
".gre" => "application/vnd.geometry-explorer",
@ -527,6 +564,7 @@ setup {
".i2g" => "application/vnd.intergeo",
".qbo" => "application/vnd.intu.qbo",
".qfx" => "application/vnd.intu.qfx",
".car" => "application/vnd.ipld.car",
".rcprofile" => "application/vnd.ipunplugged.rcprofile",
".irp" => "application/vnd.irepository.package+xml",
".xpr" => "application/vnd.is-xpr",
@ -554,6 +592,7 @@ setup {
".skp" => "application/vnd.koan",
".skt" => "application/vnd.koan",
".sse" => "application/vnd.kodak-descriptor",
".las" => "application/vnd.las",
".lasjson" => "application/vnd.las.las+json",
".lasxml" => "application/vnd.las.las+xml",
".lbd" => "application/vnd.llamagraphics.life-balance.desktop",
@ -586,10 +625,12 @@ setup {
".portpkg" => "application/vnd.macports.portpkg",
".mvt" => "application/vnd.mapbox-vector-tile",
".mdc" => "application/vnd.marlin.drm.mdcf",
".3tz" => "application/vnd.maxar.archive.3tz+zip",
".mmdb" => "application/vnd.maxmind.maxmind-db",
".mcd" => "application/vnd.mcd",
".mc1" => "application/vnd.medcalcdata",
".cdkey" => "application/vnd.mediastation.cdkey",
".rxt" => "application/vnd.medicalholodeck.recordxr",
".mfm" => "application/vnd.mfmp",
".flo" => "application/vnd.micrografx.flo",
".igx" => "application/vnd.micrografx.igx",
@ -643,6 +684,8 @@ setup {
".mus" => "application/vnd.musician",
".msty" => "application/vnd.muvee.style",
".taglet" => "application/vnd.mynfc",
".line" => "application/vnd.nebumind.line",
".nebul" => "application/vnd.nebumind.line",
".bkm" => "application/vnd.nervana",
".entity" => "application/vnd.nervana",
".kcm" => "application/vnd.nervana",
@ -662,9 +705,9 @@ setup {
".edm" => "application/vnd.novadigm.EDM",
".edx" => "application/vnd.novadigm.EDX",
".ext" => "application/vnd.novadigm.EXT",
".odb" => "application/vnd.oasis.opendocument.base",
".odc" => "application/vnd.oasis.opendocument.chart",
".otc" => "application/vnd.oasis.opendocument.chart-template",
".odb" => "application/vnd.oasis.opendocument.database",
".odf" => "application/vnd.oasis.opendocument.formula",
".odg" => "application/vnd.oasis.opendocument.graphics",
".otg" => "application/vnd.oasis.opendocument.graphics-template",
@ -707,13 +750,12 @@ setup {
".oprc" => "application/vnd.palm",
".pdb" => "application/vnd.palm",
".pqa" => "application/vnd.palm",
".prc" => "application/vnd.palm",
".plp" => "application/vnd.panoply",
".dive" => "application/vnd.patentdive",
".paw" => "application/vnd.pawaafile",
".str" => "application/vnd.pg.format",
".ei6" => "application/vnd.pg.osasli",
".pil" => "application/vnd.piaccess.application-license",
".pil" => "application/vnd.piaccess.application-licence",
".efif" => "application/vnd.picsel",
".wg" => "application/vnd.pmi.widget",
".plf" => "application/vnd.pocketlearn",
@ -732,6 +774,8 @@ setup {
".rar" => "application/vnd.rar",
".bed" => "application/vnd.realvnc.bed",
".mxl" => "application/vnd.recordare.musicxml",
".reload" => "application/vnd.resilient.logic",
".rlm" => "application/vnd.resilient.logic",
".cryptonote" => "application/vnd.rig.cryptonote",
".cod" => "application/vnd.rim.cod",
".link66" => "application/vnd.route66.link66+xml",
@ -789,6 +833,7 @@ setup {
".sds" => "application/vnd.stardivision.chart",
".sda" => "application/vnd.stardivision.draw",
".sdd" => "application/vnd.stardivision.impress",
".smf" => "application/vnd.stardivision.math",
".sdw" => "application/vnd.stardivision.writer",
".sgl" => "application/vnd.stardivision.writer-global",
".smzip" => "application/vnd.stepmania.package",
@ -806,6 +851,11 @@ setup {
".stw" => "application/vnd.sun.xml.writer.template",
".sus" => "application/vnd.sus-calendar",
".susp" => "application/vnd.sus-calendar",
".ml2" => "application/vnd.sybyl.mol2",
".mol2" => "application/vnd.sybyl.mol2",
".sy2" => "application/vnd.sybyl.mol2",
".scl" => "application/vnd.sycle+xml",
".syft.json" => "application/vnd.syft+json",
".sis" => "application/vnd.symbian.install",
".xsm" => "application/vnd.syncml+xml",
".bdm" => "application/vnd.syncml.dm+wbxml",
@ -839,6 +889,8 @@ setup {
".mxi" => "application/vnd.vd-study",
".study-inter" => "application/vnd.vd-study",
".vwx" => "application/vnd.vectorworks",
".aion" => "application/vnd.veritone.aion+json",
".vtnstd" => "application/vnd.veritone.aion+json",
".istc" => "application/vnd.veryant.thin",
".isws" => "application/vnd.veryant.thin",
".VES" => "application/vnd.ves.encrypted",
@ -854,6 +906,7 @@ setup {
".wbxml" => "application/vnd.wap.wbxml",
".wmlc" => "application/vnd.wap.wmlc",
".wmlsc" => "application/vnd.wap.wmlscriptc",
".wafl" => "application/vnd.wasmflow.wafl",
".wtb" => "application/vnd.webturbo",
".p2p" => "application/vnd.wfa.p2p",
".wsc" => "application/vnd.wfa.wsc",
@ -862,7 +915,6 @@ setup {
".m" => "application/vnd.wolfram.mathematica.package",
".nbp" => "application/vnd.wolfram.player",
".wpd" => "application/vnd.wordperfect",
".wp5" => "application/vnd.wordperfect5.1",
".wqd" => "application/vnd.wqd",
".stf" => "application/vnd.wt.stf",
".wv" => "application/vnd.wv.csp+wbxml",
@ -934,7 +986,6 @@ setup {
".fbdoc" => "application/x-maker",
".frame" => "application/x-maker",
".maker" => "application/x-maker",
".application" => "application/x-ms-application",
".wmd" => "application/x-ms-wmd",
".wmz" => "application/x-ms-wmz",
".bat" => "application/x-msdos-program",
@ -976,7 +1027,6 @@ setup {
".src" => "application/x-wais-source",
".wz" => "application/x-wingz",
".crt" => "application/x-x509-ca-cert",
".xcf" => "application/x-xcf",
".fig" => "application/x-xfig",
".xpi" => "application/x-xpinstall",
".xz" => "application/x-xz",
@ -1014,7 +1064,7 @@ setup {
".lbc" => "audio/iLBC",
".mhas" => "audio/mhas",
".mxmf" => "audio/mobile-xmf",
".m4a" => "audio/mpeg",
".m4a" => "audio/mp4",
".mp1" => "audio/mpeg",
".mp2" => "audio/mpeg",
".mp3" => "audio/mpeg",
@ -1107,7 +1157,6 @@ setup {
".sd" => "chemical/x-mdl-sdfile",
".tgf" => "chemical/x-mdl-tgf",
".mcif" => "chemical/x-mmcif",
".mol2" => "chemical/x-mol2",
".b" => "chemical/x-molconn-Z",
".gpt" => "chemical/x-mopac-graph",
".mop" => "chemical/x-mopac-input",
@ -1129,11 +1178,15 @@ setup {
".woff" => "font/woff",
".woff2" => "font/woff2",
".exr" => "image/aces",
".apng" => "image/apng",
".avci" => "image/avci",
".avcs" => "image/avcs",
".avif" => "image/avif",
".hif" => "image/avif",
".bmp" => "image/bmp",
".cgm" => "image/cgm",
".drle" => "image/dicom-rle",
".dpx" => "image/dpx",
".emf" => "image/emf",
".fit" => "image/fits",
".fits" => "image/fits",
@ -1160,6 +1213,7 @@ setup {
".jpm" => "image/jpm",
".jpf" => "image/jpx",
".jpx" => "image/jpx",
".jxl" => "image/jxl",
".jxr" => "image/jxr",
".jxra" => "image/jxrA",
".jxrs" => "image/jxrS",
@ -1176,11 +1230,10 @@ setup {
".pti" => "image/prs.pti",
".svg" => "image/svg+xml",
".svgz" => "image/svg+xml",
".T38" => "image/t38",
".t38" => "image/t38",
".tif" => "image/tiff",
".tiff" => "image/tiff",
".tfx" => "image/tiff-fx",
".webp" => "image/webp",
".wmf" => "image/wmf",
".psd" => "image/vnd.adobe.photoshop",
".azv" => "image/vnd.airzip.accelerator.azv",
@ -1200,7 +1253,6 @@ setup {
".PGB" => "image/vnd.globalgraphics.pgb",
".pgb" => "image/vnd.globalgraphics.pgb",
".ico" => "image/vnd.microsoft.icon",
".apng" => "image/vnd.mozilla.apng",
".mdi" => "image/vnd.ms-modi",
".b16" => "image/vnd.pco.b16",
".hdr" => "image/vnd.radiance",
@ -1235,6 +1287,7 @@ setup {
".ppm" => "image/x-portable-pixmap",
".rgb" => "image/x-rgb",
".xbm" => "image/x-xbitmap",
".xcf" => "image/x-xcf",
".xpm" => "image/x-xpixmap",
".xwd" => "image/x-xwindowdump",
".u8msg" => "message/global",
@ -1244,6 +1297,7 @@ setup {
".art" => "message/rfc822",
".eml" => "message/rfc822",
".mail" => "message/rfc822",
".jt" => "model/JT",
".gltf" => "model/gltf+json",
".glb" => "model/gltf-binary",
".iges" => "model/iges",
@ -1253,13 +1307,23 @@ setup {
".silo" => "model/mesh",
".mtl" => "model/mtl",
".obj" => "model/obj",
".prc" => "model/prc",
".step" => "model/step",
".stp" => "model/step",
".stpx" => "model/step+xml",
".stpz" => "model/step+zip",
".stpxz" => "model/step-xml+zip",
".stl" => "model/stl",
".u3d" => "model/u3d",
".vrm" => "model/vrml",
".vrml" => "model/vrml",
".wrl" => "model/vrml",
".x3db" => "model/x3d+fastinfoset",
".x3dv" => "model/x3d+vrml",
".x3dvz" => "model/x3d+vrml",
".x3d" => "model/x3d+xml",
".x3dz" => "model/x3d+xml",
".x3dv" => "model/x3d-vrml",
".x3dvz" => "model/x3d-vrml",
".cld" => "model/vnd.cld",
".dae" => "model/vnd.collada+xml",
".dwf" => "model/vnd.dwf",
".dor" => "model/vnd.gdl",
@ -1274,25 +1338,33 @@ setup {
".moml" => "model/vnd.moml+xml",
".mts" => "model/vnd.mts",
".ogex" => "model/vnd.opengex",
".pyox" => "model/vnd.pytha.pyox",
".vds" => "model/vnd.sap.vds",
".usda" => "model/vnd.usda",
".usdz" => "model/vnd.usdz+zip",
".bsp" => "model/vnd.valve.source.compiled-map",
".vtu" => "model/vnd.vtu",
".vpm" => "multipart/voice-message",
".bmed" => "multipart/vnd.bint.med-plus",
".sgm" => "text/SGML",
".sgml" => "text/SGML",
".appcache" => "text/cache-manifest",
".manifest" => "text/cache-manifest",
".ics" => "text/calendar",
".ifb" => "text/calendar",
".CQL" => "text/cql",
".css" => "text/css; charset=utf-8",
".csv" => "text/csv; charset=utf-8",
".csvs" => "text/csv-schema",
".soa" => "text/dns",
".zone" => "text/dns",
".323" => "text/h323",
".gff3" => "text/gff3",
".htm" => "text/html",
".html" => "text/html",
".shtml" => "text/html",
".uls" => "text/iuls",
".es" => "text/javascript",
".js" => "text/javascript",
".mjs" => "text/javascript",
".cnd" => "text/jcr-cnd",
".markdown" => "text/markdown; charset=utf-8",
".md" => "text/markdown; charset=utf-8",
@ -1307,10 +1379,10 @@ setup {
".rst" => "text/prs.fallenstein.rst",
".dsc" => "text/prs.lines.tag",
".tag" => "text/prs.lines.tag",
".rtx" => "text/richtext",
".sct" => "text/scriptlet",
".sgm" => "text/sgml",
".sgml" => "text/sgml",
".shaclc" => "text/shaclc",
".shc" => "text/shaclc",
".shex" => "text/shex",
".spdx" => "text/spdx",
".tsv" => "text/tab-separated-values",
".tm" => "text/texmacs",
".roff" => "text/troff",
@ -1322,6 +1394,7 @@ setup {
".vcard" => "text/vcard",
".vcf" => "text/vcard",
".vtt" => "text/vtt",
".wgsl" => "text/wgsl",
".dms" => "text/vnd.DMClientScript",
".a" => "text/vnd.a",
".abc" => "text/vnd.abc",
@ -1329,11 +1402,14 @@ setup {
".curl" => "text/vnd.curl",
".copyright" => "text/vnd.debian.copyright",
".jtd" => "text/vnd.esmertec.theme-descriptor",
".VFK" => "text/vnd.exchangeable",
".ged" => "text/vnd.familysearch.gedcom",
".flt" => "text/vnd.ficlab.flt",
".fly" => "text/vnd.fly",
".flx" => "text/vnd.fmi.flexstor",
".dot" => "text/vnd.graphviz",
".gv" => "text/vnd.graphviz",
".hans" => "text/vnd.hans",
".hgl" => "text/vnd.hgl",
".3dm" => "text/vnd.in3d.3dml",
".3dml" => "text/vnd.in3d.3dml",
@ -1389,7 +1465,6 @@ setup {
".tex" => "text/x-tex; charset=utf-8",
".vcs" => "text/x-vcalendar",
".axv" => "video/annodex",
".dl" => "video/dl",
".dif" => "video/dv",
".dv" => "video/dv",
".fli" => "video/fli",
@ -1452,9 +1527,6 @@ setup {
".wvx" => "video/x-ms-wvx",
".avi" => "video/x-msvideo",
".movie" => "video/x-sgi-movie",
".ice" => "x-conference/x-cooltalk",
".sisx" => "x-epoc/x-sisx-app",
".vrm" => "x-world/x-vrml",
# other useful mappings

View File

@ -1,45 +0,0 @@
dist_man8_MANS=lighttpd2.8 lighttpd2-worker.8
EXTRA_DIST=\
jquery-1.10.1.min.js \
bootstrap.min.js \
bootstrap.min.css \
bootstrap-theme.min.css \
style.css \
doc_schema.xsd \
core_config.xml \
core_config_angel.xml \
core_fetch.xml \
core_introduction.xml \
core_lua.xml \
core_pattern.xml \
core_regex.xml \
mod_accesslog.xml \
mod_access.xml \
mod_auth.xml \
mod_balance.xml \
mod_cache_disk_etag.xml \
mod_core.lua.xml \
mod_debug.xml \
mod_deflate.xml \
mod_dirlist.xml \
mod_expire.xml \
mod_fastcgi.xml \
mod_flv.xml \
mod_fortune.xml \
mod_gnutls.xml \
mod_limit.xml \
mod_lua.xml \
mod_memcached.xml \
mod_openssl.xml \
mod_progress.xml \
mod_proxy.xml \
mod_redirect.xml \
mod_rewrite.xml \
mod_scgi.xml \
mod_secdownload.lua.xml \
mod_status.xml \
mod_throttle.xml \
mod_userdir.xml \
mod_vhost.xml \
plugin_core.xml \
compile.rb

View File

@ -3,7 +3,7 @@
require 'rubygems'
require 'nokogiri'
require 'redcloth'
require 'kramdown'
require 'cgi'
@ -214,7 +214,7 @@ class Documentation
indent = real_lines.map { |l| _count_indent l }.min
code = lines.map { |line| _remove_indent(indent, line).rstrip }.join("\n") + "\n"
code = lines.map { |line| _remove_indent(indent, line) }.join() + "\n"
code.gsub(/\A\n+/, "").gsub(/\n\n+/, "\n\n").gsub(/\n+\Z/, "\n")
end
@ -222,9 +222,9 @@ class Documentation
@html.pre { @html.code { @html << _format_code(xml) } }
end
def _parse_textile(xml)
def _parse_markdown(xml)
tx = _format_code(xml)
@html << RedCloth.new(tx).to_html
@html << Kramdown::Document.new(tx, :auto_ids => false).to_html
end
def _parse_html(xml)
@ -238,8 +238,9 @@ class Documentation
xml.children.each do |child|
if child.text?
@html.p child.content.strip
elsif ['html','textile'].include? child.name
text = child.content.strip
raise "invalid non-empty text #{text.inspect}" if text != ""
elsif ['html','markdown'].include? child.name
self.send('_parse_' + child.name, child)
else
raise 'invalid description element ' + child.name
@ -425,8 +426,8 @@ class ModuleDocumentation < GenericModuleDocumentation
xml.children.each do |child|
if child.text?
text = child.content.strip
@html.p text if text.length > 0
elsif ['action','setup','option','html','textile','example','section'].include? child.name
raise "invalid non-empty text #{text.inspect}" if text != ""
elsif ['action','setup','option','html','markdown','example','section'].include? child.name
self.send('_parse_' + child.name, child)
else
raise 'invalid section element ' + child.name
@ -479,8 +480,8 @@ class AngelModuleDocumentation < GenericModuleDocumentation
xml.children.each do |child|
if child.text?
text = child.content.strip
@html.p text if text.length > 0
elsif ['item','html','textile','example','section'].include? child.name
raise "invalid non-empty text #{text.inspect}" if text != ""
elsif ['item','html','markdown','example','section'].include? child.name
self.send('_parse_' + child.name, child)
else
raise 'invalid section element ' + child.name
@ -543,8 +544,8 @@ class ChapterDocumentation < Documentation
xml.children.each do |child|
if child.text?
text = child.content.strip
@html.p text if text.length > 0
elsif ['html','textile','example','section'].include? child.name
raise "invalid non-empty text #{text.inspect}" if text != ""
elsif ['html','markdown','example','section'].include? child.name
self.send('_parse_' + child.name, child)
else
raise 'invalid section element ' + child.name
@ -736,7 +737,8 @@ end
if __FILE__ == $0
output_directory = ARGV[0] || '.'
output_directory = File.absolute_path(ARGV[0] || '.')
Dir.chdir(File.dirname(__FILE__))
if not system("xmllint --noout --schema doc_schema.xsd *.xml 2>&1")
STDERR.puts "Couldn't validate XML files"

View File

@ -1,178 +1,187 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Main Configuration">
<description>
<textile>
At the heart of each webserver is the configuration file. It controls the whole behaviour and therefore has to be mighty but at the same time easy enough to get the desired results without hassle.
In the lighttpd config you control how it reacts on requests. To achieve this you have to express some kind of logic - just like in a programming language.
</textile>
</description>
<description><markdown>
At the heart of each webserver is the configuration file. It controls the whole behaviour and therefore has to be mighty but at the same time easy enough to get the desired results without hassle.
In the lighttpd config you control how it reacts on requests. To achieve this you have to express some kind of logic just like in a programming language.
</markdown></description>
<section title="Basic Syntax">
<textile><![CDATA[
The syntax for the lighttpd 2.0 configuration file is somewhat similar to various programming languages - kind of a mixture. But don't be afraid, it is really simple. No pointers involved :)
The basic blocks are "values":#core_config__values, "variables":#core_config__variables, "function calls":#core_config__funcalls and "conditions":#core_config__conditions.
]]></textile>
<markdown><![CDATA[
The syntax for the lighttpd 2.0 configuration file is somewhat similar to various programming languages kind of a mixture. But don't be afraid, it is really simple. No pointers involved :)
The basic blocks are [values](#core_config__values), [variables](#core_config__variables), [function calls](#core_config__funcalls) and [conditions](#core_config__conditions).
]]></markdown>
</section>
<section title="Values" anchor="values">
<section title="Boolean">
<textile><![CDATA[
<markdown><![CDATA[
There are two boolean values:
* @true@
* @false@
]]></textile>
* `true`
* `false`
]]></markdown>
</section>
<section title="Integers">
<textile><![CDATA[
<markdown><![CDATA[
Integers are stored as signed ints with 64 bits (max value around 9 * 10^18). There are three basic ways to use them:
* decimal integers: starting with any non zero digit, like @128@
* octal integers: starting with a zero, like @0644@
* hexadecimal integers: starting with @0x@ like @0xff@
* decimal integers: starting with any non zero digit, like `128`
* octal integers: starting with a zero, like `0644`
* hexadecimal integers: starting with `0x` like `0xff`
All three can have a suffix representing a factor the number gets multiplied with:
* @byte@: @1@
* @kbyte@: @1024@
* @mbyte@: @1024*1024@
* @gbyte@: @1024*1024*1024@
* @tbyte@: @1024*1024*1024*1024@
* @pbyte@: @1024*1024*1024*1024*1024@
* @bit@: @1 / 8@
* @kbit@: @1024 / 8@
* @mbit@: @1024*1024 / 8@
* @gbit@: @1024*1024*1024 / 8@
* @tbit@: @1024*1024*1024*1024 / 8@
* @pbit@: @1024*1024*1024*1024*1024 / 8@
* @sec@: @1@
* @min@: @60@
* @hours@: @3600@
* @days@: @24*3600@
For sizes the base unit is byte, and for intervalls seconds.
]]></textile>
* `byte`: `1`
* `kbyte`: `1024`
* `mbyte`: `1024*1024`
* `gbyte`: `1024*1024*1024`
* `tbyte`: `1024*1024*1024*1024`
* `pbyte`: `1024*1024*1024*1024*1024`
* `bit`: `1 / 8`
* `kbit`: `1024 / 8`
* `mbit`: `1024*1024 / 8`
* `gbit`: `1024*1024*1024 / 8`
* `tbit`: `1024*1024*1024*1024 / 8`
* `pbit`: `1024*1024*1024*1024*1024 / 8`
* `sec`: `1`
* `min`: `60`
* `hours`: `3600`
* `days`: `24*3600`
For sizes the base unit is byte, and for intervals seconds.
]]></markdown>
</section>
<section title="Strings">
<textile><![CDATA[
<markdown><![CDATA[
There are 4 ways to specify a string:
* @'hello world'@
* @"hello world"@
* @e'hello world'@
* @e"hello world"@
* `'hello world'`
* `"hello world"`
* `e'hello world'`
* `e"hello world"`
The basic escape rules are the same for both:
* @"\n"@ is a newline, @"\r"@ a carriage return, @"\t"@ a tab stop
* @"\\"@ is one @\@, @"\""@ is one double quote @"@ and @"\'"@ a single quote @'@
* escaping single/double quote is optional if the symbol is not used to terminate the string, i.e. @'\"'@ = @'"'@ and @"\'"@ = @"'"@
* @"\xNN"@: NN must be hexadecimal characters, and the string is replaced with the decoded 8-bit value as a single byte
* All other @\@ occurences are *not* removed from the string.
The @e'..'@ and @e"..."@ variant do not allow any occurences of the last kind to happen.
* `"\n"` is a newline, `"\r"` a carriage return, `"\t"` a tab stop
* `"\\"` is one `\`, `"\""` is one double quote `"` and `"\'"` a single quote `'`
* escaping single/double quote is optional if the symbol is not used to terminate the string, i.e. `'\"'` = `'"'` and `"\'"` = `"'"`
* `"\xNN"`: NN must be hexadecimal characters, and the string is replaced with the decoded 8-bit value as a single byte
* All other `\` occurences are **not** removed from the string.
The `e'..'` and `e"..."` variant do not allow any occurences of the last kind to happen.
All other characters are allowed (the strings are parsed as 8-bit binary; lighttpd2 usually doesn't care about the encoding).
]]></textile>
]]></markdown>
</section>
<section title="Lists">
<textile><![CDATA[
<markdown><![CDATA[
Lists are ordered collections of other values:
* @[1, true, "foo"]@ (simple list)
* @[]@ (empty list)
* @[1]@ (list with one element)
* @[[1,2],[3,4],5]@ (nested lists)
* @[1,2,]@ (final value can have a trailing @,@ too)
* @(1, 2, 3)@ (alternative brackets with more than one element)
Note that @(1)@ is not a list; parentheses can also be used to group expressions as in @1*(2+3)@, and it is therefore recommend to use only @[]@ to specify lists.
]]></textile>
* `[1, true, "foo"]` (simple list)
* `[]` (empty list)
* `[1]` (list with one element)
* `[[1,2],[3,4],5]` (nested lists)
* `[1,2,]` (final value can have a trailing `,` too)
* `(1, 2, 3)` (alternative brackets with more than one element)
Note that `(1)` is not a list; parentheses can also be used to group expressions as in `1*(2+3)`, and it is therefore recommend to use only `[]` to specify lists.
]]></markdown>
</section>
<section title="Key-Value Lists">
<textile><![CDATA[
<markdown><![CDATA[
Key-value lists associates keys to values (both can be of any type); the syntax is:
* @[ "a" => 1, "b" => 10 ]@
As with normal lists the final value can have a trailing @,@ too. You cannot mix simple values and key-value associations in one list (nesting them works).
* `[ "a" => 1, "b" => 10 ]`
The @key => value@ operator is also only syntactic sugar for a @[key, value]@ list, the above example is the same as:
* @[ [a, 1], [b, 10] ]@
As with normal lists the final value can have a trailing `,` too. You cannot mix simple values and key-value associations in one list (nesting them works).
The `key => value` operator is also only syntactic sugar for a `[key, value]` list, the above example is the same as:
* `[ [a, 1], [b, 10] ]`
This especially means that key-value lists are ordered too, although they can get converted to hash tables in certain function calls internally.
]]></textile>
]]></markdown>
</section>
<section title="Expressions">
<textile><![CDATA[
<markdown><![CDATA[
There are operators available for some value types:
* for integers: @+@, @-@, @*@ and @/@
* for strings: @+@ (concatenate two strings)
* for lists: @+@ (append lists)
* for integers: `+`, `-`, `*` and `/`
* for strings: `+` (concatenate two strings)
* for lists: `+` (append lists)
Also you can cast strings and booleans to integers and any value to strings:
* @cast(int) "256"@ (only supports decimal representations and no suffix like above)
* @cast(int) true@ (@true@ maps to @1@ and @false@ to @0@)
* @cast(string) 5@
* `cast(int) "256"` (only supports decimal representations and no suffix like above)
* `cast(int) true` (`true` maps to `1` and `false` to `0`)
* `cast(string) 5`
Expressions can be grouped to override default association:
* @3 * (1 + 2)@ vs. @3 * 1 + 2@ and so on
]]></textile>
* `3 * (1 + 2)` vs. `3 * 1 + 2` and so on
]]></markdown>
</section>
<section title="Action Blocks">
<textile><![CDATA[
<markdown><![CDATA[
An action block consists of a list of function calls (in action context) and conditionals; it is treated like a value, i.e. can be assigned to variables and used as parameter in function calls.
Action blocks can also contain variable assignments and setup blocks/function calls, which are not part of the "action block value" itself, but are evaluated while parsing the config.
The syntax is:
<pre>
```
{
log "hello world";
if req.path =$ ".hidden" { static; }
}
</pre>
```
The complete config is an action block too (but without the surrounding curly braces); conditionals also use action blocks for their branches.
Each action block that is not a condition branch starts a new nested variable scope;
]]></textile>
]]></markdown>
</section>
<section title="Variables" anchor="variables">
<textile><![CDATA[
Variable names start with a alphabetic character (@a-z@ and @A-Z@) or an underscore @_@, and are followed by alphanumeric characters, underscores @_@ and dots @.@; keywords are not allowed as variable names.
<markdown><![CDATA[
Variable names start with a alphabetic character (`a-z` and `A-Z`) or an underscore `_`, and are followed by alphanumeric characters, underscores `_` and dots `.`; keywords are not allowed as variable names.
Variables store values, and the name can be used in place of an actual value; later modifications to a variable have no influence on previous uses (i.e. are only evaluated while *parsing* the config).
Variables store values, and the name can be used in place of an actual value; later modifications to a variable have no influence on previous uses (i.e. are only evaluated while **parsing** the config).
Variables are assigned values with @=@ (and a terminating @;@)
Variables are assigned values with `=` (and a terminating `;`)
<pre>
```
my_types = [".txt" => "text/html"];
php = {
if phys.path =$ ".php" { fastcgi "unix:/var/run/lighttpd/php.sock"; }
};
</pre>
```
By default variables assignment overwrites an existing variable (in its previous scope) or, if it doesn't exist, creates a new one in the local scope (i.e. it will only be available in the current scope and nested descendants).
You can explicitly create a new variable in the local scope (hiding variables in parent scopes with the same name) by prefixing the assignment with @local@:
You can explicitly create a new variable in the local scope (hiding variables in parent scopes with the same name) by prefixing the assignment with `local`:
<pre>
```
local wwwpath = "/var/www/example.com";
</pre>
```
You can also create variables in the global scope by prefixing the assignment with @global@.
The main config already is in a nested scope (i.e. *not* the global scope). The global scope is not destroyed after config loading, and can be used in delayed config loading (say from SQL in the future).
You can also create variables in the global scope by prefixing the assignment with `global`.
The main config already is in a nested scope (i.e. **not** the global scope). The global scope is not destroyed after config loading, and can be used in delayed config loading (say from SQL in the future).
If a variable name is used in a context it will always use the definition from the nearest scope.
]]></textile>
]]></markdown>
<example>
<description>
<description><markdown>
This example illustrates that variables are evaluated while parsing the config.
</description>
</markdown></description>
<config>
foo = "bar";
if req.path == "/somepath" {
@ -184,9 +193,9 @@
</example>
<example>
<description>
<description><markdown>
This example illustrates scoping.
</description>
</markdown></description>
<config>
foo = "bar";
php = {
@ -200,57 +209,60 @@
</section>
<section title="Special Variables">
<textile><![CDATA[
@sys.*@ variables are readonly. right now the following @sys.*@ variables are available:
* @sys.pid@: the process id of lighttpd
* @sys.cwd@: the current working directory
* @sys.env.X@: the system environment variable with name @X@ (for any @X@)
]]></textile>
<markdown><![CDATA[
`sys.*` variables are readonly. right now the following `sys.*` variables are available:
* `sys.pid`: the process id of lighttpd
* `sys.cwd`: the current working directory
* `sys.env.X`: the system environment variable with name `X` (for any `X`)
]]></markdown>
</section>
</section>
<section title="Function calls" anchor="funcalls">
<textile><![CDATA[
<markdown><![CDATA[
There are three types of function calls:
* actions
* setups
* options
Actions can only be used in action (block) context, setups only in setup (block) context, and options can be used in both.
A setup context is started with the keyword @setup@, and is followed by either a single setup function call or a setup block.
A setup context is started with the keyword `setup`, and is followed by either a single setup function call or a setup block.
Setup function calls are run immediately when they occur (they are used to "setup" the webserver environment, like listening on TCP sockets, and setting default options), while action function calls are run for each request (mapping request urls to physical paths, handling requests, modifying the default options).
The actions, setups and options are provided by the "modules":index_modules.html#index_modules.
]]></textile>
The actions, setups and options are provided by the [modules](index_modules.html#index_modules).
]]></markdown>
<section title="Includes" anchor="includes">
<textile><![CDATA[
<markdown><![CDATA[
Includes are similar to function calls in the syntax, but are directly handled by the config parser. They are only allowed in action context, as they insert a reference to an action block at the point they are used.
There are three types of includes:
* @include "/etc/lighttpd/vhosts/*.conf";@: include files like the main config itself; the path can contain wildcards
* @include_shell "/etc/lighttpd/config_generator.sh";@: runs the specified command, and parses the output of it as config file
* @include_lua "/etc/lighttpd/complex.lua"@: includes a Lua config file. The single action to be executed must be returned in the global @actions@ variable (or leave it empty to do nothing). See also "@lua.handler@":mod_lua.html#mod_lua__action_lua-handler
* `include "/etc/lighttpd/vhosts/*.conf";`: include files like the main config itself; the path can contain wildcards
* `include_shell "/etc/lighttpd/config_generator.sh";`: runs the specified command, and parses the output of it as config file
* `include_lua "/etc/lighttpd/complex.lua"`: includes a Lua config file. The single action to be executed must be returned in the global `actions` variable (or leave it empty to do nothing). See also [`lua.handler`](mod_lua.html#mod_lua__action_lua-handler).
Includes also create a new nested scope.
]]></textile>
]]></markdown>
</section>
<section title="Debug Print">
<textile><![CDATA[
Similar to includes @__print@ is a special function, but is available in action and setup context. It logs the string values of its parameter(s) with log level "debug".
]]></textile>
<markdown><![CDATA[
Similar to includes `__print` is a special function, but is available in action and setup context. It logs the string values of its parameter(s) with log level "debug".
]]></markdown>
</section>
</section>
<section title="Conditions" anchor="conditions">
<textile><![CDATA[
Conditions (known from Lighttpd 1.x) are the equivalent to "if"s in most programming languages. There are also "else" and "elseif" equivalents.
They are created by a comparison of a condition variable and a value that is evaluated at runtime (for each request).
Conditions can be nested, and you can group them with @and@ and @or@ operators. @and@ binds stronger than @or@, although it is preferred to group them with parentheses.
]]></textile>
<markdown><![CDATA[
Conditions (known from Lighttpd 1.x) are the equivalent to "if"s in most programming languages. There are also "else" and "elseif" equivalents.
They are created by a comparison of a condition variable and a value that is evaluated at runtime (for each request).
Conditions can be nested, and you can group them with `and` and `or` operators. `and` binds stronger than `or`, although it is preferred to group them with parentheses.
]]></markdown>
<example>
<config>
@ -269,31 +281,34 @@
</example>
<section title="Syntax">
<textile><![CDATA[
<markdown><![CDATA[
The basic syntax forms are:
* @if <expr> { ... }@
* @if <expr> { ... } else { ... }@
* @if <expr> { ... } else if <expr2> { ... }@
* @if <expr> { ... } else if <expr2> { ... } ...@ (continue with @else@ or @else if@)
A condition expression @<expr>@ is:
* @(<expr>)@
* @<expr1> and <expr2>@
* @<expr1> or <expr1>@ (@<expr1> and <expr2> or <expr3>@ = @(<expr1> and <expr2>) or <expr3>@; @and@ has higher precedence)
* @<condvar> <op> <value>@ for @<condvar>@ being a condition variable (with a type different from boolean), @<op>@ an condition operator and @<value>@ a string or a number.
* @<condvar>@ or @!<condvar>@ for a boolean condition variable.
]]></textile>
* `if <expr> { ... }`
* `if <expr> { ... } else { ... }`
* `if <expr> { ... } else if <expr2> { ... }`
* `if <expr> { ... } else if <expr2> { ... } ...` (continue with `else` or `else if`)
A condition expression `<expr>` is:
* `(<expr>)`
* `<expr1> and <expr2>`
* `<expr1> or <expr1>` (`<expr1> and <expr2> or <expr3>` = `(<expr1> and <expr2>) or <expr3>`; `and` has higher precedence)
* `<condvar> <op> <value>` for `<condvar>` being a condition variable (with a type different from boolean), `<op>` an condition operator and `<value>` a string or a number.
* `<condvar>` or `!<condvar>` for a boolean condition variable.
]]></markdown>
</section>
<section title="Condition variables" anchor="condition_vars">
<textile><![CDATA[
<markdown><![CDATA[
There are three categories of condvars:
* request.xyz (can be abbreviated by req.xyz)
* physical.xyz (can be abbreviated by phys.xyz)
* response.xyz (can be abbreviated by resp.xyz)
table(table table-striped).
|_. variable |_. description |
| variable | description |
|----------|-------------|
| request.localip | ip address of the listing socket, the client connected to (filename for unix sockets) |
| request.localport | port number of the listening socket, -1 for unix sockets |
| request.remoteip | ip address of the client |
@ -308,7 +323,7 @@
| request.header["name"] | request header _name_ e.g. request.header["referer"] |
| request.is_handled | boolean condition, does request already have a handler (static, fastcgi..) |
| request.environment["name"] | (or short request.env["name"]) CGI environment |
| | |
|-|-|
| physical.path | physical path of the file to be served. e.g. document root + path |
| physical.exists | boolean condition, indicates whether the requested file (normal file, directory or even a special file) exists |
| physical.size | integer. size of the requested file. -1 if file doesn't exist |
@ -316,24 +331,26 @@
| physical.is_file | boolean condition, indicates whether the requested file is a normal file (e.g. no unix socket etc) |
| physical.docroot | document root |
| physical.pathinfo | pathinfo |
| | |
|-|-|
| response.status | response status code (blocks request until response header is available) |
| response.header["name"] | response header (blocks request until response header is available) |
]]></textile>
{:.table .table-striped}
]]></markdown>
</section>
<section title="Condition operators">
<textile><![CDATA[
table(table table-striped).
|_. op |_. description |_. op |_. description |
| <notextile>==</notextile> | compares two values on equality | != | negative == |
<markdown><![CDATA[
| op | description | op | description |
|----|-------------|----|-------------|
| == | compares two values on equality | != | negative == |
| <= | less than or equal | < | less than |
| >= | greater than or equal | > | greater than |
| =~ | regular expression match | !~ | negative =~ |
| =^ | prefix match | !^ | negative =^ |
| =$ | suffix match | !$ | negative =$ |
| =/ | cidr match | !/ | negative =/ |
]]></textile>
{:.table .table-striped}
]]></markdown>
</section>
</section>

View File

@ -1,39 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<angel-module xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Angel Configuration">
<description>
<textile>
lighttpd2 consists of two main binaries: the angel (@lighttpd2@) and the worker (@lighttpd2-worker@). The "main configuration":core_config.html#core_config is used by the worker, and this chapter describes the configuration for the angel.
A standard distribution should install a angel config in @/etc/lighttpd2/angel.conf@ with reasonable defaults which should work for most basic setups.
</textile>
</description>
<description><markdown>
lighttpd2 consists of two main binaries: the angel (`lighttpd2`) and the worker (`lighttpd2-worker`). The [main configuration](core_config.html#core_config) is used by the worker, and this chapter describes the configuration for the angel.
A standard distribution should install a angel config in `/etc/lighttpd2/angel.conf` with reasonable defaults which should work for most basic setups.
</markdown></description>
<section title="Angel concept">
<textile>
<markdown>
You can start the worker without the angel, but the angel provides some useful features:
* The angel itself usually runs as root (needed for example to bind to privileged ports), but will spawn the worker with dropped privileges (usually a user like @www-data@ is used). The worker doesn't do any privilege dropping itself.
* The angel itself usually runs as root (needed for example to bind to privileged ports), but will spawn the worker with dropped privileges (usually a user like `www-data` is used). The worker doesn't do any privilege dropping itself.
* The angel can open/create log files for the worker with root permissions
* The angel supports a graceful restart of the worker for config reloading: a new instance is spawned, and if it started successfully (checking config, ...) it will replace the old instance. The old instance will finish the remaining requests.
* The angel supports a graceful restart of the worker for config reloading: a new instance is spawned, and if it started successfully (checking config, ...) it will replace the old instance. The old instance will finish the remaining requests.
As the angel is responsible for creating the listening network sockets, it can keep them open all the time and no request is lost.
* The angel also does a simple supervise: if the worker crashes the angel will respawn it.
</textile>
</markdown>
</section>
<section title="Config items">
<textile>
The config syntax is very similar to the "main configuration":core_config, although it has no action blocks, setup blocks, conditionals and scopes.
</textile>
<markdown>
The config syntax is very similar to the [main configuration](core_config), although it has no action blocks, setup blocks, conditionals and scopes.
</markdown>
<item name="user">
<short>drops privileges for spawning the worker</short>
<parameter name="username">
<short>username to drop privileges to for spawning the worker</short>
</parameter>
<description>
<textile>
This item can only be specified once; if it is not specified it won't drop privileges at all, which is useful if the angel itself doesn't run as root. It should go without saying that you should never run the worker as root.
The username is also used to find all groups the user is in.
</textile>
</description>
<description><markdown>
This item can only be specified once; if it is not specified it won't drop privileges at all, which is useful if the angel itself doesn't run as root. It should go without saying that you should never run the worker as root.
The username is also used to find all groups the user is in.
</markdown></description>
<example>
<config>
user "www-data";
@ -46,12 +43,10 @@
<parameter name="groupname">
<short>groupname to drop privileges to for spawning the worker</short>
</parameter>
<description>
<textile>
Specify the main group to drop privileges to; a process can have multiple groups, and the others are given by the groups the user specified by @user@ is in.
The default is the main group of the user specified by @user@, or not dropping privileges at all.
</textile>
</description>
<description><markdown>
Specify the main group to drop privileges to; a process can have multiple groups, and the others are given by the groups the user specified by `user` is in.
The default is the main group of the user specified by `user`, or not dropping privileges at all.
</markdown></description>
<example>
<config>
group "www-data";
@ -62,13 +57,11 @@
<item name="binary">
<short>specifies path to worker binary</short>
<parameter name="path">
<short>path to the @lighttpd2-worker@ binary</short>
<short>path to the lighttpd2-worker binary</short>
</parameter>
<description>
<textile>
This item should only be needed if you didn't install the binaries at all (for testing).
</textile>
</description>
<description><markdown>
This item should only be needed if you didn't install the binaries at all (for testing).
</markdown></description>
<example>
<config>
binary "/home/source/lighttpd2/autobuild/src/main/lighttpd2-worker";
@ -81,11 +74,9 @@
<parameter name="path">
<short>path to the main config file</short>
</parameter>
<description>
<textile>
By default @/etc/lighttpd2/lighttpd.conf@ is used.
</textile>
</description>
<description><markdown>
By default `/etc/lighttpd2/lighttpd.conf` is used.
</markdown></description>
<example>
<config>
config "/etc/lighttpd2-test/lighttpd.conf";
@ -98,11 +89,9 @@
<parameter name="path">
<short>path to the lua config file</short>
</parameter>
<description>
<textile>
By default a normal config file is used; you must use either a normal config file or a lua config file.
</textile>
</description>
<description><markdown>
By default a normal config file is used; you must use either a normal config file or a lua config file.
</markdown></description>
<example>
<config>
luaconfig "/etc/lighttpd2/lighttpd.lua";
@ -115,11 +104,9 @@
<parameter name="path">
<short>path to the directory containing modules for the worker</short>
</parameter>
<description>
<textile>
This item should only be needed if you didn't install the binaries at all (for testing). For autotool builds the "real" module binaries are in a @.libs@ subdirectory.
</textile>
</description>
<description><markdown>
This item should only be needed if you didn't install the binaries at all (for testing). For autotool builds the "real" module binaries are in a `.libs` subdirectory.
</markdown></description>
<example>
<config>
modules_path "/home/source/lighttpd2/autobuild/src/modules/.libs";
@ -132,12 +119,10 @@
<parameter name="wrappers">
<short>path to a wrapper command and its arguments</short>
</parameter>
<description>
<textile>
This item appends all given strings to the comannd prefix list (which starts as empty list). Before spawning the worker the binary path to the worker and its arguments (config, module path) are appended.
Wrappers can be used to run the worker with valgrind, strace and similar.
</textile>
</description>
<description><markdown>
This item appends all given strings to the command prefix list (which starts as empty list). Before spawning the worker the binary path to the worker and its arguments (config, module path) are appended.
Wrappers can be used to run the worker with valgrind, strace and similar.
</markdown></description>
<example>
<config>
# in multiple lines
@ -156,11 +141,9 @@
<parameter name="vars">
<short>list of environment variables to add for the worker to run with</short>
</parameter>
<description>
<textile><![CDATA[
Append the given list of environment variables (starts empty), which can be either strings of the form @"var=xyz"@ or key-value pairs @"var" => "xyz"@ (the keys must not contain any @=@).
]]></textile>
</description>
<description><markdown><![CDATA[
Append the given list of environment variables (starts empty), which can be either strings of the form `"var=xyz"` or key-value pairs `"var" => "xyz"` (the keys must not contain any `=`).
]]></markdown></description>
<example>
<config>
# helps debugging with valgrind:
@ -174,11 +157,9 @@
<parameter name="varnames">
<short>list of environment variable names to copy</short>
</parameter>
<description>
<textile>
Adds copies of variables from the current environment. By default all variables will be dropped.
</textile>
</description>
<description><markdown>
Adds copies of variables from the current environment. By default all variables will be dropped.
</markdown></description>
<example>
<config>
env_copy [ "PATH" ];
@ -191,10 +172,10 @@
<parameter name="limit">
<short>limit in bytes</short>
</parameter>
<description>
Maximum size of a core file, in bytes, that may be created by the worker. Core files are created when the worker crashes.
<description><markdown>
Maximum size of a core file, in bytes, that may be created by the worker. Core files are created when the worker crashes.
0 disables core files, and by default the limit is not changed.
</description>
</markdown></description>
</item>
<item name="max_open_files">
@ -202,10 +183,10 @@
<parameter name="limit">
<short>maximum number of open files</short>
</parameter>
<description>
The worker limits the maximum number of connection based on the maximum number of open files (max connections = max open files / 4).
<description><markdown>
The worker limits the maximum number of connection based on the maximum number of open files (max connections = max open files / 4).
By default the limit is not changed.
</description>
</markdown></description>
<example>
<config>
# max 4096 connections
@ -219,20 +200,19 @@
<parameter name="list">
<short>list of network mask (CIDR) + optional port or unix domain socket addresses</short>
</parameter>
<description>
<textile>
The worker uses the angel to bind TCP/unix sockets; the angel checks whether those binds are allowed. If no @allow_listen@ is specified, all TCP binds (IPv4 and IPv6) using port 80 or 443 are allowed.
IPv4 and IPv6 use different masks (no IPv4 to IPv6 mapping), the network length for the CIDR mask is optional (defaults to a host address), and the port is optional too (allowing both 80 and 443 if omitted).
Formats:
* TCP on IPv4: @ipv4@, @ipv4:port@, @ipv4/net@, @ipv4/net:port@
* TCP on IPv6: @ipv6@, @ipv6/net@, @[ipv6]@, @[ipv6/net]@, @[ipv6]:port@, @[ipv6/net]:port@
* Unix domain: @unix:/wildcard/path/to/*.socket@
</textile>
</description>
<description><markdown>
The worker uses the angel to bind TCP/unix sockets; the angel checks whether those binds are allowed. If no `allow_listen` is specified, all TCP binds (IPv4 and IPv6) using port 80 or 443 are allowed.
IPv4 and IPv6 use different masks (no IPv4 to IPv6 mapping), the network length for the CIDR mask is optional (defaults to a host address), and the port is optional too (allowing both 80 and 443 if omitted).
Formats:
* TCP on IPv4: `ipv4`, `ipv4:port`, `ipv4/net`, `ipv4/net:port`
* TCP on IPv6: `ipv6`, `ipv6/net`, `[ipv6]`, `[ipv6/net]`, `[ipv6]:port`, `[ipv6/net]:port`
* Unix domain: `unix:/wildcard/path/to/*.socket`
</markdown></description>
<example>
<description>
Only allow TCP port 8080 for IPv4 and IPv6 and unix domain socket @/run/lighttpd/internal.sock@.
</description>
<description><markdown>
Only allow TCP port 8080 for IPv4 and IPv6 and unix domain socket `/run/lighttpd/internal.sock`.
</markdown></description>
<config>
allow_listen [ "0.0.0.0/0:8080", "[::/0]:8080" ];
allow_listen "unix:/run/lighttpd/internal.sock";

View File

@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Fetch API" order="core_regex_after_01_fetch">
<description>
<textile>
The Fetch API provides a common interface between lighttpd modules to lookup entries in a database. Both lookup key and data are simple (binary) strings.
<description><markdown>
The Fetch API provides a common interface between lighttpd modules to lookup entries in a database. Both lookup key and data are simple (binary) strings.
So far only a "fetch.files_static":plugin_core.html#plugin_core__setup_fetch-files_static is providing a database, and only "gnutls":mod_gnutls.html#mod_gnutls__setup_gnutls is using it to lookup SNI certificates.
</textile>
</description>
So far only a [fetch.files_static](plugin_core.html#plugin_core__setup_fetch-files_static) is providing a database, and only [gnutls](mod_gnutls.html#mod_gnutls__setup_gnutls) is using it to lookup SNI certificates.
</markdown></description>
</chapter>

View File

@ -2,21 +2,23 @@
<chapter xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Introduction" order="a01_introduction">
<section title="Running lighttpd2">
<textile><![CDATA[
<markdown><![CDATA[
You need two config files for lighttpd, which are usually in the following two locations:
* "@/etc/lighttpd2/lighttpd.conf@":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/lighttpd.conf: the main config, see "Main Configuration":core_config.html#core_config. It can be split into multiple files, see "Includes":core_config.html#core_config__includes.
* "@/etc/lighttpd2/angel.conf@":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/angel.conf: the angel config, see "Angel Configuration":core_config_angel.html#core_config_angel.
* [`/etc/lighttpd2/lighttpd.conf`](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/lighttpd.conf): the main config, see [Main Configuration](core_config.html#core_config). It can be split into multiple files, see [Includes](core_config.html#core_config__includes).
* [`/etc/lighttpd2/angel.conf`](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/angel.conf): the angel config, see [Angel Configuration](core_config_angel.html#core_config_angel).
The "@contrib/@":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib directory in the sources includes example config files.
The [`contrib/`](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib) directory in the sources includes example config files.
Then start lighttpd2 with:
<pre>/usr/sbin/lighttpd2 -c /etc/lighttpd2/angel.conf</pre>
```
/usr/sbin/lighttpd2 -c /etc/lighttpd2/angel.conf
```
The process will not fork into background, you need to do that yourself if you want that.
Our recommended way to run lighttpd2 is "runit":http://smarden.org/runit/useinit.html (have a look at the "@contrib/service@":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/service directory).
]]></textile>
The process will not fork into background, you need to do that yourself if you want that.
Our recommended way to run lighttpd2 is [runit](http://smarden.org/runit/useinit.html) (have a look at the [`contrib/service`](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/service) directory).
]]></markdown>
</section>
</chapter>

View File

@ -1,26 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Lua API" order="core_regex_after_02_lua">
<description>
<textile>
Lua can be used to generate configs (like a shortcut to "@include_shell@":core_config.html#core_config__includes) or to write actual response handlers.
<description><markdown>
Lua can be used to generate configs (like a shortcut to [`include_shell`](core_config.html#core_config__includes)) or to write actual response handlers.
Using Lua to generate configs doesn't have any performance impact; in this case Lua is only run at startup to generate the config, and there is no Lua involved for processing requests.
Using Lua to generate configs doesn't have any performance impact; in this case Lua is only run at startup to generate the config, and there is no Lua involved for processing requests.
As a @lua_State@ itself is not thread-safe, you have two ways to use Lua configs:
* "@include_lua@":core_config.html#core_config__includes and "@lua.plugin@":mod_lua.html#mod_lua__setup_lua-plugin : using a global server lock, but with sharing the same @lua_State@ in all workers
* "@lua_handler@":mod_lua.html#mod_lua__action_lua-handler: without locking, and every worker has its own @lua_State@ (and they cannot share their global context).
</textile>
</description>
As a `lua_State` itself is not thread-safe, you have two ways to use Lua configs:
* [`include_lua`](core_config.html#core_config__includes) and [`lua.plugin`](mod_lua.html#mod_lua__setup_lua-plugin): using a global server lock, but with sharing the same `lua_State` in all workers
* [`lua_handler`](mod_lua.html#mod_lua__action_lua-handler): without locking, and every worker has its own `lua_State` (and they cannot share their global context).
</markdown></description>
<section title="Lua Config">
<textile>
This section describe how to translate concepts from the main config to Lua. You can write the whole config in Lua or only parts and include them (for example with "@include_lua@":core_config.html#core_config__includes).
</textile>
<markdown>
This section describe how to translate concepts from the main config to Lua. You can write the whole config in Lua or only parts and include them (for example with [`include_lua`](core_config.html#core_config__includes)).
</markdown>
<example title="Example - debug.lua">
<description><textile><![CDATA[
The following Lua snippet saved as "debug.lua" could for example be included with @include_lua "debug.lua"@.
]]></textile></description>
<description><markdown><![CDATA[
The following Lua snippet saved as "debug.lua" could for example be included with `include_lua "debug.lua"`.
]]></markdown></description>
<config><![CDATA[
function mydebug(vr)
@ -55,62 +54,63 @@
</example>
<section title="Values">
<textile><![CDATA[
* Boolean: Lua supports @true@ and @false@ directly
* Integers: Lua has its own number type (usually a "@double@":http://en.wikipedia.org/wiki/Double-precision_floating-point_format), and doesn't know any of the suffixes.
<markdown><![CDATA[
* Boolean: Lua supports `true` and `false` directly
* Integers: Lua has its own number type (usually a [`double`](https://en.wikipedia.org/wiki/Double-precision_floating-point_format)), and doesn't know any of the suffixes.
* Strings: Lua supports strings directly. Check the Lua reference for the various quoting styles.
* Lists and Key-Value-Lists: Lua has a "table" type; it can contain sequential lists and associative mappings. Use @{1, 2, 3}@ to create simple lists, @{a=1, b=2}@ to create unique mappings (which get converted to Key-Value-Lists) or @{{"a",1},{"a",2}}@ to explicitly create Key-Value-Lists (where a key can be used more than once and the order matters).
Don't mix sequential lists and associative mappings.
If you get a List (possible a Key-Value-List) value from lighttpd it is represented as sequential list but has a special @__index@ meta-table method supporting strings and @nil@ as lookup parameter, i.e. you can treat a Key-Value-List like an associative mapping in Lua (see for example the options handling in "contrib/secdownload.lua":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/secdownload.lua).
* Lists and Key-Value-Lists: Lua has a "table" type; it can contain sequential lists and associative mappings. Use `{1, 2, 3}` to create simple lists, `{a=1, b=2}` to create unique mappings (which get converted to Key-Value-Lists) or `{{"a",1},{"a",2}}` to explicitly create Key-Value-Lists (where a key can be used more than once and the order matters).
Don't mix sequential lists and associative mappings.
If you get a List (possible a Key-Value-List) value from lighttpd it is represented as sequential list but has a special `__index` meta-table method supporting strings and `nil` as lookup parameter, i.e. you can treat a Key-Value-List like an associative mapping in Lua (see for example the options handling in [contrib/secdownload.lua](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/secdownload.lua)).
* Expressions and variables just are the usual Lua things; there is no direct access to the lighttpd config variables (yet).
* Action blocks: you can make an action from a list of actions using the "list action":plugin_core.html#plugin_core__action_list (@act = action.list(act1, act2)@)
]]></textile>
* Action blocks: you can make an action from a list of actions using the [list action](plugin_core.html#plugin_core__action_list) (`act = action.list(act1, act2)`)
]]></markdown>
</section>
<section title="Function calls">
<textile><![CDATA[
Action context is given by prefixing the function name with @action.@, and setup context by prefixing with @setup.@. Don't try to call setups in request handling.
<markdown><![CDATA[
Action context is given by prefixing the function name with `action.`, and setup context by prefixing with `setup.`. Don't try to call setups in request handling.
Also each Lua function can act as an action (see the debug.lua example above), taking a virtual request object as parameter.
Includes are not supported, neither is the debug @__print@ (there are other logging methods available).
]]></textile>
Includes are not supported, neither is the debug `__print` (there are other logging methods available).
]]></markdown>
</section>
<section title="Conditions">
<textile><![CDATA[
<markdown><![CDATA[
Conditions are the ugliest part: there is no way translating native Lua if statements into the lighttpd config, so they need to be constructed manually.
Only the long names of the condition variables are available in Lua. The condition operators are all given names and appended to the condition variable, and then called with the value to compare with.
table(table table-striped).
|_. op |_. Lua name |_. op |_. Lua name |
| <notextile>==</notextile> | @:eq@ | != | @:ne@ |
| <= | @:le@ | < | @:lt@ |
| >= | @:ge@ | > | @:gt@ |
| =~ | @:match@ | !~ | @:nomatch@ |
| =^ | @:prefix@ | !^ | @:notprefix@ |
| =$ | @:suffix@ | !$ | @:notsuffix@ |
| =/ | @:ip@ | !/ | @:notip@ |
| op | Lua name | op | Lua name |
|----|-----------|----|----------|
| == | `:eq` | != | `:ne` |
| <= | `:le` | < | `:lt` |
| >= | `:ge` | > | `:gt` |
| =~ | `:match` | !~ | `:nomatch` |
| =^ | `:prefix` | !^ | `:notprefix` |
| =$ | `:suffix` | !$ | `:notsuffix` |
| =/ | `:ip` | !/ | `:notip` |
{:.table .table-striped }
Boolean condition variables are called with @:is()@ or @:isnot()@.
Boolean condition variables are called with `:is()` or `:isnot()`.
The result of such call (a "condition") is then passed as first parameter to "@action.when@":plugin_core#plugin_core__action_when.
]]></textile>
The result of such call (a "condition") is then passed as first parameter to [`action.when`](plugin_core#plugin_core__action_when).
]]></markdown>
<example title="Example - admin only">
<description><textile>
Translating @if req.env["REMOTE_USER"] != "admin" { auth.deny; }@ to Lua:
</textile></description>
<description><markdown>
Translating `if req.env["REMOTE_USER"] != "admin" { auth.deny; }` to Lua:
</markdown></description>
<config><![CDATA[
actions = action.when(request.environment["REMOTE_USER"]:ne("admin"), action.auth.deny())
]]></config>
</example>
<example title="Example - physical files only">
<description><textile>
Translating @if !phys.exists { auth.deny; }@ to Lua:
</textile></description>
<description><markdown>
Translating `if !phys.exists { auth.deny; }` to Lua:
</markdown></description>
<config><![CDATA[
actions = action.when(physical.exists:isnot(), action.auth.deny())
]]></config>
@ -119,66 +119,67 @@
</section>
<section title="API">
<textile><![CDATA[
<markdown><![CDATA[
This section documents the object types you need to handle requests; you will probably start from the Virtual Request object you get as parameter in your handler.
Object fields should be accessed with @.field@ or @["field"]@, for example:
Object fields should be accessed with `.field` or `["field"]`, for example:
<pre>
```
e = vr.env
e["XXX"] = "abc"
</pre>
```
Fields tagged with (ro) are read only; that does not mean the fields value can't be modified, you only cannot overwrite the field with another object. Readonly string / number properties are really read only though.
Call object methods with @:method(...)@:
Call object methods with `:method(...)`:
<pre>
```
vr:print("Hello World")
</pre>
```
*Note*:
The @obj:method(par1, par2, ...)@ syntax is just another way to say @obj["method"](obj, par1, par2, ...)@ (but @obj@ is only evaluated once), so field and method names live in the same namespace.
This means that our container types cannot provide access to fields which have the same names as the methods (and the methods starting with "__" are not listed here), so you have to use explicit access methods to read generic fields in such containers (write is not a problem as we don't allow writing methods).
All container types should provide a @get@ and a @set@ method to provide "clean" access to the container contents.
**Note**:
The `obj:method(par1, par2, ...)` syntax is just another way to say `obj["method"](obj, par1, par2, ...)` (but `obj` is only evaluated once), so field and method names live in the same namespace.
This means that our container types cannot provide access to fields which have the same names as the methods (and the methods starting with "__" are not listed here), so you have to use explicit access methods to read generic fields in such containers (write is not a problem as we don't allow writing methods).
All container types should provide a `get` and a `set` method to provide "clean" access to the container contents.
h3. pairs()
### pairs()
Some objects may provide a @:pairs()@ method to loop through the fields (not the methods); this works for simple things like
Some objects may provide a `:pairs()` method to loop through the fields (not the methods); this works for simple things like
<pre>
```
for k, v in vr.env:pairs() do
vr:print("env['" .. k .. "'] = '" .. v .. "'")
end
</pre>
```
lua expects that the @:pairs@ method returns a @next, obj, startkey@ tuple and loops through the list with @k = startkey; while k, v = next(obj, k) do ... end@; but the @next()@ method is supposed to use @k@ as previous key and to return the next one.
Our @next@ methods will keep the current position in an internal object (associated with the @next@ function as upvalue), and will advance on every call ignoring the @obj@ and @k@ parameter.
]]></textile>
lua expects that the `:pairs` method returns a `next, obj, startkey` tuple and loops through the list with `k = startkey; while k, v = next(obj, k) do ... end`; but the `next()` method is supposed to use `k` as previous key and to return the next one.
Our `next` methods will keep the current position in an internal object (associated with the `next` function as upvalue), and will advance on every call ignoring the `obj` and `k` parameter.
]]></markdown>
<section title="Global constants">
<textile><![CDATA[
@liHandlerResult@ enumeration values:
<markdown><![CDATA[
`liHandlerResult` enumeration values:
* @lighty.HANDLER_GO_ON@
* @lighty.HANDLER_COMEBACK@
* @lighty.HANDLER_WAIT_FOR_EVENT@
* @lighty.HANDLER_ERROR@
]]></textile>
* `lighty.HANDLER_GO_ON`
* `lighty.HANDLER_COMEBACK`
* `lighty.HANDLER_WAIT_FOR_EVENT`
* `lighty.HANDLER_ERROR`
]]></markdown>
</section>
<section title="Global methods">
<textile><![CDATA[
* @lighty.print@ (and @lighty.error@ and @print@): print parameters via lua "tostring" method as ERROR in global server context
* @lighty.warning@: print parameters via lua "tostring" method as WARNING in global server context
* @lighty.info@: print parameters via lua "tostring" method as INFO in global server context
* @lighty.debug@: print parameters via lua "tostring" method as DEBUG in global server context
* @lighty.filter_in(class)@: creates a new action, which adds a incoming filter from @class:new(vr)@ if called at runtime
* @lighty.filter_out(class)@: creates a new action, which adds a outgoing filter from @class:new(vr)@ if called at runtime
* @lighty.md5(str)@: calculates the md5 checksum of the string @str@ (returns the digest as string in hexadecimal)
* @lighty.sha1(str)@: calculates the sha1 checksum of the string @str@ (returns the digest as string in hexadecimal)
* @lighty.sha256(str)@: calculates the sha256 checksum of the string @str@ (returns the digest as string in hexadecimal)
]]></textile>
<markdown><![CDATA[
* `lighty.print` (and `lighty.error` and `print`): print parameters via lua "tostring" method as ERROR in global server context
* `lighty.warning`: print parameters via lua "tostring" method as WARNING in global server context
* `lighty.info`: print parameters via lua "tostring" method as INFO in global server context
* `lighty.debug`: print parameters via lua "tostring" method as DEBUG in global server context
* `lighty.filter_in(class)`: creates a new action, which adds a incoming filter from `class:new(vr)` if called at runtime
* `lighty.filter_out(class)`: creates a new action, which adds a outgoing filter from `class:new(vr)` if called at runtime
* `lighty.md5(str)`: calculates the md5 checksum of the string `str` (returns the digest as string in hexadecimal)
* `lighty.sha1(str)`: calculates the sha1 checksum of the string `str` (returns the digest as string in hexadecimal)
* `lighty.sha256(str)`: calculates the sha256 checksum of the string `str` (returns the digest as string in hexadecimal)
* `lighty.path_simplify(str)`: return simplified path
]]></markdown>
<example>
<config><![CDATA[
@ -205,167 +206,177 @@
</section>
<section title="Virtual Request">
<textile><![CDATA[
<markdown><![CDATA[
Fields:
* @con@(ro): Connection
* @in@(ro): Chunk Queue, read request post content
* @out@(ro): Chunk Queue, write response content
* @env@(ro): Environment, (fast)cgi environment
* @req@(ro): Request, data from request header
* @resp@(ro): Response, response header data
* @phys@(ro): Physical, paths and filenames
* @is_handled@(ro): whether vrequest is already handled
* @has_response@(ro): whether the response headers (and status) is available
* `con`(ro): Connection
* `in`(ro): Chunk Queue, read request post content
* `out`(ro): Chunk Queue, write response content
* `env`(ro): Environment, (fast)cgi environment
* `req`(ro): Request, data from request header
* `resp`(ro): Response, response header data
* `phys`(ro): Physical, paths and filenames
* `is_handled`(ro): whether vrequest is already handled
* `has_response`(ro): whether the response headers (and status) is available
Methods:
* @print(...)@: print parameters via lua @tostring@ method as ERROR in Virtual Request context
* @warning(...)@: print parameters via lua @tostring@ method as WARNING in Virtual Request context
* @info(...)@: print parameters via lua @tostring@ method as INFO in Virtual Request context
* @debug(...)@: print parameters via lua @tostring@ method as DEBUG in Virtual Request context
* @handle_direct()@: handle vrequest (i.e. provide headers and body); returns true if not already handled.
* @enter_action(act)@: push a new action on the action stack (return HANDLER_WAIT_FOR_EVENT to rerun after the pushed actions are done, HANDLER_GO_ON if you are done)
* @st, res, errno, msg = stat(filename)@: async stat(filename). Following results are possible
** st is the stat result, res == HANDLER_GO_ON, if the file was found. errno and msg are NIL. In all other cases st is NIL and res != HANDLER_GO_ON.
** res == HANDLER_WAIT_FOR_EVENT: stat() is in progress, just try again later (and return HANDLER_WAIT_FOR_EVENT in the meantime)
** res == HANDLER_ERROR: if stat() failed, errno contains the errno and msg the error message for the errno code.
* @add_filter_in(obj)@: adds @obj@ as lua incoming filter (needs to respond to @obj:handle(vr, outq, inq)@ and optionally @obj:finished()@); returns a Filter object
* @add_filter_out(obj)@: adds @obj@ as lua outgoing filter (needs to respond to @obj:handle(vr, outq, inq)@ and optionally @obj:finished()@); returns a Filter object
]]></textile>
* `print(...)`: print parameters via lua `tostring` method as ERROR in Virtual Request context
* `warning(...)`: print parameters via lua `tostring` method as WARNING in Virtual Request context
* `info(...)`: print parameters via lua `tostring` method as INFO in Virtual Request context
* `debug(...)`: print parameters via lua `tostring` method as DEBUG in Virtual Request context
* `handle_direct()`: handle vrequest (i.e. provide headers and body); returns true if not already handled.
* `enter_action(act)`: push a new action on the action stack (return HANDLER_WAIT_FOR_EVENT to rerun after the pushed actions are done, HANDLER_GO_ON if you are done)
* `st, res, errno, msg = stat(filename)`: async stat(filename). Following results are possible
* st is the stat result, res == HANDLER_GO_ON, if the file was found. errno and msg are NIL. In all other cases st is NIL and res != HANDLER_GO_ON.
* res == HANDLER_WAIT_FOR_EVENT: stat() is in progress, just try again later (and return HANDLER_WAIT_FOR_EVENT in the meantime)
* res == HANDLER_ERROR: if stat() failed, errno contains the errno and msg the error message for the errno code.
* `add_filter_in(obj)`: adds `obj` as lua incoming filter (needs to respond to `obj:handle(vr, outq, inq)` and optionally `obj:finished()`); returns a Filter object
* `add_filter_out(obj)`: adds `obj` as lua outgoing filter (needs to respond to `obj:handle(vr, outq, inq)` and optionally `obj:finished()`); returns a Filter object
]]></markdown>
</section>
<section title="Connection">
<textile><![CDATA[
* @local@: address of local socket
* @remote@: address of remote host
]]></textile>
<markdown><![CDATA[
* `local`: address of local socket
* `remote`: address of remote host
]]></markdown>
</section>
<section title="Environment">
<textile><![CDATA[
Fields are the keys in the environment, so it behaves like a lua table; if you use keys starting with "__" or keys with the name of one of the methods below, you have to use the @get@ method to read them, for example:
<markdown><![CDATA[
Fields are the keys in the environment, so it behaves like a lua table; if you use keys starting with "__" or keys with the name of one of the methods below, you have to use the `get` method to read them, for example:
<pre>
x = env["set"] -- doesn't work, returns the set method instead
x = env:get("set") -- use this instead
x = env["set"] -- doesn't work, returns the set method instead
x = env:get("set") -- use this instead
x = env[y] -- don't do this, as y may be a special key like "set"
x = env:get(y) -- just do it the safe way if you are not sure
</pre>
x = env[y] -- don't do this, as y may be a special key like "set"
x = env:get(y) -- just do it the safe way if you are not sure
Methods:
* @get(k)@: safe way for @env[k]@
* @set(k, v)@: safe way for @env[k] = v@
* @unset(k)@: safe way for @env[k] = nil@
* @weak_set(k, v)@: don't override old value, safe way for @env[k] = env[k] or v@
* @pairs()@: use to loop through keys: @for k, v in env:pairs() do ... end@
* @clear()@: remove all entries
]]></textile>
* `get(k)`: safe way for `env[k]`
* `set(k, v)`: safe way for `env[k] = v`
* `unset(k)`: safe way for `env[k] = nil`
* `weak_set(k, v)`: don't override old value, safe way for `env[k] = env[k] or v`
* `pairs()`: use to loop through keys: `for k, v in env:pairs() do ... end`
* `clear()`: remove all entries
]]></markdown>
</section>
<section title="Chunk Queue">
<textile><![CDATA[
<markdown><![CDATA[
Fields:
* @is_closed@: whether the ChunkQueue is closed
* `is_closed`: whether the ChunkQueue is closed
Methods:
* @add(s)@: appends a string to the queue
* @add({filename="/..."})@: appends a file to the queue (only regular files allowed)
* @reset()@: removes all chunks, resets counters
* @steal_all(from)@: steal all chunks from another queue (useful in a filter if you decide to pass all data through it)
* @skip_all()@: skips all chunks (removes all chunks but does *not* reset counters)
]]></textile>
* `add(s)`: appends a string to the queue
* `add({filename="/..."})`: appends a file to the queue (only regular files allowed)
* `reset()`: removes all chunks, resets counters
* `steal_all(from)`: steal all chunks from another queue (useful in a filter if you decide to pass all data through it)
* `skip_all()`: skips all chunks (removes all chunks but does **not** reset counters)
]]></markdown>
</section>
<section title="Request">
<textile><![CDATA[
<markdown><![CDATA[
Fields:
* @headers@(ro): HTTP Headers
* @http_method@(ro): HTTP method string ("GET", "POST", "HEAD", ...)
* @http_version@(ro): HTTP version string ("HTTP/1.0", "HTTP/1.1")
* @content_length@(ro): Numeric value of Content-Length header (not updated automatically if someone changes the header value), -1 if not specified
* @uri@: Request URI
]]></textile>
* `headers`(ro): HTTP Headers
* `http_method`(ro): HTTP method string ("GET", "POST", "HEAD", ...)
* `http_version`(ro): HTTP version string ("HTTP/1.0", "HTTP/1.1")
* `content_length`(ro): Numeric value of Content-Length header (not updated automatically if someone changes the header value), -1 if not specified
* `uri`: Request URI
]]></markdown>
</section>
<section title="Request URI">
<textile><![CDATA[
<markdown><![CDATA[
Fields:
* @raw@: Request uri as it was in the HTTP Request Line (or a rewrite result)
* @raw_path@: not decoded path with querystring (will be the same as @raw@ for most requests, unless someone does something like @GET http://example.com/test?abc HTTP/1.1@)
* @raw_orig_path@: same as raw_path, but saved before any rewrite happened
* @scheme@: "http" or "https"
* @authority@: complete host name header (or authority in an absolute url), e.g. "user@www.example.com.:8080"
* @path@: decoded and simplified path name, without authority, scheme, query-string; e.g. "/index.php"
* @host@: simple hostname, without auth information, without port, without trailing dot; e.g. "www.example.com"
* @query@: The querystring, e.g. "a=1&b=2"
]]></textile>
* `raw`: Request uri as it was in the HTTP Request Line (or a rewrite result)
* `raw_path`: not decoded path with querystring (will be the same as `raw` for most requests, unless someone does something like `GET http://example.com/test?abc HTTP/1.1`)
* `raw_orig_path`: same as raw_path, but saved before any rewrite happened
* `scheme`: "http" or "https"
* `authority`: complete host name header (or authority in an absolute url), e.g. "user@www.example.com.:8080"
* `path`: decoded and simplified path name, without authority, scheme, query-string; e.g. "/index.php"
* `host`: simple hostname, without auth information, without port, without trailing dot; e.g. "www.example.com"
* `query`: The querystring, e.g. "a=1&b=2"
]]></markdown>
</section>
<section title="Response">
<textile><![CDATA[
<markdown><![CDATA[
Fields:
* @headers@(ro): HTTP Headers
* @status@: HTTP status code
]]></textile>
* `headers`(ro): HTTP Headers
* `status`: HTTP status code
]]></markdown>
</section>
<section title="Physical">
<textile><![CDATA[
<markdown><![CDATA[
Fields:
* @path@: physical path
* @doc_root@: document root
* @pathinfo@: pathinfo
]]></textile>
* `path`: physical path
* `doc_root`: document root
* `pathinfo`: pathinfo
]]></markdown>
</section>
<section title="HTTP Headers">
<textile><![CDATA[
<markdown><![CDATA[
Same restriction as Environment for fields.
Methods:
* @get(k)@: joins all header values for the key @k@ with ", " (as the rfc allows it)
* @set(k, v)@: removes all headers with key @k@ and, if v is not nil, appends new "k: v" header
* @append(k, v)@: appends ", v" to last header value with key k if it already exists, @insert(k, v)@ otherwise
* @insert(k, v)@: appends new "k: v" header to list
* @unset(k)@: removes all headers with key @k@
* @pairs()@: loops through all headers. Please note that the keys are not unique!
* @list(k)@: loops through all headers with key @k@
* @clear()@: remove all headers
]]></textile>
* `get(k)`: joins all header values for the key `k` with ", " (as the rfc allows it)
* `set(k, v)`: removes all headers with key `k` and, if v is not nil, appends new "k: v" header
* `append(k, v)`: appends ", v" to last header value with key k if it already exists, `insert(k, v)` otherwise
* `insert(k, v)`: appends new "k: v" header to list
* `unset(k)`: removes all headers with key `k`
* `pairs()`: loops through all headers. Please note that the keys are not unique!
* `list(k)`: loops through all headers with key `k`
* `clear()`: remove all headers
]]></markdown>
</section>
<section title="Filter">
<textile><![CDATA[
<markdown><![CDATA[
Represents a "liFilter".
Fields:
* @in@(ro): Chunk Queue, incoming stream
* @out@(ro): Chunk Queue, outgoing stream
]]></textile>
* `in`(ro): Chunk Queue, incoming stream
* `out`(ro): Chunk Queue, outgoing stream
]]></markdown>
</section>
<section title="Stat struct">
<textile><![CDATA[
Represents "struct stat". Most fields should be self explaining (@man stat@ if you don't know them).
<markdown><![CDATA[
Represents "struct stat". Most fields should be self explaining (`man 2 stat` ([debian manpage](https://manpages.debian.org/stat.2.en.html)) if you don't know them).
Fields:
* @is_file@(ro): S_ISREG(mode)
* @is_dir@(ro): S_ISDIR(mode)
* @is_char@(ro): S_ISCHR(mode)
* @is_block@(ro): S_ISBLK(mode)
* @is_socket@(ro): S_ISSOCK(mode)
* @is_link@(ro): S_ISLNK(mode)
* @is_fifo@(ro): S_ISFIFO(mode)
* @mode@(ro)
* @mtime@(ro)
* @ctime@(ro)
* @atime@(ro)
* @uid@(ro)
* @gid@(ro)
* @size@(ro)
* @ino@(ro)
* @ino@(ro)
]]></textile>
* `is_file`(ro): S_ISREG(mode)
* `is_dir`(ro): S_ISDIR(mode)
* `is_char`(ro): S_ISCHR(mode)
* `is_block`(ro): S_ISBLK(mode)
* `is_socket`(ro): S_ISSOCK(mode)
* `is_link`(ro): S_ISLNK(mode)
* `is_fifo`(ro): S_ISFIFO(mode)
* `mode`(ro)
* `mtime`(ro)
* `ctime`(ro)
* `atime`(ro)
* `uid`(ro)
* `gid`(ro)
* `size`(ro)
* `ino`(ro)
* `dev`(ro)
]]></markdown>
</section>
</section>

View File

@ -1,32 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Patterns">
<description>
<textile>
The lighttpd config supports "patterns" in various places (docroot, redirect, rewrite, env.set, ...); and they share the following structure.
<description><markdown>
The lighttpd config supports "patterns" in various places (docroot, redirect, rewrite, env.set, ...); and they share the following structure.
There are two kinds of "captures" available; one from the action itself (like captures from a regular expression in redirect/rewrite, or the labels from the hostname in docroot), and the captures from the previous matching regular expression conditional in the action stack. If there was no capture of the selected kind the values will be empty strings.
</textile>
</description>
There are two kinds of "captures" available; one from the action itself (like captures from a regular expression in redirect/rewrite, or the labels from the hostname in docroot), and the captures from the previous matching regular expression conditional in the action stack. If there was no capture of the selected kind the values will be empty strings.
</markdown></description>
<section title="Syntax">
<textile>
<markdown>
A pattern is a string consisting of the following parts:
* simple text. can contain special characters $ and % only when they are escaped with \ - remember, that the \ has to be escaped too for the config, so you'll probably have to use \\ to escape. You are allowed to escape ? too (used for special "split" in rewrite).
* simple text. can contain special characters $ and % only when they are escaped with `\` remember, that the `\` has to be escaped too for the config, so you'll probably have to use `\\` to escape. You are allowed to escape `?` too (used for special "split" in rewrite).
* "%" capture references (previous matching regular expression conditional); either followed by a single digit, or a range (see below for range syntax)
* "$" capture references (depends on action); either followed by a single digit, or a range (see below for range syntax)
* "%" references to "condition variables":core_config.html#core_config__condition_vars, for example: @%{req.path}@; the conditional can be prefixed with "enc:" (@%{enc:req.path}@), in which case the value will be urlencoded.
</textile>
* "%" references to [condition variables](core_config.html#core_config__condition_vars), for example: `%{req.path}`; the conditional can be prefixed with "enc:" (`%{enc:req.path}`), in which case the value will be urlencoded.
</markdown>
</section>
<section title="Ranges">
<textile><![CDATA[
Ranges can either be a single element @[n]@ (@n@ can have more than one digit), a closed range @[n-m]@ or an open range @[n-]@ or @[-m]@;
the open end is always replaced with "G_MAXUINT" (a very big positive integer). ranges can be "reversed", i.e. @n > m@.
<markdown><![CDATA[
Ranges can either be a single element `[n]` (`n` can have more than one digit), a closed range `[n-m]` or an open range `[n-]` or `[-m]`;
the open end is always replaced with "G_MAXUINT" (a very big positive integer). ranges can be "reversed", i.e. `n > m`.
There are now two different ways ranges are used:
* ranges of regular expression captures: the captures are just inserted for all values in the range; if the range is reversed, it starts with the highest index in the range.
* ranges of labels in a hostname: similar to the first range, but the inserted labels are separated by a "."; the index 0 stands for "complete hostname", and ranges including 0 are reduced to the complete hostname; the labels are numbered from top-level, and the range is intepreted reversed (just have a look at the examples, and it will be clear).
]]></textile>
* ranges of labels in a hostname: similar to the first range, but the inserted labels are separated by a "."; the index 0 stands for "complete hostname", and ranges including 0 are reduced to the complete hostname; the labels are numbered from top-level, and the range is interpreted reversed (just have a look at the examples, and it will be clear).
]]></markdown>
</section>
<example title="Example: simple redirect">
@ -36,12 +36,10 @@
</example>
<example title="Example: docroot">
<description>
<textile>
* a request to "http://example.com/project/trunk" would lead to docroot "/var/www/project/trunk/htdocs"
* a request to "http://sub.example.com/" would lead to docroot "/var/www/vhosts/com/sub.example"
</textile>
</description>
<description><markdown>
* a request to "http://example.com/project/trunk" would lead to docroot "/var/www/project/trunk/htdocs"
* a request to "http://sub.example.com/" would lead to docroot "/var/www/vhosts/com/sub.example"
</markdown></description>
<config>
if req.path =~ "^/project/([^/]*)" {
docroot "/var/www/projects/%1/htdocs";

View File

@ -1,21 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="urn:lighttpd.net:lighttpd2/doc1" title="Regular expressions">
<description>
<textile>
lighttpd2 uses the "Perl-compatible regular expressions" implementation from GLib, see their "Regular expression syntax":https://developer.gnome.org/glib/stable/glib-regex-syntax.html documentation.
<description><markdown>
lighttpd2 uses the "Perl-compatible regular expressions" implementation from GLib, see their [Regular expression syntax](https://developer.gnome.org/glib/stable/glib-regex-syntax.html) documentation.
The config format has different ways to provide strings (you can quote with either @'@ or @"@; the character used to quote has to be escaped with @\@ if used inside the string).
The simple (standard) way @"text"@ has the following escape rules:
* @"\n"@ is a newline, @"\r"@ a carriage return, @"\t"@ a tab stop
* @"\\"@ is one @\@, @"\""@ is one double quote @"@ and @"\'"@ a single quote @'@
* escaping single/double quote is optional if the symbol is not used to terminate the string, i.e. @'\"'@ = @'"'@ and @"\'"@ = @"'"@
* @"\xNN"@: NN must be hexadecimal characters, and the string is replaced with the decoded 8-bit value as a single byte
* All other @\@ occurences are *not* removed from the string.
The config format has different ways to provide strings (you can quote with either `'` or `"`; the character used to quote has to be escaped with `\` if used inside the string).
The simple (standard) way `"text"` has the following escape rules:
This way is the preferred one for regular expressions; only to actually match a @\@ you have to do additional escaping (@"\\\\"@; @"\x5C"@ = @"\\"@ is not working), and @\\@ is usually not doing what you wanted (matching a digit: @"\\d"@ = @"\d"@). All other escape rules are compatible with what pcre is doing.
* `"\n"` is a newline, `"\r"` a carriage return, `"\t"` a tab stop
* `"\\"` is one `\`, `"\""` is one double quote `"` and `"\'"` a single quote `'`
* escaping single/double quote is optional if the symbol is not used to terminate the string, i.e. `'\"'` = `'"'` and `"\'"` = `"'"`
* `"\xNN"`: NN must be hexadecimal characters, and the string is replaced with the decoded 8-bit value as a single byte
* All other `\` occurences are **not** removed from the string.
The second way is to place an @e@ before the string like this: @e"text"@. It has the same rules like the normal string, but does not allow unknown escape sequences (the last rule above).
To match a digit with pcre this way you'd have to write @e"\\d"@ instead of @"\d"@.
</textile>
</description>
This way is the preferred one for regular expressions; only to actually match a `\` you have to do additional escaping (`"\\\\"`; `"\x5C"` = `"\\"` is not working), and `\\` is usually not doing what you wanted (matching a digit: `"\\d"` = `"\d"`). All other escape rules are compatible with what pcre is doing.
The second way is to place an `e` before the string like this: `e"text"`. It has the same rules like the normal string, but does not allow unknown escape sequences (the last rule above).
To match a digit with pcre this way you'd have to write `e"\\d"` instead of `"\d"`.
</markdown></description>
</chapter>

View File

@ -91,11 +91,11 @@
<attribute name="name" type="Name" use="required" />
</complexType>
<complexType name="DescriptionType" mixed="true">
<complexType name="DescriptionType">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="html" type="anyType" />
<element name="textile" type="anyType" />
<element name="markdown" type="anyType" />
</choice>
</sequence>
</complexType>
@ -111,7 +111,7 @@
<attribute name="anchor" type="token" use="optional" />
</complexType>
<complexType name="ModuleSectionType" mixed="true">
<complexType name="ModuleSectionType">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="action" type="d:ActionSetupType" />
@ -119,7 +119,7 @@
<element name="option" type="d:OptionType" />
<element name="html" type="anyType" />
<element name="textile" type="anyType" />
<element name="markdown" type="anyType" />
<element name="example" type="d:ExampleType" />
<element name="section" type="d:ModuleSectionType" />
</choice>
@ -150,11 +150,11 @@
<attribute name="order" type="Name" use="optional" />
</complexType>
<complexType name="ChapterSectionType" mixed="true">
<complexType name="ChapterSectionType">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="html" type="anyType" />
<element name="textile" type="anyType" />
<element name="markdown" type="anyType" />
<element name="example" type="d:ExampleType" />
<element name="section" type="d:ChapterSectionType" />
</choice>
@ -198,13 +198,13 @@
<attribute name="name" type="Name" use="required" />
</complexType>
<complexType name="AngelModuleSectionType" mixed="true">
<complexType name="AngelModuleSectionType">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="item" type="d:AngelItemType" />
<element name="html" type="anyType" />
<element name="textile" type="anyType" />
<element name="markdown" type="anyType" />
<element name="example" type="d:ExampleType" />
<element name="section" type="d:AngelModuleSectionType" />
</choice>

View File

@ -14,7 +14,7 @@ CGI, basic and digest HTTP authentication, output compression, URL rewriting.
.PP
This manual page only lists the command line arguments. For details
on how to configure \fBlighttpd\fP and its modules see the online documentation:
http://redmine.lighttpd.net/projects/lighttpd2/wiki
https://redmine.lighttpd.net/projects/lighttpd2/wiki
.PP
You probably want to use the angel instead of this application: lighttpd2(8)
.
@ -42,13 +42,13 @@ Show version and exit.
Show a brief help message and exit.
.
.SH SEE ALSO
Online Documentation: http://redmine.lighttpd.net/projects/lighttpd2/wiki
Online Documentation: https://redmine.lighttpd.net/projects/lighttpd2/wiki
.PP
spawn-fcgi(1), lighttpd2(8)
.
.SH AUTHOR
Jan Kneschke <jan@kneschke.de>
.PP
Stefan Buehler <stbuehler@web.de>
Stefan Buehler <source@stbuehler.de>
.PP
Thomas Porzelt <tp@cryosphere.de>

View File

@ -17,7 +17,7 @@ permissions are needed (opening network sockets, ...)
.PP
This manual page only lists the command line arguments. For details
on how to configure \fBlighttpd\fP and its modules see the online documentation:
http://redmine.lighttpd.net/projects/lighttpd2/wiki
https://redmine.lighttpd.net/projects/lighttpd2/wiki
.
.SH OPTIONS
The following options are supported:
@ -40,13 +40,13 @@ Show version and exit.
Show a brief help message and exit.
.
.SH SEE ALSO
Online Documentation: http://redmine.lighttpd.net/projects/lighttpd2/wiki
Online Documentation: https://redmine.lighttpd.net/projects/lighttpd2/wiki
.PP
lighttpd2-worker(8)
.
.SH AUTHOR
Jan Kneschke <jan@kneschke.de>
.PP
Stefan Buehler <stbuehler@web.de>
Stefan Buehler <source@stbuehler.de>
.PP
Thomas Porzelt <tp@cryosphere.de>

4
doc/meson.build Normal file
View File

@ -0,0 +1,4 @@
install_man(
'lighttpd2.8',
'lighttpd2-worker.8',
)

View File

@ -13,13 +13,13 @@
<parameter name="rules">
<short>A key value list mapping "access" and/or "deny" keys to a list of CIDR addresses or "all".</short>
</parameter>
<description>
Checks the client IP address agains the rules. Default is to deny all addresses. The most precise matching rule defines the result ("192.168.100.0/24" takes precedence over "192.168.0.0/16"; similar to routing tables); if the same CIDR is in both lists the second action is taken. "all" is a synonym for "0.0.0.0/0" and "::/0", matching all IPv4 and IPv6 addresses.
</description>
<description><markdown>
Checks the client IP address against the rules. Default is to deny all addresses. The most precise matching rule defines the result ("192.168.100.0/24" takes precedence over "192.168.0.0/16"; similar to routing tables); if the same CIDR is in both lists the second action is taken. "all" is a synonym for "0.0.0.0/0" and "::/0", matching all IPv4 and IPv6 addresses.
</markdown></description>
<example title="Example: restrict access to local network" anchor="#">
<description>
<description><markdown>
Limit access to clients from the local network. The deny rule isn't strictly required, as the default is to deny anyway. The smaller CIDR strings for the local networks override the global deny rule.
</description>
</markdown></description>
<config>
setup {
module_load "mod_access";
@ -32,9 +32,9 @@
</config>
</example>
<example title="Example: restrict access to subnet with exception" anchor="#">
<description>
<description><markdown>
Limit access to clients from "192.168.10.0/24", but deny access to "192.168.10.1". As "192.168.10.1" (equivalent to "192.168.10.1/32") is a more precise match it overwrites the allow rule for the subnet "192.168.10.0/24" containing it.
</description>
</markdown></description>
<config>
setup {
module_load "mod_access";
@ -52,11 +52,9 @@
<short>url to redirect to if access was denied (not implemented yet)</short>
<parameter name="url" />
<default><text>not set</text></default>
<description>
<textile>
*NOT IMPLEMENTED YET*
</textile>
</description>
<description><markdown>
**NOT IMPLEMENTED YET**
</markdown></description>
</option>
<option name="access.log_blocked">

View File

@ -6,42 +6,41 @@
<short>defines the log format</short>
<parameter name="format" />
<default><value>"%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""</value></default>
<description>
<textile><![CDATA[
Some format specifiers take a mandatory key, enclosed in curly braces between percent sign and the actual specifier. CLF means "common log format", if a value is zero, a '-' is used instead.
<description><markdown><![CDATA[
Some format specifiers take a mandatory key, enclosed in curly braces between percent sign and the actual specifier. CLF means "common log format", if a value is zero, a '-' is used instead.
table(table table-striped).
|_. specifier |_. description |
| %% | Percent sign itself |
| %a | Remote IP-address |
| %A | Local IP-address|
| %b | Size of response in bytes, excluding HTTP headers (CLF) |
| %B | Size of response in bytes, excluding HTTP headers |
| %{foobar}C | (*not implemented yet*) Contents of cookie @foobar@ of the request |
| %D | Time taken to serve the request in microseconds |
| %{foobar}e | Contents of the request environment variable @foobar@ |
| %f | Path to physical file |
| %h | Remote IP-address (same as @%a@) |
| %{foobar}i | Contents of request header @foobar@ |
| %m | Request method (GET, POST, etc) |
| %{foobar}o | Contents of response header @foobar@ |
| %p | Local port |
| %q | Querystring |
| %r | First line of request (GET /foo.html?bar HTTP/1.1) |
| %s | Response status code |
| %t | Time/date the request was received in standard english format |
| %T | Time taken to serve the request in seconds |
| %u | Authed user (from mod_auth). Same as @%{REMOTE_USER}e@ |
| %U | Request path (not including querystring) |
| %v | Server name as set through the @server.name@ option or the request hostname of @server.name@ is not set |
| %V | Request hostname |
| %X | Connection status after response: "X" if aborted before completed, "+" if keepalive, "-" if no keepalive |
| %I | Bytes received including HTTP headers and request body |
| %O | Bytes sent including HTTP headers and response body |
| specifier | description |
|--|--|
| %% | Percent sign itself |
| %a | Remote IP-address |
| %A | Local IP-address|
| %b | Size of response in bytes, excluding HTTP headers (CLF) |
| %B | Size of response in bytes, excluding HTTP headers |
| %{foobar}C | (**not implemented yet**) Contents of cookie `foobar` of the request |
| %D | Time taken to serve the request in microseconds |
| %{foobar}e | Contents of the request environment variable `foobar` |
| %f | Path to physical file |
| %h | Remote IP-address (same as `%a`) |
| %{foobar}i | Contents of request header `foobar` |
| %m | Request method (GET, POST, etc) |
| %{foobar}o | Contents of response header `foobar` |
| %p | Local port |
| %q | Querystring |
| %r | First line of request (GET /foo.html?bar HTTP/1.1) |
| %s | Response status code |
| %t | Time/date the request was received in standard english format |
| %T | Time taken to serve the request in seconds |
| %u | Authed user (from mod_auth). Same as `%{REMOTE_USER}e` |
| %U | Request path (not including querystring) |
| %v | Server name as set through the `server.name` option or the request hostname of `server.name` is not set |
| %V | Request hostname |
| %X | Connection status after response: "X" if aborted before completed, "+" if keepalive, "-" if no keepalive |
| %I | Bytes received including HTTP headers and request body |
| %O | Bytes sent including HTTP headers and response body |
{:.table .table-striped}
Modifiers right after the percent sign like Apache provides them, are not supported. "<" or ">" are ignored, everything else results in a parse error. Specifiers supported by Apache but not lighty: %l, %n, %P
]]></textile>
</description>
Modifiers right after the percent sign like Apache provides them, are not supported. "<" or ">" are ignored, everything else results in a parse error. Specifiers supported by Apache but not lighty: %l, %n, %P
]]></markdown></description>
<example>
<config>
accesslog.format "%h %V %u %t \"%r\" %>s %b";
@ -53,9 +52,9 @@
<short>defines the log target</short>
<parameter name="target" />
<default><text>logging disabled</text></default>
<description>
<html>Enable logging by setting a log target. Supports the same log targets as <a href="plugin_core.html#plugin_core__action_log">log</a>.</html>
</description>
<description><markdown>
Enable logging by setting a log target. Supports the same log targets as [log](plugin_core.html#plugin_core__action_log).
</markdown></description>
<example>
<config>
setup {

View File

@ -2,22 +2,18 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>requires authentication from clients using a username and password. It supports the basic (digest not yet) authentication method as well as plaintext, htpasswd and htdigest backends.</short>
<description>
<textile>
*IMPORTANT NOTE*: You need to put the auth actions before generating content! If a content handler is already active (like php or static or dirlist), auth will be ignored!
<description><markdown>
**IMPORTANT NOTE**: You need to put the auth actions before generating content! If a content handler is already active (like php or static or dirlist), auth will be ignored!
* Basic:
The "basic" method transfers the username and the password in cleartext over the network (base64 encoded) and might result in security problems if not used in conjunction with an encrypted communication channel between client and server.
It is recommend to use https in conjunction with basic authentication.
* Digest (not supported yet):
The "digest" method only transfers a hashed value over the network which performs a lot of work to harden the authentication process in insecure networks (like the internet).
The "digest" method doesn't work with the htpasswd backend, only with plaintext and htdigest.
*NOTE*: The digest method is broken in Internet Explorer &lt; 7. Use basic instead if this is a problem for you. (not supported for now anyway)
</textile>
</description>
* Basic:
The "basic" method transfers the username and the password in cleartext over the network (base64 encoded) and might result in security problems if not used in conjunction with an encrypted communication channel between client and server.
It is recommend to use https in conjunction with basic authentication.
* Digest (not supported yet):
The "digest" method only transfers a hashed value over the network which performs a lot of work to harden the authentication process in insecure networks (like the internet).
The "digest" method doesn't work with the htpasswd backend, only with plaintext and htdigest.
**NOTE**: The digest method is broken in Internet Explorer &lt; 7. Use basic instead if this is a problem for you. (not supported for now anyway)
</markdown></description>
<action name="auth.plain">
<short>requires authentication using a plaintext file</short>
@ -37,9 +33,9 @@
</entry>
</table>
</parameter>
<description>
requires authentication using a plaintext file containing user:password pairs seperated by newlines (\n).
</description>
<description><markdown>
requires authentication using a plaintext file containing user:password pairs separated by newlines (\n).
</markdown></description>
</action>
<action name="auth.htpasswd">
@ -60,14 +56,12 @@
</entry>
</table>
</parameter>
<description>
<textile>
* requires authentication using a htpasswd file containing user:encrypted_password pairs seperated by newlines (\n)
* passwords are encrypted using crypt(3), use the htpasswd binary from apache to manage the file
** hashes starting with "$apr1$" ARE supported (htpasswd -m)
** hashes starting with "{SHA}" ARE supported (followed by sha1_base64(password), htpasswd -s)
</textile>
</description>
<description><markdown>
* requires authentication using a htpasswd file containing user:encrypted_password pairs separated by newlines (\n)
* passwords are encrypted using crypt(3), use the htpasswd binary from apache to manage the file
* hashes starting with "$apr1$" ARE supported (htpasswd -m)
* hashes starting with "{SHA}" ARE supported (followed by sha1_base64(password), htpasswd -s)
</markdown></description>
</action>
<action name="auth.htdigest">
@ -88,14 +82,12 @@
</entry>
</table>
</parameter>
<description>
<textile>
* requires authentication using a htdigest file containing user:realm:hashed_password tuples seperated by newlines (\n)
* the hashes are bound to the realm, so you can't change the realm without resetting the passwords
* passwords are saved as (modified) md5 hashes:
@md5hex(username + ":" + realm + ":" + password)@
</textile>
</description>
<description><markdown>
* requires authentication using a htdigest file containing user:realm:hashed_password tuples separated by newlines (\n)
* the hashes are bound to the realm, so you can't change the realm without resetting the passwords
* passwords are saved as (modified) md5 hashes:
`md5hex(username + ":" + realm + ":" + password)`
</markdown></description>
</action>
<action name="auth.deny">
@ -122,11 +114,9 @@
</example>
<example>
<description>
<textile>
You can use @auth.require_user@ from the mod_lua plugin "contrib/core.lua":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core.lua for the REMOTE_USER check too:
</textile>
</description>
<description><markdown>
You can use `auth.require_user` from the mod_lua plugin [contrib/core.lua](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core.lua) for the REMOTE_USER check too:
</markdown></description>
<config>
setup {

View File

@ -2,20 +2,20 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>balances between different backends.</short>
<description>
<description><markdown>
Using an action from mod_balance also activates a backlog: lighttpd2 will then put requests in a backlog if no backend is available and try again later.
Be careful: the referenced actions may get executed more than once (until one is successful!), so don't loop rewrites in them or something similar.
</description>
</markdown></description>
<action name="balance.rr">
<short>balance between actions (list or single action) with Round-Robin</short>
<parameter name="actions">
<short>the actions to balance between</short>
</parameter>
<description>
<description><markdown>
Round-Robin (rr) the requests are distributed equally over all backends.
</description>
</markdown></description>
<example>
<config>
balance.rr { fastcgi "127.0.0.1:9090"; };
@ -33,9 +33,9 @@
<parameter name="actions">
<short>the actions to balance between</short>
</parameter>
<description>
<description><markdown>
Shortest-Queue-First (sqf) is similar to Round-Robin and prefers the backend with the shortest wait-queue.
</description>
</markdown></description>
<example>
<config>
balance.sqf { fastcgi "127.0.0.1:9090"; };

View File

@ -2,31 +2,29 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>caches generated content on disk if an etag response header is set; if the backend sends an already cached etag, the backend is closed and the file is sent directly.</short>
<description>
<textile>
Please note: This will not skip the backend, as it will need at least the reponse headers.
<description><markdown>
Please note: This will not skip the backend, as it will need at least the response headers.
*Hint:*
Use a cron-job like the following to remove old cached data, e.g. in crontab daily:
**Hint:**
Use a cron-job like the following to remove old cached data, e.g. in crontab daily:
<pre>
find /var/cache/lighttpd/cache_etag/ -type f -mtime +2 -exec rm -r {} \;
</pre>
```
find /var/cache/lighttpd/cache_etag/ -type f -mtime +2 -exec rm -r {} \;
```
*Hint:*
Have a look at "mod_deflate":mod_deflate.html#mod_deflate to see this module in action.
</textile>
</description>
**Hint:**
Have a look at [mod_deflate](mod_deflate.html#mod_deflate) to see this module in action.
</markdown></description>
<action name="cache.disk.etag">
<short>cache responses based on the ETag response header</short>
<parameter name="path">
<short>directory to store the cached results in</short>
</parameter>
<description>
<description><markdown>
This blocks action progress until the response headers are done (i.e. there has to be a content generator before it (like fastcgi/dirlist/static file).
You could insert it multiple times of course (e.g. before and after deflate).
</description>
</markdown></description>
<example>
<config>

View File

@ -3,16 +3,17 @@
<short>provides some useful helpers written in lua</short>
<section title="Install">
<textile>
By default distributions (and @make install@) should provide the necessary files; but you can always find them in the "contrib":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib folder:
* @core.lua@
* @core__cached_html.lua@
* @core__xsendfile.lua@
<markdown>
By default distributions (and `make install`) should provide the necessary files; but you can always find them in the [contrib](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib) folder:
* `core.lua`
* `core__cached_html.lua`
* `core__xsendfile.lua`
That way you can modify them for your own needs if you have to (although it is recommended to change the names of the files and the actions, so you don't get conflicts).
lighttpd should search for @core.lua@ in the correct (install) locations, so you don't need the absolute path here.
</textile>
lighttpd should search for `core.lua` in the correct (install) locations, so you don't need the absolute path here.
</markdown>
</section>
<action name="core.wsgi">
@ -23,23 +24,19 @@
<parameter name="action">
<short>action block connecting to the wsgi backend</short>
</parameter>
<description>
<textile>
See "Howto WSGI":https://redmine.lighttpd.net/projects/lighttpd2/wiki/Howto_WSGI for an example.
<description><markdown>
See [Howto WSGI](https://redmine.lighttpd.net/projects/lighttpd2/wiki/Howto_WSGI) for an example.
WSGI applications expect the url to be split into @SCRIPT_NAME@ and @PATH_INFO@ (CGI environment variables); @SCRIPT_NAME@ is their "application root", and @PATH_INFO@ the requsted resource in the application.
By default, lighttpd uses an empty @PATH_INFO@ (unless you used the "pathinfo;" action, but this doesn't help as we're not dealing with static files here).
WSGI applications expect the url to be split into `SCRIPT_NAME` and `PATH_INFO` (CGI environment variables); `SCRIPT_NAME` is their "application root", and `PATH_INFO` the requested resource in the application.
By default, lighttpd uses an empty `PATH_INFO` (unless you used the "pathinfo;" action, but this doesn't help as we're not dealing with static files here).
*Important*: WSGI is an "extension" of CGI; it doesn't specify a transport protocol, you can use it with plain CGI, FastCGI or SCGI (or anything else that supports the basic CGI protocol)
</textile>
</description>
**Important**: WSGI is an "extension" of CGI; it doesn't specify a transport protocol, you can use it with plain CGI, FastCGI or SCGI (or anything else that supports the basic CGI protocol)
</markdown></description>
<example>
<description>
<textile>
Example: Trac in @/trac@, listening via FastCGI on @unix:/var/run/lighttpd/trac.socket@.
</textile>
</description>
<description><markdown>
Example: Trac in `/trac`, listening via FastCGI on `unix:/var/run/lighttpd/trac.socket`.
</markdown></description>
<config>
setup {
module_load ("mod_lua", "mod_fastcgi");
@ -92,20 +89,18 @@
<parameter name="userlist">
<short>list of usernames to allow</short>
</parameter>
<description>
<textile>
This helper constructs a regular expression to match against request.environment["REMOTE_USER"], so the example below is the same as:
<description><markdown>
This helper constructs a regular expression to match against request.environment["REMOTE_USER"], so the example below is the same as:
<pre>
auth.plain [ "method" => "basic", "realm" => "test", "file" => "/etc/lighttpd2/test.plain" ];
if req.env["REMOTE_USER"] !~ "^(foo1|foo2)$" { auth.deny; }
</pre>
```
auth.plain [ "method" => "basic", "realm" => "test", "file" => "/etc/lighttpd2/test.plain" ];
if req.env["REMOTE_USER"] !~ "^(foo1|foo2)$" { auth.deny; }
```
This action uses lua only to create the action, no lua is executed to handle requests in this case.
This action uses lua only to create the action, no lua is executed to handle requests in this case.
Be careful: the empty username matches unauthenticated users.
</textile>
</description>
Be careful: the empty username matches unauthenticated users.
</markdown></description>
<example>
<config>
setup {

View File

@ -6,9 +6,9 @@
<action name="debug.show_connections">
<short>shows a page similar to the one from mod_status, listing all active connections</short>
<description>
<description><markdown>
By specifying one or more "connection ids" via querystring (parameter "con"), one can request additional debug output for specific connections.
</description>
</markdown></description>
<example>
<config>
if req.path == "/debug/connections" { debug.show_connections; }
@ -19,18 +19,16 @@
<action name="debug.profiler_dump">
<short>dumps all allocated memory to the profiler output file if profiling enabled</short>
<description>
<textile>
lighttpd2 needs to be compiled with profiler support, and profiling has to be enabled by setting the environment variable @LIGHTY_PROFILE_MEM@ to the path of a target log file.
</textile>
</description>
<description><markdown>
lighttpd2 needs to be compiled with profiler support, and profiling has to be enabled by setting the environment variable `LIGHTY_PROFILE_MEM` to the path of a target log file.
</markdown></description>
</action>
<action name="debug.show_events">
<short>shows a plain text list of all events</short>
<description>
<description><markdown>
this is a very low level debug tool for developers.
</description>
</markdown></description>
<example>
<config>
if req.path == "/debug/events" { debug.show_events; }
@ -43,14 +41,18 @@
<parameter name="timeout">
<short>timeout after which to display events (default: disabled)</short>
</parameter>
<parameter name="repeat">
<short>timeout after which to repeat displaying events (default: disabled)</short>
</parameter>
<description>
<description><markdown>
this is a very low level debug tool for developers; it shows which event listeners keep lighttpd2 alive when it should stop.
</description>
</markdown></description>
<example>
<config>
setup { debug.show_events_after_shutdown 5; }
setup { debug.show_events_after_shutdown 5, 15; }
</config>
</example>
</setup>

View File

@ -38,24 +38,28 @@
</option>
<section title="Notes">
<textile>
*Important*: As @deflate;@ waits for the response headers, you must handle the request before it (see below how to check whether the request is handled).
<markdown>
**Important**: As `deflate;` waits for the response headers, you must handle the request before it (see below how to check whether the request is handled).
If the request is not handled, you will get a "500 - Internal error" and a message in the error.log.
Does not compress:
* response status: 100, 101, 204, 205, 206, 304
* already compressed content
* if more than one etag response header is sent
* if no common encoding is found
Supported encodings
* gzip, deflate (needs zlib)
* bzip2 (needs bzip2)
* Modifies etag response header (if present)
* Adds "Vary: Accept-Encoding" response header
* Resets Content-Length header
</textile>
`deflate` also:
* modifies etag response header (if present)
* adds "Vary: Accept-Encoding" response header
* resets Content-Length header
</markdown>
</section>
<example title="Simple config" anchor="#">

View File

@ -52,9 +52,9 @@
</parameter>
<example>
<description>
<description><markdown>
shows a directory listing including the content of HEADER.txt above the list and hiding itself from it; also hides all files ending in ".bak"
</description>
</markdown></description>
<config>
setup {
module_load ("mod_dirlist");

View File

@ -2,47 +2,41 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>add "Expires" and "Cache-Control" headers to the response</short>
<description>
<textile><![CDATA[
This allows you to control client-side caching of responses based on a simple rule/formula.
If a response is cached using an "Expires" and "Cache-Control" header, then the client will not issue a new request for it until the date specified by the header is reached.
<description><markdown><![CDATA[
This allows you to control client-side caching of responses based on a simple rule/formula.
If a response is cached using an "Expires" and "Cache-Control" header, then the client will not issue a new request for it until the date specified by the header is reached.
Adding expire headers to static content like css, javascript, images or similar, can greatly reduce the amount of requests you get and therefor save resources.
Use "modification" as @<base>@ if your content changes in specific intervals like every 15 minutes.
]]></textile>
</description>
Adding expire headers to static content like css, javascript, images or similar, can greatly reduce the amount of requests you get and therefor save resources.
Use "modification" as `<base>` if your content changes in specific intervals like every 15 minutes.
]]></markdown></description>
<action name="expire">
<short>adds an "Expires" header to the response</short>
<parameter name="rule">
<short>the rule to calculate the "Expires" header value with</short>
</parameter>
<description>
<textile><![CDATA[
The rule/formula used here, complies with the one mod_expire for Apache uses:
<description><markdown><![CDATA[
The rule/formula used here, complies with the one mod_expire for Apache uses:
<pre>
<base> [plus] (<num> <type>)+
</pre>
* @<base>@ is one of "access", "now" or "modification"; "now" being equivalent to "access".
* "@plus@" is optional and does nothing.
* @<num>@ is any positive integer.
* @<type>@ is one of "seconds, "minutes", "hours", "days", "weeks", "months" or "years".
* `<base>` is one of "access", "now" or "modification"; "now" being equivalent to "access".
* "`plus`" is optional and does nothing.
* `<num>` is any positive integer.
* `<type>` is one of "seconds", "minutes", "hours", "days", "weeks", "months" or "years".
The trailing "s" in @<type>@ is optional.
The trailing "s" in `<type>` is optional.
If you use "modification" as @<base>@ and the file does not exist or cannot be accessed, mod_expire will do nothing and request processing will go on.
If you use "modification" as `<base>` and the file does not exist or cannot be accessed, mod_expire will do nothing and request processing will go on.
The expire action will overwrite any existing "Expires" header.
It will append the max-age value to any existing "Cache-Control" header.
]]></textile>
</description>
The expire action will overwrite any existing "Expires" header.
It will append the max-age value to any existing "Cache-Control" header.
]]></markdown></description>
<example>
<description>
<description><markdown>
Cache image, css, txt and js files for 1 week.
</description>
</markdown></description>
<config>
setup {
module_load "mod_expire";

View File

@ -7,22 +7,18 @@
<parameter name="socket">
<short>socket to connect to, either "ip:port" or "unix:/path"</short>
</parameter>
<description>
<textile>
Don't confuse FastCGI with CGI! Not all CGI backends can be used as FastCGI backends (but you can use "fcgi-cgi":https://redmine.lighttpd.net/projects/fcgi-cgi/wiki to run CGI backends with lighttpd2).
</textile>
</description>
<description><markdown>
Don't confuse FastCGI with CGI! Not all CGI backends can be used as FastCGI backends (but you can use [fcgi-cgi](https://redmine.lighttpd.net/projects/fcgi-cgi/wiki) to run CGI backends with lighttpd2).
</markdown></description>
<example>
<config>
fastcgi "127.0.0.1:9090"
</config>
</example>
<example>
<description>
<textile>
Start php for example with spawn-fcgi: @spawn-fcgi -n -s /var/run/lighttpd2/php.sock -- /usr/bin/php5-cgi@
</textile>
</description>
<description><markdown>
Start php for example with spawn-fcgi: `spawn-fcgi -n -s /var/run/lighttpd2/php.sock -- /usr/bin/php5-cgi`
</markdown></description>
<config>
setup {
module_load "mod_fastcgi";

View File

@ -4,13 +4,11 @@
<action name="flv">
<short>pseudo stream the current file as flash</short>
<description>
<textile>
Lets flash players seek with the "start" query string parameter to an (byte) offset in the file, and prepends a simple flash header before streaming the file from that offset.
<description><markdown>
Lets flash players seek with the "start" query string parameter to an (byte) offset in the file, and prepends a simple flash header before streaming the file from that offset.
Uses "video/x-flv" as hard-coded content type.
</textile>
</description>
Uses "video/x-flv" as hard-coded content type.
</markdown></description>
<example>
<config>
if phys.path =$ ".flv" {
@ -19,13 +17,11 @@
</config>
</example>
<example>
<description>
<textile>
Use caching and bandwidth throttling to save traffic. Use a small burst threshold to prevent the player from buffering at the beginning.
<description><markdown>
Use caching and bandwidth throttling to save traffic. Use a small burst threshold to prevent the player from buffering at the beginning.
This config will make browsers cache videos for 1 month and limit bandwidth to 150 kilobyte/s after 500 kilobytes.
</textile>
</description>
This config will make browsers cache videos for 1 month and limit bandwidth to 150 kilobyte/s after 500 kilobytes.
</markdown></description>
<config>
if phys.path =$ ".flv" {
expire "access 1 month";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>loads quotes (aka fortune coookies) from a file and provides actions to add a random quote as response header (X-fortune) or display it as a page.</short>
<short>loads quotes (aka fortune cookies) from a file and provides actions to add a random quote as response header (X-fortune) or display it as a page.</short>
<setup name="fortune.load">
<short>loads cookies from a file, can be called multiple times to load data from multiple files</short>

View File

@ -67,11 +67,9 @@
</example>
<example title="TLS with SNI from fetch backend">
<description>
<textile>
For a SNI hostname @example.com@ lighttpd2 will try to find the private key and certificate(s) in @/etc/certs/lighttpd_sni_example.com.pem@.
</textile>
</description>
<description><markdown>
For a SNI hostname `example.com` lighttpd2 will try to find the private key and certificate(s) in `/etc/certs/lighttpd_sni_example.com.pem`.
</markdown></description>
<config>
setup {
fetch.files_static "sni" => "/etc/certs/lighttpd_sni_*.pem";
@ -144,48 +142,51 @@
</setup>
<section title="Server Name Indication (SNI)">
<textile>
"TLS SNI":http://en.wikipedia.org/wiki/Server_Name_Indication means that a client can send the hostname of the server it tries to connect to *unencrypted* in the TLS handshake.
<markdown>
[TLS SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) means that a client can send the hostname of the server it tries to connect to **unencrypted** in the TLS handshake.
If you want to host multiple hostnames on the same IP address (quite common) there are some options how to do it (they can be combined):
* Use a wildcard as "CommonName" (CN) in the certificate like @*.example.com@ (although this usually doesn't match @example.com@)
* Use a wildcard as "CommonName" (CN) in the certificate like `*.example.com` (although this usually doesn't match `example.com`)
* Use "Subject Alternative Names" in the certificate
* Provide different certificates based on the SNI hostname in the TLS handshake.
Clients supporting SNI usually support the other options too, but not all clients support SNI.
GnuTLS has some basic SNI support built in; if you specify multiple @pemfile@ s in the options, it will pick the first with a certificate that matches the SNI hostname.
GnuTLS has some basic SNI support built in; if you specify multiple `pemfile` s in the options, it will pick the first with a certificate that matches the SNI hostname.
lighttpd2 has an optional extended SNI support (which has to be enabled at compile time, and is required for the @sni-*@ options to be available). It is designed to load certificates asynchronously from backends (files, SQL, ...) on demand, using the "fetch API":core_fetch.html#core_fetch.
In this case lighttpd2 will fetch the certificate based on the SNI hostname from the given @sni-backend@ before GnuTLS is started for a connection.
If a SNI hostname was given by the client, but no certificate was found in the backend, it will use @sni-fallback-pemfile@ (if set) instead of @pemfile@.
lighttpd2 has an optional extended SNI support (which has to be enabled at compile time, and is required for the `sni-*` options to be available). It is designed to load certificates asynchronously from backends (files, SQL, ...) on demand, using the [fetch API](core_fetch.html#core_fetch).
In this case lighttpd2 will fetch the certificate based on the SNI hostname from the given `sni-backend` before GnuTLS is started for a connection.
If a SNI hostname was given by the client, but no certificate was found in the backend, it will use `sni-fallback-pemfile` (if set) instead of `pemfile`.
Combining @sni-backend@, @sni-fallback-pemfile@ and multiple @pemfile@ s won't work - it will only use the first configured @pemfile@ (if no SNI hostname was given by the client, otherwise @sni-*@ certificates are used).
Combining `sni-backend`, `sni-fallback-pemfile` and multiple `pemfile` s won't work - it will only use the first configured `pemfile` (if no SNI hostname was given by the client, otherwise `sni-*` certificates are used).
Also note that lighttpd2 does NOT verify whether the SNI hostname matches the hostname in the HTTP request. SNI is only used by the client to tell the server for which hostname it should send the certificate (i.e. what the client is using to verify it).
</textile>
</markdown>
</section>
<section title="GnuTLS priority string">
<textile>
<markdown>
The GnuTLS priority string configures which ciphers and protocol versions are available, and also a small set of options (workarounds to activate and so on).
Example: @"SECURE:-VERS-SSL3.0:-SHA1:+SHA1:-RSA:+RSA:%SERVER_PRECEDENCE"@
* @SECURE@: starts with @SECURE@ level: only secure ciphers and secure curves
* @-VERS-SSL3.0@: disables SSL3.0 support (all clients should support at least TLS1.0 now)
* @-SHA1:SHA1@ puts SHA1 back at the list for MAC algorithms (preferring the other SHA variants)
* @-RSA:+RSA@: prefer (RSA) DHE/ECDHE key exchanges over simple RSA
* @%SERVER_PRECEDENCE@ a flag telling GnuTLS to use its own order of preference instead of the order provided by the client.
Example: `"SECURE:-VERS-SSL3.0:-SHA1:+SHA1:-RSA:+RSA:%SERVER_PRECEDENCE"`
* `SECURE`: starts with `SECURE` level: only secure ciphers and secure curves
* `-VERS-SSL3.0`: disables SSL3.0 support (all clients should support at least TLS1.0 now)
* `-SHA1:SHA1` puts SHA1 back at the list for MAC algorithms (preferring the other SHA variants)
* `-RSA:+RSA`: prefer (RSA) DHE/ECDHE key exchanges over simple RSA
* `%SERVER_PRECEDENCE` a flag telling GnuTLS to use its own order of preference instead of the order provided by the client.
See also:
* "Priority strings":http://gnutls.org/manual/html_node/Priority-Strings.html#Priority-Strings (GnuTLS manual)
* "GnuTLS Priority Strings":http://blog.lighttpd.net/gnutls-priority-strings.html
* @gnutls-cli -l --priority "SECURE:-VERS-SSL3.0:-SHA1:+SHA1:-RSA:+RSA:%SERVER_PRECEDENCE"@
</textile>
* [Priority strings](https://gnutls.org/manual/html_node/Priority-Strings.html#Priority-Strings) (GnuTLS manual)
* [GnuTLS Priority Strings](https://blog.lighttpd.net/gnutls-priority-strings.html)
* `gnutls-cli -l --priority "SECURE:-VERS-SSL3.0:-SHA1:+SHA1:-RSA:+RSA:%SERVER_PRECEDENCE"`
</markdown>
</section>
<section title="OCSP stapling">
<textile>
"OCSP stapling":https://en.wikipedia.org/wiki/OCSP_stapling is used to assure a client the certificate is still valid (i.e. not revoked); you can put an OCSP response into the certificate file in an "OCSP RESPONSE"-PEM block (there is probably no standard for this, juse base64-encode the DER-response you have), or specify the (DER or PEM formatted) OCSP response as separate file using "ocsp" in a "pemfile" block.
<markdown>
[OCSP stapling](https://en.wikipedia.org/wiki/OCSP_stapling) is used to assure a client the certificate is still valid (i.e. not revoked); you can put an OCSP response into the certificate file in an "OCSP RESPONSE"-PEM block (there is probably no standard for this, just base64-encode the DER-response you have), or specify the (DER or PEM formatted) OCSP response as separate file using "ocsp" in a "pemfile" block.
Server Name Indication (SNI) should work fine, as an OCSP response is only used if it matches the certificate in use for the connection.
@ -195,60 +196,56 @@
If you have your certificate and the issuer-certificate (the one that signed yours) in separate files you can request an OCSP response like that (using the GnuTLS "ocsptool"):
<pre>
ocsptool --ask --load-issuer issuer.pem --load-cert cert.pem --outfile ocsp.der
</pre>
Converting into PEM format can be done like this:
<pre>
(echo "-----BEGIN OCSP RESPONSE-----"; base64 --wrap=64 ocsp.der; echo "-----END OCSP RESPONSE-----") > ocsp.pem
</pre>
If you have trouble identifying which certificates you need, here the more detailed explanation:
You usually have a list of certificates in the PEM file you pass to lighttpd. The first certificate usually has a "Subject" pointing to your server name (CN), like: "Subject: CN=lighttpd.net". It also has a "Issuer" attribute (like "C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3"). The issuer certificate needs a "Subject" matching that "Issuer", and should be the second certificate in the PEM file (unless it already is the root CA, in which case it is usually omitted).
@ocsptool@ will always use the first certificate in a file and ignore the others, so you can use the normal PEM file you pass to lighttpd as argument after @--load-cert@, but you need to extract the issuer certificate if you don't have it in a separate file. The following @awk@ script extracts the second PEM block from a file:
`ocsptool` will always use the first certificate in a file and ignore the others, so you can use the normal PEM file you pass to lighttpd as argument after `--load-cert`, but you need to extract the issuer certificate if you don't have it in a separate file. The following `awk` script extracts the second PEM block from a file:
<pre>
awk '
BEGIN { block = 0 }
/^-----BEGIN / { ++block; }
{ if (block > 1) print; }
' "certs.pem" > "issuer.pem"
</pre>
</textile>
</markdown>
</section>
<section title="protect-against-beast">
<textile>
"BEAST":http://en.wikipedia.org/wiki/Transport_Layer_Security#BEAST_attack is considered mitigated on clients by many now, so this workaround is no longer recommended and disabled by default.
<markdown>
[BEAST](https://en.wikipedia.org/wiki/Transport_Layer_Security#BEAST_attack) is considered mitigated on clients by many now, so this workaround is no longer recommended and disabled by default.
It enabled it will enforce the usage of RC4 on TLS1.0 and before (TLS1.1 and TLS1.2 are not vulnerable); but RC4 has issues on its own.
</textile>
</markdown>
</section>
<section title="DH parameters">
<textile>
The @DHE_RSA@ key exchange requires parameters (similar to the curves used for @ECDHE_RSA@); the parameters specify a prime @p@ and a group generator @g@ of the multiplicative group of integers modulo @p@ (i.e. for all @x@ in @1..p-1@ exists an @e@ with @g^e = x@); sometimes @g@ might only create a sufficiently large subgroup (for example of size @(p-1)/2@).
<markdown>
The `DHE_RSA` key exchange requires parameters (similar to the curves used for `ECDHE_RSA`); the parameters specify a prime `p` and a group generator `g` of the multiplicative group of integers modulo `p` (i.e. for all `x` in `1..p-1` exists an `e` with `g^e = x`); sometimes `g` might only create a sufficiently large subgroup (for example of size `(p-1)/2`).
The security of the DH key exchange depends (among other things) on the bit length of @p@; therefore lighttpd includes default 4096-bit parameters (provided by the GnuTLS certtool with @certtool --get-dh-params --bits=4096@ in version 3.0.22), and these should be safe to use (key lengths > 1024 are not supported by some older clients; if you need to support those you either have to disable DH key exchange or specify 1024-bit parameters).
The security of the DH key exchange depends (among other things) on the bit length of `p`; therefore lighttpd includes default 4096-bit parameters (provided by the GnuTLS certtool with `certtool --get-dh-params --bits=4096` in version 3.0.22), and these should be safe to use (key lengths > 1024 are not supported by some older clients; if you need to support those you either have to disable DH key exchange or specify 1024-bit parameters).
You can use either GnuTLS or openssl to generate your own parameters:
* @certtool --generate-dh-params --bits=2048@
* @openssl dhparam -dsaparam 2048@
* @openssl dhparam -2 2048@
* @openssl dhparam -5 2048@
The GnuTLS @certtool@ only generates "DSA" parameters (any prime with a large generator), while @openssl@ can generate "DH" parameters with a generator of 2 or 5 combined with a Sophie Germain prime @(p-1)/2@ (i.e. both @p@ and @(p-1)/2@ are primes) or "DSA" parameters using the @-dsaparam@ option.
* `certtool --generate-dh-params --bits=2048`
* `openssl dhparam -dsaparam 2048`
* `openssl dhparam -2 2048`
* `openssl dhparam -5 2048`
"DH" parameters take a lot more time to generate, but you can reuse keys for those (although it is not recommended, search for @SSL_OP_SINGLE_DH_USE@ in the openssl manual on @SSL_CTX_set_tmp_dh_callback@). Keys for "DSA" parameters should not be reused, i.e. one should generate a new private key for each connection, which is the case in mod_gnutls. The default parameters provided by lighttpd are "DH" parameters.
The GnuTLS `certtool` only generates "DSA" parameters (any prime with a large generator), while `openssl` can generate "DH" parameters with a generator of 2 or 5 combined with a Sophie Germain prime `(p-1)/2` (i.e. both `p` and `(p-1)/2` are primes) or "DSA" parameters using the `-dsaparam` option.
"DH" parameters take a lot more time to generate, but you can reuse keys for those (although it is not recommended, search for `SSL_OP_SINGLE_DH_USE` in the openssl manual on `SSL_CTX_set_tmp_dh_callback`). Keys for "DSA" parameters should not be reused, i.e. one should generate a new private key for each connection, which is the case in mod_gnutls. The default parameters provided by lighttpd are "DH" parameters.
See also:
* "Diffie-Hellman(-Merkle) key exchange":http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
* "OpenSSL: Documents, dhparam(1)":https://www.openssl.org/docs/apps/dhparam.html
* "OpenSSL: Documents, SSL_CTX_set_tmp_dh_callback(3)":https://www.openssl.org/docs/ssl/SSL_CTX_set_tmp_dh_callback.html#NOTES
</textile>
* [Diffie-Hellman(-Merkle) key exchange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
* [OpenSSL: Documents, dhparam(1)](https://www.openssl.org/docs/apps/dhparam.html)
* [OpenSSL: Documents, SSL_CTX_set_tmp_dh_callback(3)](https://www.openssl.org/docs/ssl/SSL_CTX_set_tmp_dh_callback.html#NOTES)
</markdown>
</section>
</module>

View File

@ -2,10 +2,9 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>limits concurrent connections or requests per second.</short>
<description>
<description><markdown>
Both limits can be "in total" or per IP.
</description>
</markdown></description>
<action name="limit.con">
<short>limits the total amount of concurrent connections to the specified limit.</short>
@ -15,9 +14,9 @@
<parameter name="action">
<short>(optional) an action to be executed when the limit is reached</short>
</parameter>
<description>
<description><markdown>
If no action is defined a 503 error page will be returned. If it is specified there is no other special handling apart from running the specified action when the limit is reached.
</description>
</markdown></description>
<example>
<config>
limit.con 10;
@ -33,9 +32,9 @@
<parameter name="action">
<short>(optional) an action to be executed when the limit is reached</short>
</parameter>
<description>
<description><markdown>
If no action is defined a 503 error page will be returned. If it is specified there is no other special handling apart from running the specified action when the limit is reached.
</description>
</markdown></description>
<example>
<config>
limit.con_ip 2;
@ -51,9 +50,9 @@
<parameter name="action">
<short>(optional) an action to be executed when the limit is reached</short>
</parameter>
<description>
<description><markdown>
If no action is defined a 503 error page will be returned. If it is specified there is no other special handling apart from running the specified action when the limit is reached.
</description>
</markdown></description>
<example>
<config>
limit.req 100;
@ -69,9 +68,9 @@
<parameter name="action">
<short>(optional) an action to be executed when the limit is reached</short>
</parameter>
<description>
<description><markdown>
If no action is defined a 503 error page will be returned. If it is specified there is no other special handling apart from running the specified action when the limit is reached.
</description>
</markdown></description>
<example>
<config>
limit.req_ip 100;
@ -80,9 +79,9 @@
</action>
<example title="Limiting concurrent connections" anchor="#">
<description>
<description><markdown>
This config snippet will allow only 10 active downloads overall and 1 per IP. If the limit is exceeded, either because more than 10 people try to access this resource or one person tries a second time while having one download running already, they will be redirected to /connection_limit_reached.html.
</description>
</markdown></description>
<config>
setup {
module_load ("mod_limit","mod_redirect");
@ -100,10 +99,10 @@
</example>
<example title="Limiting requests per second" anchor="#">
<description>
This config snippet will write a message to the log containing the clien IP address if the /login page is hit more than once in a second.
<description><markdown>
This config snippet will write a message to the log containing the client IP address if the /login page is hit more than once in a second.
It will however also not do anything else. The client will be able to use the /login page as often as he wants.
</description>
</markdown></description>
<config>
setup {
module_load "mod_limit";

View File

@ -2,11 +2,9 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>load lua plugins and actions</short>
<description>
<textile><![CDATA[
Also see "Lua API":core_lua.html#core_lua.
]]></textile>
</description>
<description><markdown><![CDATA[
Also see [Lua API](core_lua.html#core_lua).
]]></markdown></description>
<setup name="lua.plugin">
<short>load file as lua plugin</short>
@ -19,13 +17,11 @@
<parameter name="lua-args">
<short>arguments forwarded to the lua plugin</short>
</parameter>
<description>
<textile>
A lua plugin can register setup and action callbacks (like any C module) by creating a setups / actions table in the global lua namespace.
<description><markdown>
A lua plugin can register setup and action callbacks (like any C module) by creating a setups / actions table in the global lua namespace.
The filename and the third argument @lua-args@ are available as parameters in @...@ in the lua script.
</textile>
</description>
The filename and the third argument `lua-args` are available as parameters in `...` in the lua script.
</markdown></description>
<example>
<config>
setup {
@ -37,9 +33,9 @@
</setup>
<example title="Example plugin" anchor="#">
<description><textile>
(see "contrib/core.lua":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core.lua for a real example)
</textile></description>
<description><markdown>
(see [contrib/core.lua](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core.lua) for a real example)
</markdown></description>
<config>
local filename, args = ...
@ -74,18 +70,17 @@
<parameter name="lua-args">
<short>arguments forwarded to the lua plugin</short>
</parameter>
<description>
<textile>
lua.handler is basically the same as "include_lua":core_config.html#core_config__includes with the following differences:
* each worker loads the lua file itself
* it isn't loaded before it is used, so you won't see errors in the script at load time
* it cannot call setup functions
* it supports arguments to the script (@local filename, args = ...@)
* doesn't lock the global lua lock, so it performs better when you use multiple workers
<description><markdown>
lua.handler is basically the same as [include_lua](core_config.html#core_config__includes) with the following differences:
See "contrib/core.lua":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core.lua for how we load some external actions like "contrib/core__xsendfile.lua":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core__xsendfile.lua
</textile>
</description>
* each worker loads the lua file itself
* it isn't loaded before it is used, so you won't see errors in the script at load time
* it cannot call setup functions
* it supports arguments to the script (`local filename, args = ...`)
* doesn't lock the global lua lock, so it performs better when you use multiple workers
See [contrib/core.lua](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core.lua) for how we load some external actions like [contrib/core__xsendfile.lua](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/core__xsendfile.lua).
</markdown></description>
<example>
<config>
setup {

View File

@ -2,20 +2,18 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>caches content on memcached servers</short>
<description>
<textile><![CDATA[
@lookup@ tries to find data associated with the key, and returns it as http body with status 200 if it finds something.
@store@ stores a http body (generated by another backend) in memcached.
<description><markdown><![CDATA[
`lookup` tries to find data associated with the key, and returns it as http body with status 200 if it finds something.
`store` stores a http body (generated by another backend) in memcached.
Caching always requires you to think about what you want; you cannot cache content that changes with every request!
Caching always requires you to think about what you want; you cannot cache content that changes with every request!
So most of the time you probably want to set a TTL for the stored content in memcached; your users probably don't need new content to be available the next second, perhaps 60 seconds is still good (obviously not true for a chat...).
So most of the time you probably want to set a TTL for the stored content in memcached; your users probably don't need new content to be available the next second, perhaps 60 seconds is still good (obviously not true for a chat...).
The other way is to purge the keys in your dynamic backend; you can set the memcached content from your backend too, which probably is faster than @memcached.store@.
The other way is to purge the keys in your dynamic backend; you can set the memcached content from your backend too, which probably is faster than `memcached.store`.
If the key is longer than 255 bytes or contains characters outside the range 0x21 - 0x7e we will use a hash of it instead (for now sha1, but that may change).
]]></textile>
</description>
If the key is longer than 255 bytes or contains characters outside the range 0x21 - 0x7e we will use a hash of it instead (for now sha1, but that may change).
]]></markdown></description>
<action name="memcached.lookup">
<short>searches the content in a memcached database</short>
@ -41,7 +39,7 @@
</action>
<action name="memcached.store">
<short>stores the generated respone in a memcached database</short>
<short>stores the generated response in a memcached database</short>
<parameter name="options">
<table>
<entry name="server">
@ -85,24 +83,26 @@
</example>
<section title="Lua API" anchor="#">
<textile><![CDATA[
mod_memcached exports a Lua API to per-worker @luaState@s too (for use in lua.handler):
<markdown><![CDATA[
mod_memcached exports a Lua API to per-worker `luaState`s too (for use in lua.handler):
@memcached.new(address)@ creates a new connection; a connection provides:
* @req = con:get(key, cb | vr)@
* @req = con:set(key, value, cb | vr, [ttl])@
* @con:setq(key, value, [ttl])@
`memcached.new(address)` creates a new connection; a connection provides:
* `req = con:get(key, cb | vr)`
* `req = con:set(key, value, cb | vr, [ttl])`
* `con:setq(key, value, [ttl])`
If a callback was given, the callback gets called with a response object; otherwise the response will be in req.response when ready.
The response object has:
* @code@: 1 - Ok, 2 - Not stored, 3 - Exists, 4 - Not found, 5 - Error
* @error@: error message
* @key@: the lookup key
* @flags@
* @ttl@
* @cas@
* @data@
]]></textile>
* `code`: 1 Ok, 2 Not stored, 3 Exists, 4 Not found, 5 Error
* `error`: error message
* `key`: the lookup key
* `flags`
* `ttl`
* `cas`
* `data`
]]></markdown>
</section>
</module>

View File

@ -45,13 +45,11 @@
</table>
</parameter>
<description>
<textile>
For @ciphers@ see OpenSSL "ciphers":https://www.openssl.org/docs/manmaster/man1/ciphers.html string
<description><markdown>
For `ciphers` see OpenSSL [ciphers](https://www.openssl.org/docs/manmaster/man1/ciphers.html) string
For @options@ see "options":https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html. Explicitly specify the reverse flag by toggling the "NO_" prefix to override defaults.
</textile>
</description>
For `options` see [options](https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html). Explicitly specify the reverse flag by toggling the "NO_" prefix to override defaults.
</markdown></description>
<example title="Simple TLS on IPv4 and IPv6">
<config>
@ -106,14 +104,13 @@
<parameter name="list">
<short>list of subsets to export</short>
</parameter>
<description>
<textile>
Supported subsets:
* "client" - set @SSL_CLIENT_S_DN_@ short-named entries
* "client-cert" - set @SSL_CLIENT_CERT@ to client certificate PEM
* "server" - set @SSL_SERVER_S_DN_@ short-named entries
* "server-cert" - set @SSL_SERVER_CERT@ to server certificate PEM
</textile>
</description>
<description><markdown>
Supported subsets:
* "client" set `SSL_CLIENT_S_DN_` short-named entries
* "client-cert" set `SSL_CLIENT_CERT` to client certificate PEM
* "server" set `SSL_SERVER_S_DN_` short-named entries
* "server-cert" set `SSL_SERVER_CERT` to server certificate PEM
</markdown></description>
</action>
</module>

View File

@ -2,19 +2,16 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>track connection progress (state) via a unique identifier</short>
<description>
<textile><![CDATA[
mod_progress lets you track connection progress (or rather state) using a lookup table in which connections are registered via a random unique identifier specified with the request.
It is most commonly used to implement progress bars for file uploads.
<description><markdown><![CDATA[
mod_progress lets you track connection progress (or rather state) using a lookup table in which connections are registered via a random unique identifier specified with the request.
It is most commonly used to implement progress bars for file uploads.
A request to the webserver is registered using the @progress.track@ action and being tracked by a random unique identifier supplied with the @X-Progress-Id@ querystring parameter.
From that moment on, other requests can fetch the state of the first request through the @progress.show@ action specifying the @X-Progress-Id@ used earlier.
Even after a tracked request finished and the connection to the client is gone, requests can for a limited amount of time get the status of it to see it as "done".
A request to the webserver is registered using the `progress.track` action and being tracked by a random unique identifier supplied with the `X-Progress-Id` querystring parameter.
From that moment on, other requests can fetch the state of the first request through the `progress.show` action specifying the `X-Progress-Id` used earlier.
Even after a tracked request finished and the connection to the client is gone, requests can for a limited amount of time get the status of it to see it as "done".
A live demonstration of a progress bar implementation can be seen at http://demo.lighttpd.net/progress/
Check the sourcecode there for further insight.
]]></textile>
</description>
Check the source code there for further insight.
]]></markdown></description>
<setup name="progress.ttl">
@ -47,26 +44,26 @@
<parameter name="format">
<short>(optional) output format, one of "legacy", "json" or "jsonp". Defaults to "json".</short>
</parameter>
<description>
<textile><![CDATA[
Output formats:
* legacy: @new Object({"state": "running"", "received": 123456, "sent": 0, "request_size": 200000, "response_size": 0})@
* json: @{"state": "running", "received": 123456, "sent": 0, "request_size": 200000, "response_size": 0}@
* jsonp: @progress({"state": "running", "received": 123456, "sent": 0, "request_size": 200000, "response_size": 0})@
The function name (default "progress") can be altered by supplying a X-Progress-Callback querystring parameter.
<description><markdown><![CDATA[
Output formats:
The JSON object can contain the following members:
* *state*: One of @"unknown"@, @"running"@, @"done"@ or @"error"@.
* *received*: Bytes received by lighty or uploaded by the client.
* *request_size*: Total size of request or uploaded file as specified via the Content-Length request header.
* *sent*: Bytes sent by lighty or downloaded by the client.
* *response_size*: Total size of response. Attention: this might grow over time in case of streaming from a backend.
* *status*: HTTP status code of response.
* legacy: `new Object({"state": "running"", "received": 123456, "sent": 0, "request_size": 200000, "response_size": 0})`
* json: `{"state": "running", "received": 123456, "sent": 0, "request_size": 200000, "response_size": 0}`
* jsonp: `progress({"state": "running", "received": 123456, "sent": 0, "request_size": 200000, "response_size": 0})`
The function name (default "progress") can be altered by supplying a X-Progress-Callback querystring parameter.
@received@, @request_size@, @sent@ and @response_size@ are only available if @state@ is @"running"@ or @"done"@.
@status@ is only available if @state@ is @"error"@.
]]></textile>
</description>
The JSON object can contain the following members:
* **state**: One of `"unknown"`, `"running"`, `"done"` or `"error"`.
* **received**: Bytes received by lighty or uploaded by the client.
* **request_size**: Total size of request or uploaded file as specified via the Content-Length request header.
* **sent**: Bytes sent by lighty or downloaded by the client.
* **response_size**: Total size of response. Attention: this might grow over time in case of streaming from a backend.
* **status**: HTTP status code of response.
`received`, `request_size`, `sent` and `response_size` are only available if `state` is `"running"` or `"done"`.
`status` is only available if `state` is `"error"`.
]]></markdown></description>
<example>
<config><![CDATA[

View File

@ -7,11 +7,9 @@
<parameter name="socket">
<short>socket to connect to, either "ip:port" or "unix:/path"</short>
</parameter>
<description>
<textile><![CDATA[
proxy uses @request.raw_path@ for the URL (including the query string) to send to the backend.
]]></textile>
</description>
<description><markdown><![CDATA[
proxy uses `request.raw_path` for the URL (including the query string) to send to the backend.
]]></markdown></description>
<example>
<config>
setup {

View File

@ -2,25 +2,21 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>redirect clients by sending a http status code 301 plus Location header</short>
<description>
<textile>
It supports matching "regular expressions":core_regex.html#core_regex and "substitution":core_pattern.html#core_pattern with captured substrings as well as other placeholders.
</textile>
</description>
<description><markdown>
It supports matching [regular expressions](core_regex.html#core_regex) and [substitution](core_pattern.html#core_pattern) with captured substrings as well as other placeholders.
</markdown></description>
<action name="redirect">
<short>redirect clients</short>
<parameter name="rule">
<short>a simple target string or one rule, mapping a regular expression to a target string, or a list of rules.</short>
</parameter>
<description>
<textile>
* The target string is a "pattern":core_pattern.html#core_pattern.
* The "regular expressions":core_regex.html#core_regex are used to match the request path (always starts with "/"!)
* If a list of rules is given, redirect stops on the first match.
* By default the target string is interpreted as absolute uri; if it starts with '?' it will replace the query string, if it starts with '/' it will replace the current path, and if it starts with './' it is interpreted relative to the current "directory" in the path.
</textile>
</description>
<description><markdown>
* The target string is a [pattern](core_pattern.html#core_pattern).
* The [regular expressions](core_regex.html#core_regex) are used to match the request path (always starts with "/"!)
* If a list of rules is given, redirect stops on the first match.
* By default the target string is interpreted as absolute uri; if it starts with '?' it will replace the query string, if it starts with '/' it will replace the current path, and if it starts with './' it is interpreted relative to the current "directory" in the path.
</markdown></description>
<example title="Example: redirect always (http to https)">
<config>
setup {
@ -59,9 +55,9 @@
</example>
<example>
<description>
<description><markdown>
redirect all non www. requests. for example: foo.tld/bar?x=y to www.foo.tld/bar?x=y
</description>
</markdown></description>
<config>
if request.host !~ "^www\.(.*)$" {
redirect "." => "http://www.%1/$0?%{request.query}";

View File

@ -2,31 +2,27 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>modifies request path and querystring</short>
<description>
<textile>
It supports matching "regular expressions":core_regex.html#core_regex and "substitution":core_pattern.html#core_pattern with captured substrings as well as other placeholders.
<description><markdown>
It supports matching [regular expressions](core_regex.html#core_regex) and [substitution](core_pattern.html#core_pattern) with captured substrings as well as other placeholders.
If your rewrite target does not contain any questionmark (@?@), then the querystring will not be altered.
If it does contain @?@ the querystring will be overwritten with the part after the @?@. To append the original querystring, use @%{request.query}@.
If your rewrite target does not contain any question mark (`?`), then the querystring will not be altered.
If it does contain `?` the querystring will be overwritten with the part after the `?`. To append the original querystring, use `%{request.query}`.
*IMPORTANT*: rewrite only changes the url, not the physical filename that it got mapped to by docroot or alias actions. So you need your docroot and alias actions after the rewrite.
If you have conditional rewrites like @if !phys.is_file { rewrite ... }@ you need docroot/alias both before (so it can check for the physical file) *and* after it (to build the new physical path).
</textile>
</description>
**IMPORTANT**: rewrite only changes the url, not the physical filename that it got mapped to by docroot or alias actions. So you need your docroot and alias actions after the rewrite.
If you have conditional rewrites like `if !phys.is_file { rewrite ... }` you need docroot/alias both before (so it can check for the physical file) **and** after it (to build the new physical path).
</markdown></description>
<action name="rewrite">
<short>modify request path and querystring</short>
<parameter name="rule">
<short>a simple target string or one rule, mapping a regular expression to a target string, or a list of rules.</short>
</parameter>
<description>
<textile>
* The target string is a "pattern":core_pattern.html#core_pattern.
* The "regular expressions":core_regex.html#core_regex are used to match the request path (always starts with "/" and does *not* include the query string!)
* If a list of rules is given, rewrite stops on the first match.
* Replaces the query string iff the target string contains an @?@
</textile>
</description>
<description><markdown>
* The target string is a [pattern](core_pattern.html#core_pattern).
* The [regular expressions](core_regex.html#core_regex) are used to match the request path (always starts with "/" and does **not** include the query string!)
* If a list of rules is given, rewrite stops on the first match.
* Replaces the query string iff the target string contains an `?`
</markdown></description>
<example title="Example: rewrite always">
<config>
setup {
@ -52,11 +48,9 @@
</config>
</example>
<example title="Example: pretty urls">
<description>
<textile>
Note: you really should move the logic for such rewrites into your application, and just rewrite all pretty urls to your index.php without putting the actions into the querystring.
</textile>
</description>
<description><markdown>
Note: you really should move the logic for such rewrites into your application, and just rewrite all pretty urls to your index.php without putting the actions into the querystring.
</markdown></description>
<config><![CDATA[
setup {
module_load "mod_rewrite";
@ -80,15 +74,13 @@
<parameter name="rule">
<short>a simple target string or one rule, mapping a regular expression to a target string, or a list of rules.</short>
</parameter>
<description>
<textile>
Similar to "@rewrite@":mod_rewrite.html#mod_rewrite__action_rewrite, but matches the raw path (i.e. the path before URL decoding and sanitizing) and the result is decoded again.
<description><markdown>
Similar to [`rewrite`](mod_rewrite.html#mod_rewrite__action_rewrite), but matches the raw path (i.e. the path before URL decoding and sanitizing) and the result is decoded again.
"@rewrite@":mod_rewrite.html#mod_rewrite__action_rewrite writes the result to @request.path@ and possibly @request.query@ and uses URL encoding to generate @request.raw_path@ from those.
"@rewrite_raw@":mod_rewrite.html#mod_rewrite__action_rewrite_raw writes @request.raw_path@ and decodes it into @request.path@ and @request.query@; this means the query string is always overwritten.
In both cases @request.path@ gets simplified afterwards.
</textile>
</description>
[`rewrite`](mod_rewrite.html#mod_rewrite__action_rewrite) writes the result to `request.path` and possibly `request.query` and uses URL encoding to generate `request.raw_path` from those.
[`rewrite_raw`](mod_rewrite.html#mod_rewrite__action_rewrite_raw) writes `request.raw_path` and decodes it into `request.path` and `request.query`; this means the query string is always overwritten.
In both cases `request.path` gets simplified afterwards.
</markdown></description>
</action>
<option name="rewrite.debug">

View File

@ -3,13 +3,14 @@
<short>protects files with a time limited code</short>
<section title="Install">
<textile><![CDATA[
By default distributions (and @make install@) should provide the necessary files; but you can always find them in the "contrib":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib folder:
* @secdownload.lua@
* @secdownload__secdownload.lua@
<markdown><![CDATA[
By default distributions (and `make install`) should provide the necessary files; but you can always find them in the [contrib](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib) folder:
* `secdownload.lua`
* `secdownload__secdownload.lua`
That way you can modify them for your own needs if you have to (although it is recommended to change the names of the files and the actions, so you don't get conflicts).
]]></textile>
]]></markdown>
</section>
<action name="secdownload">
@ -30,12 +31,10 @@
</entry>
</table>
</parameter>
<description>
<textile><![CDATA[
The @prefix@ is not used to build the filename; include it manually in the @document-root@ (works like @alias "/prefix" => "/docroot"@, see "@alias@":plugin_core.html#plugin_core__action_alias).
secdownload doesn't actually handle the (valid) request, it just provides the mapping to a filename (and rejects invalid requests).
]]></textile>
</description>
<description><markdown><![CDATA[
The `prefix` is not used to build the filename; include it manually in the `document-root` (works like `alias "/prefix" => "/docroot"`, see [`alias`](plugin_core.html#plugin_core__action_alias)).
secdownload doesn't actually handle the (valid) request, it just provides the mapping to a filename (and rejects invalid requests).
]]></markdown></description>
<example>
<config><![CDATA[
setup {
@ -48,33 +47,31 @@
</action>
<section title="Generating URLs">
<textile><![CDATA[
To generate URLs that are valid for @secdownload@ you need the same secret.
The url takes the form @prefix + md5hex(secret + filepath + timestamp) + '/' + timestamp + filepath@; timestamp is the "Unix time":http://en.wikipedia.org/wiki/Unix_time formatted as hexadecimal number.
<markdown><![CDATA[
To generate URLs that are valid for `secdownload` you need the same secret.
The url takes the form `prefix + md5hex(secret + filepath + timestamp) + '/' + timestamp + filepath`; timestamp is the [Unix time](https://en.wikipedia.org/wiki/Unix_time) formatted as hexadecimal number.
For example with PHP:
<pre>
$secret = "abc";
$uri_prefix = "/sec/";
$secret = "abc";
$uri_prefix = "/sec/";
# filename; please note file name starts with "/"
$f = "/secret-file.txt";
# filename; please note file name starts with "/"
$f = "/secret-file.txt";
# current timestamp
$t = time();
# current timestamp
$t = time();
$t_hex = sprintf("%08x", $t);
$m = md5($secret.$f.$t_hex);
$t_hex = sprintf("%08x", $t);
$m = md5($secret.$f.$t_hex);
# generate link
printf('<a href="%s%s/%s%s">%s</a>', $uri_prefix, $m, $t_hex, $f, $f);
</pre>
# generate link
printf('<a href="%s%s/%s%s">%s</a>', $uri_prefix, $m, $t_hex, $f, $f);
The config example above would map this url to the file @/secret/path/secret-file.txt@.
The config example above would map this url to the file `/secret/path/secret-file.txt`.
For more examples see "mod_secdownload (lighttpd 1.4.x)":https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModSecDownload#Examples
]]></textile>
For more examples see [mod_secdownload (lighttpd 1.4.x)](https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModSecDownload#Examples).
]]></markdown>
</section>
</module>

View File

@ -18,19 +18,18 @@
<parameter name="mode">
<short>(optional) "short"</short>
</parameter>
<description>
<textile>
The "short" mode removes connection and runtime details (recommended for "public" status).
<description><markdown>
The "short" mode removes connection and runtime details (recommended for "public" status).
The status page accepts the following query-string parameters:
* @?mode=runtime@: shows the runtime details
* "@format=plain@: shows the "short" stats in plain text format
</textile>
</description>
The status page accepts the following query-string parameters:
* `?mode=runtime`: shows the runtime details
* `format=plain`: shows the "short" stats in plain text format
</markdown></description>
<example>
<description>
<description><markdown>
If /server-status is requested, a page with lighttpd statistics is displayed.
</description>
</markdown></description>
<config>
setup {
module_load "mod_status";

View File

@ -2,9 +2,9 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>limits outgoing bandwidth usage</short>
<description>
<description><markdown>
All rates are in bytes/sec. The magazines are filled up in fixed intervals (compile time constant; defaults to 200ms).
</description>
</markdown></description>
<action name="io.throttle">
<short>set the outgoing throttle limits for current connection</short>
@ -14,11 +14,9 @@
<parameter name="burst">
<short>optional, defaults to 2*rate</short>
</parameter>
<description>
<textile>
@burst@ is the initial and maximum value for the @magazine@; doing IO drains the @magazine@, which fills up again over time with the specified @rate@.
</textile>
</description>
<description><markdown>
`burst` is the initial and maximum value for the `magazine`; doing IO drains the `magazine`, which fills up again over time with the specified `rate`.
</markdown></description>
</action>
<action name="io.throttle_pool">
@ -26,15 +24,13 @@
<parameter name="rate">
<short>bytes/sec limit</short>
</parameter>
<description>
<textile>
all connections in the same pool are limited as whole. Each @io.throttle_pool@ action creates its own pool.
</textile>
</description>
<description><markdown>
all connections in the same pool are limited as whole. Each `io.throttle_pool` action creates its own pool.
</markdown></description>
<example>
<description>
<description><markdown>
Using the same pool in more than one place:
</description>
</markdown></description>
<config>
setup {
module_load "mod_throttle";
@ -53,15 +49,13 @@
<parameter name="rate">
<short>bytes/sec limit</short>
</parameter>
<description>
<textile>
all connections from the same IP address in the same pool are limited as whole. Each @io.throttle_ip@ action creates its own pool.
</textile>
</description>
<description><markdown>
all connections from the same IP address in the same pool are limited as whole. Each `io.throttle_ip` action creates its own pool.
</markdown></description>
<example>
<description>
<description><markdown>
Using the same pool in more than one place:
</description>
</markdown></description>
<config>
setup {
module_load "mod_throttle";

View File

@ -2,41 +2,39 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>allows you to have user-specific document roots being accessed through http://domain/~user/</short>
<description>
<textile><![CDATA[
The document root can be built by using the home directory of a user which is specified by /~username/ at the beginning of the request path.
Alternatively, mod_userdir can build the docroot from a pattern similar to @vhost.pattern@ but using the username instead of the hostname.
]]></textile>
</description>
<description><markdown><![CDATA[
The document root can be built by using the home directory of a user which is specified by /~username/ at the beginning of the request path.
Alternatively, mod_userdir can build the docroot from a pattern similar to `vhost.pattern` but using the username instead of the hostname.
]]></markdown></description>
<action name="userdir">
<short>builds the document root by replacing certain placeholders in path with (parts of) the username.</short>
<parameter name="path">
<short>the path to build the document root with</short>
</parameter>
<description>
<textile><![CDATA[
If @path@ does not start with a slash (/), then the document root is prepended with the home directory of the given user as specified in /etc/passwd.
Otherwise the @path@ specifies the absolute docroot to be used.
<description><markdown><![CDATA[
If `path` does not start with a slash (/), then the document root is prepended with the home directory of the given user as specified in /etc/passwd.
Otherwise the `path` specifies the absolute docroot to be used.
Placeholders are:
* @*@ is replaced by the complete username
* @$1@-@$9@ are replaced by the n-th letter of the username, e.g. @$2@ is the second letter
Placeholders are:
Examples:
* `*` is replaced by the complete username
* `$1`-`$9` are replaced by the n-th letter of the username, e.g. `$2` is the second letter
Request for http://host/~lighty/foo.html (assuming "/home/lighty" is the home of the "lighty" user):
Examples:
table(table table-striped).
|_. @path@ |_. docroot |_. physicalpath|
| "public_html" | /home/lighty/public_html/ | /home/lighty/public_html/foo.html |
| "/usr/web/*/" | /usr/web/lighty/ | /usr/web/lighty/foo.html |
| "/usr/web" | /usr/web/lighty/ | /usr/web/lighty/foo.html |
| "/www/users/$1/$1$2/*/" | /www/users/l/li/lighty/ | /www/users/l/li/lighty/foo.html |
Request for http://host/~lighty/foo.html (assuming "/home/lighty" is the home of the "lighty" user):
*Note*: username "root" is not allowed for security reasons.
]]></textile>
</description>
| `path` | docroot | physicalpath|
|-|-|-|
| "public_html" | /home/lighty/public_html/ | /home/lighty/public_html/foo.html |
| "/usr/web/*/" | /usr/web/lighty/ | /usr/web/lighty/foo.html |
| "/usr/web" | /usr/web/lighty/ | /usr/web/lighty/foo.html |
| "/www/users/$1/$1$2/*/" | /www/users/l/li/lighty/ | /www/users/l/li/lighty/foo.html |
{:.table .table-striped}
**Note**: username "root" is not allowed for security reasons.
]]></markdown></description>
<example>
<config><![CDATA[
setup {

View File

@ -2,23 +2,19 @@
<module xmlns="urn:lighttpd.net:lighttpd2/doc1">
<short>offers various ways to implement virtual webhosts</short>
<description>
<textile>
It can map hostnames to actions and offers multiple ways to do so.
These ways differ in the flexibility of mapping (what to map and what to map to) as well as performance.
</textile>
</description>
<description><markdown>
It can map hostnames to actions and offers multiple ways to do so.
These ways differ in the flexibility of mapping (what to map and what to map to) as well as performance.
</markdown></description>
<action name="vhost.map">
<short>maps given hostnames to action blocks</short>
<parameter name="mapping">
<short>key-value list with hostnames as keys and actions as values</short>
</parameter>
<description>
<textile>
@vhost.map@ offers a fast (lookup through hash-table) and flexible mapping, but maps only exact hostnames (no pattern/regex matching). The server port is never considered part of the hostname. Use the key @default@ (keyword, not as string) to specify a default action.
</textile>
</description>
<description><markdown>
`vhost.map` offers a fast (lookup through hash-table) and flexible mapping, but maps only exact hostnames (no pattern/regex matching). The server port is never considered part of the hostname. Use the key `default` (keyword, not as string) to specify a default action.
</markdown></description>
<example>
<config>
vhost.map ["host1" => actionblock1, "host2" => actionblock2, ..., "hostN" => actionblockN, default => actionblock0];
@ -31,11 +27,9 @@
<parameter name="mapping">
<short>key-value list with regular expressions for hostnames as keys and actions as values</short>
</parameter>
<description>
<textile>
@vhost.map_regex@ walks through the list in the given order and stops at the first match; if no regular expression matched it will use the @default@ action (if specified).
</textile>
</description>
<description><markdown>
`vhost.map_regex` walks through the list in the given order and stops at the first match; if no regular expression matched it will use the `default` action (if specified).
</markdown></description>
<example>
<config>
vhost.map_regex ["host1regex" => actionblock1, "host2regex" => actionblock2, ..., "hostNregex" => actionblockN, default => actionblock0];
@ -49,17 +43,16 @@
</option>
<example>
<description>
<textile>
Combining both actions is also possible.
<description><markdown>
Combining both actions is also possible.
What it does (for example):
* if @example.com@ or @www.example.com@ is requested, the block named "examplesite" will be executed
* if @mydomain.tld@ is requested, the block named "mydomain" will be executed
* if @mydomain.com@ or @www.mydomain.net@ is requested, the block named "mydomain" will be executed (through the regex matching)
* if @www.mydomain.tld@ or something entirely different is requested, the block named "defaultdom" will be executed
</textile>
</description>
What it does (for example):
* if `example.com` or `www.example.com` is requested, the block named "examplesite" will be executed
* if `mydomain.tld` is requested, the block named "mydomain" will be executed
* if `mydomain.com` or `www.mydomain.net` is requested, the block named "mydomain" will be executed (through the regex matching)
* if `www.mydomain.tld` or something entirely different is requested, the block named "defaultdom" will be executed
</markdown></description>
<config>
setup {
module_load "mod_vhost";

View File

@ -3,30 +3,32 @@
<short>contains the core features for generic request handling, static files, log files and buffer limits.</short>
<section title="Socket addresses">
The following address formats can be used:
<markdown>
The following address formats can be used:
</markdown>
<section title="IPv4">
<textile>
Either with port @192.168.0.1:80@ or without @192.168.0.1@; you can either use real IPs or @0.0.0.0@ to listen on all network interfaces.
</textile>
<markdown>
Either with port `192.168.0.1:80` or without `192.168.0.1`; you can either use real IPs or `0.0.0.0` to listen on all network interfaces.
</markdown>
</section>
<section title="IPv6">
<textile>
Similar to IPv4; just put the IPv6 between "[" and "]" like this: @[::1]:80@ (IPv6 localhost with port 80).
<markdown>
Similar to IPv4; just put the IPv6 between "[" and "]" like this: `[::1]:80` (IPv6 localhost with port 80).
Please note that lighttpd always listens to IPv6 only (some platforms listen to IPv4 too on [::] by default).
</textile>
</markdown>
</section>
<section title="Unix domain sockets">
<textile>
A unix domain socket needs a filename where the socket is placed; use @unix:/path/to/socket@ as socket address.
<markdown>
A unix domain socket needs a filename where the socket is placed; use `unix:/path/to/socket` as socket address.
Please don't put unix domain sockets in @/tmp@. Use @/var/run/lighttpd/@ or something like that, where only root or selected "trusted" users can create files.
Please don't put unix domain sockets in `/tmp`. Use `/var/run/lighttpd/` or something like that, where only root or selected "trusted" users can create files.
This may be not supported in all places where a socket address can be specified.
</textile>
</markdown>
</section>
</section>
@ -82,32 +84,26 @@
<option name="stat.async">
<short>enables async stat() calls</short>
<default><value>true</value></default>
<description>
<textile>
If a filename is in lighttpd's stat "cache", lighttpd assumes the kernel still has the entry in memory, and @stat()@ therefore is unlikely to block.
Otherwise it will ask a background thread to call @stat()@, so the main worker threads are not waiting on a slow disk (or a network filesystem), but only if @stat.async@ is enabled.
<description><markdown>
If a filename is in lighttpd's stat "cache", lighttpd assumes the kernel still has the entry in memory, and `stat()` therefore is unlikely to block.
Otherwise it will ask a background thread to call `stat()`, so the main worker threads are not waiting on a slow disk (or a network filesystem), but only if `stat.async` is enabled.
If you know your disk is fast enough (perhaps a ramdisk?) and want to save the context switch to the background thread you can disable this.
</textile>
</description>
If you know your disk is fast enough (perhaps a ramdisk?) and want to save the context switch to the background thread you can disable this.
</markdown></description>
</option>
<option name="buffer_request_body">
<short>enable buffering request body on disk</short>
<default><value>true</value></default>
<description>
<textile>
Some backends like to wait for the complete response before forwarding/handling it. For this they require this option to save some memory.
</textile>
</description>
<description><markdown>
Some backends like to wait for the complete response before forwarding/handling it. For this they require this option to save some memory.
</markdown></description>
</option>
<option name="strict.post_content_length">
<short>require Content-Length for POST requests</short>
<default><value>true</value></default>
<description>
<textile>
Some clients don't send Content-Length for POST requests with empty body; they should send @Content-Length: 0@. When this check is enabled they'll get a @411 Length required@ error.
</textile>
</description>
<description><markdown>
Some clients don't send Content-Length for POST requests with empty body; they should send `Content-Length: 0`. When this check is enabled they'll get a `411 Length required` error.
</markdown></description>
</option>
<option name="static.exclude_extensions">
@ -124,12 +120,10 @@
<short>server name; is used in some places instead of the HTTP request hostname if the latter was not specified in the (HTTP/1.0) request</short>
<parameter name="hostname" />
<default><value>""</value></default>
<description>
<textile>
Even HTTP/1.0 clients usually specify a Host: header; without Host: header you could only run one domain on one IP address.
This option is for the rare case that you want to handle clients without Host: header support in a nice way.
</textile>
</description>
<description><markdown>
Even HTTP/1.0 clients usually specify a Host: header; without Host: header you could only run one domain on one IP address.
This option is for the rare case that you want to handle clients without Host: header support in a nice way.
</markdown></description>
<example>
<config>
server.name "lighttpd.net";
@ -140,21 +134,19 @@
<short>used to display server name + version in different places (HTTP response header, CGI environment, mod_dirlist footer, ...)</short>
<parameter name="tag" />
<default><value>"lighttpd/2.0.0"</value></default>
<description>
<description><markdown>
The default is "lighttpd/" + the current version.
</description>
</markdown></description>
</option>
<option name="mime_types">
<short>maps file extensions to MIME types</short>
<parameter name="mapping" />
<default><value>[]</value></default>
<description>
<textile>
Default MIME type is "application/octet-stream". The sources contain a "mimetypes example config":http://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/mimetypes.conf with many standard mappings.
<description><markdown>
Default MIME type is "application/octet-stream". The sources contain a [mimetypes example config](https://git.lighttpd.net/lighttpd/lighttpd2.git/tree/contrib/mimetypes.conf) with many standard mappings.
The longest matching suffix is used (@".tar.gz"@ always wins over @".gz"@), and in case of duplicate entries the last one is used.
</textile>
</description>
The longest matching suffix is used (`".tar.gz"` always wins over `".gz"`), and in case of duplicate entries the last one is used.
</markdown></description>
<example>
<config>
mime_types [ ".htm" => "text/html", ".txt" => "text/plain; charset=utf-8" ];
@ -164,7 +156,9 @@
</section>
<section title="Actions needed from lua">
These action are not needed (or usable) in non-lua configs.
<markdown>
These action are not needed (or usable) in non-lua configs.
</markdown>
<action name="list">
<short>(lua) combines a list of actions into one action, only needed in lua</short>
@ -192,13 +186,11 @@
<parameter name="patterns">
<short>One or more patterns to build docroot from</short>
</parameter>
<description>
<textile>
Uses "patterns":core_pattern.html#core_pattern to build document roots (base location of files to server).
@docroot@ uses the first pattern that results in an existing directory; otherwise it uses the *last* entry.
You'll want the @docroot@ action *before* @alias@ actions!
</textile>
</description>
<description><markdown>
Uses [patterns](core_pattern.html#core_pattern) to build document roots (base location of files to server).
`docroot` uses the first pattern that results in an existing directory; otherwise it uses the **last** entry.
You'll want the `docroot` action **before** `alias` actions!
</markdown></description>
<example>
<config>
docroot ("/var/www/vhosts/$0/htdocs", "/var/www/default/htdocs");
@ -211,14 +203,15 @@
<parameter name="mapping">
<short>maps prefix to base location on disk</short>
</parameter>
<description>
<textile>
The prefix is removed from the url path before it is appended to the base location.
You'll want the @docroot@ action *before* @alias@ actions!
<description><markdown>
The prefix is removed from the URL path before it is appended to the base location.
You'll want the `docroot` action **before** `alias` actions!
"Patterns":core_pattern.html#core_pattern are supported for alias targets as in @docroot@. As only one pattern per prefix can be given @alias@ does not check whether the target exists.
</textile>
</description>
[Patterns](core_pattern.html#core_pattern) are supported for alias targets as in `docroot`. As only one pattern per prefix can be given `alias` does not check whether the target exists.
Trailing slashes in the prefix used to indicate "directory handling" and get ignored for matching; "directory handling" is now always on.
That means URL paths only match at separator boundaries; the prefix `/a` (and `/a/`) matches the paths `/a`, `/a/` and `/a/b`, but not `/ab`.
</markdown></description>
<example>
<config>
docroot ("/var/www/vhosts/$0/htdocs", "/var/www/default/htdocs");
@ -236,19 +229,18 @@
<parameter name="filenames">
<short>filenames to look for</short>
</parameter>
<description>
<textile>
If the physical path is a directory search for the specified filenames; prefix a filename with '/' to search in the doc-root.
<description><markdown>
If the physical path is a directory search for the specified filenames; prefix a filename with '/' to search in the doc-root.
It works like this:
* if current physical path points to a regular file do nothing
* walk through the list of filenames to look for:
** if filename does not start with '/' and the current physical path doesn't point to a directory, ignore the entry
** if filename does not start with '/' and the url didn't end in a '/', redirect request to url with '/' appended
** if filename does not start with '/' search for it in current physical path (which is a directory)
** if filename does start with '/' search for it in the doc-root
</textile>
</description>
It works like this:
* if current physical path points to a regular file do nothing
* walk through the list of filenames to look for:
* if filename does not start with '/' and the current physical path doesn't point to a directory, ignore the entry
* if filename does not start with '/' and the url didn't end in a '/', redirect request to url with '/' appended
* if filename does not start with '/' search for it in current physical path (which is a directory)
* if filename does start with '/' search for it in the doc-root
</markdown></description>
<example>
<config>
setup {
@ -265,15 +257,13 @@
</action>
<action name="pathinfo">
<short>splits physical path into existing file/directory and the remaining PATH_INFO</short>
<description>
<textile>
Searches for the longest prefix of the physical path name that exists, splitting only at the directory separator @/@; also never leaves the document root (technically speaking the filename can't get shorter than the document root).
</textile>
</description>
<description><markdown>
Searches for the longest prefix of the physical path name that exists, splitting only at the directory separator `/`; also never leaves the document root (technically speaking the filename can't get shorter than the document root).
</markdown></description>
<example>
<description>
The following example maps @http://example.com/index.php/some/site@ to the file @/var/www/index.php@ with @PATH_INFO=/some/site@ (given @/var/www/index.php@ is a normal file).
</description>
<description><markdown>
The following example maps `http://example.com/index.php/some/site` to the file `/var/www/index.php` with `PATH_INFO=/some/site` (given `/var/www/index.php` is a normal file).
</markdown></description>
<config>
docroot "/var/www";
pathinfo;
@ -281,9 +271,9 @@
</config>
</example>
<example>
<description>
The following example maps @http://example.com/some/site@ to the file @/var/www/index.php@ with @PATH_INFO=/some/site@ (given @/var/www/index.php@ is a normal file, and @/var/www/some@ does not exist).
</description>
<description><markdown>
The following example maps `http://example.com/some/site` to the file `/var/www/index.php` with `PATH_INFO=/some/site` (given `/var/www/index.php` is a normal file, and `/var/www/some` does not exist).
</markdown></description>
<config>
docroot "/var/www";
pathinfo;
@ -297,31 +287,29 @@
<section title="Generating responses">
<action name="static">
<short>handle GET and HEAD requests with a static file from disk</short>
<description>
<textile>
This action is automatically appended to the global config (unless a lua config is specified at the command line).
<description><markdown>
This action is automatically appended to the global config (unless a lua config is specified at the command line).
Does nothing if:
* the request is already handled
* no physical path was set (missing @docroot@, @alias@, ...)
* the physical path points to a directory
Does nothing if:
All other problems lead to an error page, for example:
* wrong request method (405)
* file not found (404)
* couldn't open file (403)
* filename matches @static.exclude_extensions@ (403)
* ...
</textile>
</description>
* the request is already handled
* no physical path was set (missing `docroot`, `alias`, ...)
* the physical path points to a directory
All other problems lead to an error page, for example:
* wrong request method (405)
* file not found (404)
* couldn't open file (403)
* filename matches `static.exclude_extensions` (403)
* ...
</markdown></description>
</action>
<action name="static_no_fail">
<short>handle GET and HEAD requests with a static file from disk</short>
<description>
<textile>
same as @static@, but doesn't return any error pages; instead request handling continues.
</textile>
</description>
<description><markdown>
same as `static`, but doesn't return any error pages; instead request handling continues.
</markdown></description>
</action>
<action name="respond">
<short>returns a quick response with optional body</short>
@ -331,12 +319,10 @@
<parameter name="content">
<short>(optional) pattern for response body</short>
</parameter>
<description>
<textile>
Generates a simple response (our favorite benchmark handler).
The body is parsed as "pattern":core_pattern.html#core_pattern.
</textile>
</description>
<description><markdown>
Generates a simple response (our favorite benchmark handler).
The body is parsed as [pattern](core_pattern.html#core_pattern).
</markdown></description>
<example>
<config>
respond 403 => "Forbidden";
@ -351,30 +337,28 @@
</section>
<section title="Logging">
<section title="Log levels">
<textile>
For standard logging ("error.log") lighttpd knows the following levels:
* @debug@
* @info@
* @warning@
* @error@
* @abort@ (right before terminating the process)
* @backend@ (for log data from backends, like FastCGI stderr stream)
</textile>
</section>
<section title="Log levels"><markdown>
For standard logging ("error.log") lighttpd knows the following levels:
<section title="Log targets">
<textile>
The following log targets are known:
* not logging: empty string
* files: @file:/var/log/error.log@ or just @/var/log/error.log@
* stderr: @stderr:@ or @stderr@
* syslog: @syslog:@ (not supported yet)
* pipes: @pipe:command@ or @| command@ (not supported yet)
* `debug`
* `info`
* `warning`
* `error`
* `abort` (right before terminating the process)
* `backend` (for log data from backends, like FastCGI stderr stream)
</markdown></section>
Unknown strings are mapped to @stderr@.
</textile>
</section>
<section title="Log targets"><markdown>
The following log targets are known:
* not logging: empty string
* files: `file:/var/log/error.log` or just `/var/log/error.log`
* stderr: `stderr:` or `stderr`
* syslog: `syslog:` (not supported yet)
* pipes: `pipe:command` or `| command` (not supported yet)
Unknown strings are mapped to `stderr`.
</markdown></section>
<action name="log">
<short>overwrite log targets for all log levels</short>
@ -397,11 +381,9 @@
<parameter name="message">
<short>message pattern string</short>
</parameter>
<description>
<textile>
Writes the specified message to the log using level @info@; the message is parsed as "pattern":core_pattern.html#core_pattern.
</textile>
</description>
<description><markdown>
Writes the specified message to the log using level `info`; the message is parsed as [pattern](core_pattern.html#core_pattern).
</markdown></description>
<example>
<config>
log.write "hello world";
@ -431,21 +413,19 @@
<parameter name="format">
<short>a strftime format string</short>
</parameter>
<description>
<textile>
See "strftime":http://pubs.opengroup.org/onlinepubs/007904875/functions/strftime.html for the format string syntax.
<description><markdown>
See [strftime](https://pubs.opengroup.org/onlinepubs/007904875/functions/strftime.html) for the format string syntax.
The default format string is @"%d/%b/%Y %T %Z"@.
</textile>
</description>
The default format string is `"%d/%b/%Y %T %Z"`.
</markdown></description>
</setup>
</section>
<section title="Connection environment">
<textile>
The connection environment is a set of variable with names and values (both simple strings). CGI backends will forward the environment in addition to the standard CGI environment variables.
<markdown>
The connection environment is a set of variable with names and values (both simple strings). CGI backends will forward the environment in addition to the standard CGI environment variables.
The connection environment overwrites the standard CGI values.
</textile>
</markdown>
<action name="env.set">
<short>sets a connection environment variable</short>
@ -455,11 +435,9 @@
<parameter name="value">
<short>the pattern value to set</short>
</parameter>
<description>
<textile>
The value is parsed as "pattern":core_pattern.html#core_pattern.
</textile>
</description>
<description><markdown>
The value is parsed as [pattern](core_pattern.html#core_pattern).
</markdown></description>
<example>
<config>
env.set "INFO" => "%{req.path}";
@ -474,11 +452,9 @@
<parameter name="value">
<short>the pattern value to set</short>
</parameter>
<description>
<textile>
The value is parsed as "pattern":core_pattern.html#core_pattern. @env.add@ does not overwrite already existing values.
</textile>
</description>
<description><markdown>
The value is parsed as [pattern](core_pattern.html#core_pattern). `env.add` does not overwrite already existing values.
</markdown></description>
<example>
<config>
env.add "INFO" => "%{req.path}";
@ -507,7 +483,9 @@
</section>
<section title="Response header">
All header values that get set are parsed as "patterns":core_pattern.html#core_pattern.
<markdown>
All header values that get set are parsed as [patterns](core_pattern.html#core_pattern).
</markdown>
<action name="header.add">
<short>adds a new response header line</short>
@ -517,12 +495,10 @@
<parameter name="value">
<short>pattern header value</short>
</parameter>
<description>
<textile>
The HTTP spec requires that multiple headers with the same name could be merged by joining their values with ",".
In real life this doesn't work always, especially not for "Cookie" headers; so this action actually adds a separate header line.
</textile>
</description>
<description><markdown>
The HTTP spec requires that multiple headers with the same name could be merged by joining their values with ",".
In real life this doesn't work always, especially not for "Cookie" headers; so this action actually adds a separate header line.
</markdown></description>
<example>
<config>
header.add "Cache-Control" => "public";
@ -537,11 +513,9 @@
<parameter name="value">
<short>pattern header value</short>
</parameter>
<description>
<textile>
If header already exists appends new value separated by ", "; otherwise adds a new header line.
</textile>
</description>
<description><markdown>
If header already exists appends new value separated by ", "; otherwise adds a new header line.
</markdown></description>
</action>
<action name="header.overwrite">
<short>overwrite response header line or add new one</short>
@ -551,11 +525,9 @@
<parameter name="value">
<short>pattern header value</short>
</parameter>
<description>
<textile>
If header already exists overwrites the value; otherwise a new line gets added.
</textile>
</description>
<description><markdown>
If header already exists overwrites the value; otherwise a new line gets added.
</markdown></description>
</action>
<action name="header.remove">
<short>remove existing response header</short>
@ -575,15 +547,13 @@
<action name="set_status">
<short>modify HTTP status code</short>
<description>
<textile>
Modifies the HTTP status code, but doesn't handle the request in any way.
Later actions could overwrite the status, or a backend (FastCGI, proxy, ...) might overwrite it if the response is parsed later.
Only works if some action actually handled the request.
<description><markdown>
Modifies the HTTP status code, but doesn't handle the request in any way.
Later actions could overwrite the status, or a backend (FastCGI, proxy, ...) might overwrite it if the response is parsed later.
Only works if some action actually handled the request.
Lighttpd will generate error pages (if it knows the code) if the action that handled the request didn't generate a response body and a body is allowed.
</textile>
</description>
Lighttpd will generate error pages (if it knows the code) if the action that handled the request didn't generate a response body and a body is allowed.
</markdown></description>
<example>
<config>
# hide all 404s at end of config by setting 403
@ -595,7 +565,9 @@
</section>
<section title="Request headers">
All header values that get set are parsed as "patterns":core_pattern.html#core_pattern.
<markdown>
All header values that get set are parsed as [patterns](core_pattern.html#core_pattern).
</markdown>
<action name="req_header.add">
<short>adds a new request header line</short>
@ -605,11 +577,9 @@
<parameter name="value">
<short>pattern header value</short>
</parameter>
<description>
<textile>
Same as "header.add":plugin_core.html#plugin_core__action_header-add for request headers.
</textile>
</description>
<description><markdown>
Same as [header.add](plugin_core.html#plugin_core__action_header-add) for request headers.
</markdown></description>
</action>
<action name="req_header.append">
<short>appends value to request header line</short>
@ -619,11 +589,9 @@
<parameter name="value">
<short>pattern header value</short>
</parameter>
<description>
<textile>
Same as "header.append":plugin_core.html#plugin_core__action_header-append for request headers.
</textile>
</description>
<description><markdown>
Same as [header.append](plugin_core.html#plugin_core__action_header-append) for request headers.
</markdown></description>
</action>
<action name="req_header.overwrite">
<short>overwrite request header line or add new one</short>
@ -633,28 +601,22 @@
<parameter name="value">
<short>pattern header value</short>
</parameter>
<description>
<textile>
Same as "header.overwrite":plugin_core.html#plugin_core__action_header-overwrite for request headers.
</textile>
</description>
<description><markdown>
Same as [header.overwrite](plugin_core.html#plugin_core__action_header-overwrite) for request headers.
</markdown></description>
</action>
<action name="req_header.remove">
<short>remove existing request header</short>
<parameter name="name">
<short>header name</short>
</parameter>
<description>
<textile>
Same as "header.remove":plugin_core.html#plugin_core__action_header-remove for request headers.
</textile>
</description>
<description><markdown>
Same as [header.remove](plugin_core.html#plugin_core__action_header-remove) for request headers.
</markdown></description>
<example>
<description>
<textile>
Remove @Accept-Encoding@ request header to workaround the "BREACH":http://en.wikipedia.org/wiki/BREACH_(security_exploit) vulnerability in https.
</textile>
</description>
<description><markdown>
Remove `Accept-Encoding` request header to workaround the [BREACH](https://en.wikipedia.org/wiki/BREACH_(security_exploit)) vulnerability in https.
</markdown></description>
<config>
if request.scheme == "https" {
# create a copy of the header value
@ -678,7 +640,7 @@
</example>
</action>
<action name="io.buffer_in">
<short>set memory limit for intcoming chunkqueues (default is 256KiB)</short>
<short>set memory limit for incoming chunkqueues (default is 256KiB)</short>
<parameter name="limit">
<short>limit in bytes (0 means unlimited)</short>
</parameter>
@ -697,11 +659,9 @@
<parameter name="mapping">
<short>maps strings (or default) to actions</short>
</parameter>
<description>
<textile>
The pattern is parsed as "pattern":core_pattern.html#core_pattern. Have a look at "mod_vhost":mod_vhost.html#mod_vhost for special mappings on hostnames.
</textile>
</description>
<description><markdown>
The pattern is parsed as [pattern](core_pattern.html#core_pattern). Have a look at [mod_vhost](mod_vhost.html#mod_vhost) for special mappings on hostnames.
</markdown></description>
<example>
<config>
map "%{req.path}" => [
@ -763,9 +723,9 @@
<parameter name="names">
<short>string or list of strings with the module name(s)</short>
</parameter>
<description>
<description><markdown>
modules can be "loaded" more than once without error
</description>
</markdown></description>
<example>
<config>
setup {
@ -791,15 +751,13 @@
<parameter name="threads">
<short>number of threads</short>
</parameter>
<description>
<textile><![CDATA[
For example the stat cache uses such background threads.
<description><markdown><![CDATA[
For example the stat cache uses such background threads.
if @threads = 0@ the tasks are run in foreground (no background threads).
if @threads < 0@ all worker share a GThreadPool.
if @threads > 0@ each worker has its own thread pool with @threads@ threads.
]]></textile>
</description>
if `threads = 0` the tasks are run in foreground (no background threads).
if `threads < 0` all worker share a GThreadPool.
if `threads > 0` each worker has its own thread pool with `threads` threads.
]]></markdown></description>
</setup>
<setup name="fetch.files_static">
<short>starts a Fetch API provider</short>
@ -809,9 +767,9 @@
<parameter name="filename-pattern">
<short>A filename pattern including exactly on *</short>
</parameter>
<description>
Loads all filenames matching the wildcard pattern (which must include exactly on @*@) into the fetch storage.
</description>
<description><markdown>
Loads all filenames matching the wildcard pattern (which must include exactly on `*`) into the fetch storage.
</markdown></description>
<example>
<config>
setup {

View File

@ -1 +0,0 @@
SUBDIRS=lighttpd

View File

@ -1,7 +0,0 @@
headerfiles=$(filter-out $(srcdir)/config.h,$(wildcard $(srcdir)/*.h))
EXTRA_DIST=$(headerfiles)
headersdir=$(includedir)/lighttpd
headers_DATA=$(headerfiles) config.h

View File

@ -1,5 +1,5 @@
#ifndef _LIGHTTPD_ANGEL_CONIG_PARSER_H_
#define _LIGHTTPD_ANGEL_CONIG_PARSER_H_
#ifndef _LIGHTTPD_ANGEL_CONFIG_PARSER_H_
#define _LIGHTTPD_ANGEL_CONFIG_PARSER_H_
/* error handling */
#define LI_ANGEL_CONFIG_PARSER_ERROR li_angel_config_parser_error_quark()

View File

@ -115,7 +115,7 @@ LI_API gboolean li_angel_send_result(
GString *error, GString *data, GArray *fds,
GError **err);
/* free temporary needed memroy; call this once in while after some activity */
/* free temporary needed memory; call this once in while after some activity */
LI_API void li_angel_cleanup_tables(liAngelConnection *acon);
/* Usage */

View File

@ -12,7 +12,7 @@
*/
/* angel obviously doesn't work across platforms, so we don't need
* to care about endianess
* to care about endianness
*/
/* The buffer may be bigger of course, but a single string should not

View File

@ -11,6 +11,7 @@ typedef struct liPlugins liPlugins;
typedef gboolean (*liPluginInitCB) (liServer *srv, liPlugin *p);
typedef void (*liPluginFreeCB) (liServer *srv, liPlugin *p);
typedef void (*liPluginStopCB) (liServer *srv, liPlugin *p);
typedef void (*liPluginCleanConfigCB) (liServer *srv, liPlugin *p);
typedef gboolean (*liPluginCheckConfigCB) (liServer *srv, liPlugin *p, GError **err);
@ -37,8 +38,8 @@ struct liPlugin {
GHashTable *angel_callbacks; /**< map (const gchar*) -> liPluginHandleCallCB */
liPluginFreeCB handle_free; /**< called before plugin is unloaded */
liPluginStopCB handle_stop; /**< called to stop server */
liPluginCleanConfigCB handle_clean_config; /**< called before the reloading of the config is started or after the reloading failed */
liPluginCheckConfigCB handle_check_config; /**< called before activating a config to ensure everything works */
liPluginActivateConfigCB handle_activate_config; /**< called to activate a config after successful loading it. this cannot fail */
@ -49,25 +50,25 @@ struct liPlugin {
struct liPlugins {
GString *config_filename;
GHashTable *items, *load_items; /**< gchar* -> server_item */
GHashTable *items; /**< gchar* -> server_item */
liModules *modules;
GHashTable *module_refs, *load_module_refs; /** gchar* -> server_module */
GHashTable *ht_plugins, *load_ht_plugins;
GHashTable *module_refs; /** gchar* -> server_module */
GHashTable *ht_plugins;
GPtrArray *plugins, *load_plugins; /* plugin* */
GPtrArray *plugins; /* plugin* */
};
LI_API void li_plugins_init(liServer *srv, const gchar *module_dir, gboolean module_resident);
LI_API void li_plugins_clear(liServer *srv);
LI_API void li_plugins_config_clean(liServer *srv);
LI_API gboolean li_plugins_config_load(liServer *srv, const gchar *filename);
LI_API void li_plugins_stop(liServer *srv);
LI_API gboolean li_plugins_handle_item(liServer *srv, GString *itemname, liValue *parameters, GError **err);
/* "core" is a reserved module name for interal use */
/* "core" is a reserved module name for internal use */
LI_API gboolean li_plugins_load_module(liServer *srv, const gchar *name);
/* Needed by modules to register their plugin(s) */
LI_API liPlugin *li_angel_plugin_register(liServer *srv, liModule *mod, const gchar *name, liPluginInitCB init);

View File

@ -3,70 +3,6 @@
#include <lighttpd/angel_base.h>
typedef struct liPluginCoreParsing liPluginCoreParsing;
struct liPluginCoreParsing {
GPtrArray *env; /* <gchar*> */
GString *user;
uid_t user_uid;
gid_t user_gid;
GString *group;
gid_t group_gid;
GString *binary;
GString *config;
GString *luaconfig;
GString *modules_path;
GPtrArray *wrapper; /* <gchar*> */
gint64 rlim_core, rlim_nofile;
liInstanceConf *instconf;
GPtrArray *listen_masks;
};
typedef struct liPluginCoreConfig liPluginCoreConfig;
struct liPluginCoreConfig {
/* Parsing/Load */
liPluginCoreParsing parsing;
/* Running */
liInstanceConf *instconf;
GPtrArray *listen_masks;
liInstance *inst;
GHashTable *listen_sockets;
liEventSignal sig_hup;
};
typedef struct liPluginCoreListenMask liPluginCoreListenMask;
struct liPluginCoreListenMask {
enum {
LI_PLUGIN_CORE_LISTEN_MASK_IPV4,
LI_PLUGIN_CORE_LISTEN_MASK_IPV6,
LI_PLUGIN_CORE_LISTEN_MASK_UNIX
} type;
union {
struct {
guint32 addr;
guint32 networkmask;
guint16 port;
} ipv4;
struct {
guint8 addr[16];
guint network;
guint16 port;
} ipv6;
struct {
GString *path;
} unix_socket;
} value;
};
LI_API gboolean li_plugin_core_init(liServer *srv);
#endif

View File

@ -29,6 +29,7 @@ struct liInstance {
liServer *srv;
liInstanceConf *ic;
int pid; /** < remember PID for process as instance ID, even if process is already gone */
liProc *proc;
liEventChild child_watcher;

View File

@ -51,7 +51,7 @@ struct liBackendConfig {
liSocketAddress sock_addr;
/* >0: real limit for current connections + pendings connects
/* >0: real limit for current connections + pending connects
* <0: unlimited connections, absolute value limits the number of pending connects per worker
* =0: no limit
*

View File

@ -28,7 +28,7 @@ typedef struct liCollectInfo liCollectInfo;
/** li_collect_start returns NULL if the callback was called directly (e.g. for only one worker and ctx = wrk) */
LI_API liCollectInfo* li_collect_start(liWorker *ctx, liCollectFuncCB func, gpointer fdata, liCollectCB cb, gpointer cbdata);
/** li_collect_start_global uses srv->main_worker to call cb(), and never returns direclty */
/** li_collect_start_global uses srv->main_worker to call cb(), and never returns directly */
LI_API liCollectInfo* li_collect_start_global(liServer *srv, liCollectFuncCB func, gpointer fdata, liCollectCB cb, gpointer cbdata);
LI_API void li_collect_break(liCollectInfo* ci); /** this will result in complete == FALSE in the callback; call it if cbdata gets invalid */

View File

@ -118,9 +118,9 @@ LI_API void li_connection_request_done(liConnection *con);
*/
LI_API void li_connection_update_io_timeout(liConnection *con);
/* handles IOStream events for a connection; updates transfered bytes and io timeouts;
/* handles IOStream events for a connection; updates transferred bytes and io timeouts;
* *pcon is needed to handle cases then the connections gets reset while handling io stuff
* NULL == *pcon is ok - it won't update transfered bytes and io timeouts then.
* NULL == *pcon is ok - it won't update transferred bytes and io timeouts then.
* closes outgoing stream on reading EOF
*/
LI_API void li_connection_simple_tcp(liConnection **pcon, liIOStream *stream, gpointer *context, liIOStreamEvent event);

View File

@ -102,7 +102,7 @@ LI_API void li_lua_init2(liLuaState* LL, liServer* srv, liWorker* wrk);
LI_API int li_lua_push_traceback(lua_State *L, int nargs);
/* nargs: number of arguments *with* object; object must be the first of the arguments
* returns: FALSE: an error occured. stack balance -nargs (i.e. popped args)
* returns: FALSE: an error occurred. stack balance -nargs (i.e. popped args)
* TRUE: stack balance nresp-narg; popped args, pushed results
* srv/vr are only needed for error logging
* if optional is TRUE don't log an error if the method doesn't exist
@ -116,7 +116,7 @@ LI_API void li_lua_new_globals(lua_State *L);
LI_API GString* li_lua_print_get_string(lua_State *L, int from, int to);
/* pairs() for a GHashTable GString -> GString:
* Don't modify the hastable while iterating:
* Don't modify the hashtable while iterating:
* - no new keys
* - no delete
* Modifying values is fine; g_hash_table_insert() as long as the key already exists too.

View File

@ -35,7 +35,7 @@ struct liFetchCallbacks {
/* called on every lookup, should do a very simple check to verify the entry is still valid.
* DON'T MODIFY entry->data! return FALSE to trigger a new lookup, return TRUE if entry is still valid.
* you can trigger a refresh before returing TRUE with li_fetch_entry_refresh(entry)
* you can trigger a refresh before returning TRUE with li_fetch_entry_refresh(entry)
*/
gboolean (*revalidate)(liFetchDatabase* db, gpointer data, liFetchEntry *entry);

View File

@ -6,7 +6,7 @@
* the public domain worldwide. This software is distributed without
* any warranty.
*
* For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
* For details, see <https://creativecommons.org/publicdomain/zero/1.0/>.
* SPDX-License-Identifier: CC0-1.0
*/

View File

@ -7,7 +7,7 @@
/*
* Logging uses a dedicated thread in order to prevent blocking write io from blocking normal operations in worker threads.
* Code handling vrequests should use the VR_ERROR(), VR_DEBUG() etc makros. Otherwise the ERROR(), DEBUG() etc makros should be used.
* Code handling vrequests should use the VR_ERROR(), VR_DEBUG() etc macros. Otherwise the ERROR(), DEBUG() etc macros should be used.
* Basic examples: VR_WARNING(vr, "%s", "something unexpected happened") ERROR(srv, "%d is not bigger than %d", 23, 42)
*
* Log targets specify where the log messages are written to. They are kept open for a certain amount of time (default 30s).

View File

@ -13,7 +13,7 @@ typedef enum {
LI_MEMCACHED_NOT_STORED,
LI_MEMCACHED_EXISTS,
LI_MEMCACHED_NOT_FOUND,
LI_MEMCACHED_RESULT_ERROR /* some error occured */
LI_MEMCACHED_RESULT_ERROR /* some error occurred */
} liMemcachedResult;
typedef void (*liMemcachedCB)(liMemcachedRequest *request, liMemcachedResult result, liMemcachedItem *item, GError **err);

View File

@ -0,0 +1 @@
configure_file(output: 'config.h', configuration: conf_data)

View File

@ -17,11 +17,16 @@
/** see li_module_load */
#define MODULE_DEPENDS(mods, name) do { \
if (!li_module_load(mods, name)) { \
ERROR(mods->main, "Couldn't load dependency '%s'", name); \
GError *err = NULL; \
if (!li_module_load(mods, name, &err)) { \
ERROR(mods->main, "Couldn't load dependency '%s': %s", name, err->message); \
g_error_free(err); \
return FALSE; \
} } while(0)
#define LI_MODULES_ERROR li_modules_error_quark()
LI_API GQuark li_modules_error_quark(void);
typedef struct liModule liModule;
typedef struct liModules liModules;
@ -58,7 +63,7 @@ LI_API void li_modules_free(liModules *mods);
* returns NULL if it couldn't load the module.
*
* You should release modules after you used them with li_module_release or li_module_release_name */
LI_API liModule* li_module_load(liModules *mods, const gchar* name);
LI_API liModule* li_module_load(liModules *mods, const gchar* name, GError **error);
/* find module by name */
LI_API liModule *li_module_lookup(liModules *mods, const gchar *name);

View File

@ -21,6 +21,6 @@ LI_API void li_profiler_enable(gchar *output_path); /* enables the profiler */
LI_API void li_profiler_finish(void);
LI_API void li_profiler_dump(gint minsize); /* dumps memory statistics to file specified in LI_PROFILE_MEM env var */
LI_API void li_profiler_hashtable_insert(const gpointer addr, gsize size); /* registers an allocated block with the profiler */
LI_API void li_profiler_hashtable_remove(const gpointer addr); /* unregisters an allocated block with the profiler */
LI_API void li_profiler_hashtable_remove(const gpointer addr); /* deregisters an allocated block with the profiler */
#endif

View File

@ -18,7 +18,7 @@ typedef void (*liServerPrepareCallbackCB)(liServer *srv, gpointer data, gboolean
typedef enum {
LI_SERVER_INIT, /** start state */
LI_SERVER_LOADING, /** config loaded, prepare listeing sockets/open log files */
LI_SERVER_LOADING, /** config loaded, prepare listening sockets/open log files */
LI_SERVER_SUSPENDED, /** ready to go, no logs */
LI_SERVER_WARMUP, /** listen() active, no logs yet, handling remaining connections */
LI_SERVER_RUNNING, /** listen() and logs active */

View File

@ -45,9 +45,7 @@
# endif
#endif
#ifdef HAVE_CONFIG_H
# include <lighttpd/config.h>
#endif
#include <lighttpd/config.h>
#define GLIB_DISABLE_DEPRECATION_WARNINGS

View File

@ -64,14 +64,22 @@ struct liStatCacheEntry {
liStatCache *sc;
GPtrArray *vrequests; /* vrequests waiting for this info */
guint refcount; /* vrequests, delete_queue and tasklet hold references; dirlist/entrie cache entries are always in delete_queue too */
/*
* vrequests, liStatCache.delete_queue and tasklet hold references.
* Entries in liStatCache.dirlists and .entries are always in delete_queue too
* and don't hold references on their owb.
*/
guint refcount;
liWaitQueueElem queue_elem; /* queue element for the delete_queue */
gboolean cached;
};
struct liStatCache {
/* map GString* path (sce->data.path) to liStatCacheEntry* (sce), doesn't hold a reference */
GHashTable *dirlists;
/* map GString* path (sce->data.path) to liStatCacheEntry* (sce), doesn't hold a reference */
GHashTable *entries;
/* queue of liStatCacheEntry* through sce->queue_elem */
liWaitQueue delete_queue;
gdouble ttl;

View File

@ -32,7 +32,7 @@ INLINE void li_stream_safe_reset_and_release(liStream** pstream);
LI_API void li_stream_connect(liStream *source, liStream *dest);
LI_API void li_stream_disconnect(liStream *stream); /* disconnects stream->source and stream */
LI_API void li_stream_disconnect_dest(liStream *stream); /* disconnects stream->dest and stream. only for errors/conection resets */
LI_API void li_stream_disconnect_dest(liStream *stream); /* disconnects stream->dest and stream. only for errors/connection resets */
LI_API void li_stream_reset(liStream *stream); /* disconnect both sides */
LI_API void li_stream_notify(liStream *stream); /* new data in stream->cq, notify stream->dest */

View File

@ -1,9 +1,7 @@
#ifndef SYS_SOCKET_H
#define SYS_SOCKET_H
#ifdef HAVE_CONFIG_H
#include <lighttpd/config.h>
#endif
#ifdef _WIN32
#ifndef FD_SETSIZE
@ -66,8 +64,26 @@ int inet_aton(const char *cp, struct in_addr *inp);
#endif /* HAVE_IPV6 */
#endif /* HAVE_INET_NTOP */
typedef union liSockAddr liSockAddr;
union liSockAddr {
typedef union liSockAddrPtr liSockAddrPtr;
union liSockAddrPtr {
char *raw;
#ifdef HAVE_IPV6
struct sockaddr_in6 *ipv6;
#endif
struct sockaddr_in *ipv4;
#ifdef HAVE_SYS_UN_H
struct sockaddr_un *un;
#endif
struct sockaddr *plain;
#ifdef HAVE_SOCKADDR_STORAGE
struct sockaddr_storage *storage;
#endif
};
typedef union liSockAddrStorage liSockAddrStorage;
union liSockAddrStorage {
#ifdef HAVE_IPV6
struct sockaddr_in6 ipv6;
#endif
@ -85,7 +101,18 @@ union liSockAddr {
typedef struct liSocketAddress liSocketAddress;
struct liSocketAddress {
socklen_t len;
liSockAddr *addr;
/*
* address union pointer
*
* as we only allocate storage for the target address family,
* the compiler complains when we use a pointer to a "storage"
* (big size) address type and dereference it - as the allocation
* is too small (even if we then only access allocated parts
* within the storage type).
* So use type punning through union of pointers (C11 allows this;
* it doesn't have the concept of "active" members as C++ does).
*/
liSockAddrPtr addr_up;
};
#endif

View File

@ -207,7 +207,7 @@ typedef struct liRequestUri liRequestUri;
typedef struct liPhysical liPhysical;
/* respone.h */
/* response.h */
typedef struct liResponse liResponse;

View File

@ -10,7 +10,7 @@ typedef enum {
} liCounterType;
/* log message, print backtrace, and abort() (use LI_FATAL(msg) to call it) */
LI_API void li_fatal(const char *filename, unsigned int line, const char *function, const char *msg) HEDLEY_NO_RETURN;
LI_API HEDLEY_NO_RETURN void li_fatal(const char *filename, unsigned int line, const char *function, const char *msg);
/* if libunwind is available this prints a backtrace to STDERR */
LI_API void li_print_backtrace_stderr(void);
/* LI_FORCE_ASSERT is *always* active - in debug and release builds */
@ -84,9 +84,11 @@ LI_API void li_string_append_int(GString *dest, gint64 val);
LI_API void li_apr_sha1_base64(GString *dest, const GString *passwd);
LI_API void li_apr_md5_crypt(GString *dest, const GString *password, const GString *salt);
LI_API void li_safe_crypt(GString *dest, const GString *password, const GString *salt);
/* dest can be empty if salt is invalid (in which case li_safe_crypt returns FALSE) */
LI_API gboolean li_safe_crypt(GString *dest, const GString *password, const GString *salt);
INLINE GString* _li_g_string_append_len(GString *s, const gchar *val, gssize len);
/* g_string_append_len is a macro, and g_string_append_len(s, GSTR_LEN(x)) doesn't work; build inline wrapper */
INLINE GString *li_g_string_append_len(GString *s, const gchar *val, gssize len);
INLINE void li_g_string_clear(GString *s);
INLINE void li_g_string_free(gpointer data);
@ -130,7 +132,7 @@ LI_API gboolean _li_set_sys_error(GError **error, const gchar *msg, const gchar
INLINE void li_path_append_slash(GString *path) {
if (path->len == 0 || path->str[path->len-1] != '/')
g_string_append_len(path, "/", 1);
li_g_string_append_len(path, "/", 1);
}
/** warning: This "GString" does not make sure that there is a terminating '\0', and you shouldn't modify the GString */
@ -142,12 +144,8 @@ INLINE GString li_const_gstring(const gchar *str, gsize len) {
return gs;
}
#ifndef g_string_append_len
# define g_string_append_len _li_g_string_append_len
#endif
INLINE GString* _li_g_string_append_len(GString *s, const gchar *val, gssize len) {
return g_string_insert_len(s, -1, val, len);
INLINE GString* li_g_string_append_len(GString *s, const gchar *val, gssize len) {
return g_string_append_len(s, val, len);
}
INLINE void li_g_string_clear(GString *s) {

View File

@ -42,7 +42,7 @@ LI_API void li_waitqueue_stop(liWaitQueue *queue);
/* updates the delay of the timer. if timer is active, it is stopped and restarted */
LI_API void li_waitqueue_set_delay(liWaitQueue *queue, gdouble delay);
/* updates the timeout of the waitqueue, you should allways call this at the end of your callback */
/* updates the timeout of the waitqueue, you should always call this at the end of your callback */
LI_API void li_waitqueue_update(liWaitQueue *queue);
/* moves the element to the end of the queue if already queued, appends it to the end otherwise */

View File

@ -12,11 +12,11 @@ struct lua_State;
typedef struct liStatistics liStatistics;
struct liStatistics {
guint64 bytes_out; /** bytes transfered, outgoing */
guint64 bytes_in; /** bytes transfered, incoming */
guint64 bytes_out; /** bytes transferred, outgoing */
guint64 bytes_in; /** bytes transferred, incoming */
guint64 requests; /** processed requests */
guint64 active_cons_cum; /** cummulative value of active connections, updated once a second */
guint64 active_cons_cum; /** cumulative value of active connections, updated once a second */
guint64 actions_executed; /** actions executed */

3
include/meson.build Normal file
View File

@ -0,0 +1,3 @@
inc_dir = include_directories('.', is_system: true)
subdir('lighttpd')

333
meson.build Normal file
View File

@ -0,0 +1,333 @@
project(
'lighttpd',
'c',
default_options: [
'buildtype=debugoptimized',
'c_std=c99', # gnu99?
],
version: '2.0.0',
license: 'MIT',
)
libexec_dir = get_option('prefix') / get_option('libexecdir')
# include_dir = get_option('prefix') / get_option('includedir')
modules_dir = get_option('prefix') / get_option('libdir') / (meson.project_name() + '-' + meson.project_version())
lua_dir = get_option('prefix') / get_option('datadir') / 'lighttpd2/lua'
compiler = meson.get_compiler('c')
dep_not_found = dependency('', required: false)
if target_machine.system() == 'windows'
add_project_arguments(
'-DNVALGRIND',
language: 'c'
)
# link ws2_32 ?
# ... ?
endif
# ragel to compile parsers
ragel_bin = find_program('ragel')
ragel_gen = generator(
ragel_bin,
output: '@BASENAME@.c',
arguments: ['-C', '-T1', '-o', '@OUTPUT@', '@INPUT@'],
)
ragel_gen_t0 = generator(
ragel_bin,
output: '@BASENAME@.c',
arguments: ['-C', '-T0', '-o', '@OUTPUT@', '@INPUT@'],
)
add_project_arguments(
'-D_FILE_OFFSET_BITS=64',
'-D_LARGEFILE_SOURCE',
'-D_LARGE_FILES',
language: 'c',
)
conf_data = configuration_data()
conf_data.set_quoted('PACKAGE_VERSION', meson.project_version())
conf_data.set_quoted('PACKAGE_NAME', meson.project_name())
conf_data.set_quoted('DEFAULT_LIBEXECDIR', libexec_dir)
conf_data.set_quoted('DEFAULT_LIBDIR', modules_dir)
# if target_machine.system() == 'windows'
# conf_data.set_quoted('DEFAULT_LIBDIR', 'lib')
# endif
conf_data.set_quoted('DEFAULT_LUADIR', lua_dir)
dep_threads = dependency('threads')
dep_gthread = dependency('gthread-2.0', version: '>=2.16')
dep_gmodule = dependency('gmodule-2.0', version: '>=2.16')
# find libev manually
dep_ev = compiler.find_library(
'ev',
has_headers: 'ev.h',
)
if not compiler.has_function(
'ev_time',
prefix: '#include <ev.h>',
dependencies: dep_ev,
)
error('Missing ev_time() in libev')
endif
if get_option('lua')
dep_lua = dependency('lua5.1', 'lua-5.1', 'lua')
opt_dep_lua = dep_lua
conf_data.set10('HAVE_LUA_H', true)
else
dep_lua = disabler()
opt_dep_lua = dep_not_found
endif
if get_option('unwind')
opt_dep_unwind = dependency('libunwind')
conf_data.set10('HAVE_LIBUNWIND', true)
else
opt_dep_unwind = dep_not_found
endif
if get_option('openssl')
dep_openssl = dependency('openssl', version: '>=1.1') # should find both ssl and crypto
else
dep_openssl = disabler()
endif
if get_option('gnutls')
dep_gnutls = dependency('gnutls')
else
dep_gnutls = disabler()
endif
if get_option('sni')
opt_dep_idn = declare_dependency(
compile_args: '-DUSE_SNI',
dependencies: dependency('libidn')
)
else
opt_dep_idn = dep_not_found
endif
if get_option('bzip2')
opt_dep_bzip2 = compiler.find_library(
'bz2',
has_headers: 'bzlib.h',
)
if not compiler.has_function(
'BZ2_bzCompressInit',
prefix: '#include <bzlib.h>',
dependencies: opt_dep_bzip2,
)
error('Found libbz2, but missing BZ2_bzCompressInit()')
endif
conf_data.set10('HAVE_BZIP', true)
else
opt_dep_bzip2 = dep_not_found
endif
if get_option('deflate') ## zlib/gzip??
opt_dep_zlib = dependency('zlib')
conf_data.set10('HAVE_ZLIB', true)
else
opt_dep_zlib = dep_not_found
endif
if opt_dep_bzip2.found() or opt_dep_zlib.found()
dep_deflate = declare_dependency(dependencies: [opt_dep_bzip2, opt_dep_zlib])
else
dep_deflate = disabler()
endif
warn_c_args = [
'-Wshadow',
'-W',
'-pedantic',
]
warn_link_args = []
if get_option('extra-warnings')
warn_c_args += [
'-Wmissing-declarations',
'-Wdeclaration-after-statement',
'-Wcast-align',
'-Wsign-compare',
'-Wnested-externs',
'-Wpointer-arith',
'-Wmissing-prototypes',
'-Wshadow',
'-Wno-pointer-sign',
'-Wformat-security',
]
endif
check_sys_includes = [
'inttypes.h',
'stddef.h',
'stdint.h',
'sys/mman.h',
'sys/resource.h',
'sys/sendfile.h',
'sys/types.h',
'sys/uio.h',
'sys/un.h',
'unistd.h',
]
if get_option('profiler')
check_sys_includes += ['execinfo.h']
add_project_arguments(
'-DWITH_PROFILER',
language: 'c'
)
endif
check_libc_functions = [
'getrlimit',
'gmtime_r',
'inet_aton',
'inet_ntop',
'localtime_r',
'madvise',
'mmap',
'posix_fadvise',
'sendfile',
'sendfile64',
'sendfilev',
'writev',
'accept4',
]
# run compiler/env checks
foreach sys_include: check_sys_includes
if compiler.has_header(sys_include)
conf_data.set10('HAVE_' + sys_include.underscorify().to_upper(), true)
endif
endforeach
foreach libc_function: check_libc_functions
if compiler.has_function(libc_function)
conf_data.set10('HAVE_' + libc_function.underscorify().to_upper(), true)
endif
endforeach
add_project_arguments(
compiler.get_supported_arguments(warn_c_args),
language: 'c'
)
add_project_link_arguments(
compiler.get_supported_link_arguments(warn_link_args),
language: 'c'
)
# manual libcrypt with crypt_r check
lib_crypt = compiler.find_library(
'crypt',
required: false,
has_headers: 'crypt.h',
)
if lib_crypt.found()
if compiler.has_function(
'crypt_r',
prefix: '#include <crypt.h>',
dependencies: lib_crypt,
)
conf_data.set10('HAVE_CRYPT_H', true)
conf_data.set10('HAVE_CRYPT_R', true)
else
error('Found libcrypt, but missing crypt_r')
endif
else
warning('Missing libcrypt, using crypt instead of crypt_r')
endif
# need libm for fmod in throttle.c
lib_m = compiler.find_library('m')
# IPv6 support is mandatory by default
if get_option('ipv6')
if compiler.has_type(
'struct sockaddr_in6',
prefix: '\n'.join([
'#include <sys/types.h>',
'#include <sys/socket.h>',
'#include <netinet/in.h>',
]),
)
conf_data.set10('HAVE_IPV6', true)
else
error('Missing struct sockaddr_in6, needed for IPv6 support')
endif
endif
# auto detect 'struct sockaddr_storage' - should work fine without it.
if compiler.has_type(
'struct sockaddr_storage',
prefix: '#include <sys/socket.h>',
)
conf_data.set10('HAVE_SOCKADDR_STORAGE', true)
endif
if target_machine.system() == 'freebsd'
lib_kvm = compiler.find_library(
'kvm',
has_headers: 'kvm.h',
)
if not compiler.has_function(
'kvm_open',
prefix: '#include <kvm.h>',
dependencies: lib_kvm,
)
error('Found libkvm, but missing kvm_open')
endif
else
lib_kvm = dep_not_found
endif
main_deps = [
dep_threads,
dep_gthread,
dep_gmodule,
dep_ev,
]
subdir('contrib')
subdir('doc')
subdir('include')
subdir('src')
subdir('tests')
summary(
{
'libexec path': libexec_dir,
'modules path': modules_dir,
'lua plugin path': lua_dir,
},
section: 'Paths',
)
summary(
{
'lua': get_option('lua'),
'ipv6': get_option('ipv6'),
'config-parser': get_option('config-parser'),
'unwind': get_option('unwind'),
'openssl': get_option('openssl'),
'gnutls': get_option('gnutls'),
'sni': get_option('sni'),
'bzip2': get_option('bzip2'),
'deflate': get_option('deflate'),
'profiler': get_option('profiler'),
},
section: 'Features',
)
summary(
{
'detected libcrypt/crypt_r()': lib_crypt.found(),
'detected mmap()': conf_data.get('HAVE_MMAP', 0) == 1,
'detected writev()': conf_data.get('HAVE_WRITEV', 0) == 1,
'detected sendfile*()': (
conf_data.get('HAVE_SENDFILE', 0) == 1
or conf_data.get('HAVE_SENDFILE64', 0) == 1
or conf_data.get('HAVE_SENDFILEV', 0) == 1
),
},
section: 'Detected',
)

12
meson_options.txt Normal file
View File

@ -0,0 +1,12 @@
option('lua', type : 'boolean', value : true, description : 'Build with lua (5.1); extends core and other modules, and builds mod_lua')
option('ipv6', type : 'boolean', value : true, description : 'Build with IPv6 support')
option('config-parser', type : 'boolean', value : true, description : 'Build with standard config parser')
option('unwind', type : 'boolean', value : true, description : 'Build with (lib)unwind support in asserts to print backtraces')
option('openssl', type : 'boolean', value : true, description : 'Build mod_openssl')
option('gnutls', type : 'boolean', value : true, description : 'Build mod_gnutls')
option('sni', type : 'boolean', value : true, description : 'Build mod_openssl/mod_gnutls with SNI support')
option('bzip2', type : 'boolean', value : true, description : 'Build mod_deflate with bzip2 support')
option('deflate', type : 'boolean', value : true, description : 'Build mod_deflate with zlib (deflate) support')
option('extra-warnings', type : 'boolean', value : true, description : 'Build with extra warnings enabled')
# option('static', type : 'boolean', value : false, description : 'Build static lighttpd with all modules included')
option('profiler', type : 'boolean', value : false, description : 'Build with memory profiler')

View File

@ -6,7 +6,7 @@
SRCTEST=src/main/lighttpd_worker.c
PACKAGE=lighttpd
REV=${REV}
BASEDOWNLOADURL="http://download.lighttpd.net/lighttpd/snapshots-2.0.x"
BASEDOWNLOADURL="https://download.lighttpd.net/lighttpd/snapshots-2.0.x"
if [ ! -f ${SRCTEST} ]; then
echo "Current directory is not the source directory"

13
pyproject.toml Normal file
View File

@ -0,0 +1,13 @@
[tool.pyright]
include = ["tests"]
[[tool.pyright.executionEnvironments]]
root = "tests"
[tool.mypy]
warn_unused_configs = true
mypy_path = "tests"
files = "tests"
implicit_reexport = false
show_error_codes = true
follow_imports = "silent"

View File

@ -1,483 +0,0 @@
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckFunctionExists)
INCLUDE(CheckVariableExists)
INCLUDE(CheckTypeSize)
INCLUDE(CheckLibraryExists)
INCLUDE(CMakeDetermineCCompiler)
INCLUDE(FindThreads)
INCLUDE(FindPkgConfig)
INCLUDE(LighttpdMacros)
FIND_PACKAGE(Ragel REQUIRED)
FIND_PACKAGE(LibEV REQUIRED)
cmake_policy(VERSION 2.6.4)
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES)
OPTION(WITH_LUA "with lua 5.1 for lua-configfile [default: on]" ON)
OPTION(WITHOUT_CONFIG_PARSER "without standard config parser [default: off]" OFF)
OPTION(WITH_UNWIND "with (lib)unwind support in asserts to print backtraces [default: on]" ON)
OPTION(WITH_OPENSSL "with openssl support [default: on]" ON)
OPTION(WITH_GNUTLS "with gnutls support [default: on]" ON)
OPTION(WITH_SNI "with SNI support for gnutls/openssl, needs libidn [default: on]" ON)
OPTION(BUILD_STATIC "build a static lighttpd with all modules added")
OPTION(BUILD_EXTRA_WARNINGS "extra warnings [default: on]" ON)
OPTION(WITH_BZIP "with bzip2 support for mod_deflate [default: on]" ON)
OPTION(WITH_ZLIB "with deflate support for mod_deflate [default: on]" ON)
OPTION(WITH_PROFILER "with memory profiler")
OPTION(BUILD_UNIT_TESTS "build unit tests for testing")
IF(BUILD_STATIC)
SET(LIGHTTPD_STATIC 1)
ENDIF(BUILD_STATIC)
SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_SYSTEM_INCLUDE_PATH})
CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H)
CHECK_INCLUDE_FILES(stddef.h HAVE_STDDEF_H)
CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H)
CHECK_INCLUDE_FILES(sys/mman.h HAVE_SYS_MMAN_H)
CHECK_INCLUDE_FILES(sys/resource.h HAVE_SYS_RESOURCE_H)
CHECK_INCLUDE_FILES(sys/sendfile.h HAVE_SYS_SENDFILE_H)
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILES(sys/uio.h HAVE_SYS_UIO_H)
CHECK_INCLUDE_FILES(sys/un.h HAVE_SYS_UN_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES(execinfo.h HAVE_EXECINFO_H)
# will be needed for auth
CHECK_INCLUDE_FILES(crypt.h HAVE_CRYPT_H)
# check if we need libcrypt for crypt_r()
CHECK_LIBRARY_EXISTS(crypt crypt_r "" HAVE_LIBCRYPT_CRYPT_R)
IF(HAVE_LIBCRYPT_CRYPT_R)
SET(HAVE_CRYPT_R 1 FORCE)
SET(HAVE_LIBCRYPT 1 FORCE)
ELSE(HAVE_LIBCRYPT_CRYPT_R)
CHECK_LIBRARY_EXISTS(crypt crypt "" HAVE_LIBCRYPT)
ENDIF(HAVE_LIBCRYPT_CRYPT_R)
CHECK_FUNCTION_EXISTS(crypt_r HAVE_CRYPT_R)
CHECK_LIBRARY_EXISTS(kvm kvm_open "" HAVE_LIBKVM)
CHECK_TYPE_SIZE(long SIZEOF_LONG)
CHECK_TYPE_SIZE(off_t SIZEOF_OFF_T)
CHECK_FUNCTION_EXISTS(chroot HAVE_CHROOT)
CHECK_FUNCTION_EXISTS(getrlimit HAVE_GETRLIMIT)
CHECK_FUNCTION_EXISTS(gmtime_r HAVE_GMTIME_R)
CHECK_FUNCTION_EXISTS(inet_aton HAVE_INET_ATON)
CHECK_FUNCTION_EXISTS(inet_ntop HAVE_INET_NTOP)
CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS(madvise HAVE_MADVISE)
CHECK_FUNCTION_EXISTS(mmap HAVE_MMAP)
CHECK_FUNCTION_EXISTS(posix_fadvise HAVE_POSIX_FADVISE)
CHECK_FUNCTION_EXISTS(sendfile HAVE_SENDFILE)
CHECK_FUNCTION_EXISTS(sendfile64 HAVE_SENDFILE64)
CHECK_FUNCTION_EXISTS(sendfilev HAVE_SENDFILEV)
CHECK_FUNCTION_EXISTS(writev HAVE_WRITEV)
CHECK_FUNCTION_EXISTS(accept4 HAVE_ACCEPT4)
CHECK_C_SOURCE_COMPILES("
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0;
return 0;
}" HAVE_IPV6)
CHECK_C_SOURCE_COMPILES("
#include <sys/socket.h>
int main() {
struct sockaddr_storage s;
return 0;
}" HAVE_SOCKADDR_STORAGE)
# glib/gthread
pkg_check_modules(GTHREAD REQUIRED gthread-2.0>=2.16)
pkg_check_modules(GMODULE REQUIRED gmodule-2.0>=2.16)
IF(WITH_LUA)
pkg_search_module(LUA REQUIRED lua lua5.1 lua-5.1)
SET(HAVE_LIBLUA 1 "Have liblua")
SET(HAVE_LUA_H 1 "Have liblua header")
ENDIF(WITH_LUA)
IF(WITH_GNUTLS)
pkg_search_module(GNUTLS REQUIRED gnutls)
ENDIF(WITH_GNUTLS)
IF(WITH_UNWIND)
pkg_search_module(UNWIND REQUIRED libunwind)
SET(HAVE_LIBUNWIND 1 "Have libunwind")
ENDIF(WITH_UNWIND)
IF(WITH_OPENSSL)
CHECK_INCLUDE_FILES(openssl/ssl.h HAVE_OPENSSL_SSL_H)
IF(HAVE_OPENSSL_SSL_H)
CHECK_LIBRARY_EXISTS(crypto BIO_f_base64 "" HAVE_LIBCRYPTO)
IF(HAVE_LIBCRYPTO)
SET(OPENSSL_NO_KRB5 1)
CHECK_LIBRARY_EXISTS(ssl SSL_new "" HAVE_LIBSSL)
ENDIF(HAVE_LIBCRYPTO)
ENDIF(HAVE_OPENSSL_SSL_H)
ENDIF(WITH_OPENSSL)
IF(WITH_SNI)
pkg_search_module(IDN REQUIRED libidn)
ADD_DEFINITIONS(-DUSE_SNI)
ENDIF(WITH_SNI)
IF(WITH_BZIP)
CHECK_INCLUDE_FILES(bzlib.h HAVE_BZLIB_H)
CHECK_LIBRARY_EXISTS(bz2 BZ2_bzCompressInit "" HAVE_LIBBZ2)
IF(HAVE_BZLIB_H AND HAVE_LIBBZ2)
SET(BZIP_LDFLAGS "-lbz2")
SET(BZIP_CFLAGS "")
SET(HAVE_BZIP 1)
ENDIF(HAVE_BZLIB_H AND HAVE_LIBBZ2)
ENDIF(WITH_BZIP)
IF(WITH_ZLIB)
CHECK_INCLUDE_FILES(zlib.h HAVE_ZLIB_H)
CHECK_LIBRARY_EXISTS(z deflate "" HAVE_LIBZ)
IF(HAVE_ZLIB_H AND HAVE_LIBZ)
SET(ZLIB_LDFLAGS "-lz")
SET(ZLIB_CFLAGS "")
SET(HAVE_ZLIB 1)
ENDIF(HAVE_ZLIB_H AND HAVE_LIBZ)
ENDIF(WITH_ZLIB)
IF(WITH_PROFILER)
CHECK_INCLUDE_FILES(execinfo.h HAVE_EXECINFO_H)
ENDIF(WITH_PROFILER)
IF(NOT BUILD_STATIC)
CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN_H)
ENDIF(NOT BUILD_STATIC)
IF(NOT SBINDIR)
SET(SBINDIR "sbin")
ENDIF(NOT SBINDIR)
IF(NOT LIGHTTPD_MODULES_DIR)
SET(LIGHTTPD_MODULES_DIR "lib${LIB_SUFFIX}/lighttpd")
ENDIF(NOT LIGHTTPD_MODULES_DIR)
IF(NOT WIN32)
ADD_DEFINITIONS(
-DLIBRARY_DIR="\\"${CMAKE_INSTALL_PREFIX}/${LIGHTTPD_MODULES_DIR}\\""
)
ELSE(NOT WIN32)
## We use relative path in windows
ADD_DEFINITIONS(
-DLIBRARY_DIR="\\"lib\\""
)
ENDIF(NOT WIN32)
## Write out config.h
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_BINARY_DIR}/include/lighttpd/config.h)
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include)
SET(COMMON_SRC
angel_connection.c
angel_data.c
buffer.c
encoding.c
events.c
fetch.c
idlist.c
ip_parsers.c
jobqueue.c
memcached.c
mempool.c
module.c
radix.c
sys_memory.c
sys_socket.c
tasklet.c
utils.c
value.c
waitqueue.c
)
IF(WITH_PROFILER)
SET(COMMON_SRC ${COMMON_SRC}
profiler.c
)
ENDIF(WITH_PROFILER)
ADD_PREFIX(COMMON_SRC common/)
SET(LIGHTTPD_SHARED_SRC
angel.c
angel_fake.c
actions.c
base_lua.c
backends.c
chunk.c
chunk_parser.c
collect.c
condition.c
connection.c
environment.c
etag.c
filter.c
filter_chunked.c
filter_buffer_on_disk.c
http_headers.c
http_range_parser.c
http_request_parser.c
http_response_parser.c
lighttpd_glue.c
log.c
mimetype.c
network.c
network_write.c network_writev.c
network_sendfile.c
options.c
pattern.c
plugin.c
request.c
response.c
server.c
stat_cache.c
stream.c
stream_http_response.c
stream_simple_socket.c
throttle.c
url_parser.c
value.c
virtualrequest.c
worker.c
plugin_core.c
)
IF(NOT WITHOUT_CONFIG_PARSER)
SET(LIGHTTPD_SHARED_SRC ${LIGHTTPD_SHARED_SRC}
config_parser.c
)
ENDIF(NOT WITHOUT_CONFIG_PARSER)
IF(WITH_LUA)
SET(LIGHTTPD_SHARED_SRC ${LIGHTTPD_SHARED_SRC}
actions_lua.c
condition_lua.c
config_lua.c
value_lua.c
chunk_lua.c
core_lua.c
environment_lua.c
filters_lua.c
http_headers_lua.c
physical_lua.c
request_lua.c
response_lua.c
stat_lua.c
subrequest_lua.c
virtualrequest_lua.c
)
ENDIF(WITH_LUA)
ADD_PREFIX(LIGHTTPD_SHARED_SRC main/)
SET(ANGEL_SHARED_SRC
angel_config_parser.c
angel_log.c
angel_plugin.c
angel_plugin_core.c
angel_proc.c
angel_server.c
angel_value.c
)
ADD_PREFIX(ANGEL_SHARED_SRC angel/)
## Build parsers by using ragel...
RAGEL_PARSER(main/config_parser.rl -T0)
RAGEL_PARSER(main/http_range_parser.rl)
RAGEL_PARSER(main/http_request_parser.rl)
RAGEL_PARSER(main/http_response_parser.rl)
RAGEL_PARSER(common/ip_parsers.rl)
RAGEL_PARSER(main/url_parser.rl)
RAGEL_PARSER(angel/angel_config_parser.rl)
SET(L_INSTALL_TARGETS)
ADD_LIBRARY(lighttpd-${PACKAGE_VERSION}-common SHARED
${COMMON_SRC}
)
ADD_LIBRARY(lighttpd-${PACKAGE_VERSION}-shared SHARED
${LIGHTTPD_SHARED_SRC}
)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-shared lighttpd-${PACKAGE_VERSION}-common)
ADD_LIBRARY(lighttpd-${PACKAGE_VERSION}-sharedangel SHARED
${ANGEL_SHARED_SRC}
)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-sharedangel lighttpd-${PACKAGE_VERSION}-common)
ADD_EXECUTABLE(lighttpd2-worker
main/lighttpd_worker.c
)
TARGET_LINK_LIBRARIES(lighttpd2-worker lighttpd-${PACKAGE_VERSION}-common lighttpd-${PACKAGE_VERSION}-shared)
ADD_EXECUTABLE(lighttpd2
angel/angel_main.c
)
TARGET_LINK_LIBRARIES(lighttpd2 lighttpd-${PACKAGE_VERSION}-common lighttpd-${PACKAGE_VERSION}-sharedangel)
SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} lighttpd2-worker lighttpd2 lighttpd-${PACKAGE_VERSION}-common lighttpd-${PACKAGE_VERSION}-shared lighttpd-${PACKAGE_VERSION}-sharedangel)
IF(BUILD_EXTRA_WARNINGS)
SET(WARN_CFLAGS " -g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Wsign-compare -Wnested-externs -Wpointer-arith -Wmissing-prototypes -Wshadow -Wno-pointer-sign -Wformat-security")
SET(WARN_LDFLAGS " -g -O2 -g2 -Wall -Wl,--as-needed -Wl,--no-undefined")
# -Werror
ELSE(BUILD_EXTRA_WARNINGS)
SET(WARN_CFLAGS "")
SET(WARN_LDFLAGS "")
ENDIF(BUILD_EXTRA_WARNINGS)
SET(COMMON_LDFLAGS "${LUA_LDFLAGS} ${LIBEV_LDFLAGS} ${GTHREAD_LDFLAGS} ${GMODULE_LDFLAGS}${WARN_LDFLAGS}")
SET(COMMON_CFLAGS "${LUA_CFLAGS_OTHER} ${LIBEV_CFLAGS_OTHER} ${GTHREAD_CFLAGS_OTHER} ${GMODULE_CFLAGS_OTHER}${WARN_CFLAGS}")
SET(COMMON_INCLUDE_DIRECTORIES ${LUA_INCLUDE_DIRS} ${LIBEV_INCLUDE_DIRS} ${GTHREAD_INCLUDE_DIRS} ${GMODULE_INCLUDE_DIRS})
ADD_AND_INSTALL_LIBRARY(mod_access "modules/mod_access.c")
ADD_AND_INSTALL_LIBRARY(mod_accesslog "modules/mod_accesslog.c")
ADD_AND_INSTALL_LIBRARY(mod_auth "modules/mod_auth.c")
ADD_AND_INSTALL_LIBRARY(mod_balance "modules/mod_balance.c")
ADD_AND_INSTALL_LIBRARY(mod_cache_disk_etag "modules/mod_cache_disk_etag.c")
ADD_AND_INSTALL_LIBRARY(mod_debug "modules/mod_debug.c")
ADD_AND_INSTALL_LIBRARY(mod_dirlist "modules/mod_dirlist.c")
ADD_AND_INSTALL_LIBRARY(mod_expire "modules/mod_expire.c")
ADD_AND_INSTALL_LIBRARY(mod_fastcgi "modules/mod_fastcgi.c;modules/fastcgi_stream.c")
ADD_AND_INSTALL_LIBRARY(mod_flv "modules/mod_flv.c")
ADD_AND_INSTALL_LIBRARY(mod_fortune "modules/mod_fortune.c")
ADD_AND_INSTALL_LIBRARY(mod_limit "modules/mod_limit.c")
ADD_AND_INSTALL_LIBRARY(mod_memcached "modules/mod_memcached.c")
ADD_AND_INSTALL_LIBRARY(mod_progress "modules/mod_progress.c")
ADD_AND_INSTALL_LIBRARY(mod_proxy "modules/mod_proxy.c")
ADD_AND_INSTALL_LIBRARY(mod_redirect "modules/mod_redirect.c")
ADD_AND_INSTALL_LIBRARY(mod_rewrite "modules/mod_rewrite.c")
ADD_AND_INSTALL_LIBRARY(mod_scgi "modules/mod_scgi.c")
ADD_AND_INSTALL_LIBRARY(mod_status "modules/mod_status.c")
ADD_AND_INSTALL_LIBRARY(mod_throttle "modules/mod_throttle.c")
ADD_AND_INSTALL_LIBRARY(mod_userdir "modules/mod_userdir.c")
ADD_AND_INSTALL_LIBRARY(mod_vhost "modules/mod_vhost.c")
IF(HAVE_ZLIB OR HAVE_BZIP)
ADD_AND_INSTALL_LIBRARY(mod_deflate "modules/mod_deflate.c")
TARGET_LINK_LIBRARIES(mod_deflate ${BZIP_LDFLAGS} ${ZLIB_LDFLAGS})
ADD_TARGET_PROPERTIES(mod_deflate COMPILE_FLAGS ${BZIP_CFLAGS} ${ZLIB_CFLAGS})
ENDIF(HAVE_ZLIB OR HAVE_BZIP)
IF(WITH_LUA)
ADD_AND_INSTALL_LIBRARY(mod_lua "modules/mod_lua.c")
ENDIF(WITH_LUA)
IF(WITH_GNUTLS)
ADD_AND_INSTALL_LIBRARY(mod_gnutls "modules/mod_gnutls.c;modules/gnutls_filter.c;modules/gnutls_ocsp.c")
TARGET_LINK_LIBRARIES(mod_gnutls ${GNUTLS_LDFLAGS} ${IDN_LDFLAGS})
ADD_TARGET_PROPERTIES(mod_gnutls COMPILE_FLAGS ${GNUTLS_CFLAGS} ${IDN_CFLAGS})
ENDIF(WITH_GNUTLS)
IF(WITH_OPENSSL)
ADD_AND_INSTALL_LIBRARY(mod_openssl "modules/mod_openssl.c;modules/openssl_filter.c")
TARGET_LINK_LIBRARIES(mod_openssl ssl crypto ${IDN_LDFLAGS})
ADD_TARGET_PROPERTIES(mod_openssl COMPILE_FLAGS ${IDN_CFLAGS})
ENDIF(WITH_OPENSSL)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-common ${COMMON_LDFLAGS} ${UNWIND_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd-${PACKAGE_VERSION}-common COMPILE_FLAGS ${COMMON_CFLAGS} ${UNWIND_CFLAGS})
TARGET_INCLUDE_DIRECTORIES(lighttpd-${PACKAGE_VERSION}-common PUBLIC ${COMMON_INCLUDE_DIRECTORIES})
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-shared ${COMMON_LDFLAGS} m)
ADD_TARGET_PROPERTIES(lighttpd-${PACKAGE_VERSION}-shared COMPILE_FLAGS ${COMMON_CFLAGS})
TARGET_INCLUDE_DIRECTORIES(lighttpd-${PACKAGE_VERSION}-shared PUBLIC ${COMMON_INCLUDE_DIRECTORIES})
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-sharedangel ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd-${PACKAGE_VERSION}-sharedangel COMPILE_FLAGS ${COMMON_CFLAGS})
TARGET_INCLUDE_DIRECTORIES(lighttpd-${PACKAGE_VERSION}-sharedangel PUBLIC ${COMMON_INCLUDE_DIRECTORIES})
TARGET_LINK_LIBRARIES(lighttpd2-worker ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd2-worker COMPILE_FLAGS ${COMMON_CFLAGS})
TARGET_INCLUDE_DIRECTORIES(lighttpd2-worker PUBLIC ${COMMON_INCLUDE_DIRECTORIES})
TARGET_LINK_LIBRARIES(lighttpd2 ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd2 COMPILE_FLAGS ${COMMON_CFLAGS})
TARGET_INCLUDE_DIRECTORIES(lighttpd2 PUBLIC ${COMMON_INCLUDE_DIRECTORIES})
IF(HAVE_LIBCRYPT)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-common crypt)
ENDIF(HAVE_LIBCRYPT)
IF(HAVE_LIBKVM)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-common kvm)
ENDIF(HAVE_LIBKVM)
IF(CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -g -Wshadow -W -pedantic")
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_WITHDEBINFO} -O2")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
SET_TARGET_PROPERTIES(lighttpd2-worker PROPERTIES CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
IF(WIN32)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVALGRIND")
ADD_TARGET_PROPERTIES(lighttpd2-worker COMPILE_FLAGS "-DLI_DECLARE_EXPORTS")
TARGET_LINK_LIBRARIES(lighttpd2-worker ws2_32)
IF(MINGW)
TARGET_LINK_LIBRARIES(lighttpd2-worker msvcr70)
ADD_TARGET_PROPERTIES(lighttpd2-worker LINK_FLAGS "-Wl,-subsystem,console")
ENDIF(MINGW)
ENDIF(WIN32)
IF(NOT WIN32)
INSTALL(TARGETS ${L_INSTALL_TARGETS}
RUNTIME DESTINATION ${SBINDIR}
LIBRARY DESTINATION ${LIGHTTPD_MODULES_DIR}
ARCHIVE DESTINATION ${LIGHTTPD_MODULES_DIR}/static)
ELSE(NOT WIN32)
## HACK to make win32 to install our libraries in desired directory..
INSTALL(TARGETS lighttpd2-worker
RUNTIME DESTINATION ${SBINDIR}
ARCHIVE DESTINATION lib/static)
LIST(REMOVE_ITEM L_INSTALL_TARGETS lighttpd2-worker)
INSTALL(TARGETS ${L_INSTALL_TARGETS}
RUNTIME DESTINATION ${SBINDIR}/lib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
ENDIF(NOT WIN32)
IF(BUILD_UNIT_TESTS)
MACRO(ADD_TEST_BINARY TESTNAME EXENAME SRCFILES)
ADD_EXECUTABLE(${EXENAME} ${SRCFILES})
TARGET_LINK_LIBRARIES(${EXENAME} ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(${EXENAME} COMPILE_FLAGS ${COMMON_CFLAGS})
TARGET_INCLUDE_DIRECTORIES(${EXENAME} PUBLIC ${COMMON_INCLUDE_DIRECTORIES})
TARGET_LINK_LIBRARIES(${EXENAME} lighttpd-${PACKAGE_VERSION}-common lighttpd-${PACKAGE_VERSION}-shared)
ADD_TEST(${TESTNAME} ${EXENAME})
ENDMACRO(ADD_TEST_BINARY)
ADD_TEST_BINARY(Chunk-UnitTest test-chunk unittests/test-chunk.c)
ADD_TEST_BINARY(HttpRequestParser-UnitTest test-http-request-parser unittests/test-http-request-parser.c)
ADD_TEST_BINARY(IpParser-UnitTest test-ip-parser unittests/test-ip-parser.c)
ADD_TEST_BINARY(Radix-UnitTest test-radix unittests/test-radix.c)
ADD_TEST_BINARY(RangeParser-UnitTest test-range-parser unittests/test-range-parser.c)
ADD_TEST_BINARY(Utils-UnitTest test-utils unittests/test-utils.c)
ENDIF(BUILD_UNIT_TESTS)

View File

@ -1,9 +0,0 @@
SUBDIRS=common main modules angel unittests
EXTRA_DIST=CMakeLists.txt config.h.cmake lighttpd2.pc.in
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = lighttpd2.pc
$(pkgconfig_DATA): ../config.status

View File

@ -1,36 +0,0 @@
sbin_PROGRAMS=lighttpd2
lib_LTLIBRARIES=liblighttpd2-sharedangel.la
common_cflags=-I$(top_srcdir)/include -I$(top_builddir)/include
lighttpd_angel_shared_src= \
angel_log.c \
angel_plugin.c \
angel_plugin_core.c \
angel_proc.c \
angel_server.c \
angel_value.c
parsers= \
angel_config_parser.c
nodist_lighttpd_angel_shared_src=$(parsers)
BUILT_SOURCES=$(parsers)
CLEANFILES=$(parsers)
EXTRA_DIST=angel_config_parser.rl
angel_config_parser.c: angel_config_parser.rl
$(RAGEL) -C -T1 -o $@ $<
liblighttpd2_sharedangel_la_SOURCES=$(lighttpd_angel_shared_src)
nodist_liblighttpd2_sharedangel_la_SOURCES=$(nodist_lighttpd_angel_shared_src)
liblighttpd2_sharedangel_la_CPPFLAGS=$(common_cflags) $(GTHREAD_CFLAGS) $(GMODULE_CFLAGS) $(LIBEV_CFLAGS) $(LUA_CFLAGS) -DDEFAULT_LIBEXECDIR='"$(libexecdir)"'
liblighttpd2_sharedangel_la_LDFLAGS=-release $(PACKAGE_VERSION) -export-dynamic $(GTHREAD_LIBS) $(GMODULE_LIBS) $(LIBEV_LIBS)
liblighttpd2_sharedangel_la_LIBADD=../common/liblighttpd2-common.la
lighttpd2_SOURCES=angel_main.c
lighttpd2_CPPFLAGS=$(common_cflags) $(GTHREAD_CFLAGS) $(GMODULE_CFLAGS) $(LIBEV_CFLAGS) $(LUA_CFLAGS) -DDEFAULT_LIBDIR='"$(pkglibdir)"'
lighttpd2_LDFLAGS=-export-dynamic $(GTHREAD_LIBS) $(GMODULE_LIBS) $(LIBEV_LIBS) $(LUA_LIBS)
lighttpd2_LDADD=../common/liblighttpd2-common.la liblighttpd2-sharedangel.la

Some files were not shown because too many files have changed in this diff Show More