mirror of
https://github.com/dunglas/frankenphp.git
synced 2025-12-24 13:38:11 +08:00
Compare commits
60 Commits
ci/fix-doc
...
docs/xdebu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31da3af1f0 | ||
|
|
47d5de99db | ||
|
|
5d1289cc0d | ||
|
|
5cb5d0b8f1 | ||
|
|
a910e39b06 | ||
|
|
1abd549eb7 | ||
|
|
15a600cdaa | ||
|
|
ee05142582 | ||
|
|
6f69939b0d | ||
|
|
e7e0dbfa3d | ||
|
|
e127cf5e1c | ||
|
|
d973206174 | ||
|
|
0e163a0a75 | ||
|
|
eed3a019a6 | ||
|
|
40924d2996 | ||
|
|
2426a2fff7 | ||
|
|
ba33754ea4 | ||
|
|
c11488f99d | ||
|
|
6a3db9429d | ||
|
|
7b4f34d7da | ||
|
|
f182eba6f0 | ||
|
|
b18a079eb9 | ||
|
|
71661c45e2 | ||
|
|
408cc5fb5a | ||
|
|
822f80829e | ||
|
|
1511decad6 | ||
|
|
07a74e5c5a | ||
|
|
9a88401b03 | ||
|
|
83aaa0977f | ||
|
|
68b1d6f632 | ||
|
|
e0531fa17c | ||
|
|
7a81855f12 | ||
|
|
90eaa3a680 | ||
|
|
ecd7e4d5f2 | ||
|
|
14d1fd93a4 | ||
|
|
2d87fdaf0d | ||
|
|
1768f8b073 | ||
|
|
d36a80c76e | ||
|
|
3af07894d8 | ||
|
|
06dbc988b6 | ||
|
|
7f32ab6404 | ||
|
|
f5af2a2e87 | ||
|
|
c9d33b981b | ||
|
|
2c6e201ea6 | ||
|
|
b71dae9b03 | ||
|
|
963b3e0f59 | ||
|
|
a6fc22505c | ||
|
|
c00a011221 | ||
|
|
d1a6e38438 | ||
|
|
36b752d0a6 | ||
|
|
feaa950d89 | ||
|
|
f90e4614b6 | ||
|
|
f152a5fdaf | ||
|
|
b60fc5c374 | ||
|
|
5da805d9ee | ||
|
|
a996c2ee28 | ||
|
|
4cb77b552d | ||
|
|
241ca55d7a | ||
|
|
ae958516ea | ||
|
|
b61900eae1 |
11
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
11
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -7,6 +7,10 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Before submitting a bug, please double-check that your problem [is not
|
||||
a known issue](https://frankenphp.dev/docs/known-issues/)
|
||||
(especially if you use XDebug or Tideways), and that is has not
|
||||
[already been reported](https://github.com/dunglas/frankenphp/issues).
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
@@ -65,6 +69,13 @@ body:
|
||||
- aarch64
|
||||
- Other (tell us more in the description)
|
||||
default: 0
|
||||
- type: textarea
|
||||
id: php
|
||||
attributes:
|
||||
label: PHP configuration
|
||||
description: |
|
||||
Please copy and paste the output of the `phpinfo()` function.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
9
.github/workflows/docker.yaml
vendored
9
.github/workflows/docker.yaml
vendored
@@ -1,9 +1,14 @@
|
||||
---
|
||||
name: Build Docker images
|
||||
concurrency:
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
@@ -162,7 +167,7 @@ jobs:
|
||||
*.cache-from=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-${{ matrix.platform }}
|
||||
*.cache-from=type=gha,scope=refs/heads/main-${{ matrix.platform }}
|
||||
*.cache-to=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-${{ matrix.platform }},ignore-error=true
|
||||
${{ fromJson(needs.prepare.outputs.push) && '*.output=type=image,name=dunglas/frankenphp,push-by-digest=true,name-canonical=true,push=true' || '' }}
|
||||
${{ fromJson(needs.prepare.outputs.push) && format('*.output=type=image,name={0},push-by-digest=true,name-canonical=true,push=true', env.IMAGE_NAME) || '' }}
|
||||
env:
|
||||
SHA: ${{ github.sha }}
|
||||
VERSION: ${{ github.ref_type == 'tag' && github.ref_name || needs.prepare.outputs.ref || github.sha }}
|
||||
@@ -246,7 +251,7 @@ jobs:
|
||||
set -x
|
||||
# shellcheck disable=SC2046,SC2086
|
||||
docker buildx imagetools create $(jq -cr '.target."${{ matrix.target }}-${{ matrix.variant }}".tags | map("-t " + .) | join(" ")' <<< ${METADATA}) \
|
||||
$(printf 'dunglas/frankenphp@sha256:%s ' *)
|
||||
$(printf "${IMAGE_NAME}@sha256:%s " *)
|
||||
env:
|
||||
METADATA: ${{ needs.prepare.outputs.metadata }}
|
||||
-
|
||||
|
||||
67
.github/workflows/static.yaml
vendored
67
.github/workflows/static.yaml
vendored
@@ -1,9 +1,14 @@
|
||||
---
|
||||
name: Build binary releases
|
||||
concurrency:
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
@@ -68,12 +73,18 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ${{ fromJson(needs.prepare.outputs.platforms) }}
|
||||
debug: [false]
|
||||
include:
|
||||
- race: ""
|
||||
-
|
||||
qemu: true
|
||||
- platform: linux/amd64
|
||||
-
|
||||
platform: linux/amd64
|
||||
qemu: false
|
||||
name: Build ${{ matrix.platform }} static binary
|
||||
-
|
||||
platform: linux/amd64
|
||||
qemu: false
|
||||
debug: true
|
||||
name: Build ${{ matrix.platform }} static binary${{ matrix.debug && ' (debug)' || '' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ prepare ]
|
||||
steps:
|
||||
@@ -95,7 +106,7 @@ jobs:
|
||||
version: latest
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: ${{ fromJson(needs.prepare.outputs.push) }}
|
||||
if: ${{ fromJson(needs.prepare.outputs.push) && !matrix.debug }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
@@ -106,23 +117,24 @@ jobs:
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
pull: true
|
||||
load: ${{ !fromJson(needs.prepare.outputs.push) }}
|
||||
load: ${{ !fromJson(needs.prepare.outputs.push) || matrix.debug }}
|
||||
targets: static-builder
|
||||
set: |
|
||||
${{ matrix.debug && 'static-builder.args.DEBUG_SYMBOLS=1' || '' }}
|
||||
*.tags=
|
||||
*.platform=${{ matrix.platform }}
|
||||
*.cache-from=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder
|
||||
*.cache-from=type=gha,scope=refs/heads/main-static-builder
|
||||
*.cache-to=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder,ignore-error=true
|
||||
${{ fromJson(needs.prepare.outputs.push) && '*.output=type=image,name=dunglas/frankenphp,push-by-digest=true,name-canonical=true,push=true' || '' }}
|
||||
*.cache-from=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder${{ matrix.debug && '-debug' && '' }}
|
||||
*.cache-from=type=gha,scope=refs/heads/main-static-builder${{ matrix.debug && '-debug' && '' }}
|
||||
*.cache-to=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder${{ matrix.debug && '-debug' && '' }},ignore-error=true
|
||||
${{ (fromJson(needs.prepare.outputs.push) && !matrix.debug) && format('*.output=type=image,name={0},push-by-digest=true,name-canonical=true,push=true', env.IMAGE_NAME) || '' }}
|
||||
env:
|
||||
SHA: ${{ github.sha }}
|
||||
VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref || github.sha}}
|
||||
VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref || github.sha }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
# Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600
|
||||
name: Export metadata
|
||||
if: fromJson(needs.prepare.outputs.push)
|
||||
if: fromJson(needs.prepare.outputs.push) && !matrix.debug
|
||||
run: |
|
||||
mkdir -p /tmp/metadata
|
||||
|
||||
@@ -133,7 +145,7 @@ jobs:
|
||||
METADATA: ${{ steps.build.outputs.metadata }}
|
||||
-
|
||||
name: Upload metadata
|
||||
if: fromJson(needs.prepare.outputs.push)
|
||||
if: fromJson(needs.prepare.outputs.push) && !matrix.debug
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: metadata-static-builder
|
||||
@@ -142,11 +154,11 @@ jobs:
|
||||
retention-days: 1
|
||||
-
|
||||
name: Copy binary
|
||||
if: ${{ !fromJson(needs.prepare.outputs.push) }}
|
||||
if: ${{ !fromJson(needs.prepare.outputs.push) || matrix.debug }}
|
||||
run: |
|
||||
digest=$(jq -r '."static-builder"."containerimage.config.digest"' <<< "${METADATA}")
|
||||
docker create --platform=${{ matrix.platform }} --name static-builder "${digest}"
|
||||
docker cp "static-builder:/go/src/app/dist/${BINARY}" "${BINARY}"
|
||||
docker cp "static-builder:/go/src/app/dist/${BINARY}" "${BINARY}${{ matrix.debug && '-debug' || '' }}"
|
||||
env:
|
||||
METADATA: ${{ steps.build.outputs.metadata }}
|
||||
BINARY: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
|
||||
@@ -155,8 +167,15 @@ jobs:
|
||||
if: ${{ !fromJson(needs.prepare.outputs.push) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
|
||||
path: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
|
||||
name: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}${{ matrix.debug && '-debug' || '' }}
|
||||
path: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}${{ matrix.debug && '-debug' || '' }}
|
||||
-
|
||||
name: Upload debug asset
|
||||
if: fromJson(needs.prepare.outputs.push) && matrix.debug && (needs.prepare.outputs.ref || github.ref_type == 'tag')
|
||||
run: gh release upload "${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref }}" frankenphp-linux-x86_64-debug --repo dunglas/frankenphp --clobber
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -189,7 +208,7 @@ jobs:
|
||||
run: |
|
||||
# shellcheck disable=SC2046,SC2086
|
||||
docker buildx imagetools create $(jq -cr '.target."static-builder".tags | map("-t " + .) | join(" ")' <<< "${METADATA}") \
|
||||
$(printf 'dunglas/frankenphp@sha256:%s ' *)
|
||||
$(printf "${IMAGE_NAME}@sha256:%s " *)
|
||||
env:
|
||||
METADATA: ${{ needs.prepare.outputs.metadata }}
|
||||
-
|
||||
@@ -214,8 +233,12 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
build-mac:
|
||||
name: Build macOS x86_64 binaries
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ['arm64', 'x86_64']
|
||||
name: Build macOS ${{ matrix.platform }} binaries
|
||||
runs-on: ${{ matrix.platform == 'arm64' && 'macos-14' || 'macos-13' }}
|
||||
needs: [ prepare ]
|
||||
env:
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
@@ -227,7 +250,7 @@ jobs:
|
||||
-
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
go-version: '1.22'
|
||||
cache-dependency-path: |
|
||||
go.sum
|
||||
caddy/go.sum
|
||||
@@ -254,5 +277,5 @@ jobs:
|
||||
if: github.ref_type == 'branch'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: frankenphp-mac-x86_64
|
||||
path: dist/frankenphp-mac-x86_64
|
||||
name: frankenphp-mac-${{ matrix.platform }}
|
||||
path: dist/frankenphp-mac-${{ matrix.platform }}
|
||||
|
||||
8
.github/workflows/tests.yaml
vendored
8
.github/workflows/tests.yaml
vendored
@@ -4,9 +4,13 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -22,7 +26,7 @@ jobs:
|
||||
-
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
go-version: '1.22'
|
||||
cache-dependency-path: |
|
||||
go.sum
|
||||
caddy/go.sum
|
||||
@@ -66,6 +70,6 @@ jobs:
|
||||
run: ./reload_test.sh
|
||||
-
|
||||
name: Lint Go code
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
@@ -105,6 +105,32 @@ Build FrankenPHP images from scratch for arm64 & amd64 and push to Docker Hub:
|
||||
docker buildx bake -f docker-bake.hcl --pull --no-cache --push
|
||||
```
|
||||
|
||||
## Debugging Segmentation Faults With Static Builds
|
||||
|
||||
1. Download the debug version of the FrankenPHP binary from GitHub or create your custom static build including debug symbols:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder.args.DEBUG_SYMBOLS=1 \
|
||||
--set "static-builder.platform=linux/amd64" \
|
||||
static-builder
|
||||
docker cp $(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp
|
||||
```
|
||||
|
||||
2. Replace your current version of `frankenphp` by the debug FrankenPHP executable
|
||||
3. Start FrankenPHP as usual (alternatively, you can directly start FrankenPHP with GDB: `gdb --args ./frankenphp run`)
|
||||
4. Attach to the process with GDB:
|
||||
|
||||
```console
|
||||
gdb -p `pidof frankenphp`
|
||||
```
|
||||
|
||||
5. If necessary, type `continue` in the GDB shell
|
||||
6. Make FrankenPHP crash
|
||||
7. Type `bt` in the GDB shell
|
||||
8. Copy the output
|
||||
|
||||
## Debugging Segmentation Faults in GitHub Actions
|
||||
|
||||
1. Open `.github/workflows/tests.yml`
|
||||
@@ -175,3 +201,17 @@ docker buildx bake -f docker-bake.hcl --pull --no-cache --push
|
||||
apk add strace util-linux gdb
|
||||
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
|
||||
```
|
||||
|
||||
## Translating the Documentation
|
||||
|
||||
To translate the documentation and the site in a new language,
|
||||
follow these steps:
|
||||
|
||||
1. Create a new directory named with the language's 2-character ISO code in this repository's `docs/` directory
|
||||
2. Copy all the `.md` files in the root of the `docs/` directory into the new directory (always use the English version as source for translation, as it's always up to date)
|
||||
3. Copy the `README.md` and `CONTRIBUTING.md` files from the root directory to the new directory
|
||||
4. Translate the content of the files, but don't change the filenames, also don't translates strings starting with `> [!` (it's special markup for GitHub)
|
||||
5. Create a Pull Request with the translations
|
||||
6. In the [site repository](https://github.com/dunglas/frankenphp-website/tree/main), copy and translate the translation files in the `content/`, `data/` and `i18n/` directories
|
||||
7. Translate the values in the created YAML file
|
||||
8. Open a Pull Request on the site repository
|
||||
|
||||
@@ -6,7 +6,7 @@ FrankenPHP is a modern application server for PHP built on top of the [Caddy](ht
|
||||
|
||||
FrankenPHP gives superpowers to your PHP apps thanks to its stunning features: [*Early Hints*](https://frankenphp.dev/docs/early-hints/), [worker mode](https://frankenphp.dev/docs/worker/), [real-time capabilities](https://frankenphp.dev/docs/mercure/), automatic HTTPS, HTTP/2, and HTTP/3 support...
|
||||
|
||||
FrankenPHP works with any PHP app and makes your Symfony and Laravel projects faster than ever thanks to the provided integration with the worker mode.
|
||||
FrankenPHP works with any PHP app and makes your Laravel and Symfony projects faster than ever thanks to their official integrations with the worker mode.
|
||||
|
||||
FrankenPHP can also be used as a standalone Go library to embed PHP in any app using `net/http`.
|
||||
|
||||
@@ -28,7 +28,7 @@ Go to `https://localhost`, and enjoy!
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Do not attempt to use `https://127.0.0.1`. Use `localhost` and accept the self-signed certificate.
|
||||
> Do not attempt to use `https://127.0.0.1`. Use `https://localhost` and accept the self-signed certificate.
|
||||
> Use the [`SERVER_NAME` environment variable](docs/config.md#environment-variables) to change the domain to use.
|
||||
|
||||
### Standalone Binary
|
||||
@@ -59,6 +59,7 @@ You can also run command-line scripts with:
|
||||
* [Create **standalone**, self-executable PHP apps](https://frankenphp.dev/docs/embed/)
|
||||
* [Create static binaries](https://frankenphp.dev/docs/static/)
|
||||
* [Compile from sources](https://frankenphp.dev/docs/compile/)
|
||||
* [Laravel integration](https://frankenphp.dev/docs/laravel/)
|
||||
* [Known issues](https://frankenphp.dev/docs/known-issues/)
|
||||
* [Demo app (Symfony) and benchmarks](https://github.com/dunglas/frankenphp-demo)
|
||||
* [Go library documentation](https://pkg.go.dev/github.com/dunglas/frankenphp)
|
||||
|
||||
@@ -63,7 +63,8 @@ RUN apk add --no-cache --virtual .build-deps \
|
||||
oniguruma-dev \
|
||||
openssl-dev \
|
||||
readline-dev \
|
||||
sqlite-dev
|
||||
sqlite-dev \
|
||||
upx
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
@@ -88,6 +89,7 @@ ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLA
|
||||
WORKDIR /go/src/app/caddy/frankenphp
|
||||
RUN GOBIN=/usr/local/bin go install -ldflags "-w -s -extldflags '-Wl,-z,stack-size=0x80000' -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
|
||||
setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
|
||||
upx --best /usr/local/bin/frankenphp && \
|
||||
frankenphp version
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
@@ -9,23 +9,25 @@ fi
|
||||
|
||||
arch="$(uname -m)"
|
||||
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
md5binary="md5sum"
|
||||
if [ "${os}" = "darwin" ]; then
|
||||
os="mac"
|
||||
md5binary="md5 -q"
|
||||
fi
|
||||
|
||||
if [ -z "${PHP_EXTENSIONS}" ]; then
|
||||
if [ "${os}" = "mac" ] && [ "${arch}" = "x86_64" ]; then
|
||||
# Temporary fix for https://github.com/crazywhalecc/static-php-cli/issues/280 (remove ldap)
|
||||
export PHP_EXTENSIONS="apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,igbinary,intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,sysvsem,tokenizer,xml,xmlreader,xmlwriter,zip,zlib"
|
||||
else
|
||||
export PHP_EXTENSIONS="apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,igbinary,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,sysvsem,tokenizer,xml,xmlreader,xmlwriter,zip,zlib"
|
||||
fi
|
||||
export PHP_EXTENSIONS="apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,igbinary,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,sysvsem,tokenizer,xml,xmlreader,xmlwriter,zip,zlib"
|
||||
fi
|
||||
|
||||
if [ -z "${PHP_EXTENSION_LIBS}" ]; then
|
||||
export PHP_EXTENSION_LIBS="bzip2,freetype,libavif,libjpeg,liblz4,libwebp,libzip"
|
||||
fi
|
||||
|
||||
# the Brotli library must always be built as it is required by http://github.com/dunglas/caddy-cbrotli
|
||||
if ! echo "${PHP_EXTENSION_LIBS}" | grep -q "\bbrotli\b"; then
|
||||
export PHP_EXTENSION_LIBS="${PHP_EXTENSION_LIBS},brotli"
|
||||
fi
|
||||
|
||||
if [ -z "${PHP_VERSION}" ]; then
|
||||
export PHP_VERSION="8.3"
|
||||
fi
|
||||
@@ -57,9 +59,9 @@ if [ -n "${CLEAN}" ]; then
|
||||
go clean -cache
|
||||
fi
|
||||
|
||||
# Build libphp if ncessary
|
||||
# Build libphp if necessary
|
||||
if [ -f "dist/static-php-cli/buildroot/lib/libphp.a" ]; then
|
||||
cd dist/static-php-cli
|
||||
cd dist/static-php-cli
|
||||
else
|
||||
mkdir -p dist/
|
||||
cd dist/
|
||||
@@ -73,16 +75,20 @@ else
|
||||
fi
|
||||
|
||||
if type "brew" > /dev/null; then
|
||||
packages="composer"
|
||||
if ! type "composer" > /dev/null; then
|
||||
packages="composer"
|
||||
fi
|
||||
if ! type "go" > /dev/null; then
|
||||
packages="${packages} go"
|
||||
fi
|
||||
if [ -n "${RELEASE}" ]; then
|
||||
if [ -n "${RELEASE}" ] && ! type "gh" > /dev/null; then
|
||||
packages="${packages} gh"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
brew install --formula --quiet ${packages}
|
||||
if [ -n "${packages}" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
brew install --formula --quiet ${packages}
|
||||
fi
|
||||
fi
|
||||
|
||||
composer install --no-dev -a
|
||||
@@ -95,11 +101,10 @@ else
|
||||
extraOpts="${extraOpts} --no-strip"
|
||||
fi
|
||||
|
||||
./bin/spc doctor
|
||||
./bin/spc fetch --with-php="${PHP_VERSION}" --for-extensions="${PHP_EXTENSIONS}"
|
||||
# the Brotli library must always be built as it is required by http://github.com/dunglas/caddy-cbrotli
|
||||
./bin/spc doctor --auto-fix
|
||||
./bin/spc download --with-php="${PHP_VERSION}" --for-extensions="${PHP_EXTENSIONS}" --for-libs="${PHP_EXTENSION_LIBS}" --ignore-cache-sources=php-src
|
||||
# shellcheck disable=SC2086
|
||||
./bin/spc build --enable-zts --build-embed ${extraOpts} "${PHP_EXTENSIONS}" --with-libs="brotli,${PHP_EXTENSION_LIBS}"
|
||||
./bin/spc build --debug --enable-zts --build-embed ${extraOpts} "${PHP_EXTENSIONS}" --with-libs="${PHP_EXTENSION_LIBS}"
|
||||
fi
|
||||
|
||||
CGO_CFLAGS="-DFRANKENPHP_VERSION=${FRANKENPHP_VERSION} -I${PWD}/buildroot/include/ $(./buildroot/bin/php-config --includes | sed s#-I/#-I"${PWD}"/buildroot/#g)"
|
||||
@@ -123,7 +128,7 @@ cd ../..
|
||||
# Embed PHP app, if any
|
||||
if [ -n "${EMBED}" ] && [ -d "${EMBED}" ]; then
|
||||
tar -cf app.tar -C "${EMBED}" .
|
||||
md5 -q app.tar > app_checksum.txt
|
||||
${md5binary} app.tar > app_checksum.txt
|
||||
fi
|
||||
|
||||
if [ "${os}" = "linux" ]; then
|
||||
@@ -144,6 +149,10 @@ if [ -d "${EMBED}" ]; then
|
||||
truncate -s 0 app_checksum.txt
|
||||
fi
|
||||
|
||||
if type "upx" > /dev/null && [ -z "${DEBUG_SYMBOLS}" ] && [ -z "${NO_COMPRESS}" ]; then
|
||||
upx --best "dist/${bin}"
|
||||
fi
|
||||
|
||||
"dist/${bin}" version
|
||||
|
||||
if [ -n "${RELEASE}" ]; then
|
||||
|
||||
@@ -203,9 +203,9 @@ type FrankenPHPModule struct {
|
||||
// SplitPath sets the substrings for splitting the URI into two parts. The first matching substring will be used to split the "path info" from the path. The first piece is suffixed with the matching substring and will be assumed as the actual resource (CGI script) name. The second piece will be set to PATH_INFO for the CGI script to use. Default: `.php`.
|
||||
SplitPath []string `json:"split_path,omitempty"`
|
||||
// ResolveRootSymlink enables resolving the `root` directory to its actual value by evaluating a symbolic link, if one exists.
|
||||
ResolveRootSymlink bool `json:"resolve_root_symlink,omitempty"`
|
||||
ResolveRootSymlink *bool `json:"resolve_root_symlink,omitempty"`
|
||||
// Env sets an extra environment variable to the given value. Can be specified more than once for multiple environment variables.
|
||||
Env map[string]string `json:"env,omitempty"`
|
||||
Env frankenphp.PreparedEnv `json:"env,omitempty"`
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
@@ -225,8 +225,9 @@ func (f *FrankenPHPModule) Provision(ctx caddy.Context) error {
|
||||
if frankenphp.EmbeddedAppPath == "" {
|
||||
f.Root = "{http.vars.root}"
|
||||
} else {
|
||||
rrs := false
|
||||
f.Root = filepath.Join(frankenphp.EmbeddedAppPath, defaultDocumentRoot)
|
||||
f.ResolveRootSymlink = false
|
||||
f.ResolveRootSymlink = &rrs
|
||||
}
|
||||
} else {
|
||||
if frankenphp.EmbeddedAppPath != "" && filepath.IsLocal(f.Root) {
|
||||
@@ -238,6 +239,11 @@ func (f *FrankenPHPModule) Provision(ctx caddy.Context) error {
|
||||
f.SplitPath = []string{".php"}
|
||||
}
|
||||
|
||||
if f.ResolveRootSymlink == nil {
|
||||
rrs := true
|
||||
f.ResolveRootSymlink = &rrs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -250,16 +256,16 @@ func (f FrankenPHPModule) ServeHTTP(w http.ResponseWriter, r *http.Request, _ ca
|
||||
documentRoot := repl.ReplaceKnown(f.Root, "")
|
||||
|
||||
env := make(map[string]string, len(f.Env)+1)
|
||||
env["REQUEST_URI"] = origReq.URL.RequestURI()
|
||||
env["REQUEST_URI\x00"] = origReq.URL.RequestURI()
|
||||
for k, v := range f.Env {
|
||||
env[k] = repl.ReplaceKnown(v, "")
|
||||
}
|
||||
|
||||
fr, err := frankenphp.NewRequestWithContext(
|
||||
r,
|
||||
frankenphp.WithRequestDocumentRoot(documentRoot, f.ResolveRootSymlink),
|
||||
frankenphp.WithRequestDocumentRoot(documentRoot, *f.ResolveRootSymlink),
|
||||
frankenphp.WithRequestSplitPath(f.SplitPath),
|
||||
frankenphp.WithRequestEnv(env),
|
||||
frankenphp.WithRequestPreparedEnv(env),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -292,15 +298,24 @@ func (f *FrankenPHPModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||
return d.ArgErr()
|
||||
}
|
||||
if f.Env == nil {
|
||||
f.Env = make(map[string]string)
|
||||
f.Env = make(frankenphp.PreparedEnv)
|
||||
}
|
||||
f.Env[args[0]] = args[1]
|
||||
f.Env[args[0]+"\x00"] = args[1]
|
||||
|
||||
case "resolve_root_symlink":
|
||||
if d.NextArg() {
|
||||
if v, err := strconv.ParseBool(d.Val()); err == nil {
|
||||
f.ResolveRootSymlink = &v
|
||||
|
||||
if d.NextArg() {
|
||||
return d.ArgErr()
|
||||
}
|
||||
}
|
||||
|
||||
return d.ArgErr()
|
||||
}
|
||||
f.ResolveRootSymlink = true
|
||||
rrs := true
|
||||
f.ResolveRootSymlink = &rrs
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,7 +459,8 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
|
||||
if phpsrv.Root == "" {
|
||||
phpsrv.Root = filepath.Join(frankenphp.EmbeddedAppPath, defaultDocumentRoot)
|
||||
fsrv.Root = phpsrv.Root
|
||||
phpsrv.ResolveRootSymlink = false
|
||||
rrs := false
|
||||
phpsrv.ResolveRootSymlink = &rrs
|
||||
} else if filepath.IsLocal(fsrv.Root) {
|
||||
phpsrv.Root = filepath.Join(frankenphp.EmbeddedAppPath, phpsrv.Root)
|
||||
fsrv.Root = phpsrv.Root
|
||||
|
||||
101
caddy/go.mod
101
caddy/go.mod
@@ -2,6 +2,8 @@ module github.com/dunglas/frankenphp/caddy
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.22.0
|
||||
|
||||
replace github.com/dunglas/frankenphp => ../
|
||||
|
||||
retract v1.0.0-rc.1 // Human error
|
||||
@@ -10,20 +12,15 @@ require (
|
||||
github.com/caddyserver/caddy/v2 v2.7.6
|
||||
github.com/caddyserver/certmagic v0.20.0
|
||||
github.com/dunglas/caddy-cbrotli v1.0.0
|
||||
github.com/dunglas/frankenphp v1.0.3
|
||||
github.com/dunglas/mercure/caddy v0.15.9
|
||||
github.com/dunglas/vulcain/caddy v1.0.1
|
||||
github.com/dunglas/frankenphp v1.1.2
|
||||
github.com/dunglas/mercure/caddy v0.15.10
|
||||
github.com/dunglas/vulcain/caddy v1.0.2
|
||||
github.com/spf13/cobra v1.8.0
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
go.uber.org/zap v1.26.0
|
||||
go.uber.org/zap v1.27.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
||||
github.com/micromdm/scep/v2 v2.1.0 // indirect
|
||||
github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
)
|
||||
require github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935 // indirect
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
@@ -34,8 +31,9 @@ require (
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/MauriceGit/skiplist v0.0.0-20211105230623-77f5c8d3e145 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.8.0 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.9.0 // indirect
|
||||
github.com/alecthomas/chroma/v2 v2.12.0 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
||||
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
@@ -48,27 +46,29 @@ require (
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
||||
github.com/dolthub/maphash v0.1.0 // indirect
|
||||
github.com/dunglas/httpsfv v1.0.2 // indirect
|
||||
github.com/dunglas/mercure v0.15.9 // indirect
|
||||
github.com/dunglas/vulcain v1.0.1 // indirect
|
||||
github.com/dunglas/mercure v0.15.10 // indirect
|
||||
github.com/dunglas/vulcain v1.0.2 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
||||
github.com/getkin/kin-openapi v0.122.0 // indirect
|
||||
github.com/gammazero/deque v0.2.1 // indirect
|
||||
github.com/getkin/kin-openapi v0.123.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.10 // indirect
|
||||
github.com/go-kit/kit v0.13.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.5 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
@@ -77,7 +77,7 @@ require (
|
||||
github.com/google/certificate-transparency-go v1.1.7 // indirect
|
||||
github.com/google/go-tpm v0.9.0 // indirect
|
||||
github.com/google/go-tspi v0.3.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240125082051-42cd04596328 // indirect
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
@@ -89,17 +89,17 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/invopop/yaml v0.2.0 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.3 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
|
||||
github.com/jackc/pgtype v1.14.1 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.1 // indirect
|
||||
github.com/jackc/pgtype v1.14.2 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.3 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/kevburnsjr/skipfilter v0.0.1 // indirect
|
||||
github.com/klauspost/compress v1.17.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
@@ -107,8 +107,10 @@ require (
|
||||
github.com/mastercactapus/proxyprotocol v0.0.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/maypok86/otter v1.2.0 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mholt/acmez v1.2.0 // indirect
|
||||
github.com/micromdm/scep/v2 v2.1.0 // indirect
|
||||
github.com/miekg/dns v1.1.58 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
@@ -120,10 +122,10 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.46.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/prometheus/client_golang v1.19.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.50.0 // indirect
|
||||
github.com/prometheus/procfs v0.13.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/quic-go v0.41.0 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
@@ -136,7 +138,7 @@ require (
|
||||
github.com/slackhq/nebula v1.8.2 // indirect
|
||||
github.com/smallstep/certificates v0.25.0 // indirect
|
||||
github.com/smallstep/nosql v0.6.0 // indirect
|
||||
github.com/smallstep/truststore v0.12.1 // indirect
|
||||
github.com/smallstep/truststore v0.13.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
@@ -145,7 +147,7 @@ require (
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tailscale/tscert v0.0.0-20230806124524-28a91b69a046 // indirect
|
||||
github.com/tidwall/gjson v1.17.0 // indirect
|
||||
github.com/tidwall/gjson v1.17.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
@@ -153,41 +155,42 @@ require (
|
||||
github.com/urfave/cli v1.22.14 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
github.com/yuin/goldmark v1.6.0 // indirect
|
||||
github.com/yuin/goldmark v1.7.0 // indirect
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.8 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.etcd.io/bbolt v1.3.9 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/autoprop v0.45.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel v1.23.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.23.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.23.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.step.sm/cli-utils v0.8.0 // indirect
|
||||
go.step.sm/crypto v0.36.0 // indirect
|
||||
go.step.sm/linkedca v0.20.1 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/net v0.22.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/term v0.16.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240228224816-df926f6c8641 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect
|
||||
google.golang.org/grpc v1.62.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
|
||||
197
caddy/go.sum
197
caddy/go.sum
@@ -31,8 +31,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/RoaringBitmap/roaring v0.9.4/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
|
||||
github.com/RoaringBitmap/roaring v1.8.0 h1:h3Tbzc/4K7sW3sRMlBdOIW77x9rikkqvOgU/j+ofkn0=
|
||||
github.com/RoaringBitmap/roaring v1.8.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/RoaringBitmap/roaring v1.9.0 h1:lwKhr90/j0jVXJyh5X+vQN1VVn77rQFfYnh6RDRGCcE=
|
||||
github.com/RoaringBitmap/roaring v1.9.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
@@ -104,20 +104,22 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
|
||||
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
|
||||
github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4=
|
||||
github.com/dunglas/caddy-cbrotli v1.0.0 h1:+WNqXBkWyMcIpXB2rVZ3nwcElUbuAzf0kPxNXU4D+u0=
|
||||
github.com/dunglas/caddy-cbrotli v1.0.0/go.mod h1:KZsUu3fnQBgO0o3YDoQuO3Z61dFgUncr1F8rg8acwQw=
|
||||
github.com/dunglas/httpsfv v1.0.2 h1:iERDp/YAfnojSDJ7PW3dj1AReJz4MrwbECSSE59JWL0=
|
||||
github.com/dunglas/httpsfv v1.0.2/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg=
|
||||
github.com/dunglas/mercure v0.15.9 h1:Jdbi4jwzfIkZCcDX54W5C21S4kQX2AszfcoOAnSLZPw=
|
||||
github.com/dunglas/mercure v0.15.9/go.mod h1:1CY1/D2sZ3RxLWCcAODowg/2yINbiG7IJf2fJCFDj3A=
|
||||
github.com/dunglas/mercure/caddy v0.15.9 h1:YqHNSZ6XKKQsK2jiMkttOIkaq80e0lC8rnOXaV/bhxQ=
|
||||
github.com/dunglas/mercure/caddy v0.15.9/go.mod h1:cM+991N0bpMw4R/79DM4dCEtbyyikHfZfwDOiCF/qx4=
|
||||
github.com/dunglas/vulcain v1.0.1 h1:S6bJYYwb8q7BlyQwYqHio0lyPYfBUvzY2dB3WlZXELU=
|
||||
github.com/dunglas/vulcain v1.0.1/go.mod h1:i209S5QmwiSpsxj/nqTsDAd7TP7OyG4MrsEX0jqAF1o=
|
||||
github.com/dunglas/vulcain/caddy v1.0.1 h1:wso79xuGcxgrxsCCYeGiurfNz/N20jI8JHjPWuu2BPU=
|
||||
github.com/dunglas/vulcain/caddy v1.0.1/go.mod h1:haPwAQt1G5+O/+zIcwvD+02CkBNGHbxtTvNfUHP0o0w=
|
||||
github.com/dunglas/mercure v0.15.10 h1:U2CmOmOg2b8CFipjHCLweywjII6iwrIFfWepdkWdekU=
|
||||
github.com/dunglas/mercure v0.15.10/go.mod h1:RLRg+ZBrNLqmvgO5yIAdXjR9s4gR3p3r/bgCl/Wd5rQ=
|
||||
github.com/dunglas/mercure/caddy v0.15.10 h1:DGIUJpvwT127XYQguTmA+aS3RTL0+fFv4c7Naqs/iDE=
|
||||
github.com/dunglas/mercure/caddy v0.15.10/go.mod h1:4Ai8/5HMYU/wkVRQ54G2REpGIEwV73RgeycbBEW8EAI=
|
||||
github.com/dunglas/vulcain v1.0.2 h1:SVZ1zPn4sw5xC0oVOoUdw+5nQF1yZ5tyJkyzWtZ7vTw=
|
||||
github.com/dunglas/vulcain v1.0.2/go.mod h1:KcW9ni72f6qjfxMq+/yvHT7ZSbdQErEwj4cWNaTkS/k=
|
||||
github.com/dunglas/vulcain/caddy v1.0.2 h1:nTR5uGHPUHj8D5oI0E8TpZ0BMSTlqQvsQD1TMaNJ2mk=
|
||||
github.com/dunglas/vulcain/caddy v1.0.2/go.mod h1:t9P6SbtnTj0qyGaIx765YjthZ0hxLYutvM4+oKuVG68=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
@@ -130,8 +132,10 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
|
||||
github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10=
|
||||
github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
|
||||
github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
|
||||
github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
|
||||
github.com/getkin/kin-openapi v0.123.0 h1:zIik0mRwFNLyvtXK274Q6ut+dPh6nlxBp0x7mNrPhs8=
|
||||
github.com/getkin/kin-openapi v0.123.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
|
||||
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-kit/kit v0.4.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
@@ -145,14 +149,14 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
|
||||
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
|
||||
github.com/go-openapi/swag v0.22.5 h1:fVS63IE3M0lsuWRzuom3RLwUMVI2peDH01s6M70ugys=
|
||||
github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
@@ -164,8 +168,8 @@ github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncV
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
@@ -196,8 +200,8 @@ github.com/google/go-tpm-tools v0.4.1 h1:gYU6iwRo0tY3V6NDnS6m+XYog+b3g6YFhHQl3sY
|
||||
github.com/google/go-tpm-tools v0.4.1/go.mod h1:w03m0jynhTo7puXTYoyfpNOMqyQ9SB7sixnKWsS/1L0=
|
||||
github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=
|
||||
github.com/google/go-tspi v0.3.0/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI=
|
||||
github.com/google/pprof v0.0.0-20240125082051-42cd04596328 h1:oI+lCI2DY1BsRrdzMJBhIMxBBdlZJl31YNQC11EiyvA=
|
||||
github.com/google/pprof v0.0.0-20240125082051-42cd04596328/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
@@ -245,9 +249,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU
|
||||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
|
||||
github.com/jackc/pgconn v1.14.1 h1:smbxIaZA08n6YuxEX1sDyjV/qkbtUtkH20qLkR9MUR4=
|
||||
github.com/jackc/pgconn v1.14.1/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
|
||||
github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w=
|
||||
github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
@@ -263,29 +266,26 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0=
|
||||
github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag=
|
||||
github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.14.1 h1:LyDar7M2K0tShCWqzJ/ctzF1QC3Wzc9c8a6cHE0PFdc=
|
||||
github.com/jackc/pgtype v1.14.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.14.2 h1:QBdZQTKpPdBlw2AdKwHEyqUcm/lrl2cwWAHjCMyln/o=
|
||||
github.com/jackc/pgtype v1.14.2/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0=
|
||||
github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
|
||||
github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
|
||||
github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
@@ -295,11 +295,11 @@ github.com/kevburnsjr/skipfilter v0.0.1 h1:EWl1lWUJfIehrKYIEkps0Cl67lCfS2pUM9iZF
|
||||
github.com/kevburnsjr/skipfilter v0.0.1/go.mod h1:jfaRyFOYVUtIa6IIC+0mB1qiZqhHw+DKvFowCBuijSk=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E=
|
||||
github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -339,6 +339,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/maypok86/otter v1.2.0 h1:djwBBNpp9+dyzBTY0zscIG+pyAQVXRRRMbzztf8iJ4U=
|
||||
github.com/maypok86/otter v1.2.0/go.mod h1:mKLfoI7v1HOmQMwFgX4QkRk23mX6ge3RDvjdHOWG4R4=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||
@@ -383,21 +385,21 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||
github.com/prometheus/common v0.50.0 h1:YSZE6aa9+luNa2da6/Tik0q0A5AbR+U003TItK57CPQ=
|
||||
github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ=
|
||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
@@ -434,8 +436,8 @@ github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935 h1:kjYv
|
||||
github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935/go.mod h1:vNAduivU014fubg6ewygkAvQC0IQVXqdc8vaGl/0er4=
|
||||
github.com/smallstep/nosql v0.6.0 h1:ur7ysI8s9st0cMXnTvB8tA3+x5Eifmkb6hl4uqNV5jc=
|
||||
github.com/smallstep/nosql v0.6.0/go.mod h1:jOXwLtockXORUPPZ2MCUcIkGR6w0cN1QGZniY9DITQA=
|
||||
github.com/smallstep/truststore v0.12.1 h1:guLUKkc1UlsXeS3t6BuVMa4leOOpdiv02PCRTiy1WdY=
|
||||
github.com/smallstep/truststore v0.12.1/go.mod h1:M4mebeNy28KusGX3lJxpLARIktLcyqBOrj3ZiZ46pqw=
|
||||
github.com/smallstep/truststore v0.13.0 h1:90if9htAOblavbMeWlqNLnO9bsjjgVv2hQeQJCi/py4=
|
||||
github.com/smallstep/truststore v0.13.0/go.mod h1:3tmMp2aLKZ/OA/jnFUB0cYPcho402UG2knuJoPh4j7A=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@@ -474,15 +476,16 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tailscale/tscert v0.0.0-20230806124524-28a91b69a046 h1:8rUlviSVOEe7TMk7W0gIPrW8MqEzYfZHpsNWSf8s2vg=
|
||||
github.com/tailscale/tscert v0.0.0-20230806124524-28a91b69a046/go.mod h1:kNGUQ3VESx3VZwRwA9MSCUegIl6+saPL8Noq82ozCaU=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
|
||||
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
||||
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
@@ -504,8 +507,8 @@ github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zI
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
||||
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
|
||||
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
@@ -515,15 +518,15 @@ github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvv
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210730143726-725912489c62/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
|
||||
go.opentelemetry.io/contrib/propagators/autoprop v0.45.0 h1:FT/JCFzjzXgyp/aXkQeywnI/Tl8ZtKhvusVtZOokmFM=
|
||||
go.opentelemetry.io/contrib/propagators/autoprop v0.45.0/go.mod h1:L/2JIbqAmGzBvGJ3rXA+KXmWXUuUYUDZnhXeJttjJRg=
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.20.0 h1:PByDRx6xPygwFP+L3FTlOifJoCB10T2LdRBZcDYMTJw=
|
||||
@@ -534,18 +537,18 @@ go.opentelemetry.io/contrib/propagators/jaeger v1.20.0 h1:iVhNKkMIpzyZqxk8jkDU2n
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.20.0/go.mod h1:cpSABr0cm/AH/HhbJjn+AudBVUMgZWdfN3Gb+ZqxSZc=
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ=
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E=
|
||||
go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0=
|
||||
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo=
|
||||
go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI=
|
||||
go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.step.sm/cli-utils v0.8.0 h1:b/Tc1/m3YuQq+u3ghTFP7Dz5zUekZj6GUmd5pCvkEXQ=
|
||||
@@ -573,8 +576,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
@@ -587,17 +590,16 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f h1:3CW0unweImhOzd5FmYuRsD4Y4oQFKZIjAnKbjV4WIrw=
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -606,11 +608,10 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
@@ -640,15 +641,14 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -656,7 +656,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
@@ -671,8 +670,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -683,18 +682,18 @@ google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4=
|
||||
google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg=
|
||||
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240228224816-df926f6c8641 h1:SO1wX9btGFrwj9EzH3ocqfwiPVOxfv4ggAJajzlHA5s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240228224816-df926f6c8641/go.mod h1:wLupoVsUfYPgOMwjzhYFbaVklw/INms+dqTp0tc1fv8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 h1:DKU1r6Tj5s1vlU/moGhuGz7E3xRfwjdAfDzbsaQJtEY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -125,9 +125,11 @@ func cmdPHPServer(fs caddycmd.Flags) (int, error) {
|
||||
extensions := []string{"php"}
|
||||
tryFiles := []string{"{http.request.uri.path}", "{http.request.uri.path}/" + indexFile, indexFile}
|
||||
|
||||
rrs := true
|
||||
phpHandler := FrankenPHPModule{
|
||||
Root: root,
|
||||
SplitPath: extensions,
|
||||
Root: root,
|
||||
SplitPath: extensions,
|
||||
ResolveRootSymlink: &rrs,
|
||||
}
|
||||
|
||||
// route to redirect to canonical path if index PHP file
|
||||
|
||||
96
cgi.go
96
cgi.go
@@ -1,12 +1,15 @@
|
||||
package frankenphp
|
||||
|
||||
// #include "frankenphp.h"
|
||||
import "C"
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type serverKey int
|
||||
@@ -33,22 +36,44 @@ const (
|
||||
sslProtocol
|
||||
)
|
||||
|
||||
func allocServerVariable(cArr *[27]*C.char, env map[string]string, serverKey serverKey, envKey string, val string) {
|
||||
if val, ok := env[envKey]; ok {
|
||||
cArr[serverKey] = C.CString(val)
|
||||
delete(env, envKey)
|
||||
var knownServerKeys = map[string]struct{}{
|
||||
"CONTENT_LENGTH\x00": {},
|
||||
"DOCUMENT_ROOT\x00": {},
|
||||
"DOCUMENT_URI\x00": {},
|
||||
"GATEWAY_INTERFACE\x00": {},
|
||||
"HTTP_HOST\x00": {},
|
||||
"HTTPS\x00": {},
|
||||
"PATH_INFO\x00": {},
|
||||
"PHP_SELF\x00": {},
|
||||
"REMOTE_ADDR\x00": {},
|
||||
"REMOTE_HOST\x00": {},
|
||||
"REMOTE_PORT\x00": {},
|
||||
"REQUEST_SCHEME\x00": {},
|
||||
"SCRIPT_FILENAME\x00": {},
|
||||
"SCRIPT_NAME\x00": {},
|
||||
"SERVER_NAME\x00": {},
|
||||
"SERVER_PORT\x00": {},
|
||||
"SERVER_PROTOCOL\x00": {},
|
||||
"SERVER_SOFTWARE\x00": {},
|
||||
"SSL_PROTOCOL\x00": {},
|
||||
}
|
||||
|
||||
func setKnownServerVariable(p *runtime.Pinner, cArr *[27]C.go_string, serverKey serverKey, val string) {
|
||||
if val == "" {
|
||||
return
|
||||
}
|
||||
|
||||
cArr[serverKey] = C.CString(val)
|
||||
valData := unsafe.StringData(val)
|
||||
p.Pin(valData)
|
||||
cArr[serverKey].len = C.size_t(len(val))
|
||||
cArr[serverKey].data = (*C.char)(unsafe.Pointer(valData))
|
||||
}
|
||||
|
||||
// computeKnownVariables returns a set of CGI environment variables for the request.
|
||||
//
|
||||
// TODO: handle this case https://github.com/caddyserver/caddy/issues/3718
|
||||
// Inspired by https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
|
||||
func computeKnownVariables(request *http.Request) (cArr [27]*C.char) {
|
||||
func computeKnownVariables(request *http.Request, p *runtime.Pinner) (cArr [27]C.go_string) {
|
||||
fc, fcOK := FromContext(request.Context())
|
||||
if !fcOK {
|
||||
panic("not a FrankenPHP request")
|
||||
@@ -67,32 +92,30 @@ func computeKnownVariables(request *http.Request) (cArr [27]*C.char) {
|
||||
ip = strings.Replace(ip, "[", "", 1)
|
||||
ip = strings.Replace(ip, "]", "", 1)
|
||||
|
||||
ra, raOK := fc.env["REMOTE_ADDR"]
|
||||
ra, raOK := fc.env["REMOTE_ADDR\x00"]
|
||||
if raOK {
|
||||
cArr[remoteAddr] = C.CString(ra)
|
||||
delete(fc.env, "REMOTE_ADDR")
|
||||
setKnownServerVariable(p, &cArr, remoteAddr, ra)
|
||||
} else {
|
||||
cArr[remoteAddr] = C.CString(ip)
|
||||
setKnownServerVariable(p, &cArr, remoteAddr, ip)
|
||||
}
|
||||
|
||||
if rh, ok := fc.env["REMOTE_HOST"]; ok {
|
||||
cArr[remoteHost] = C.CString(rh) // For speed, remote host lookups disabled
|
||||
delete(fc.env, "REMOTE_HOST")
|
||||
if rh, ok := fc.env["REMOTE_HOST\x00"]; ok {
|
||||
setKnownServerVariable(p, &cArr, remoteHost, rh) // For speed, remote host lookups disabled
|
||||
} else {
|
||||
if raOK {
|
||||
cArr[remoteHost] = C.CString(ip)
|
||||
setKnownServerVariable(p, &cArr, remoteHost, ip)
|
||||
} else {
|
||||
cArr[remoteHost] = cArr[remoteAddr]
|
||||
}
|
||||
}
|
||||
|
||||
allocServerVariable(&cArr, fc.env, remotePort, "REMOTE_PORT", port)
|
||||
allocServerVariable(&cArr, fc.env, documentRoot, "DOCUMENT_ROOT", fc.documentRoot)
|
||||
allocServerVariable(&cArr, fc.env, pathInfo, "PATH_INFO", fc.pathInfo)
|
||||
allocServerVariable(&cArr, fc.env, phpSelf, "PHP_SELF", request.URL.Path)
|
||||
allocServerVariable(&cArr, fc.env, documentUri, "DOCUMENT_URI", fc.docURI)
|
||||
allocServerVariable(&cArr, fc.env, scriptFilename, "SCRIPT_FILENAME", fc.scriptFilename)
|
||||
allocServerVariable(&cArr, fc.env, scriptName, "SCRIPT_NAME", fc.scriptName)
|
||||
setKnownServerVariable(p, &cArr, remotePort, port)
|
||||
setKnownServerVariable(p, &cArr, documentRoot, fc.documentRoot)
|
||||
setKnownServerVariable(p, &cArr, pathInfo, fc.pathInfo)
|
||||
setKnownServerVariable(p, &cArr, phpSelf, request.URL.Path)
|
||||
setKnownServerVariable(p, &cArr, documentUri, fc.docURI)
|
||||
setKnownServerVariable(p, &cArr, scriptFilename, fc.scriptFilename)
|
||||
setKnownServerVariable(p, &cArr, scriptName, fc.scriptName)
|
||||
|
||||
var rs string
|
||||
if request.TLS == nil {
|
||||
@@ -100,26 +123,24 @@ func computeKnownVariables(request *http.Request) (cArr [27]*C.char) {
|
||||
} else {
|
||||
rs = "https"
|
||||
|
||||
if h, ok := fc.env["HTTPS"]; ok {
|
||||
cArr[https] = C.CString(h)
|
||||
delete(fc.env, "HTTPS")
|
||||
if h, ok := fc.env["HTTPS\x00"]; ok {
|
||||
setKnownServerVariable(p, &cArr, https, h)
|
||||
} else {
|
||||
cArr[https] = C.CString("on")
|
||||
setKnownServerVariable(p, &cArr, https, "on")
|
||||
}
|
||||
|
||||
// and pass the protocol details in a manner compatible with apache's mod_ssl
|
||||
// (which is why these have a SSL_ prefix and not TLS_).
|
||||
if p, ok := fc.env["SSL_PROTOCOL"]; ok {
|
||||
cArr[sslProtocol] = C.CString(p)
|
||||
delete(fc.env, "SSL_PROTOCOL")
|
||||
if pr, ok := fc.env["SSL_PROTOCOL\x00"]; ok {
|
||||
setKnownServerVariable(p, &cArr, sslProtocol, pr)
|
||||
} else {
|
||||
if v, ok := tlsProtocolStrings[request.TLS.Version]; ok {
|
||||
cArr[sslProtocol] = C.CString(v)
|
||||
setKnownServerVariable(p, &cArr, sslProtocol, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
allocServerVariable(&cArr, fc.env, requestScheme, "REQUEST_SCHEME", rs)
|
||||
|
||||
setKnownServerVariable(p, &cArr, requestScheme, rs)
|
||||
reqHost, reqPort, _ := net.SplitHostPort(request.Host)
|
||||
|
||||
if reqHost == "" {
|
||||
@@ -140,9 +161,9 @@ func computeKnownVariables(request *http.Request) (cArr [27]*C.char) {
|
||||
}
|
||||
}
|
||||
|
||||
allocServerVariable(&cArr, fc.env, serverName, "SERVER_NAME", reqHost)
|
||||
setKnownServerVariable(p, &cArr, serverName, reqHost)
|
||||
if reqPort != "" {
|
||||
allocServerVariable(&cArr, fc.env, serverPort, "SERVER_PORT", reqPort)
|
||||
setKnownServerVariable(p, &cArr, serverPort, reqPort)
|
||||
}
|
||||
|
||||
// Variables defined in CGI 1.1 spec
|
||||
@@ -150,12 +171,11 @@ func computeKnownVariables(request *http.Request) (cArr [27]*C.char) {
|
||||
// the parent environment from interfering.
|
||||
|
||||
// These values can not be override
|
||||
cArr[contentLength] = C.CString(request.Header.Get("Content-Length"))
|
||||
|
||||
allocServerVariable(&cArr, fc.env, gatewayInterface, "GATEWAY_INTERFACE", "CGI/1.1")
|
||||
allocServerVariable(&cArr, fc.env, serverProtocol, "SERVER_PROTOCOL", request.Proto)
|
||||
allocServerVariable(&cArr, fc.env, serverSoftware, "SERVER_SOFTWARE", "FrankenPHP")
|
||||
allocServerVariable(&cArr, fc.env, httpHost, "HTTP_HOST", request.Host) // added here, since not always part of headers
|
||||
setKnownServerVariable(p, &cArr, contentLength, request.Header.Get("Content-Length"))
|
||||
setKnownServerVariable(p, &cArr, gatewayInterface, "CGI/1.1")
|
||||
setKnownServerVariable(p, &cArr, serverProtocol, request.Proto)
|
||||
setKnownServerVariable(p, &cArr, serverSoftware, "FrankenPHP")
|
||||
setKnownServerVariable(p, &cArr, httpHost, request.Host) // added here, since not always part of headers
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM golang:1.21-alpine
|
||||
FROM golang:1.22-alpine
|
||||
|
||||
ENV CFLAGS="-ggdb3"
|
||||
ENV PHPIZE_DEPS \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM golang:1.21
|
||||
FROM golang:1.22
|
||||
|
||||
ENV CFLAGS="-ggdb3"
|
||||
ENV PHPIZE_DEPS \
|
||||
|
||||
@@ -11,7 +11,7 @@ variable "PHP_VERSION" {
|
||||
}
|
||||
|
||||
variable "GO_VERSION" {
|
||||
default = "1.21"
|
||||
default = "1.22"
|
||||
}
|
||||
|
||||
variable "SHA" {}
|
||||
|
||||
77
docs/cn/README.md
Normal file
77
docs/cn/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# FrankenPHP: 适用于 PHP 的现代应用服务器
|
||||
|
||||
<h1 align="center"><a href="https://frankenphp.dev"><img src="frankenphp.png" alt="FrankenPHP" width="600"></a></h1>
|
||||
|
||||
FrankenPHP 是建立在 [Caddy](https://caddyserver.com/) Web 服务器之上的现代 PHP 应用程序服务器。
|
||||
|
||||
FrankenPHP 凭借其令人惊叹的功能为您的 PHP 应用程序提供了超能力:[早期提示](early-hints.md)、[worker 模式](worker.md)、[实时功能](mercure.md)、自动 HTTPS、HTTP/2 和 HTTP/3 支持......
|
||||
|
||||
FrankenPHP 可与任何 PHP 应用程序一起使用,并且由于提供了与 worker 模式的集成,使您的 Symfony 和 Laravel 项目比以往任何时候都更快。
|
||||
|
||||
FrankenPHP 也可以用作独立的 Go 库,将 PHP 嵌入到任何使用 net/http 的应用程序中。
|
||||
|
||||
[**了解更多** *frankenphp.dev*](https://frankenphp.dev/cn) 以及在以下地址中:
|
||||
|
||||
<a href="https://dunglas.dev/2022/10/frankenphp-the-modern-php-app-server-written-in-go/"><img src="https://dunglas.dev/wp-content/uploads/2022/10/frankenphp.png" alt="Slides" width="600"></a>
|
||||
|
||||
## 开始
|
||||
|
||||
### Docker
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
访问 `https://localhost`, 并享受吧!
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> 不要尝试使用 `https://127.0.0.1`。使用 `https://localhost` 并接受自签名证书。
|
||||
> 使用 [`SERVER_NAME` 环境变量](config.md#环境变量) 更改要使用的域。
|
||||
|
||||
### 独立二进制
|
||||
|
||||
如果您不想使用 Docker,我们为 Linux 和 macOS 提供独立的 FrankenPHP 二进制文件
|
||||
,其中包含 [PHP 8.3](https://www.php.net/releases/8.3/en.php) 和最流行的 PHP 扩展:[下载 FrankenPHP](https://github.com/dunglas/frankenphp/releases)。
|
||||
|
||||
若要启动当前目录的内容,请运行:
|
||||
|
||||
```console
|
||||
./frankenphp php-server
|
||||
```
|
||||
|
||||
您还可以使用以下命令运行命令行脚本:
|
||||
|
||||
```console
|
||||
./frankenphp php-cli /path/to/your/script.php
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
* [worker 模式](worker.md)
|
||||
* [早期提示支持(103 HTTP status code)](early-hints.md)
|
||||
* [实时功能](mercure.md)
|
||||
* [配置](config.md)
|
||||
* [Docker 镜像](docker.md)
|
||||
* [在生产环境中部署](production.md)
|
||||
* [创建独立、可自行执行的 PHP 应用程序](embed.md)
|
||||
* [创建静态二进制文件](static.md)
|
||||
* [从源代码编译](compile.md)
|
||||
* [Laravel 集成](laravel.md)
|
||||
* [已知问题](known-issues.md)
|
||||
* [演示应用程序 (Symfony) 和性能测试](https://github.com/dunglas/frankenphp-demo)
|
||||
* [Go 库文档](https://pkg.go.dev/github.com/dunglas/frankenphp)
|
||||
* [贡献和调试](https://frankenphp.dev/docs/contributing/)
|
||||
|
||||
## 示例和框架
|
||||
|
||||
* [Symfony](https://github.com/dunglas/symfony-docker)
|
||||
* [API Platform](https://api-platform.com/docs/distribution/)
|
||||
* [Laravel](laravel.md)
|
||||
* [Sulu](https://sulu.io/blog/running-sulu-with-frankenphp)
|
||||
* [WordPress](https://github.com/dunglas/frankenphp-wordpress)
|
||||
* [Drupal](https://github.com/dunglas/frankenphp-drupal)
|
||||
* [Joomla](https://github.com/alexandreelise/frankenphp-joomla)
|
||||
* [TYPO3](https://github.com/ochorocho/franken-typo3)
|
||||
102
docs/cn/compile.md
Normal file
102
docs/cn/compile.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 从源代码编译
|
||||
|
||||
本文档解释了如何创建一个 FrankenPHP 构建,它将 PHP 加载为一个动态库。
|
||||
这是推荐的方法。
|
||||
|
||||
或者,你也可以 [编译静态版本](static.md)。
|
||||
|
||||
## 安装 PHP
|
||||
|
||||
FrankenPHP 支持 PHP 8.2 及更高版本。
|
||||
|
||||
首先,[获取 PHP 源代码](https://www.php.net/downloads.php) 并提取它们:
|
||||
|
||||
```console
|
||||
tar xf php-*
|
||||
cd php-*/
|
||||
```
|
||||
|
||||
然后,为您的平台配置 PHP:
|
||||
|
||||
### Linux
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--enable-zend-max-execution-timers
|
||||
```
|
||||
|
||||
最后,编译并安装 PHP:
|
||||
|
||||
```console
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Mac
|
||||
|
||||
使用 [Homebrew](https://brew.sh/) 包管理器安装 `libiconv`、`bison`、`re2c` 和 `pkg-config`:
|
||||
|
||||
```console
|
||||
brew install libiconv bison re2c pkg-config
|
||||
echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
然后运行 `./configure` 脚本:
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed=static \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--disable-opcache-jit \
|
||||
--enable-static \
|
||||
--enable-shared=no \
|
||||
--with-iconv=/opt/homebrew/opt/libiconv/
|
||||
```
|
||||
|
||||
这些参数是必需的,但你也可以添加其他编译参数(例如额外的扩展)。
|
||||
|
||||
最后,编译并安装 PHP:
|
||||
|
||||
```console
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## 编译 Go 应用
|
||||
|
||||
您现在可以使用 Go 库并编译我们的 Caddy 构建:
|
||||
|
||||
```console
|
||||
curl -L https://github.com/dunglas/frankenphp/archive/refs/heads/main.tar.gz | tar x
|
||||
cd frankenphp-main/caddy/frankenphp
|
||||
CGO_CFLAGS=$(php-config --includes) CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" go build
|
||||
```
|
||||
|
||||
### 使用 xcaddy
|
||||
|
||||
你可以使用 [xcaddy](https://github.com/caddyserver/xcaddy) 来编译 [自定义 Caddy 模块](https://caddyserver.com/docs/modules/) 的 FrankenPHP:
|
||||
|
||||
```console
|
||||
CGO_ENABLED=1 \
|
||||
XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'" \
|
||||
xcaddy build \
|
||||
--output frankenphp \
|
||||
--with github.com/dunglas/frankenphp/caddy \
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Add extra Caddy modules here
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> 如果你的系统基于 musl libc(Alpine Linux 上默认使用)并搭配 Symfony 使用,
|
||||
> 您可能需要增加默认堆栈大小。
|
||||
> 否则,您可能会收到如下错误 `PHP Fatal error: Maximum call stack size of 83360 bytes reached during compilation. Try splitting expression`
|
||||
>
|
||||
> 请将 `XCADDY_GO_BUILD_FLAGS` 环境变量更改为如下类似的值
|
||||
> `XCADDY_GO_BUILD_FLAGS=$'-ldflags "-w -s -extldflags \'-Wl,-z,stack-size=0x80000\'"'`
|
||||
> (根据您的应用需求更改堆栈大小)。
|
||||
154
docs/cn/config.md
Normal file
154
docs/cn/config.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# 配置
|
||||
|
||||
FrankenPHP,Caddy 以及 Mercure 和 Vulcain 模块可以使用 [Caddy 支持的格式](https://caddyserver.com/docs/getting-started#your-first-config) 进行配置。
|
||||
|
||||
在 Docker 镜像中,`Caddyfile` 位于 `/etc/caddy/Caddyfile`。
|
||||
|
||||
您也可以像往常一样使用 `php.ini` 配置 PHP。
|
||||
|
||||
在 Docker 镜像中,默认不存在 `php.ini`,您可以手动创建它或从官方模板中复制。
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# 开发:
|
||||
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
|
||||
|
||||
# 生产:
|
||||
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
|
||||
```
|
||||
|
||||
## Caddyfile 配置
|
||||
|
||||
要注册 FrankenPHP 执行器,必须设置 `frankenphp` [全局选项](https://caddyserver.com/docs/caddyfile/concepts#global-options),然后可以在站点块中使用 `php_server` 或 `php` [HTTP 指令](https://caddyserver.com/docs/caddyfile/concepts#directives) 来为您的 PHP 应用程序提供服务。
|
||||
|
||||
最小示例:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
# 启用 FrankenPHP
|
||||
frankenphp
|
||||
# 配置何时必须执行指令
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
localhost {
|
||||
# 启用压缩(可选)
|
||||
encode zstd br gzip
|
||||
# 执行当前目录中的 PHP 文件并提供资产
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
或者,可以在全局选项下指定要创建的线程数和要从服务器启动的 [worker 脚本](worker.md)。
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
num_threads <num_threads> # 设置要启动的 PHP 线程数。默认值:可用 CPU 数量的 2 倍。
|
||||
worker {
|
||||
file <path> # 设置 worker 脚本的路径。
|
||||
num <num> # 设置要启动的 PHP 线程数,默认为可用 CPU 数的 2 倍。
|
||||
env <key> <value> # 将额外的环境变量设置为给定值。可以为多个环境变量多次指定。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
或者,您可以使用 `worker` 选项的一行缩写形式:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker <file> <num>
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
如果在同一服务器上运行多个应用,还可以定义多个 worker:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker /path/to/app/public/index.php <num>
|
||||
worker /path/to/other/public/index.php <num>
|
||||
}
|
||||
}
|
||||
|
||||
app.example.com {
|
||||
root * /path/to/app/public
|
||||
php_server
|
||||
}
|
||||
|
||||
other.example.com {
|
||||
root * /path/to/other/public
|
||||
php_server
|
||||
}
|
||||
# ...
|
||||
```
|
||||
|
||||
通常你只需要 `php_server` 指令,
|
||||
但如果要完全控制,则可以使用较低级别的 `php` 指令:
|
||||
|
||||
使用 `php_server` 指令等效于以下配置:
|
||||
|
||||
```caddyfile
|
||||
route {
|
||||
# 为目录请求添加尾部斜杠
|
||||
@canonicalPath {
|
||||
file {path}/index.php
|
||||
not path */
|
||||
}
|
||||
redir @canonicalPath {path}/ 308
|
||||
# 如果请求的文件不存在,则尝试 index 文件
|
||||
@indexFiles file {
|
||||
try_files {path} {path}/index.php index.php
|
||||
split_path .php
|
||||
}
|
||||
rewrite @indexFiles {http.matchers.file.relative}
|
||||
# FrankenPHP!
|
||||
@phpFiles path *.php
|
||||
php @phpFiles
|
||||
file_server
|
||||
}
|
||||
```
|
||||
|
||||
`php_server` 和 `php` 指令具有以下选项:
|
||||
|
||||
```caddyfile
|
||||
php_server [<matcher>] {
|
||||
root <directory> # 设置站点的根目录。默认值:`root` 指令。
|
||||
split_path <delim...> # 设置用于将 URI 拆分为两部分的子字符串。第一个匹配的子字符串将用于从路径中拆分“路径信息”。第一个部分以匹配的子字符串为后缀,并将假定为实际资源(CGI 脚本)名称。第二部分将设置为PATH_INFO,供脚本使用。默认值:`.php`
|
||||
resolve_root_symlink false # 禁用将 `root` 目录在符号链接时将其解析为实际值(默认启用)。
|
||||
env <key> <value> # 设置额外的环境变量,可以设置多个环境变量。
|
||||
}
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
以下环境变量可用于在 `Caddyfile` 中注入 Caddy 指令,而无需对其进行修改:
|
||||
|
||||
* `SERVER_NAME`: 更改 [要监听的地址](https://caddyserver.com/docs/caddyfile/concepts#addresses),提供的主机名也将用于生成的 TLS 证书
|
||||
* `CADDY_GLOBAL_OPTIONS`: 注入 [全局选项](https://caddyserver.com/docs/caddyfile/options)
|
||||
* `FRANKENPHP_CONFIG`: 在 `frankenphp` 指令下注入配置
|
||||
|
||||
## PHP 配置
|
||||
|
||||
要加载 [其他 PHP INI 配置文件](https://www.php.net/manual/en/configuration.file.php#configuration.file.scan),
|
||||
可以使用 `PHP_INI_SCAN_DIR` 环境变量。
|
||||
设置后,PHP 将加载给定目录中存在 `.ini` 扩展名的所有文件。
|
||||
|
||||
## 启用调试模式
|
||||
|
||||
使用 Docker 镜像时,将 `CADDY_GLOBAL_OPTIONS` 环境变量设置为 `debug` 以启用调试模式:
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-e CADDY_GLOBAL_OPTIONS=debug \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
164
docs/cn/docker.md
Normal file
164
docs/cn/docker.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# 构建自定义 Docker 镜像
|
||||
|
||||
[FrankenPHP Docker 镜像](https://hub.docker.com/r/dunglas/frankenphp) 基于 [官方 PHP 镜像](https://hub.docker.com/_/php/)。
|
||||
Alpine Linux 和 Debian 衍生版适用于常见的处理器架构,且支持 PHP 8.2 和 PHP 8.3。[查看 Tags](https://hub.docker.com/r/dunglas/frankenphp/tags)。
|
||||
|
||||
## 如何使用镜像
|
||||
|
||||
在项目中创建 `Dockerfile`:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
COPY . /app/public
|
||||
```
|
||||
|
||||
然后运行以下命令以构建并运行 Docker 镜像:
|
||||
|
||||
```console
|
||||
docker build -t my-php-app .
|
||||
docker run -it --rm --name my-running-app my-php-app
|
||||
```
|
||||
|
||||
## 如何安装更多 PHP 扩展
|
||||
|
||||
[`docker-php-extension-installer`](https://github.com/mlocati/docker-php-extension-installer) 脚本在基础镜像中提供。
|
||||
添加额外的 PHP 扩展很简单:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# 在此处添加其他扩展:
|
||||
RUN install-php-extensions \
|
||||
pdo_mysql \
|
||||
gd \
|
||||
intl \
|
||||
zip \
|
||||
opcache
|
||||
```
|
||||
|
||||
## 如何安装更多 Caddy 模块
|
||||
|
||||
FrankenPHP 建立在 Caddy 之上,所有 [Caddy 模块](https://caddyserver.com/docs/modules/) 都可以与 FrankenPHP 一起使用。
|
||||
|
||||
安装自定义 Caddy 模块的最简单方法是使用 [xcaddy](https://github.com/caddyserver/xcaddy):
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp:latest-builder AS builder
|
||||
|
||||
# 在构建器镜像中复制 xcaddy
|
||||
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy
|
||||
|
||||
# 必须启用 CGO 才能构建 FrankenPHP
|
||||
ENV CGO_ENABLED=1 XCADDY_SETCAP=1 XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'"
|
||||
RUN xcaddy build \
|
||||
--output /usr/local/bin/frankenphp \
|
||||
--with github.com/dunglas/frankenphp=./ \
|
||||
--with github.com/dunglas/frankenphp/caddy=./caddy/ \
|
||||
# Mercure 和 Vulcain 包含在官方版本中,如果不需要你可以删除它们
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# 在此处添加额外的 Caddy 模块
|
||||
|
||||
FROM dunglas/frankenphp AS runner
|
||||
|
||||
# 将官方二进制文件替换为包含自定义模块的二进制文件
|
||||
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
|
||||
```
|
||||
|
||||
FrankenPHP 提供的 `builder` 镜像包含 libphp 的编译版本。
|
||||
[用于构建的镜像](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder) 适用于所有版本的 FrankenPHP 和 PHP,包括 Alpine 和 Debian。
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> 如果你的系统基于 musl libc(Alpine Linux 上默认使用)并搭配 Symfony 使用,
|
||||
> 您可能需要 [增加默认堆栈大小](compile.md#使用-xcaddy)。
|
||||
|
||||
## 默认启用 worker 模式
|
||||
|
||||
设置 `FRANKENPHP_CONFIG` 环境变量以使用 worker 脚本启动 FrankenPHP:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# ...
|
||||
|
||||
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
|
||||
```
|
||||
|
||||
## 开发挂载宿主机目录
|
||||
|
||||
要使用 FrankenPHP 轻松开发,请从包含应用程序源代码的主机挂载目录作为 Docker 容器中的 volume:
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public -p 80:80 -p 443:443 -p 443:443/udp --tty my-php-app
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> `--tty` 选项允许使用清晰可读的日志,而不是 JSON 日志。
|
||||
|
||||
使用 Docker Compose:
|
||||
|
||||
```yaml
|
||||
# compose.yaml
|
||||
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
# 如果要使用自定义 Dockerfile,请取消注释以下行
|
||||
#build: .
|
||||
# 如果要在生产环境中运行,请取消注释以下行
|
||||
# restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- ./:/app/public
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
# 在生产环境中注释以下行,它允许在 dev 中使用清晰可读日志
|
||||
tty: true
|
||||
|
||||
# Caddy 证书和配置所需的挂载目录
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
## 以非 root 用户身份运行
|
||||
|
||||
FrankenPHP 可以在 Docker 中以非 root 用户身份运行。
|
||||
|
||||
下面是一个示例 Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
ARG USER=www-data
|
||||
|
||||
RUN \
|
||||
# 在基于 alpine 的发行版使用 "adduser -D ${USER}"
|
||||
useradd -D ${USER}; \
|
||||
# 需要开放80和443端口的权限
|
||||
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp; \
|
||||
# 需要 /data/caddy 和 /config/caddy 目录的写入权限
|
||||
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy;
|
||||
|
||||
USER ${USER}
|
||||
```
|
||||
|
||||
## 更新
|
||||
|
||||
Docker 镜像会按照以下条件更新:
|
||||
|
||||
* 发布新的版本后
|
||||
* 每日 4:00(UTC 时间)检查新的 PHP 镜像
|
||||
|
||||
## 开发版本
|
||||
|
||||
可在此 [`dunglas/frankenphp-dev`](https://hub.docker.com/repository/docker/dunglas/frankenphp-dev) 仓库获取开发版本。
|
||||
每次在 GitHub 仓库的主分支有新的 commit 都会触发一次新的 build。
|
||||
|
||||
`latest*` tag 指向最新的 `main` 分支,且同样支持 `sha-<git-commit-hash>` 的 tag。
|
||||
21
docs/cn/early-hints.md
Normal file
21
docs/cn/early-hints.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 早期提示
|
||||
|
||||
FrankenPHP 原生支持 [103 Early Hints 状态码](https://developer.chrome.com/blog/early-hints/)。
|
||||
使用早期提示可以将网页的加载时间缩短 30%。
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
header('Link: </style.css>; rel=preload; as=style');
|
||||
headers_send(103);
|
||||
|
||||
// 慢速算法和 SQL 查询
|
||||
|
||||
echo <<<'HTML'
|
||||
<!DOCTYPE html>
|
||||
<title>Hello FrankenPHP</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
HTML;
|
||||
```
|
||||
|
||||
早期提示由普通模式和 [worker](worker.md) 模式支持。
|
||||
132
docs/cn/embed.md
Normal file
132
docs/cn/embed.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# PHP 应用程序作为独立二进制文件
|
||||
|
||||
FrankenPHP 能够将 PHP 应用程序的源代码和资源文件嵌入到静态的、独立的二进制文件中。
|
||||
|
||||
由于这个特性,PHP 应用程序可以作为独立的二进制文件分发,包括应用程序本身、PHP 解释器和生产级 Web 服务器 Caddy。
|
||||
|
||||
了解有关此功能的更多信息 [Kévin 在 SymfonyCon 上的演讲](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/)。
|
||||
|
||||
## 准备你的应用
|
||||
|
||||
在创建独立二进制文件之前,请确保应用已准备好进行打包。
|
||||
|
||||
例如,您可能希望:
|
||||
|
||||
* 给应用安装生产环境的依赖
|
||||
* 导出 autoloader
|
||||
* 如果可能,为应用启用生产模式
|
||||
* 丢弃不需要的文件,例如 `.git` 或测试文件,以减小最终二进制文件的大小
|
||||
|
||||
例如,对于 Symfony 应用程序,您可以使用以下命令:
|
||||
|
||||
```console
|
||||
# 导出项目以避免 .git/ 等目录
|
||||
mkdir $TMPDIR/my-prepared-app
|
||||
git archive HEAD | tar -x -C $TMPDIR/my-prepared-app
|
||||
cd $TMPDIR/my-prepared-app
|
||||
|
||||
# 设置适当的环境变量
|
||||
echo APP_ENV=prod > .env.local
|
||||
echo APP_DEBUG=0 >> .env.local
|
||||
|
||||
# 删除测试文件
|
||||
rm -Rf tests/
|
||||
|
||||
# 安装依赖项
|
||||
composer install --ignore-platform-reqs --no-dev -a
|
||||
|
||||
# 优化 .env
|
||||
composer dump-env prod
|
||||
```
|
||||
|
||||
## 创建 Linux 二进制文件
|
||||
|
||||
创建 Linux 二进制文件的最简单方法是使用我们提供的基于 Docker 的构建器。
|
||||
|
||||
1. 在准备好的应用的存储库中创建一个名为 `static-build.Dockerfile` 的文件。
|
||||
|
||||
```dockerfile
|
||||
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder
|
||||
|
||||
# 复制应用代码
|
||||
WORKDIR /go/src/app/dist/app
|
||||
COPY . .
|
||||
|
||||
# 构建静态二进制文件,只选择你需要的 PHP 扩展
|
||||
WORKDIR /go/src/app/
|
||||
RUN EMBED=dist/app/ \
|
||||
PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> 某些 .dockerignore 文件(例如默认的 [symfony-docker .dockerignore](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))会忽略 vendor
|
||||
> 文件夹和环境文件。在构建之前,请务必调整或删除 .dockerignore 文件。
|
||||
|
||||
2. 构建:
|
||||
|
||||
```console
|
||||
docker build -t static-app -f static-build.Dockerfile .
|
||||
```
|
||||
|
||||
3. 提取二进制文件
|
||||
|
||||
```console
|
||||
docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp
|
||||
```
|
||||
|
||||
生成的二进制文件是当前目录中名为 `my-app` 的文件。
|
||||
|
||||
## 为其他操作系统创建二进制文件
|
||||
|
||||
如果您不想使用 Docker,或者想要构建 macOS 二进制文件,你可以使用我们提供的 shell 脚本:
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
EMBED=/path/to/your/app \
|
||||
PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
在 `dist/` 目录中生成的二进制文件名称为 `frankenphp-<os>-<arch>`。
|
||||
|
||||
## 使用二进制文件
|
||||
|
||||
就是这样!`my-app` 文件(或其他操作系统上的 `dist/frankenphp-<os>-<arch>`)包含您的独立应用程序!
|
||||
|
||||
若要启动 Web 应用,请执行:
|
||||
|
||||
```console
|
||||
./my-app php-server
|
||||
```
|
||||
|
||||
如果您的应用包含 [worker 脚本](worker.md),请使用如下命令启动 worker:
|
||||
|
||||
```console
|
||||
./my-app php-server --worker public/index.php
|
||||
```
|
||||
|
||||
要启用 HTTPS(自动创建 Let's Encrypt 证书)、HTTP/2 和 HTTP/3,请指定要使用的域名:
|
||||
|
||||
```console
|
||||
./my-app php-server --domain localhost
|
||||
```
|
||||
|
||||
您还可以运行二进制文件中嵌入的 PHP CLI 脚本:
|
||||
|
||||
```console
|
||||
./my-app php-cli bin/console
|
||||
```
|
||||
|
||||
## 自定义构建
|
||||
|
||||
[阅读静态构建文档](static.md) 查看如何自定义二进制文件(扩展、PHP 版本等)。
|
||||
|
||||
## 分发二进制文件
|
||||
|
||||
创建的二进制文件不会被压缩。
|
||||
若要在发送文件之前减小文件的大小,可以对其进行压缩。
|
||||
|
||||
我们推荐使用 `xz`。
|
||||
31
docs/cn/github-actions.md
Normal file
31
docs/cn/github-actions.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 使用 GitHub Actions
|
||||
|
||||
此存储库构建 Docker 镜像并将其部署到 [Docker Hub](https://hub.docker.com/r/dunglas/frankenphp) 上
|
||||
每个批准的拉取请求或设置后在您自己的分支上。
|
||||
|
||||
## 设置 GitHub Actions
|
||||
|
||||
在存储库设置中的 `secrets` 下,添加以下字段:
|
||||
|
||||
- `REGISTRY_LOGIN_SERVER`: 要使用的 docker registry(如 `docker.io`)。
|
||||
- `REGISTRY_USERNAME`: 用于登录 registry 的用户名(如 `dunglas`)。
|
||||
- `REGISTRY_PASSWORD`: 用于登录 registry 的密码(如 `access key`)。
|
||||
- `IMAGE_NAME`: 镜像的名称(如 `dunglas/frankenphp`)。
|
||||
|
||||
## 构建和推送镜像
|
||||
|
||||
1. 创建 Pull Request 或推送到你的 Fork 分支。
|
||||
2. GitHub Actions 将生成镜像并运行每项测试。
|
||||
3. 如果生成成功,则将使用 `pr-x` 推送 registry,其中 `x` 是 PR 编号,作为标记将镜像推送到注册表。
|
||||
|
||||
## 部署镜像
|
||||
|
||||
1. 合并 Pull Request 后,GitHub Actions 将再次运行测试并生成新镜像。
|
||||
2. 如果构建成功,则 Docker 注册表中的 `main` tag 将更新。
|
||||
|
||||
## 发布
|
||||
|
||||
1. 在项目仓库中创建新 Tag。
|
||||
2. GitHub Actions 将生成镜像并运行每项测试。
|
||||
3. 如果构建成功,镜像将使用标记名称作为标记推送到 registry(例如,将创建 `v1.2.3` 和 `v1.2`)。
|
||||
4. `latest` 标签也将更新。
|
||||
99
docs/cn/known-issues.md
Normal file
99
docs/cn/known-issues.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# 已知问题
|
||||
|
||||
## Fibers
|
||||
|
||||
在 [Fibers](https://www.php.net/manual/en/language.fibers.php) 中调用 PHP 的函数和代码等语言结构,这些结构内部再调用 [cgo](https://go.dev/blog/cgo) 会导致崩溃。
|
||||
|
||||
这个问题 [正在由 Go 项目处理](https://github.com/golang/go/issues/62130)。
|
||||
|
||||
一种解决方案是不要使用从 Fibers 内部委托给 Go 的构造(如 `echo`)和函数(如 `header()`)。
|
||||
|
||||
下面的代码可能会崩溃,因为它在 Fiber 中使用了 `echo`:
|
||||
|
||||
```php
|
||||
$fiber = new Fiber(function() {
|
||||
echo 'In the Fiber'.PHP_EOL;
|
||||
echo 'Still inside'.PHP_EOL;
|
||||
});
|
||||
$fiber->start();
|
||||
```
|
||||
|
||||
相反,请从 Fiber 返回值并在外部使用它:
|
||||
|
||||
```php
|
||||
$fiber = new Fiber(function() {
|
||||
Fiber::suspend('In the Fiber'.PHP_EOL));
|
||||
Fiber::suspend('Still inside'.PHP_EOL));
|
||||
});
|
||||
echo $fiber->start();
|
||||
echo $fiber->resume();
|
||||
$fiber->resume();
|
||||
```
|
||||
|
||||
## 不支持的 PHP 扩展
|
||||
|
||||
已知以下扩展与 FrankenPHP 不兼容:
|
||||
|
||||
| 名称 | 原因 | 替代方案 |
|
||||
| ----------------------------------------------------------- | --------------- |----------------------------------------------------------------------------------------------------------------------|
|
||||
| [imap](https://www.php.net/manual/en/imap.installation.php) | 非线程安全 | [javanile/php-imap2](https://github.com/javanile/php-imap2), [webklex/php-imap](https://github.com/Webklex/php-imap) |
|
||||
|
||||
## get_browser
|
||||
|
||||
[get_browser()](https://www.php.net/manual/en/function.get-browser.php) 函数在一段时间后似乎表现不佳。解决方法是缓存(例如使用 [APCu](https://www.php.net/manual/zh/book.apcu.php))每个 User-Agent,因为它们是不变的。
|
||||
|
||||
## 独立的二进制和基于 Alpine 的 Docker 镜像
|
||||
|
||||
独立的二进制文件和基于 Alpine 的 docker 镜像 (`dunglas/frankenphp:*-alpine`) 使用的是 [musl libc](https://musl.libc.org/) 而不是 [glibc and friends](https://www.etalabs.net/compare_libcs.html),为的是保持较小的二进制大小。
|
||||
这可能会导致一些兼容性问题。特别是,glob 标志 `GLOB_BRACE` [不可用](https://www.php.net/manual/en/function.glob.php)。
|
||||
|
||||
## 在 Docker 中使用 `https://127.0.0.1`
|
||||
|
||||
默认情况下,FrankenPHP 会为 `localhost` 生成一个 TLS 证书。
|
||||
这是本地开发最简单且推荐的选项。
|
||||
|
||||
如果确实想使用 `127.0.0.1` 作为主机,可以通过将服务器名称设置为 `127.0.0.1` 来配置它以为其生成证书。
|
||||
|
||||
如果你使用 Docker,因为 [Docker 网络](https://docs.docker.com/network/) 问题,只做这些是不够的。
|
||||
您将收到类似于以下内容的 TLS 错误 `curl: (35) LibreSSL/3.3.6: error:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error`。
|
||||
|
||||
如果你使用的是 Linux,解决方案是使用 [使用宿主机网络](https://docs.docker.com/network/network-tutorial-host/):
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
--network host \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Mac 和 Windows 不支持 Docker 使用宿主机网络。在这些平台上,您必须猜测容器的 IP 地址并将其包含在服务器名称中。
|
||||
|
||||
运行 `docker network inspect bridge` 并查看 `Containers`,找到 `IPv4Address` 当前分配的最后一个 IP 地址,并增加 1。如果没有容器正在运行,则第一个分配的 IP 地址通常为 `172.17.0.2`。
|
||||
|
||||
然后将其包含在 `SERVER_NAME` 环境变量中:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1, 172.17.0.3" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> 请务必将 `172.17.0.3` 替换为将分配给容器的 IP。
|
||||
|
||||
您现在应该能够从主机访问 `https://127.0.0.1`。
|
||||
|
||||
如果不是这种情况,请在调试模式下启动 FrankenPHP 以尝试找出问题:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e CADDY_GLOBAL_OPTIONS="debug" \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
75
docs/cn/laravel.md
Normal file
75
docs/cn/laravel.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Laravel
|
||||
|
||||
## Docker
|
||||
|
||||
使用 FrankenPHP 为 [Laravel](https://laravel.com) Web 应用程序提供服务就像将项目挂载到官方 Docker 镜像的 `/app` 目录中一样简单。
|
||||
|
||||
从 Laravel 应用程序的主目录运行以下命令:
|
||||
|
||||
```console
|
||||
docker run -p 80:80 -p 443:443 -p 443:443/udp -v $PWD:/app dunglas/frankenphp
|
||||
```
|
||||
|
||||
尽情享受吧!
|
||||
|
||||
## 本地安装
|
||||
|
||||
或者,你可以从本地机器上使用 FrankenPHP 运行 Laravel 项目:
|
||||
|
||||
1. [下载与您的系统相对应的二进制文件](https://github.com/dunglas/frankenphp/releases)
|
||||
2. 将以下配置添加到 Laravel 项目根目录中名为 `Caddyfile` 的文件中:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
# 服务器的域名
|
||||
localhost {
|
||||
# 将 webroot 设置为 public/ 目录
|
||||
root * public/
|
||||
# 启用压缩(可选)
|
||||
encode zstd br gzip
|
||||
# 执行当前目录中的 PHP 文件并提供资产
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
3. 从 Laravel 项目的根目录启动 FrankenPHP:`./frankenphp run`
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
Octane 可以通过 Composer 包管理器安装:
|
||||
|
||||
```console
|
||||
composer require laravel/octane
|
||||
```
|
||||
|
||||
安装 Octane 后,您可以执行 `octane:install` Artisan 命令,该命令会将 Octane 的配置文件安装到您的应用程序中:
|
||||
|
||||
```console
|
||||
php artisan octane:install --server=frankenphp
|
||||
```
|
||||
|
||||
Octane 服务可以通过 `octane:start` Artisan 命令启动。
|
||||
|
||||
```console
|
||||
php artisan octane:start
|
||||
```
|
||||
|
||||
`octane:start` 命令可以采用以下选项:
|
||||
|
||||
* `--host`: 服务器应绑定到的 IP 地址(默认值: `127.0.0.1`)
|
||||
* `--port`: 服务器应可用的端口(默认值: `8000`)
|
||||
* `--admin-port`: 管理服务器应可用的端口(默认值: `2019`)
|
||||
* `--workers`: 应可用于处理请求的 worker 数(默认值: `auto`)
|
||||
* `--max-requests`: 在 worker 重启之前要处理的请求数(默认值: `500`)
|
||||
* `--caddyfile`: FrankenPHP `Caddyfile` 文件的路径
|
||||
* `--https`: 开启 HTTPS、HTTP/2 和 HTTP/3,自动生成和延长证书
|
||||
* `--http-redirect`: 启用 HTTP 到 HTTPS 重定向(仅在使用 `--https` 时启用)
|
||||
* `--watch`: 修改应用程序时自动重新加载服务器
|
||||
* `--poll`: 在监视时使用文件系统轮询,以便通过网络监视文件
|
||||
* `--log-level`: 在指定日志级别或高于指定日志级别的日志消息
|
||||
|
||||
你可以了解更多关于 [Laravel Octane 官方文档](https://laravel.com/docs/octane)。
|
||||
12
docs/cn/mercure.md
Normal file
12
docs/cn/mercure.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# 实时
|
||||
|
||||
FrankenPHP 带有一个内置的 Mercure Hub!
|
||||
Mercure 允许将事件实时推送到所有连接的设备:它们将立即收到 JavaScript 事件。
|
||||
|
||||
无需 JS 库或 SDK!
|
||||
|
||||

|
||||
|
||||
要启用 Mercure Hub,请按照 [Mercure 网站](https://mercure.rocks/docs/hub/config) 中的说明更新 `Caddyfile`。
|
||||
|
||||
要从您的代码中推送 Mercure 更新,我们推荐 [Symfony Mercure Component](https://symfony.com/components/Mercure)(不需要 Symfony 框架来使用)。
|
||||
141
docs/cn/production.md
Normal file
141
docs/cn/production.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# 在生产环境中部署
|
||||
|
||||
在本教程中,我们将学习如何使用 Docker Compose 在单个服务器上部署 PHP 应用程序。
|
||||
|
||||
如果您使用的是 Symfony,请阅读 Symfony Docker 项目(使用 FrankenPHP)的 [在生产环境中部署](https://github.com/dunglas/symfony-docker/blob/main/docs/production.md) 文档条目。
|
||||
|
||||
如果您使用的是 API Platform(同样使用 FrankenPHP),请参阅 [框架的部署文档](https://api-platform.com/docs/deployment/)。
|
||||
|
||||
## 准备应用
|
||||
|
||||
首先,在 PHP 项目的根目录中创建一个 `Dockerfile`:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# 请将 "your-domain-name.example.com" 替换为您的域名
|
||||
ENV SERVER_NAME=your-domain-name.example.com
|
||||
# 如果要禁用 HTTPS,请改用以下值:
|
||||
#ENV SERVER_NAME=:80
|
||||
|
||||
# 启用 PHP 生产配置
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# 将项目的 PHP 文件复制到 public 目录中
|
||||
COPY . /app/public
|
||||
# 如果你使用 Symfony 或 Laravel,你需要复制整个项目:
|
||||
#COPY . /app
|
||||
```
|
||||
|
||||
有关更多详细信息和选项,请参阅 [构建自定义 Docker 镜像](docker.md)。
|
||||
要了解如何自定义配置,请安装 PHP 扩展和 Caddy 模块。
|
||||
|
||||
如果您的项目使用 Composer,
|
||||
请务必将其包含在 Docker 镜像中并安装您的依赖。
|
||||
|
||||
然后,添加一个 `compose.yaml` 文件:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
|
||||
# Caddy 证书和配置所需的挂载目录
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> 前面的示例适用于生产用途。
|
||||
> 在开发中,你可能希望使用挂载目录,不同的 PHP 配置和不同的 `SERVER_NAME` 环境变量值。
|
||||
>
|
||||
> 见 [Symfony Docker](https://github.com/dunglas/symfony-docker) 项目
|
||||
> (使用 FrankenPHP)作为使用多阶段镜像的更高级示例,
|
||||
> Composer、额外的 PHP 扩展等。
|
||||
|
||||
最后,如果您使用 Git,请提交这些文件并推送。
|
||||
|
||||
## 准备服务器
|
||||
|
||||
若要在生产环境中部署应用程序,需要一台服务器。
|
||||
在本教程中,我们将使用 DigitalOcean 提供的虚拟机,但任何 Linux 服务器都可以工作。
|
||||
如果您已经有安装了 Docker 的 Linux 服务器,您可以直接跳到 [下一节](#配置域名)。
|
||||
|
||||
否则,请使用 [此会员链接](https://m.do.co/c/5d8aabe3ab80) 获得 200 美元的免费信用额度,创建一个帐户,然后单击“Create a Droplet”。
|
||||
然后,单击“Choose an image”部分下的“Marketplace”选项卡,然后搜索名为“Docker”的应用程序。
|
||||
这将配置已安装最新版本的 Docker 和 Docker Compose 的 Ubuntu 服务器!
|
||||
|
||||
出于测试目的,最便宜的就足够了。
|
||||
对于实际的生产用途,您可能需要在“general purpose”部分中选择一个计划来满足您的需求。
|
||||
|
||||

|
||||
|
||||
您可以保留其他设置的默认值,也可以根据需要进行调整。
|
||||
不要忘记添加您的 SSH 密钥或创建密码,然后点击“完成并创建”按钮。
|
||||
|
||||
然后,在 Droplet 预配时等待几秒钟。
|
||||
Droplet 准备就绪后,使用 SSH 进行连接:
|
||||
|
||||
```console
|
||||
ssh root@<droplet-ip>
|
||||
```
|
||||
|
||||
## 配置域名
|
||||
|
||||
在大多数情况下,您需要将域名与您的网站相关联。
|
||||
如果您还没有域名,则必须通过注册商购买。
|
||||
|
||||
然后为您的域名创建类型为 `A` 的 DNS 记录,指向服务器的 IP 地址:
|
||||
|
||||
```dns
|
||||
your-domain-name.example.com. IN A 207.154.233.113
|
||||
```
|
||||
|
||||
DigitalOcean 域服务示例(“Networking” > “Domains”):
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Let's Encrypt 是 FrankenPHP 默认用于自动生成 TLS 证书的服务,不支持使用裸 IP 地址。使用域名是使用 Let's Encrypt 的必要条件。
|
||||
|
||||
## 部署
|
||||
|
||||
使用 `git clone`、`scp` 或任何其他可能适合您需要的工具在服务器上复制您的项目。
|
||||
如果使用 GitHub,则可能需要使用 [部署密钥](https://docs.github.com/en/free-pro-team@latest/developers/overview/managing-deploy-keys#deploy-keys)。
|
||||
部署密钥也 [由 GitLab 支持](https://docs.gitlab.com/ee/user/project/deploy_keys/)。
|
||||
|
||||
Git 示例:
|
||||
|
||||
```console
|
||||
git clone git@github.com:<username>/<project-name>.git
|
||||
```
|
||||
|
||||
进入包含项目 (`<project-name>`) 的目录,并在生产模式下启动应用:
|
||||
|
||||
```console
|
||||
docker compose up -d --wait
|
||||
```
|
||||
|
||||
您的服务器已启动并运行,并且已自动为您生成 HTTPS 证书。
|
||||
去 `https://your-domain-name.example.com` 享受吧!
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Docker 有一个缓存层,请确保每个部署都有正确的构建,或者使用 --no-cache 选项重新构建项目以避免缓存问题。
|
||||
|
||||
## 在多个节点上部署
|
||||
|
||||
如果要在计算机集群上部署应用程序,可以使用 [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/),
|
||||
它与提供的 Compose 文件兼容。
|
||||
要在 Kubernetes 上部署,请查看 [API 平台提供的 Helm 图表](https://api-platform.com/docs/deployment/kubernetes/),同样也使用 FrankenPHP。
|
||||
81
docs/cn/static.md
Normal file
81
docs/cn/static.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# 创建静态构建
|
||||
|
||||
基于 [static-php-cli](https://github.com/crazywhalecc/static-php-cli) 项目(这个项目支持所有 SAPI,不仅仅是 `cli`),
|
||||
FrankenPHP 已支持创建静态二进制,无需安装本地 PHP。
|
||||
|
||||
使用这种方法,我们可构建一个包含 PHP 解释器、Caddy Web 服务器和 FrankenPHP 的可移植二进制文件!
|
||||
|
||||
FrankenPHP 还支持 [将 PHP 应用程序嵌入到静态二进制文件中](embed.md)。
|
||||
|
||||
## Linux
|
||||
|
||||
我们提供了一个 Docker 镜像来构建 Linux 静态二进制文件:
|
||||
|
||||
```console
|
||||
docker buildx bake --load static-builder
|
||||
docker cp $(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp ; docker rm static-builder
|
||||
```
|
||||
|
||||
生成的静态二进制文件名为 `frankenphp`,可在当前目录中找到。
|
||||
|
||||
如果您想在没有 Docker 的情况下构建静态二进制文件,请查看 macOS 说明,它也适用于 Linux。
|
||||
|
||||
### 自定义扩展
|
||||
|
||||
默认情况下,大多数流行的 PHP 扩展都会被编译。
|
||||
|
||||
若要减小二进制文件的大小并减少攻击面,可以选择使用 `PHP_EXTENSIONS` Docker 参数来自定义构建的扩展。
|
||||
|
||||
例如,运行以下命令以生成仅包含 `opcache,pdo_sqlite` 扩展的二进制:
|
||||
|
||||
```console
|
||||
docker buildx bake --load --set static-builder.args.PHP_EXTENSIONS=opcache,pdo_sqlite static-builder
|
||||
# ...
|
||||
```
|
||||
|
||||
若要将启用其他功能的库添加到已启用的扩展中,可以使用 `PHP_EXTENSION_LIBS` Docker 参数:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder.args.PHP_EXTENSIONS=gd \
|
||||
--set static-builder.args.PHP_EXTENSION_LIBS=libjpeg,libwebp \
|
||||
static-builder
|
||||
```
|
||||
|
||||
参见:[自定义构建](#自定义构建)
|
||||
|
||||
### GitHub Token
|
||||
|
||||
如果遇到了 GitHub API 速率限制,请在 `GITHUB_TOKEN` 的环境变量中设置 GitHub Personal Access Token:
|
||||
|
||||
```console
|
||||
GITHUB_TOKEN="xxx" docker --load buildx bake static-builder
|
||||
# ...
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
运行以下脚本以创建适用于 macOS 的静态二进制文件(需要先安装 [Homebrew](https://brew.sh/)):
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
注意:此脚本也适用于 Linux(可能也适用于其他 Unix 系统),我们提供的用于构建静态二进制的 Docker 镜像也在内部使用这个脚本。
|
||||
|
||||
## 自定义构建
|
||||
|
||||
以下环境变量可以传递给 `docker build` 和 `build-static.sh`
|
||||
脚本来自定义静态构建:
|
||||
|
||||
* `FRANKENPHP_VERSION`: 要使用的 FrankenPHP 版本
|
||||
* `PHP_VERSION`: 要使用的 PHP 版本
|
||||
* `PHP_EXTENSIONS`: 要构建的 PHP 扩展([支持的扩展列表](https://static-php.dev/zh/guide/extensions.html))
|
||||
* `PHP_EXTENSION_LIBS`: 要构建的额外库,为扩展添加额外的功能
|
||||
* `EMBED`: 要嵌入二进制文件的 PHP 应用程序的路径
|
||||
* `CLEAN`: 设置后,libphp 及其所有依赖项都是重新构建的(不使用缓存)
|
||||
* `DEBUG_SYMBOLS`: 设置后,调试符号将被保留在二进制文件内
|
||||
* `RELEASE`: (仅限维护者)设置后,生成的二进制文件将上传到 GitHub 上
|
||||
114
docs/cn/worker.md
Normal file
114
docs/cn/worker.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# 使用 FrankenPHP Workers
|
||||
|
||||
启动应用程序一次并将其保存在内存中。
|
||||
FrankenPHP 将在几毫秒内处理传入的请求。
|
||||
|
||||
## 启动 Worker 脚本
|
||||
|
||||
### Docker
|
||||
|
||||
将 `FRANKENPHP_CONFIG` 环境变量的值设置为 `worker /path/to/your/worker/script.php`:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker /app/path/to/your/worker/script.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### 独立二进制
|
||||
|
||||
使用 `php-server` 命令的 `--worker` 选项, 执行命令使当前目录的内容使用 worker:
|
||||
|
||||
```console
|
||||
./frankenphp php-server --worker /path/to/your/worker/script.php
|
||||
```
|
||||
|
||||
## Symfony Runtime
|
||||
|
||||
FrankenPHP 的 worker 模式由 [Symfony Runtime 组件](https://symfony.com/doc/current/components/runtime.html) 支持。
|
||||
要在 worker 中启动任何 Symfony 应用程序,请安装 [PHP Runtime](https://github.com/php-runtime/runtime) 的 FrankenPHP 软件包:
|
||||
|
||||
```console
|
||||
composer require runtime/frankenphp-symfony
|
||||
```
|
||||
|
||||
通过定义 `APP_RUNTIME` 环境变量来启动你的应用服务器,以使用 FrankenPHP Symfony Runtime:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
请参阅 [文档](laravel.md#laravel-octane)。
|
||||
|
||||
## 自定义应用程序
|
||||
|
||||
以下示例演示如何在不依赖第三方库的情况下创建自己的 worker 脚本:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// public/index.php
|
||||
|
||||
// 防止在客户端连接中断时 worker 线程脚本终止
|
||||
ignore_user_abort(true);
|
||||
|
||||
// 启动应用
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$myApp = new \App\Kernel();
|
||||
$myApp->boot();
|
||||
|
||||
// 循环外的处理程序以获得更好的性能(减少工作量)
|
||||
$handler = static function () use ($myApp) {
|
||||
// 收到请求时调用
|
||||
// 超全局变量 php://input
|
||||
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
};
|
||||
for($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbRequests < ((int)$_SERVER['MAX_REQUESTS'])) && $running; ++$nbRequests) {
|
||||
$running = \frankenphp_handle_request($handler);
|
||||
|
||||
// 发送 HTTP 响应后执行某些操作
|
||||
$myApp->terminate();
|
||||
|
||||
// 调用垃圾回收器以减少在页面生成过程中触发垃圾回收器的几率
|
||||
gc_collect_cycles();
|
||||
}
|
||||
// 结束清理
|
||||
$myApp->shutdown();
|
||||
```
|
||||
|
||||
然后,启动应用并使用 `FRANKENPHP_CONFIG` 环境变量来配置你的 worker:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
默认情况下,每个 CPU 启动一个 worker。
|
||||
您还可以配置要启动的 worker 数:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### 在一定数量的请求后重新启动 Worker
|
||||
|
||||
由于 PHP 最初不是为长时间运行的进程而设计的,因此仍然有许多库和遗留代码会发生内存泄露。
|
||||
在 worker 模式下使用此类代码的解决方法是在处理一定数量的请求后重新启动 worker 程序脚本:
|
||||
|
||||
前面的 worker 代码段允许通过设置名为 `MAX_REQUESTS` 的环境变量来配置要处理的最大请求数。
|
||||
@@ -1,6 +1,6 @@
|
||||
# Compile From Sources
|
||||
|
||||
This document explain how to create a FrankenPHP build that will load PHP as a dymanic library.
|
||||
This document explain how to create a FrankenPHP build that will load PHP as a dynamic library.
|
||||
This is the recommended method.
|
||||
|
||||
Alternatively, [creating static builds](static.md) is also possible.
|
||||
|
||||
@@ -6,15 +6,16 @@ In the Docker image, the `Caddyfile` is located at `/etc/caddy/Caddyfile`.
|
||||
|
||||
You can also configure PHP using `php.ini` as usual.
|
||||
|
||||
In the Docker image, the `php.ini` file is not present, you can create it or `COPY` manually.
|
||||
|
||||
If you copy `php.ini` from `$PHP_INI_DIR/php.ini-production` or `$PHP_INI_DIR/php.ini-development`, you also must set the variable `variables_order = "EGPCS"`, because the default value for `variables_order` is `"EGPCS"`, but in `php.ini-production` and `php.ini-development` we have `"GPCS"`. And in this case, `worker` does not work properly.
|
||||
In the Docker image, the `php.ini` file is not present, you can create it manually or copy an official template:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini; \
|
||||
sed -i 's/variables_order = "GPCS"/variables_order = "EGPCS"/' $PHP_INI_DIR/php.ini;
|
||||
# Developement:
|
||||
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
|
||||
|
||||
# Or production:
|
||||
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
|
||||
```
|
||||
|
||||
## Caddyfile Config
|
||||
@@ -87,7 +88,8 @@ other.example.com {
|
||||
root * /path/to/other/public
|
||||
php_server
|
||||
}
|
||||
...
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Using the `php_server` directive is generally what you need,
|
||||
@@ -121,8 +123,8 @@ The `php_server` and the `php` directives have the following options:
|
||||
```caddyfile
|
||||
php_server [<matcher>] {
|
||||
root <directory> # Sets the root folder to the site. Default: `root` directive.
|
||||
split_path <delim...> # Sets the substrings for splitting the URI into two parts. The first matching substring will be used to split the "path info" from the path. The first piece is suffixed with the matching substring and will be assumed as the actual resource (CGI script) name. The second piece will be set to PATH_INFO for the CGI script to use. Default: `.php`
|
||||
resolve_root_symlink # Enables resolving the `root` directory to its actual value by evaluating a symbolic link, if one exists.
|
||||
split_path <delim...> # Sets the substrings for splitting the URI into two parts. The first matching substring will be used to split the "path info" from the path. The first piece is suffixed with the matching substring and will be assumed as the actual resource (CGI script) name. The second piece will be set to PATH_INFO for the script to use. Default: `.php`
|
||||
resolve_root_symlink false # Disables resolving the `root` directory to its actual value by evaluating a symbolic link, if one exists (enabled by default).
|
||||
env <key> <value> # Sets an extra environment variable to the given value. Can be specified more than once for multiple environment variables.
|
||||
}
|
||||
```
|
||||
@@ -135,9 +137,9 @@ The following environment variables can be used to inject Caddy directives in th
|
||||
* `CADDY_GLOBAL_OPTIONS`: inject [global options](https://caddyserver.com/docs/caddyfile/options)
|
||||
* `FRANKENPHP_CONFIG`: inject config under the `frankenphp` directive
|
||||
|
||||
Unlike with FPM and CLI SAPIs, environment variables are **not** exposed by default in superglobals `$_SERVER` and `$_ENV`.
|
||||
As for FPM and CLI SAPIs, environment variables are exposed by default in the `$_SERVER` superglobal.
|
||||
|
||||
To propagate environment variables to `$_SERVER` and `$_ENV`, set the `php.ini` `variables_order` directive to `EGPCS`.
|
||||
The `S` value of [the `variables_order` PHP directive](https://www.php.net/manual/en/ini.core.php#ini.variables-order) is always equivalent to `ES` regardless of the placement of `E` elsewhere in this directive.
|
||||
|
||||
## PHP config
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Building Custom Docker Image
|
||||
|
||||
[FrankenPHP Docker images](https://hub.docker.com/r/dunglas/frankenphp) are based on [official PHP images](https://hub.docker.com/_/php/). Alpine Linux and Debian variants are provided for popular architectures. Variants for PHP 8.2 and PHP 8.3 are provided. [Browse tags](https://hub.docker.com/r/dunglas/frankenphp/tags).
|
||||
[FrankenPHP Docker images](https://hub.docker.com/r/dunglas/frankenphp) are based on [official PHP images](https://hub.docker.com/_/php/). Debian and Alpine Linux variants are provided for popular architectures. Debian variants are recommended.
|
||||
|
||||
Variants for PHP 8.2 and PHP 8.3 are provided. [Browse tags](https://hub.docker.com/r/dunglas/frankenphp/tags).
|
||||
|
||||
## How to Use The Images
|
||||
|
||||
@@ -12,7 +14,7 @@ FROM dunglas/frankenphp
|
||||
COPY . /app/public
|
||||
```
|
||||
|
||||
Then, run the commands to build and run the Docker image:
|
||||
Then, run these commands to build and run the Docker image:
|
||||
|
||||
```console
|
||||
docker build -t my-php-app .
|
||||
@@ -55,6 +57,7 @@ RUN xcaddy build \
|
||||
--with github.com/dunglas/frankenphp=./ \
|
||||
--with github.com/dunglas/frankenphp/caddy=./caddy/ \
|
||||
# Mercure and Vulcain are included in the official build, but feel free to remove them
|
||||
--with github.com/dunglas/caddy-cbrotli \
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Add extra Caddy modules here
|
||||
@@ -65,8 +68,8 @@ FROM dunglas/frankenphp AS runner
|
||||
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
|
||||
```
|
||||
|
||||
The `builder` image provided by FrankenPHP contains a compiled version of libphp.
|
||||
[Builders images](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder) are provided for all versions of FrankenPHP and PHP, both for Alpine and Debian.
|
||||
The `builder` image provided by FrankenPHP contains a compiled version of `libphp`.
|
||||
[Builders images](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder) are provided for all versions of FrankenPHP and PHP, both for Debian and Alpine.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
@@ -128,7 +131,7 @@ volumes:
|
||||
|
||||
## Running as a Non-Root User
|
||||
|
||||
FrankenPHP can run as non root user in Docker.
|
||||
FrankenPHP can run as non-root user in Docker.
|
||||
|
||||
Here is a sample `Dockerfile` doing this:
|
||||
|
||||
@@ -136,13 +139,16 @@ Here is a sample `Dockerfile` doing this:
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
ARG USER=www-data
|
||||
USER ${USER}
|
||||
|
||||
RUN adduser -D ${USER} \
|
||||
# Caddy requires an additional capability to bind to port 80 and 443
|
||||
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp
|
||||
# Caddy requires write access to /data/caddy and /config/caddy
|
||||
RUN chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy
|
||||
RUN \
|
||||
# Use "adduser -D ${USER}" for alpine based distros
|
||||
useradd -D ${USER}; \
|
||||
# Add additional capability to bind to port 80 and 443
|
||||
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp; \
|
||||
# Give write access to /data/caddy and /config/caddy
|
||||
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy;
|
||||
|
||||
USER ${USER}
|
||||
```
|
||||
|
||||
## Updates
|
||||
@@ -150,7 +156,7 @@ RUN adduser -D ${USER} \
|
||||
The Docker images are built:
|
||||
|
||||
* when a new release is tagged
|
||||
* daily at 4am UTC, if new versions of the official PHP images are available
|
||||
* daily at 4 am UTC, if new versions of the official PHP images are available
|
||||
|
||||
## Development Versions
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ FrankenPHP has the ability to embed the source code and assets of PHP applicatio
|
||||
|
||||
Thanks to this feature, PHP applications can be distributed as standalone binaries that include the application itself, the PHP interpreter and Caddy, a production-level web server.
|
||||
|
||||
Learn more about this feature [in the presentation made by Kévin at SymfonyCon](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/).
|
||||
Learn more about this feature [in the presentation made by Kévin at SymfonyCon 2023](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/).
|
||||
|
||||
## Preparing Your App
|
||||
|
||||
@@ -59,13 +59,18 @@ The easiest way to create a Linux binary is to use the Docker-based builder we p
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Some `.dockerignore` files (e.g. default [Symfony Docker `.dockerignore`](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))
|
||||
> will ignore the `vendor/` directory and `.env` files. Be sure to adjust or remove the `.dockerignore` file before the build.
|
||||
|
||||
2. Build:
|
||||
|
||||
```console
|
||||
docker build -t static-app -f static-build.Dockerfile .
|
||||
```
|
||||
|
||||
3. Extract the binary
|
||||
3. Extract the binary:
|
||||
|
||||
```console
|
||||
docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp
|
||||
@@ -121,7 +126,7 @@ You can also run the PHP CLI scripts embedded in your binary:
|
||||
|
||||
## Distributing The Binary
|
||||
|
||||
The created binary isn't compressed.
|
||||
To reduce the size of the file before sending it, you can compress it.
|
||||
On Linux, the created binary is compressed using [UPX](https://upx.github.io).
|
||||
|
||||
On Mac, to reduce the size of the file before sending it, you can compress it.
|
||||
We recommend `xz`.
|
||||
|
||||
177
docs/fr/CONTRIBUTING.md
Normal file
177
docs/fr/CONTRIBUTING.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Contribuer
|
||||
|
||||
## Compiler PHP
|
||||
|
||||
### Avec Docker (Linux)
|
||||
|
||||
Construisez l'image Docker de développement :
|
||||
|
||||
```console
|
||||
docker build -t frankenphp-dev -f dev.Dockerfile .
|
||||
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -p 443:443/udp -v $PWD:/go/src/app -it frankenphp-dev
|
||||
```
|
||||
|
||||
L'image contient les outils de développement habituels (Go, GDB, Valgrind, Neovim...).
|
||||
|
||||
Si la version de Docker est inférieure à 23.0, la construction échoue à cause d'un [problème de pattern](https://github.com/moby/moby/pull/42676) dans `.dockerignore`. Ajoutez les répertoires à `.dockerignore`.
|
||||
|
||||
```patch
|
||||
!testdata/*.php
|
||||
!testdata/*.txt
|
||||
+!caddy
|
||||
+!C-Thread-Pool
|
||||
+!internal
|
||||
```
|
||||
|
||||
### Sans Docker (Linux et macOS)
|
||||
|
||||
[Suivez les instructions pour compiler à partir des sources](compile.md) et passez l'indicateur de configuration `--debug`.
|
||||
|
||||
## Exécution de la suite de tests
|
||||
|
||||
```console
|
||||
go test -race -v ./...
|
||||
```
|
||||
|
||||
## Module Caddy
|
||||
|
||||
Construire Caddy avec le module FrankenPHP :
|
||||
|
||||
```console
|
||||
cd caddy/frankenphp/
|
||||
go build
|
||||
cd ../../
|
||||
```
|
||||
|
||||
Exécuter Caddy avec le module FrankenPHP :
|
||||
|
||||
```console
|
||||
cd testdata/
|
||||
../caddy/frankenphp/frankenphp run
|
||||
```
|
||||
|
||||
Le serveur est configuré pour écouter à l'adresse `127.0.0.1:8080`:
|
||||
|
||||
```console
|
||||
curl -vk https://localhost/phpinfo.php
|
||||
```
|
||||
|
||||
## Serveur de test minimal
|
||||
|
||||
Construire le serveur de test minimal :
|
||||
|
||||
```console
|
||||
cd internal/testserver/
|
||||
go build
|
||||
cd ../../
|
||||
```
|
||||
|
||||
Lancer le test serveur :
|
||||
|
||||
```console
|
||||
cd testdata/
|
||||
../internal/testserver/testserver
|
||||
```
|
||||
|
||||
Le serveur est configuré pour écouter à l'adresse `127.0.0.1:8080`:
|
||||
|
||||
```console
|
||||
curl -v http://127.0.0.1:8080/phpinfo.php
|
||||
```
|
||||
|
||||
## Construire localement les images Docker
|
||||
|
||||
Afficher le plan de compilation :
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --print
|
||||
```
|
||||
|
||||
Construire localement les images FrankenPHP pour amd64 :
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"
|
||||
```
|
||||
|
||||
Construire localement les images FrankenPHP pour arm64 :
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"
|
||||
```
|
||||
|
||||
Construire à partir de zéro les images FrankenPHP pour arm64 & amd64 et les pousser sur Docker Hub :
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --no-cache --push
|
||||
```
|
||||
|
||||
## Déboguer les erreurs de segmentation dans GitHub Actions
|
||||
|
||||
1. Ouvrir `.github/workflows/tests.yml`
|
||||
2. Activer les symboles de débogage de la bibliothèque PHP
|
||||
|
||||
```patch
|
||||
- uses: shivammathur/setup-php@v2
|
||||
# ...
|
||||
env:
|
||||
phpts: ts
|
||||
+ debug: true
|
||||
```
|
||||
|
||||
3. Activer `tmate` pour se connecter au conteneur
|
||||
|
||||
```patch
|
||||
-
|
||||
name: Set CGO flags
|
||||
run: echo "CGO_CFLAGS=$(php-config --includes)" >> "$GITHUB_ENV"
|
||||
+ -
|
||||
+ run: |
|
||||
+ sudo apt install gdb
|
||||
+ mkdir -p /home/runner/.config/gdb/
|
||||
+ printf "set auto-load safe-path /\nhandle SIG34 nostop noprint pass" > /home/runner/.config/gdb/gdbinit
|
||||
+ -
|
||||
+ uses: mxschmitt/action-tmate@v3
|
||||
```
|
||||
|
||||
4. Se connecter au conteneur
|
||||
5. Ouvrir `frankenphp.go`
|
||||
6. Activer `cgosymbolizer`
|
||||
|
||||
```patch
|
||||
- //_ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
+ _ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
```
|
||||
|
||||
7. Télécharger le module : `go get`
|
||||
8. Dans le conteneur, vous pouvez utiliser GDB et similaires :
|
||||
|
||||
```console
|
||||
go test -c -ldflags=-w
|
||||
gdb --args ./frankenphp.test -test.run ^MyTest$
|
||||
```
|
||||
|
||||
9. Quand le bug est corrigé, annulez tous les changements
|
||||
|
||||
## Ressources Diverses pour le Développement
|
||||
|
||||
* [Intégration de PHP dans uWSGI](https://github.com/unbit/uwsgi/blob/master/plugins/php/php_plugin.c)
|
||||
* [Intégration de PHP dans NGINX Unit](https://github.com/nginx/unit/blob/master/src/nxt_php_sapi.c)
|
||||
* [Intégration de PHP dans Go (go-php)](https://github.com/deuill/go-php)
|
||||
* [Intégration de PHP dans Go (GoEmPHP)](https://github.com/mikespook/goemphp)
|
||||
* [Intégration de PHP dans C++](https://gist.github.com/paresy/3cbd4c6a469511ac7479aa0e7c42fea7)
|
||||
* [Extending and Embedding PHP par Sara Golemon](https://books.google.fr/books?id=zMbGvK17_tYC&pg=PA254&lpg=PA254#v=onepage&q&f=false)
|
||||
* [Qu'est-ce que TSRMLS_CC, au juste ?](http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html)
|
||||
* [Intégration de PHP sur Mac](https://gist.github.com/jonnywang/61427ffc0e8dde74fff40f479d147db4)
|
||||
* [Bindings SDL](https://pkg.go.dev/github.com/veandco/go-sdl2@v0.4.21/sdl#Main)
|
||||
|
||||
## Ressources Liées à Docker
|
||||
|
||||
* [Définition du fichier Bake](https://docs.docker.com/build/customize/bake/file-definition/)
|
||||
* [docker buildx build](https://docs.docker.com/engine/reference/commandline/buildx_build/)
|
||||
|
||||
## Commande utile
|
||||
|
||||
```console
|
||||
apk add strace util-linux gdb
|
||||
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
|
||||
```
|
||||
77
docs/fr/README.md
Normal file
77
docs/fr/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# FrankenPHP : le serveur d'applications PHP moderne, écrit en Go
|
||||
|
||||
<h1 align="center"><a href="https://frankenphp.dev"><img src="../../frankenphp.png" alt="FrankenPHP" width="600"></a></h1>
|
||||
|
||||
FrankenPHP est un serveur d'applications moderne pour PHP construit à partir du serveur web [Caddy](https://caddyserver.com/).
|
||||
|
||||
FrankenPHP donne des super-pouvoirs à vos applications PHP grâce à ses fonctionnalités à la pointe : [*Early Hints*](early-hints.md), [mode worker](worker.md), [fonctionnalités en temps réel](mercure.md), HTTPS automatique, prise en charge de HTTP/2 et HTTP/3...
|
||||
|
||||
FrankenPHP fonctionne avec n'importe quelle application PHP et rend vos projets Laravel et Symfony plus rapides que jamais grâce à leurs intégrations officielles avec le mode worker.
|
||||
|
||||
FrankenPHP peut également être utilisé comme une bibliothèque Go autonome qui permet d'intégrer PHP dans n'importe quelle application en utilisant `net/http`.
|
||||
|
||||
Découvrez plus de détails sur ce serveur d’application dans le replay de cette conférence donnée au Forum PHP 2022 :
|
||||
|
||||
<a href="https://dunglas.dev/2022/10/frankenphp-the-modern-php-app-server-written-in-go/"><img src="https://dunglas.dev/wp-content/uploads/2022/10/frankenphp.png" alt="Diapositives" width="600"></a>
|
||||
|
||||
## Pour Commencer
|
||||
|
||||
### Docker
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Rendez-vous sur `https://localhost`, c'est parti !
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Ne tentez pas d'utiliser `https://127.0.0.1`. Utilisez `https://localhost` et acceptez le certificat auto-signé.
|
||||
> Utilisez [la variable d'environnement `SERVER_NAME`](config.md#environment-variables) pour changer le domaine à utiliser.
|
||||
|
||||
### Binaire autonome
|
||||
|
||||
Si vous préférez ne pas utiliser Docker, nous fournissons des binaires autonomes de FrankenPHP pour Linux et macOS
|
||||
contenant [PHP 8.3](https://www.php.net/releases/8.3/fr.php) et la plupart des extensions PHP populaires : [Télécharger FrankenPHP](https://github.com/dunglas/frankenphp/releases)
|
||||
|
||||
Pour servir le contenu du répertoire courant, exécutez :
|
||||
|
||||
```console
|
||||
./frankenphp php-server
|
||||
```
|
||||
|
||||
Vous pouvez également exécuter des scripts en ligne de commande avec :
|
||||
|
||||
```console
|
||||
./frankenphp php-cli /path/to/your/script.php
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Le mode worker](worker.md)
|
||||
* [Le support des Early Hints (code de statut HTTP 103)](early-hints.md)
|
||||
* [Temps réel](mercure.md)
|
||||
* [Configuration](config.md)
|
||||
* [Images Docker](docker.md)
|
||||
* [Déploiement en production](production.md)
|
||||
* [Créer des applications PHP **standalone**, auto-exécutables](embed.md)
|
||||
* [Créer un build statique](static.md)
|
||||
* [Compiler depuis les sources](compile.md)
|
||||
* [Intégration Laravel](laravel.md)
|
||||
* [Problèmes connus](known-issues.md)
|
||||
* [Application de démo (Symfony) et benchmarks](https://github.com/dunglas/frankenphp-demo)
|
||||
* [Documentation de la bibliothèque Go](https://pkg.go.dev/github.com/dunglas/frankenphp)
|
||||
* [Contribuer et débugger](CONTRIBUTING.md)
|
||||
|
||||
## Exemples et squelettes
|
||||
|
||||
* [Symfony](https://github.com/dunglas/symfony-docker)
|
||||
* [API Platform](https://api-platform.com/docs/distribution/)
|
||||
* [Laravel](laravel.md)
|
||||
* [Sulu](https://sulu.io/blog/running-sulu-with-frankenphp)
|
||||
* [WordPress](https://github.com/dunglas/frankenphp-wordpress)
|
||||
* [Drupal](https://github.com/dunglas/frankenphp-drupal)
|
||||
* [Joomla](https://github.com/alexandreelise/frankenphp-joomla)
|
||||
* [TYPO3](https://github.com/ochorocho/franken-typo3)
|
||||
101
docs/fr/compile.md
Normal file
101
docs/fr/compile.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Compiler depuis les sources
|
||||
|
||||
Ce document explique comment créer un build FrankenPHP qui chargera PHP comme une bibliothèque dynamique. C'est la méthode recommandée.
|
||||
|
||||
En alternative, il est aussi possible de [créer des builds statiques](static.md).
|
||||
|
||||
## Installer PHP
|
||||
|
||||
FrankenPHP est compatible avec PHP 8.2 et versions ultérieures.
|
||||
|
||||
Tout d'abord, [téléchargez les sources de PHP](https://www.php.net/downloads.php) et extrayez-les :
|
||||
|
||||
```console
|
||||
tar xf php-*
|
||||
cd php-*/
|
||||
```
|
||||
|
||||
Ensuite, configurez PHP pour votre système d'exploitation :
|
||||
|
||||
### Linux
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--enable-zend-max-execution-timers
|
||||
```
|
||||
|
||||
Finalement, compilez et installez PHP :
|
||||
|
||||
```console
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Mac
|
||||
|
||||
Utilisez le gestionnaire de paquets [Homebrew](https://brew.sh/) pour installer `libiconv`, `bison`, `re2c` et `pkg-config` :
|
||||
|
||||
```console
|
||||
brew install libiconv bison re2c pkg-config
|
||||
echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
Puis exécutez le script de configuration :
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed=static \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--disable-opcache-jit \
|
||||
--enable-static \
|
||||
--enable-shared=no \
|
||||
--with-iconv=/opt/homebrew/opt/libiconv/
|
||||
```
|
||||
|
||||
Les options de configuration spécifiées sont nécessaires pour la compilation, mais vous pouvez également inclure d'autres options selon vos besoins, par exemple pour ajouter des extensions supplémentaires.
|
||||
|
||||
Finalement, compilez et installez PHP :
|
||||
|
||||
```console
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Compiler l'application Go
|
||||
|
||||
Vous pouvez maintenant utiliser la bibliothèque Go et compiler notre build de Caddy :
|
||||
|
||||
```console
|
||||
curl -L https://github.com/dunglas/frankenphp/archive/refs/heads/main.tar.gz | tar x
|
||||
cd frankenphp-main/caddy/frankenphp
|
||||
CGO_CFLAGS=$(php-config --includes) CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" go build
|
||||
```
|
||||
|
||||
### Utiliser xcaddy
|
||||
|
||||
Vous pouvez utiliser à la place [xcaddy](https://github.com/caddyserver/xcaddy) pour compiler FrankenPHP avec [des modules Caddy additionnels](https://caddyserver.com/docs/modules/):
|
||||
|
||||
```console
|
||||
CGO_ENABLED=1 \
|
||||
XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'" \
|
||||
xcaddy build \
|
||||
--output frankenphp \
|
||||
--with github.com/dunglas/frankenphp/caddy \
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Add extra Caddy modules here
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Si vous utilisez musl libc (la bibliothèque par défaut sur Alpine Linux) et Symfony,
|
||||
> vous pourriez avoir besoin d'augmenter la taille par défaut de la pile.
|
||||
> Sinon, vous pourriez rencontrer des erreurs telles que `PHP Fatal error: Maximum call stack size of 83360 bytes reached during compilation. Try splitting expression`
|
||||
>
|
||||
> Pour ce faire, modifiez la variable d'environnement `XCADDY_GO_BUILD_FLAGS` en quelque chose comme
|
||||
> `XCADDY_GO_BUILD_FLAGS=$'-ldflags "-w -s -extldflags \'-Wl,-z,stack-size=0x80000\'"'`
|
||||
> (modifiez la valeur de la taille de la pile selon les besoins de votre application).
|
||||
158
docs/fr/config.md
Normal file
158
docs/fr/config.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Configuration
|
||||
|
||||
FrankenPHP, Caddy ainsi que les modules Mercure et Vulcain peuvent être configurés en utilisant [les formats pris en charge par Caddy](https://caddyserver.com/docs/getting-started#your-first-config).
|
||||
|
||||
Dans l'image Docker, le chemin du `Caddyfile` est `/etc/caddy/Caddyfile`.
|
||||
|
||||
Vous pouvez également configurer PHP en utilisant `php.ini` comme d'habitude.
|
||||
|
||||
Dans l'image Docker, le fichier `php.ini` n'est pas présent, vous pouvez le créer manuellement ou copier un template officiel :
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# Développement :
|
||||
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
|
||||
|
||||
# Ou production :
|
||||
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
|
||||
```
|
||||
|
||||
## Configuration du Caddyfile
|
||||
|
||||
Pour enregistrer l'exécutable de FrankenPHP, l'[option globale](https://caddyserver.com/docs/caddyfile/concepts#global-options) `frankenphp` doit être définie, puis les [directives HTTP](https://caddyserver.com/docs/caddyfile/concepts#directives) `php_server` ou `php` peuvent être utilisées dans les blocs de site pour servir votre application PHP.
|
||||
|
||||
Exemple minimal :
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
# Activer FrankenPHP
|
||||
frankenphp
|
||||
# Configurer l'ordre d'exécution de la directive
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
localhost {
|
||||
# Activer la compression (optionnel)
|
||||
encode zstd br gzip
|
||||
# Exécuter les fichiers PHP dans le répertoire courant et servir les assets
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
En option, le nombre de threads à créer et les [workers](worker.md) à démarrer avec le serveur peuvent être spécifiés sous l'option globale.
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
num_threads <num_threads> # Définit le nombre de threads PHP à démarrer. Par défaut : 2x le nombre de CPUs disponibles.
|
||||
worker {
|
||||
file <path> # Définit le chemin vers le script worker.
|
||||
num <num> # Définit le nombre de threads PHP à démarrer, par défaut 2x le nombre de CPUs disponibles.
|
||||
env <key> <value> # Définit une variable d'environnement supplémentaire avec la valeur donnée. Peut être spécifié plusieurs fois pour régler plusieurs variables d'environnement.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Vous pouvez également utiliser la forme courte de l'option worker en une seule ligne :
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker <file> <num>
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Vous pouvez aussi définir plusieurs workers si vous servez plusieurs applications sur le même serveur :
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker /path/to/app/public/index.php <num>
|
||||
worker /path/to/other/public/index.php <num>
|
||||
}
|
||||
}
|
||||
|
||||
app.example.com {
|
||||
root * /path/to/app/public
|
||||
php_server
|
||||
}
|
||||
|
||||
other.example.com {
|
||||
root * /path/to/other/public
|
||||
php_server
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
L'utilisation de la directive `php_server` est généralement suffisante,
|
||||
mais si vous avez besoin d'un contrôle total, vous pouvez utiliser la directive `php`, qui permet un plus grand niveau de finesse dans la configuration.
|
||||
|
||||
Utiliser la directive `php_server` est équivalent à cette configuration :
|
||||
|
||||
```caddyfile
|
||||
route {
|
||||
# Ajoute un slash final pour les requêtes de répertoire
|
||||
@canonicalPath {
|
||||
file {path}/index.php
|
||||
not path */
|
||||
}
|
||||
redir @canonicalPath {path}/ 308
|
||||
# Si le fichier demandé n'existe pas, essayer les fichiers index
|
||||
@indexFiles file {
|
||||
try_files {path} {path}/index.php index.php
|
||||
split_path .php
|
||||
}
|
||||
rewrite @indexFiles {http.matchers.file.relative}
|
||||
# FrankenPHP!
|
||||
@phpFiles path *.php
|
||||
php @phpFiles
|
||||
file_server
|
||||
}
|
||||
```
|
||||
|
||||
Les directives `php_server` et `php` disposent des options suivantes :
|
||||
|
||||
```caddyfile
|
||||
php_server [<matcher>] {
|
||||
root <directory> # Définit le dossier racine du le site. Par défaut : valeur de la directive `root` parente.
|
||||
split_path <delim...> # Définit les sous-chaînes pour diviser l'URI en deux parties. La première sous-chaîne correspondante sera utilisée pour séparer le "path info" du chemin. La première partie est suffixée avec la sous-chaîne correspondante et sera considérée comme le nom réel de la ressource (script CGI). La seconde partie sera définie comme PATH_INFO pour utilisation par le script. Par défaut : `.php`
|
||||
resolve_root_symlink false # Désactive la résolution du répertoire `root` vers sa valeur réelle en évaluant un lien symbolique, s'il existe (activé par défaut).
|
||||
env <key> <value> # Définit une variable d'environnement supplémentaire avec la valeur donnée. Peut être spécifié plusieurs fois pour plusieurs variables d'environnement.
|
||||
}
|
||||
```
|
||||
|
||||
## Variables d'environnement
|
||||
|
||||
Les variables d'environnement suivantes peuvent être utilisées pour insérer des directives Caddy dans le `Caddyfile` sans le modifier :
|
||||
|
||||
* `SERVER_NAME` : change [les adresses sur lesquelles écouter](https://caddyserver.com/docs/caddyfile/concepts#addresses), les noms d'hôte fournis seront également utilisés pour le certificat TLS généré
|
||||
* `CADDY_GLOBAL_OPTIONS` : injecte [des options globales](https://caddyserver.com/docs/caddyfile/options)
|
||||
* `FRANKENPHP_CONFIG` : insère la configuration sous la directive `frankenphp`
|
||||
|
||||
Comme pour les SAPI FPM et CLI, les variables d'environnement ne sont exposées par défaut dans la superglobale `$_SERVER`.
|
||||
|
||||
La valeur `S` de [la directive `variables_order` de PHP](https://www.php.net/manual/fr/ini.core.php#ini.variables-order) est toujours équivalente à `ES`, que `E` soit défini ailleurs dans cette directive ou non.
|
||||
|
||||
## Configuration PHP
|
||||
|
||||
Pour charger [des fichiers de configuration PHP supplémentaires](https://www.php.net/manual/fr/configuration.file.php#configuration.file.scan), la variable d'environnement `PHP_INI_SCAN_DIR` peut être utilisée.
|
||||
Lorsqu'elle est définie, PHP chargera tous les fichiers avec l'extension `.ini` présents dans les répertoires donnés.
|
||||
|
||||
## Activer le mode debug
|
||||
|
||||
Lors de l'utilisation de l'image Docker, définissez la variable d'environnement `CADDY_GLOBAL_OPTIONS` sur `debug` pour activer le mode debug :
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-e CADDY_GLOBAL_OPTIONS=debug \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
165
docs/fr/docker.md
Normal file
165
docs/fr/docker.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Création d'une image Docker personnalisée
|
||||
|
||||
Les images Docker de [FrankenPHP](https://hub.docker.com/r/dunglas/frankenphp) sont basées sur les [images PHP officielles](https://hub.docker.com/_/php/). Des variantes Debian et Alpine Linux sont fournies pour les architectures populaires. Les variantes Debian sont recommandées.
|
||||
|
||||
Des variantes pour PHP 8.2 et PHP 8.3 sont disponibles. [Parcourir les tags](https://hub.docker.com/r/dunglas/frankenphp/tags).
|
||||
|
||||
## Comment utiliser les images
|
||||
|
||||
Créez un `Dockerfile` dans votre projet :
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
COPY . /app/public
|
||||
```
|
||||
|
||||
Ensuite, exécutez ces commandes pour construire et exécuter l'image Docker :
|
||||
|
||||
```console
|
||||
docker build -t my-php-app .
|
||||
docker run -it --rm --name my-running-app my-php-app
|
||||
```
|
||||
|
||||
## Comment installer plus d'extensions PHP
|
||||
|
||||
Le script [`docker-php-extension-installer`](https://github.com/mlocati/docker-php-extension-installer) est fourni dans l'image de base.
|
||||
Il est facile d'ajouter des extensions PHP supplémentaires :
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# ajoutez des extensions supplémentaires ici :
|
||||
RUN install-php-extensions \
|
||||
pdo_mysql \
|
||||
gd \
|
||||
intl \
|
||||
zip \
|
||||
opcache
|
||||
```
|
||||
|
||||
## Comment installer plus de modules Caddy
|
||||
|
||||
FrankenPHP est construit sur Caddy, et tous les [modules Caddy](https://caddyserver.com/docs/modules/) peuvent être utilisés avec FrankenPHP.
|
||||
|
||||
La manière la plus simple d'installer des modules Caddy personnalisés est d'utiliser [xcaddy](https://github.com/caddyserver/xcaddy):
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp:latest-builder AS builder
|
||||
|
||||
# Copier xcaddy dans l'image du constructeur
|
||||
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy
|
||||
|
||||
# CGO doit être activé pour construire FrankenPHP
|
||||
ENV CGO_ENABLED=1 XCADDY_SETCAP=1 XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'"
|
||||
RUN xcaddy build \
|
||||
--output /usr/local/bin/frankenphp \
|
||||
--with github.com/dunglas/frankenphp=./ \
|
||||
--with github.com/dunglas/frankenphp/caddy=./caddy/ \
|
||||
# Mercure et Vulcain sont inclus dans la construction officielle, mais n'hésitez pas à les retirer
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Ajoutez des modules Caddy supplémentaires ici
|
||||
|
||||
FROM dunglas/frankenphp AS runner
|
||||
|
||||
# Remplacer le binaire officiel par celui contenant vos modules personnalisés
|
||||
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
|
||||
```
|
||||
|
||||
L'image builder fournie par FrankenPHP contient une version compilée de `libphp`.
|
||||
[Les images builder](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder) sont fournies pour toutes les versions de FrankenPHP et PHP, à la fois pour Debian et Alpine.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Si vous utilisez Alpine Linux et Symfony,
|
||||
> vous devrez peut-être [augmenter la taille de pile par défaut](compile.md#using-xcaddy).
|
||||
|
||||
## Activer le mode Worker par défaut
|
||||
|
||||
Définissez la variable d'environnement `FRANKENPHP_CONFIG` pour démarrer FrankenPHP avec un script worker :
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# ...
|
||||
|
||||
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
|
||||
```
|
||||
|
||||
## Utiliser un volume en développement
|
||||
|
||||
Pour développer facilement avec FrankenPHP, montez le répertoire de l'hôte contenant le code source de l'application comme un volume dans le conteneur Docker :
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public -p 80:80 -p 443:443 -p 443:443/udp --tty my-php-app
|
||||
```
|
||||
|
||||
> ![TIP]
|
||||
>
|
||||
> L'option --tty permet d'avoir des logs lisibles par un humain au lieu de logs JSON.
|
||||
|
||||
Avec Docker Compose :
|
||||
|
||||
```yaml
|
||||
# compose.yaml
|
||||
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
# décommentez la ligne suivante si vous souhaitez utiliser un Dockerfile personnalisé
|
||||
#build: .
|
||||
# décommentez la ligne suivante si vous souhaitez exécuter ceci dans un environnement de production
|
||||
# restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- ./:/app/public
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
# commentez la ligne suivante en production, elle permet d'avoir de beaux logs lisibles en dev
|
||||
tty: true
|
||||
|
||||
# Volumes nécessaires pour les certificats et la configuration de Caddy
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
## Exécution en tant qu'utilisateur non-root
|
||||
|
||||
FrankenPHP peut s'exécuter en tant qu'utilisateur non-root dans Docker.
|
||||
|
||||
Voici un exemple de `Dockerfile` le permettant :
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
ARG USER=www-data
|
||||
|
||||
RUN \
|
||||
# Utilisez "adduser -D ${USER}" pour les distributions basées sur Alpine
|
||||
useradd -D ${USER}; \
|
||||
# Ajouter la capacité supplémentaire de se lier aux ports 80 et 443
|
||||
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp; \
|
||||
# Donner l'accès en écriture à /data/caddy et /config/caddy
|
||||
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy;
|
||||
|
||||
USER ${USER}
|
||||
```
|
||||
|
||||
## Mises à jour
|
||||
|
||||
Les images Docker sont construites :
|
||||
|
||||
* lorsqu'une nouvelle version est taguée
|
||||
* tous les jours à 4h UTC, si de nouvelles versions des images officielles PHP sont disponibles
|
||||
|
||||
## Versions de développement
|
||||
|
||||
Les versions de développement sont disponibles dans le dépôt Docker [`dunglas/frankenphp-dev`](https://hub.docker.com/repository/docker/dunglas/frankenphp-dev). Un nouveau build est déclenché chaque fois qu'un commit est poussé sur la branche principale du dépôt GitHub.
|
||||
|
||||
Les tags `latest*` pointent vers la tête de la branche `main`.
|
||||
Les tags sous la forme `sha-<hash-du-commit-git>` sont également disponibles.
|
||||
21
docs/fr/early-hints.md
Normal file
21
docs/fr/early-hints.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Early Hints
|
||||
|
||||
FrankenPHP prend nativement en charge le code de statut [103 Early Hints](https://developer.chrome.com/blog/early-hints/).
|
||||
L'utilisation des Early Hints peut améliorer le temps de chargement de vos pages web de 30 %.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
header('Link: </style.css>; rel=preload; as=style');
|
||||
headers_send(103);
|
||||
|
||||
// vos algorithmes lents et requêtes SQL 🤪
|
||||
|
||||
echo <<<'HTML'
|
||||
<!DOCTYPE html>
|
||||
<title>Hello FrankenPHP</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
HTML;
|
||||
```
|
||||
|
||||
Les Early Hints sont pris en charge à la fois par les modes "standard" et [worker](worker.md).
|
||||
132
docs/fr/embed.md
Normal file
132
docs/fr/embed.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Applications PHP en tant que binaires autonomes
|
||||
|
||||
FrankenPHP a la capacité d'incorporer le code source et les assets des applications PHP dans un binaire statique et autonome.
|
||||
|
||||
Grâce à cette fonctionnalité, les applications PHP peuvent être distribuées en tant que binaires autonomes qui incluent l'application elle-même, l'interpréteur PHP et Caddy, un serveur web de qualité production.
|
||||
|
||||
Pour en savoir plus sur cette fonctionnalité, consultez [la présentation faite par Kévin à la SymfonyCon 2023](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/).
|
||||
|
||||
## Préparer votre application
|
||||
|
||||
Avant de créer le binaire autonome, assurez-vous que votre application est prête à être intégrée.
|
||||
|
||||
Vous devrez probablement :
|
||||
|
||||
* Installer les dépendances de production de l'application
|
||||
* Dumper l'autoloader
|
||||
* Activer le mode production de votre application (si disponible)
|
||||
* Supprimer les fichiers inutiles tels que `.git` ou les tests pour réduire la taille de votre binaire final
|
||||
|
||||
Par exemple, pour une application Symfony, lancez les commandes suivantes :
|
||||
|
||||
```console
|
||||
# Exporter le projet pour se débarrasser de .git/, etc.
|
||||
mkdir $TMPDIR/my-prepared-app
|
||||
git archive HEAD | tar -x -C $TMPDIR/my-prepared-app
|
||||
cd $TMPDIR/my-prepared-app
|
||||
|
||||
# Définir les variables d'environnement appropriées
|
||||
echo APP_ENV=prod > .env.local
|
||||
echo APP_DEBUG=0 >> .env.local
|
||||
|
||||
# Supprimer les tests
|
||||
rm -Rf tests/
|
||||
|
||||
# Installer les dépendances
|
||||
composer install --ignore-platform-reqs --no-dev -a
|
||||
|
||||
# Optimiser le .env
|
||||
composer dump-env prod
|
||||
```
|
||||
|
||||
## Créer un binaire Linux
|
||||
|
||||
La manière la plus simple de créer un binaire Linux est d'utiliser le builder basé sur Docker que nous fournissons.
|
||||
|
||||
1. Créez un fichier nommé `static-build.Dockerfile` dans le répertoire de votre application préparée :
|
||||
|
||||
```dockerfile
|
||||
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder
|
||||
|
||||
# Copy your app
|
||||
WORKDIR /go/src/app/dist/app
|
||||
COPY . .
|
||||
|
||||
# Build the static binary, be sure to select only the PHP extensions you want
|
||||
WORKDIR /go/src/app/
|
||||
RUN EMBED=dist/app/ \
|
||||
PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Certains fichiers `.dockerignore` (par exemple celui fourni par défaut par [Symfony Docker](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))
|
||||
> empêchent la copie du dossier `vendor/` et des fichiers `.env`. Assurez-vous d'ajuster ou de supprimer le fichier `.dockerignore` avant le build.
|
||||
|
||||
2. Construisez:
|
||||
|
||||
```console
|
||||
docker build -t static-app -f static-build.Dockerfile .
|
||||
```
|
||||
|
||||
3. Extrayez le binaire :
|
||||
|
||||
```console
|
||||
docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp
|
||||
```
|
||||
|
||||
Le binaire généré sera nommé `my-app` dans le répertoire courant.
|
||||
|
||||
## Créer un binaire pour d'autres systèmes d'exploitation
|
||||
|
||||
Si vous ne souhaitez pas utiliser Docker, ou souhaitez construire un binaire macOS, utilisez le script shell que nous fournissons :
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
EMBED=/path/to/your/app \
|
||||
PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
Le binaire obtenu est le fichier nommé `frankenphp-<os>-<arch>` dans le répertoire `dist/`.
|
||||
|
||||
## Utiliser le binaire
|
||||
|
||||
C'est tout ! Le fichier `my-app` (ou `dist/frankenphp-<os>-<arch>` sur d'autres systèmes d'exploitation) contient votre application autonome !
|
||||
|
||||
Pour démarrer l'application web, exécutez :
|
||||
|
||||
```console
|
||||
./my-app php-server
|
||||
```
|
||||
|
||||
Si votre application contient un [script worker](worker.md), démarrez le worker avec quelque chose comme :
|
||||
|
||||
```console
|
||||
./my-app php-server --worker public/index.php
|
||||
```
|
||||
|
||||
Pour activer HTTPS (un certificat Let's Encrypt est automatiquement créé), HTTP/2 et HTTP/3, spécifiez le nom de domaine à utiliser :
|
||||
|
||||
```console
|
||||
./my-app php-server --domain localhost
|
||||
```
|
||||
|
||||
Vous pouvez également exécuter les scripts CLI PHP incorporés dans votre binaire :
|
||||
|
||||
```console
|
||||
./my-app php-cli bin/console
|
||||
```
|
||||
|
||||
## Personnaliser la compilation
|
||||
|
||||
[Consultez la documentation sur la compilation statique](static.md) pour voir comment personnaliser le binaire (extensions, version PHP...).
|
||||
|
||||
## Distribuer le binaire
|
||||
|
||||
Sous Linux, le binaire est compressé par défaut à l'aide de [UPX](https://upx.github.io).
|
||||
|
||||
Sous Mac, pour réduire la taille du fichier avant de l'envoyer, vous pouvez le compresser.
|
||||
Nous recommandons `xz`.
|
||||
31
docs/fr/github-actions.md
Normal file
31
docs/fr/github-actions.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Utilisation de GitHub Actions
|
||||
|
||||
Ce dépôt construit et déploie l'image Docker sur [le Hub Docker](https://hub.docker.com/r/dunglas/frankenphp) pour
|
||||
chaque pull request approuvée ou sur votre propre fork une fois configuré.
|
||||
|
||||
## Configuration de GitHub Actions
|
||||
|
||||
Dans les paramètres du dépôt, sous "secrets", ajoutez les secrets suivants :
|
||||
|
||||
- `REGISTRY_LOGIN_SERVER` : Le registre Docker à utiliser (par exemple, `docker.io`).
|
||||
- `REGISTRY_USERNAME` : Le nom d'utilisateur à utiliser pour se connecter au registre (par exemple, `dunglas`).
|
||||
- `REGISTRY_PASSWORD` : Le mot de passe à utiliser pour se connecter au registre (par exemple, une clé d'accès).
|
||||
- `IMAGE_NAME` : Le nom de l'image (par exemple, `dunglas/frankenphp`).
|
||||
|
||||
## Construction et push de l'image
|
||||
|
||||
1. Créez une Pull Request ou poussez vers votre fork.
|
||||
2. GitHub Actions va construire l'image et exécuter tous les tests.
|
||||
3. Si la construction est réussie, l'image sera poussée vers le registre en utilisant le tag `pr-x`, où `x` est le numéro de la PR.
|
||||
|
||||
## Déploiement de l'image
|
||||
|
||||
1. Une fois la Pull Request fusionnée, GitHub Actions exécutera à nouveau les tests et construira une nouvelle image.
|
||||
2. Si la construction est réussie, le tag `main` sera mis à jour dans le registre Docker.
|
||||
|
||||
## Releases
|
||||
|
||||
1. Créez un nouveau tag dans le dépôt.
|
||||
2. GitHub Actions va construire l'image et exécuter tous les tests.
|
||||
3. Si la compilation est réussie, l'image sera poussée vers le registre en utilisant le nom du tag comme tag (par exemple, `v1.2.3` et `v1.2` seront créés).
|
||||
4. Le tag `latest` sera également mis à jour.
|
||||
108
docs/fr/known-issues.md
Normal file
108
docs/fr/known-issues.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Problèmes Connus
|
||||
|
||||
## Fibres
|
||||
|
||||
Appeller de fonctions et mots clefs PHP qui eux-mêmes appellent [cgo](https://go.dev/blog/cgo) dans des [Fibres](https://www.php.net/manual/fr/language.fibers.php) est connu pour provoquer des plantages.
|
||||
|
||||
Ce problème est [en cours de correction par le projet Go](https://github.com/golang/go/issues/62130).
|
||||
|
||||
En attendant, une solution consiste à ne pas utiliser de mots clefs (comme `echo`) et de fonctions (comme `header()`) qui délèguent à Go depuis l'intérieur de fibres.
|
||||
|
||||
Ce code risque de planter car il utilise `echo` dans une fibre :
|
||||
|
||||
```php
|
||||
$fiber = new Fiber(function() {
|
||||
echo 'Dans la fibre'.PHP_EOL;
|
||||
echo 'Toujours dedans'.PHP_EOL;
|
||||
});
|
||||
$fiber->start();
|
||||
```
|
||||
|
||||
A la place, retournez la valeur de la Fibre et utilisez-la à l'extérieur :
|
||||
|
||||
```php
|
||||
$fiber = new Fiber(function() {
|
||||
Fiber::suspend('Dans la fibre'.PHP_EOL));
|
||||
Fiber::suspend('Toujours dedans'.PHP_EOL));
|
||||
});
|
||||
echo $fiber->start();
|
||||
echo $fiber->resume();
|
||||
$fiber->resume();
|
||||
```
|
||||
|
||||
## Extensions PHP non prises en charge
|
||||
|
||||
Les extensions suivantes sont connues pour ne pas être compatibles avec FrankenPHP :
|
||||
|
||||
| Nom | Raison | Alternatives |
|
||||
| ---------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| [imap](https://www.php.net/manual/en/imap.installation.php) | Non thread-safe | [javanile/php-imap2](https://github.com/javanile/php-imap2), [webklex/php-imap](https://github.com/Webklex/php-imap) |
|
||||
| [newrelic](https://docs.newrelic.com/docs/apm/agents/php-agent/getting-started/introduction-new-relic-php/)| Non thread-safe | - |
|
||||
|
||||
## Extensions PHP boguées
|
||||
|
||||
Les extensions suivantes ont des bugs connus ou des comportements inattendus lorsqu'elles sont utilisées avec FrankenPHP :
|
||||
|
||||
| Nom | Problème |
|
||||
|---------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [Tideways](https://tideways.com/) | En mode worker, l'extension Tideways [empêche les scripts workers de se terminer correctement ou consomme 100% du CPU](https://github.com/dunglas/frankenphp/issues/578#issuecomment-1966620351). Ce problème a été signalé à Tideways. |
|
||||
| [ext-openssl](https://www.php.net/manual/fr/book.openssl.php) | Lors de l'utilisation d'une version statique de FrankenPHP (construite avec la libc musl), l'extension OpenSSL peut planter sous de fortes charges. Une solution consiste à utiliser une version liée dynamiquement (comme celle utilisée dans les images Docker). Ce bogue est [suivi par PHP](https://github.com/php/php-src/issues/13648). |
|
||||
|
||||
## get_browser
|
||||
|
||||
La fonction [get_browser()](https://www.php.net/manual/fr/function.get-browser.php) semble avoir de mauvaises performances après un certain temps. Une solution est de mettre en cache (par exemple, avec [APCu](https://www.php.net/manual/en/book.apcu.php)) les résultats par agent utilisateur, car ils sont statiques.
|
||||
|
||||
## Binaire autonome et images Docker basées sur Alpine
|
||||
|
||||
Le binaire autonome et les images docker basées sur Alpine (`dunglas/frankenphp:*-alpine`) utilisent [musl libc](https://musl.libc.org/) au lieu de [glibc et ses amis](https://www.etalabs.net/compare_libcs.html), pour garder une taille de binaire plus petite. Cela peut entraîner des problèmes de compatibilité. En particulier, le drapeau glob `GLOB_BRACE` n'est [pas disponible](https://www.php.net/manual/fr/function.glob.php).
|
||||
|
||||
## Utilisation de `https://127.0.0.1` avec Docker
|
||||
|
||||
Par défaut, FrankenPHP génère un certificat TLS pour `localhost`.
|
||||
C'est l'option est la plus simple et est recommandée pour le développement local.
|
||||
|
||||
Si vous voulez vraiment utiliser `127.0.0.1` comme hôte, il est possible de configure FrankenPHP pour générer un certificat pour cela en définissant le nom du serveur à `127.0.0.1`.
|
||||
|
||||
Malheureusement, cela ne suffit pas lors de l'utilisation de Docker à cause de [son système de gestion des réseaux](https://docs.docker.com/network/).
|
||||
Vous obtiendrez une erreur TLS similaire à `curl: (35) LibreSSL/3.3.6: error:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error`.
|
||||
|
||||
Si vous utilisez Linux, une solution est d'utiliser [le pilote de réseau "hôte"](https://docs.docker.com/network/network-tutorial-host/) :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
--network host \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Le pilote de réseau "hôte" n'est pas pris en charge sur Mac et Windows. Sur ces plateformes, vous devrez deviner l'adresse IP du conteneur et l'inclure dans les noms de serveur.
|
||||
|
||||
Exécutez la commande `docker network inspect bridge` et inpectez la clef `Containers` pour identifier la dernière adresse IP attribuée sous la clef `IPv4Address`, puis incrémentez-la de un. Si aucun conteneur n'est en cours d'exécution, la première adresse IP attribuée est généralement `172.17.0.2`.
|
||||
|
||||
Ensuite, incluez ceci dans la variable d'environnement `SERVER_NAME` :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1, 172.17.0.3" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
> ![CAUTION]
|
||||
>
|
||||
> Assurez-vous de remplacer `172.17.0.3` par l'IP qui sera attribuée à votre conteneur.
|
||||
|
||||
Vous devriez maintenant pouvoir accéder à `https://127.0.0.1` depuis la machine hôte.
|
||||
|
||||
Si ce n'est pas le cas, lancez FrankenPHP en mode debug pour essayer de comprendre le problème :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e CADDY_GLOBAL_OPTIONS="debug" \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
76
docs/fr/laravel.md
Normal file
76
docs/fr/laravel.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Laravel
|
||||
|
||||
## Docker
|
||||
|
||||
Déployer une application web [Laravel](https://laravel.com) avec FrankenPHP est très facile.
|
||||
Il suffit de monter le projet dans le répertoire `/app` de l'image Docker officielle.
|
||||
|
||||
Exécutez cette commande depuis le répertoire principal de votre application Laravel :
|
||||
|
||||
```console
|
||||
docker run -p 80:80 -p 443:443 -p 443:443/udp -v $PWD:/app dunglas/frankenphp
|
||||
```
|
||||
|
||||
Et profitez !
|
||||
|
||||
## Installation Locale
|
||||
|
||||
Vous pouvez également exécuter vos projets Laravel avec FrankenPHP depuis votre machine locale :
|
||||
|
||||
1. [Téléchargez le binaire correspondant à votre système](https://github.com/dunglas/frankenphp/releases)
|
||||
2. Ajoutez la configuration suivante dans un fichier nommé `Caddyfile` placé dans le répertoire racine de votre projet Laravel :
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
# Le nom de domaine de votre serveur
|
||||
localhost {
|
||||
# Définir le répertoire racine sur le dossier public/
|
||||
root * public/
|
||||
# Autoriser la compression (optionnel)
|
||||
encode zstd br gzip
|
||||
# Exécuter les scripts PHP du dossier public/ et servir les assets
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
3. Démarrez FrankenPHP depuis le répertoire racine de votre projet Laravel : `./frankenphp run`
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
Octane peut être installé via le gestionnaire de paquets Composer :
|
||||
|
||||
```console
|
||||
composer require laravel/octane
|
||||
```
|
||||
|
||||
Après avoir installé Octane, vous pouvez exécuter la commande Artisan `octane:install`, qui installera le fichier de configuration d'Octane dans votre application :
|
||||
|
||||
```console
|
||||
php artisan octane:install --server=frankenphp
|
||||
```
|
||||
|
||||
Le serveur Octane peut être démarré via la commande Artisan `octane:start`.
|
||||
|
||||
```console
|
||||
php artisan octane:start
|
||||
```
|
||||
|
||||
La commande `octane:start` peut prendre les options suivantes :
|
||||
|
||||
* `--host` : L'adresse IP à laquelle le serveur doit se lier (par défaut : `127.0.0.1`)
|
||||
* `--port` : Le port sur lequel le serveur doit être disponible (par défaut : `8000`)
|
||||
* `--admin-port` : Le port sur lequel le serveur administratif doit être disponible (par défaut : `2019`)
|
||||
* `--workers` : Le nombre de workers qui doivent être disponibles pour traiter les requêtes (par défaut : `auto`)
|
||||
* `--max-requests` : Le nombre de requêtes à traiter avant de recharger le serveur (par défaut : `500`)
|
||||
* `--caddyfile` : Le chemin vers le fichier `Caddyfile` de FrankenPHP
|
||||
* `--https` : Activer HTTPS, HTTP/2, et HTTP/3, et générer automatiquement et renouveler les certificats
|
||||
* `--http-redirect` : Activer la redirection HTTP vers HTTPS (uniquement activé si --https est passé)
|
||||
* `--watch` : Recharger automatiquement le serveur lorsque l'application est modifiée
|
||||
* `--poll` : Utiliser le sondage du système de fichiers pendant la surveillance pour surveiller les fichiers sur un réseau
|
||||
* `--log-level` : Enregistrer les messages au niveau de journalisation spécifié ou au-dessus
|
||||
|
||||
En savoir plus sur Laravel Octane [dans sa documentation officielle](https://laravel.com/docs/octane).
|
||||
12
docs/fr/mercure.md
Normal file
12
docs/fr/mercure.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Temps Réel
|
||||
|
||||
FrankenPHP est livré avec un hub [Mercure](https://mercure.rocks) intégré.
|
||||
Mercure permet de pousser des événements en temps réel vers tous les appareils connectés : ils recevront un événement JavaScript instantanément.
|
||||
|
||||
Aucune bibliothèque JS ou SDK requis !
|
||||
|
||||

|
||||
|
||||
Pour activer le hub Mercure, mettez à jour le `Caddyfile` comme décrit [sur le site de Mercure](https://mercure.rocks/docs/hub/config).
|
||||
|
||||
Pour pousser des mises à jour Mercure depuis votre code, nous recommandons le [Composant Mercure de Symfony](https://symfony.com/components/Mercure) (vous n'avez pas besoin du framework full stack Symfony pour l'utiliser).
|
||||
139
docs/fr/production.md
Normal file
139
docs/fr/production.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Déploiement en Production
|
||||
|
||||
Dans ce tutoriel, nous apprendrons comment déployer une application PHP sur un serveur unique en utilisant Docker Compose.
|
||||
|
||||
Si vous utilisez Symfony, lisez plutôt la page de documentation "[Déployer en production](https://github.com/dunglas/symfony-docker/blob/main/docs/production.md)" du projet Symfony Docker (qui utilise FrankenPHP).
|
||||
|
||||
Si vous utilisez API Platform (qui utilise également FrankenPHP), référez-vous à [la documentation de déploiement du framework](https://api-platform.com/docs/deployment/).
|
||||
|
||||
## Préparer votre application
|
||||
|
||||
Tout d'abord, créez un `Dockerfile` dans le répertoire racine de votre projet PHP :
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# Assurez-vous de remplacer "your-domain-name.example.com" par votre nom de domaine
|
||||
ENV SERVER_NAME=your-domain-name.example.com
|
||||
# Si vous souhaitez désactiver HTTPS, utilisez cette valeur à la place :
|
||||
#ENV SERVER_NAME=:80
|
||||
|
||||
# Activer les paramètres de production de PHP
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Copiez les fichiers PHP de votre projet dans le répertoire public
|
||||
COPY . /app/public
|
||||
# Si vous utilisez Symfony ou Laravel, vous devez copier l'intégralité du projet à la place :
|
||||
#COPY . /app
|
||||
```
|
||||
|
||||
Consultez "[Construire une image Docker personnalisée](docker.md)" pour plus de détails et d'options,
|
||||
et pour apprendre à personnaliser la configuration, installer des extensions PHP et des modules Caddy.
|
||||
|
||||
Si votre projet utilise Composer, assurez-vous de l'inclure dans l'image Docker et d'installer vos dépendances.
|
||||
|
||||
Ensuite, ajoutez un fichier `compose.yaml` :
|
||||
|
||||
```yaml
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
|
||||
# Volumes nécessaires pour les certificats et la configuration de Caddy
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Les exemples précédents sont destinés à une utilisation en production.
|
||||
> En développement, vous pourriez vouloir utiliser un volume, une configuration PHP différente et une valeur différente pour la variable d'environnement `SERVER_NAME`.
|
||||
>
|
||||
> Jetez un œil au projet [Symfony Docker](https://github.com/dunglas/symfony-docker)
|
||||
> (qui utilise FrankenPHP) pour un exemple plus avancé utilisant des images multi-étapes,
|
||||
> Composer, des extensions PHP supplémentaires, etc.
|
||||
|
||||
Pour finir, si vous utilisez Git, commitez ces fichiers et poussez-les.
|
||||
|
||||
## Préparer un serveur
|
||||
|
||||
Pour déployer votre application en production, vous avez besoin d'un serveur.
|
||||
Dans ce tutoriel, nous utiliserons une machine virtuelle fournie par DigitalOcean, mais n'importe quel serveur Linux peut fonctionner.
|
||||
Si vous avez déjà un serveur Linux avec Docker installé, vous pouvez passer directement à [la section suivante](#configurer-un-nom-de-domaine).
|
||||
|
||||
Sinon, utilisez [ce lien affilié](https://m.do.co/c/5d8aabe3ab80) pour obtenir 200$ de crédit gratuit, créez un compte, puis cliquez sur "Créer un Droplet".
|
||||
Ensuite, cliquez sur l'onglet "Marketplace" sous la section "Choisir une image" et recherchez l'application nommée "Docker".
|
||||
Cela provisionnera un serveur Ubuntu avec les dernières versions de Docker et Docker Compose déjà installées !
|
||||
|
||||
Pour des fins de test, les plans les moins chers seront suffisants.
|
||||
Pour une utilisation en production réelle, vous voudrez probablement choisir un plan dans la section "General Usage" pour répondre à vos besoins.
|
||||
|
||||

|
||||
|
||||
Vous pouvez conserver les paramètres par défaut pour les autres paramètres, ou les ajuster selon vos besoins.
|
||||
N'oubliez pas d'ajouter votre clé SSH ou de créer un mot de passe puis appuyez sur le bouton "Finalize and create".
|
||||
|
||||
Ensuite, attendez quelques secondes pendant que votre Droplet est en cours de provisionnement.
|
||||
Lorsque votre Droplet est prêt, utilisez SSH pour vous connecter :
|
||||
|
||||
```console
|
||||
ssh root@<droplet-ip>
|
||||
```
|
||||
|
||||
## Configurer un nom de domaine
|
||||
|
||||
Dans la plupart des cas, vous souhaiterez associer un nom de domaine à votre site.
|
||||
Si vous ne possédez pas encore de nom de domaine, vous devrez en acheter un via un registraire.
|
||||
|
||||
Ensuite, créez un enregistrement DNS de type `A` pour votre nom de domaine pointant vers l'adresse IP de votre serveur :
|
||||
|
||||
```dns
|
||||
your-domain-name.example.com. IN A 207.154.233.113
|
||||
```
|
||||
|
||||
Exemple avec le service DigitalOcean Domains ("Networking" > "Domains") :
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Let's Encrypt, le service utilisé par défaut par FrankenPHP pour générer automatiquement un certificat TLS, ne prend pas en charge l'utilisation d'adresses IP nues. L'utilisation d'un nom de domaine est obligatoire pour utiliser Let's Encrypt.
|
||||
|
||||
## Déploiement
|
||||
|
||||
Copiez votre projet sur le serveur en utilisant `git clone`, `scp`, ou tout autre outil qui pourrait répondre à votre besoin.
|
||||
Si vous utilisez GitHub, vous voudrez peut-être utiliser [une clef de déploiement](https://docs.github.com/en/free-pro-team@latest/developers/overview/managing-deploy-keys#deploy-keys).
|
||||
Les clés de déploiement sont également [prises en charge par GitLab](https://docs.gitlab.com/ee/user/project/deploy_keys/).
|
||||
|
||||
Exemple avec Git :
|
||||
|
||||
```console
|
||||
git clone git@github.com:<username>/<project-name>.git
|
||||
```
|
||||
|
||||
Accédez au répertoire contenant votre projet (`<project-name>`), et démarrez l'application en mode production :
|
||||
|
||||
```console
|
||||
docker compose up -d --wait
|
||||
```
|
||||
|
||||
Votre serveur est opérationnel, et un certificat HTTPS a été automatiquement généré pour vous.
|
||||
Rendez-vous sur `https://your-domain-name.example.com` !
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Docker peut avoir une couche de cache, assurez-vous d'avoir la bonne version de build pour chaque déploiement ou reconstruisez votre projet avec l'option `--no-cache` pour éviter les problèmes de cache.
|
||||
|
||||
## Déploiement sur Plusieurs Nœuds
|
||||
|
||||
Si vous souhaitez déployer votre application sur un cluster de machines, vous pouvez utiliser [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/), qui est compatible avec les fichiers Compose fournis.
|
||||
Pour un déploiement sur Kubernetes, jetez un œil au [Helm chart fourni avec API Platform](https://api-platform.com/docs/deployment/kubernetes/), qui utilise FrankenPHP.
|
||||
80
docs/fr/static.md
Normal file
80
docs/fr/static.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Créer un binaire statique
|
||||
|
||||
Au lieu d'utiliser une installation locale de la bibliothèque PHP, il est possible de créer un build statique de FrankenPHP grâce à l'excellent projet [static-php-cli](https://github.com/crazywhalecc/static-php-cli) (malgré son nom, ce projet prend en charge tous les SAPIs, pas seulement CLI).
|
||||
|
||||
Avec cette méthode, un binaire portable unique contiendra l'interpréteur PHP, le serveur web Caddy et FrankenPHP !
|
||||
|
||||
FrankenPHP permet également [d'embarquer l'application PHP dans le binaire statique](embed.md).
|
||||
|
||||
## Linux
|
||||
|
||||
Nous fournissons une image Docker pour créer un binaire statique pour Linux :
|
||||
|
||||
```console
|
||||
docker buildx bake --load static-builder
|
||||
docker cp $(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp ; docker rm static-builder
|
||||
```
|
||||
|
||||
Le binaire statique résultant est nommé `frankenphp`, et il est disponible dans le répertoire courant.
|
||||
|
||||
Si vous souhaitez construire le binaire statique sans Docker, regardez les instructions pour macOS, qui fonctionnent également pour Linux.
|
||||
|
||||
### Extensions personnalisées
|
||||
|
||||
Par défaut, la plupart des extensions PHP populaires sont compilées.
|
||||
|
||||
Pour réduire la taille du binaire et diminuer la surface d'attaque, vous pouvez choisir la liste des extensions à construire en utilisant l'argument Docker `PHP_EXTENSIONS`.
|
||||
|
||||
Par exemple, exécutez la commande suivante pour ne construire que l'extension `opcache` :
|
||||
|
||||
```console
|
||||
docker buildx bake --load --set static-builder.args.PHP_EXTENSIONS=opcache,pdo_sqlite static-builder
|
||||
# ...
|
||||
```
|
||||
|
||||
Pour ajouter des bibliothèques permettant des fonctionnalités supplémentaires aux extensions que vous avez activées, vous pouvez utiliser l'argument Docker `PHP_EXTENSION_LIBS` :
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder.args.PHP_EXTENSIONS=gd \
|
||||
--set static-builder.args.PHP_EXTENSION_LIBS=libjpeg,libwebp \
|
||||
static-builder
|
||||
```
|
||||
|
||||
Voir aussi comment [personnaliser la construction](#personnalisation-de-la-construction)
|
||||
|
||||
### Jeton GitHub
|
||||
|
||||
Si vous atteignez la limite de taux d'appels de l'API GitHub, définissez un jeton d'accès personnel GitHub dans une variable d'environnement nommée `GITHUB_TOKEN` :
|
||||
|
||||
```console
|
||||
GITHUB_TOKEN="xxx" docker --load buildx bake static-builder
|
||||
# ...
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
Exécutez le script suivant pour créer un binaire statique pour macOS (vous devez avoir [Homebrew](https://brew.sh/) d'installé) :
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
Note : ce script fonctionne également sur Linux (et probablement sur d'autres Unix) et est utilisé en interne par le builder statique basé sur Docker que nous fournissons.
|
||||
|
||||
## Personnalisation de la construction
|
||||
|
||||
Les variables d'environnement suivantes peuvent être transmises à `docker build` et au script `build-static.sh` pour personnaliser la construction statique :
|
||||
|
||||
* `FRANKENPHP_VERSION` : la version de FrankenPHP à utiliser
|
||||
* `PHP_VERSION` : la version de PHP à utiliser
|
||||
* `PHP_EXTENSIONS` : les extensions PHP à construire ([liste des extensions prises en charge](https://static-php.dev/en/guide/extensions.html))
|
||||
* `PHP_EXTENSION_LIBS` : bibliothèques supplémentaires à construire qui ajoutent des fonctionnalités aux extensions
|
||||
* `EMBED` : chemin de l'application PHP à intégrer dans le binaire
|
||||
* `CLEAN` : lorsque défini, `libphp` et toutes ses dépendances sont construites à partir de zéro (pas de cache)
|
||||
* `DEBUG_SYMBOLS` : lorsque défini, les symboles de débogage ne seront pas supprimés et seront ajoutés dans le binaire
|
||||
* `NO_COMPRESS`: ne pas compresser le binaire avec UPX
|
||||
* `RELEASE` : (uniquement pour les mainteneurs) lorsque défini, le binaire résultant sera uploadé sur GitHub
|
||||
119
docs/fr/worker.md
Normal file
119
docs/fr/worker.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Utilisation des workers FrankenPHP
|
||||
|
||||
Démarrez votre application une fois et gardez-la en mémoire.
|
||||
FrankenPHP traitera les requêtes entrantes en quelques millisecondes.
|
||||
|
||||
## Démarrage des scripts workers
|
||||
|
||||
### Docker
|
||||
|
||||
Définissez la valeur de la variable d'environnement `FRANKENPHP_CONFIG` à `worker /path/to/your/worker/script.php` :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker /app/path/to/your/worker/script.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### Binaire autonome
|
||||
|
||||
Utilisez l'option --worker de la commande php-server pour servir le contenu du répertoire courant en utilisant un worker :
|
||||
|
||||
```console
|
||||
./frankenphp php-server --worker /path/to/your/worker/script.php
|
||||
```
|
||||
|
||||
Si votre application PHP est [intégrée dans le binaire](embed.md), vous pouvez également ajouter un `Caddyfile` personnalisé dans le répertoire racine de l'application.
|
||||
Il sera utilisé automatiquement.
|
||||
|
||||
## Runtime Symfony
|
||||
|
||||
Le mode worker de FrankenPHP est pris en charge par le [Composant Runtime de Symfony](https://symfony.com/doc/current/components/runtime.html).
|
||||
Pour démarrer une application Symfony dans un worker, installez le package FrankenPHP de [PHP Runtime](https://github.com/php-runtime/runtime) :
|
||||
|
||||
```console
|
||||
composer require runtime/frankenphp-symfony
|
||||
```
|
||||
|
||||
Démarrez votre serveur d'application en définissant la variable d'environnement `APP_RUNTIME` pour utiliser le Runtime Symfony de FrankenPHP :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
Voir [la documentation dédiée](laravel.md#laravel-octane).
|
||||
|
||||
## Applications Personnalisées
|
||||
|
||||
L'exemple suivant montre comment créer votre propre script worker sans dépendre d'une bibliothèque tierce :
|
||||
|
||||
```php
|
||||
<?php
|
||||
// public/index.php
|
||||
|
||||
// Empêcher la terminaison du script worker lorsqu'une connexion client est interrompue
|
||||
ignore_user_abort(true);
|
||||
|
||||
// Démarrer votre application
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$myApp = new \App\Kernel();
|
||||
$myApp->boot();
|
||||
|
||||
// En dehors de la boucle pour de meilleures performances (moins de travail effectué)
|
||||
$handler = static function () use ($myApp) {
|
||||
// Appelé lorsqu'une requête est reçue,
|
||||
// les superglobales, php://input, etc., sont réinitialisés
|
||||
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
};
|
||||
|
||||
for($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbRequests < ((int)$_SERVER['MAX_REQUESTS'])) && $running; ++$nbRequests) {
|
||||
$running = \frankenphp_handle_request($handler);
|
||||
|
||||
// Faire quelque chose après l'envoi de la réponse HTTP
|
||||
$myApp->terminate();
|
||||
|
||||
// Exécuter le ramasse-miettes pour réduire les chances qu'il soit déclenché au milieu de la génération d'une page
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
// Nettoyage
|
||||
$myApp->shutdown();
|
||||
```
|
||||
|
||||
Ensuite, démarrez votre application et utilisez la variable d'environnement `FRANKENPHP_CONFIG` pour configurer votre worker :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Par défaut, 2 workers par CPU sont démarrés.
|
||||
Vous pouvez également configurer le nombre de workers à démarrer :
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### Redémarrer le worker après un certain nombre de requêtes
|
||||
|
||||
Comme PHP n'a pas été initialement conçu pour des processus de longue durée, de nombreuses bibliothèques et codes anciens présentent encore des fuites de mémoire.
|
||||
Une solution pour utiliser ce type de code en mode worker est de redémarrer le script worker après avoir traité un certain nombre de requêtes :
|
||||
|
||||
Le code du worker précédent permet de configurer un nombre maximal de requêtes à traiter en définissant une variable d'environnement nommée `MAX_REQUESTS`.
|
||||
@@ -12,15 +12,15 @@ In the repository settings, under secrets, add the following secrets:
|
||||
- `REGISTRY_PASSWORD`: The password to use to login to the registry (e.g. an access key).
|
||||
- `IMAGE_NAME`: The name of the image (e.g. `dunglas/frankenphp`).
|
||||
|
||||
## Building and pushing the image
|
||||
## Building and Pushing the Image
|
||||
|
||||
1. Create a pull request or push to your fork.
|
||||
1. Create a Pull Request or push to your fork.
|
||||
2. GitHub Actions will build the image and run any tests.
|
||||
3. If the build is successful, the image will be pushed to the registry using the `pr-x`, where `x` is the PR number, as the tag.
|
||||
|
||||
## Deploying the image
|
||||
## Deploying the Image
|
||||
|
||||
1. Once the pull request is merged, GitHub Actions will again run the tests and build a new image.
|
||||
1. Once the Pull Request is merged, GitHub Actions will again run the tests and build a new image.
|
||||
2. If the build is successful, the `main` tag will be updated in the Docker registry.
|
||||
|
||||
## Releases
|
||||
|
||||
@@ -34,13 +34,23 @@ $fiber->resume();
|
||||
|
||||
The following extensions are known not to be compatible with FrankenPHP:
|
||||
|
||||
| Name | Reason | Alternatives |
|
||||
| ----------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| [imap](https://www.php.net/manual/en/imap.installation.php) | Not thread-safe | [javanile/php-imap2](https://github.com/javanile/php-imap2), [webklex/php-imap](https://github.com/Webklex/php-imap) |
|
||||
| Name | Reason | Alternatives |
|
||||
| ---------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| [imap](https://www.php.net/manual/en/imap.installation.php) | Not thread-safe | [javanile/php-imap2](https://github.com/javanile/php-imap2), [webklex/php-imap](https://github.com/Webklex/php-imap) |
|
||||
| [newrelic](https://docs.newrelic.com/docs/apm/agents/php-agent/getting-started/introduction-new-relic-php/)| Not thread-safe | - |
|
||||
|
||||
## Buggy PHP Extensions
|
||||
|
||||
The following extensions have known bugs and unexpected behaviors when used with FrankenPHP:
|
||||
|
||||
| Name | Problem |
|
||||
|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [Tideways](https://tideways.com/) | In worker mode, the Tideways extension [prevents worker scripts from finishing properly](https://github.com/dunglas/frankenphp/issues/578#issuecomment-1966620351) or consumes 100% of the CPU. This has been reported to Tideways. |
|
||||
| [ext-openssl](https://www.php.net/manual/en/book.openssl.php) | When using a static build of FrankenPHP (built with the musl libc), the OpenSSL extension may crash under heavy loads. A workaround is to use a dynamically linked build (like the one used in Docker images). This bug is [being tracked by PHP](https://github.com/php/php-src/issues/13648). |
|
||||
|
||||
## get_browser
|
||||
|
||||
The [get_browser()](https://www.php.net/manual/en/function.get-browser.php) function seems to perform badly after a while. A workaround is to cache (e.g. with APCU) the results per User Agent, as they are static.
|
||||
The [get_browser()](https://www.php.net/manual/en/function.get-browser.php) function seems to perform badly after a while. A workaround is to cache (e.g. with [APCu](https://www.php.net/manual/en/book.apcu.php)) the results per User Agent, as they are static.
|
||||
|
||||
## Standalone Binary and Alpine-based Docker Images
|
||||
|
||||
@@ -80,7 +90,7 @@ docker run \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
> ![CAUTION]
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Be sure to replace `172.17.0.3` with the IP that will be assigned to your container.
|
||||
|
||||
@@ -90,9 +100,41 @@ If that's not the case, start FrankenPHP in debug mode to try to figure out the
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e CADDY_GLOBAL_OPTIONS="debug"
|
||||
-e CADDY_GLOBAL_OPTIONS="debug" \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## Composer Scripts Referencing `@php`
|
||||
|
||||
[Composer scripts](https://getcomposer.org/doc/articles/scripts.md) may want to execute a PHP binary for some tasks, e.g. in [a Laravel project](laravel.md) to run `@php artisan package:discover --ansi`. This [currently fails](https://github.com/dunglas/frankenphp/issues/483#issuecomment-1899890915) for two reasons:
|
||||
|
||||
* Composer does not know how to call the FrankenPHP binary;
|
||||
* Composer may add PHP settings using the `-d` flag in the command, which FrankenPHP does not yet support.
|
||||
|
||||
As a workaround, we can create a shell script in `/usr/local/bin/php` which strips the unsupported parameters and then calls FrankenPHP:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
args=("$@")
|
||||
index=0
|
||||
for i in "$@"
|
||||
do
|
||||
if [ "$i" == "-d" ]; then
|
||||
unset 'args[$index]'
|
||||
unset 'args[$index+1]'
|
||||
fi
|
||||
index=$((index+1))
|
||||
done
|
||||
|
||||
/usr/local/bin/frankenphp php-cli ${args[@]}
|
||||
```
|
||||
|
||||
Then set the environment variable `PHP_BINARY` to the path of our php script and composer should pass:
|
||||
|
||||
```bash
|
||||
export PHP_BINARY=/usr/local/bin/php
|
||||
composer install
|
||||
```
|
||||
|
||||
@@ -27,15 +27,12 @@ Alternatively, you can run your Laravel projects with FrankenPHP from your local
|
||||
|
||||
# The domain name of your server
|
||||
localhost {
|
||||
# Set the webroot to the public/ dir
|
||||
# Set the webroot to the public/ directory
|
||||
root * public/
|
||||
# Enable compression (optional)
|
||||
encode zstd br gzip
|
||||
# Execute PHP files in the current directory and serve assets
|
||||
php_server {
|
||||
# Required for the public/storage/ dir
|
||||
resolve_root_symlink
|
||||
}
|
||||
# Execute PHP files from the public/ directory and serve assets
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
@@ -70,7 +67,7 @@ The `octane:start` command can take the following options:
|
||||
* `--max-requests`: The number of requests to process before reloading the server (default: `500`)
|
||||
* `--caddyfile`: The path to the FrankenPHP `Caddyfile` file
|
||||
* `--https`: Enable HTTPS, HTTP/2, and HTTP/3, and automatically generate and renew certificates
|
||||
* --http-redirect : Enable HTTP to HTTPS redirection (only enabled if --https is passed)
|
||||
* `--http-redirect`: Enable HTTP to HTTPS redirection (only enabled if --https is passed)
|
||||
* `--watch`: Automatically reload the server when the application is modified
|
||||
* `--poll`: Use file system polling while watching in order to watch files over a network
|
||||
* `--log-level`: Log messages at or above the specified log level
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Real-time
|
||||
|
||||
FrankenPHP comes with a built-in Mercure hub!
|
||||
FrankenPHP comes with a built-in [Mercure](https://mercure.rocks) hub!
|
||||
Mercure allows to push events in real-time to all the connected devices: they will receive a JavaScript event instantly.
|
||||
|
||||
No JS library or SDK required!
|
||||
|
||||
@@ -54,7 +54,8 @@ volumes:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> [!NOTE]
|
||||
>
|
||||
> The previous examples are intended for production usage.
|
||||
> In development, you may want to use a volume, a different PHP configuration and a different value for the `SERVER_NAME` environment variable.
|
||||
>
|
||||
@@ -104,7 +105,8 @@ Example with the DigitalOcean Domains service ("Networking" > "Domains"):
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
> [!NOTE]
|
||||
>
|
||||
> Let's Encrypt, the service used by default by FrankenPHP to automatically generate a TLS certificate doesn't support using bare IP addresses. Using a domain name is mandatory to use Let's Encrypt.
|
||||
|
||||
## Deploying
|
||||
@@ -129,10 +131,11 @@ Your server is up and running, and a HTTPS certificate has been automatically ge
|
||||
Go to `https://your-domain-name.example.com` and enjoy!
|
||||
|
||||
> [!CAUTION]
|
||||
> Docker can have a cache layer, make sure you have the right build for each deployment or rebuild your project with --no-cache option to avoid cache issue.
|
||||
>
|
||||
> Docker can have a cache layer, make sure you have the right build for each deployment or rebuild your project with `--no-cache` option to avoid cache issue.
|
||||
|
||||
## Deploying on Multiple Nodes
|
||||
|
||||
If you want to deploy your app on a cluster of machines, you can use [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/),
|
||||
which is compatible with the provided Compose files.
|
||||
To deploy on Kubernetes, take a look at [the Helm chart provided with API Platform](https://api-platform.com/docs/deployment/kubernetes/), which can be easily adapted for use with Symfony Docker.
|
||||
To deploy on Kubernetes, take a look at [the Helm chart provided with API Platform](https://api-platform.com/docs/deployment/kubernetes/), which uses FrankenPHP.
|
||||
|
||||
@@ -43,7 +43,7 @@ docker buildx bake \
|
||||
static-builder
|
||||
```
|
||||
|
||||
See also: [customizing the build](#customizing-the-build)
|
||||
See also how to [customize the build](#customizing-the-build)
|
||||
|
||||
### GitHub Token
|
||||
|
||||
@@ -74,8 +74,9 @@ script to customize the static build:
|
||||
* `FRANKENPHP_VERSION`: the version of FrankenPHP to use
|
||||
* `PHP_VERSION`: the version of PHP to use
|
||||
* `PHP_EXTENSIONS`: the PHP extensions to build ([list of supported extensions](https://static-php.dev/en/guide/extensions.html))
|
||||
* `PHP_EXTENSION_LIBS`: extra libraries to build that add extra features to the extensions
|
||||
* `PHP_EXTENSION_LIBS`: extra libraries to build that add features to the extensions
|
||||
* `EMBED`: path of the PHP application to embed in the binary
|
||||
* `CLEAN`: when set, libphp and all its dependencies are built from scratch (no cache)
|
||||
* `NO_COMPRESS`: don't compress the resulting binary using UPX
|
||||
* `DEBUG_SYMBOLS`: when set, debug-symbols will not be stripped and will be added within the binary
|
||||
* `RELEASE`: (maintainers only) when set, the resulting binary will be uploaded on GitHub
|
||||
|
||||
203
docs/tr/CONTRIBUTING.md
Normal file
203
docs/tr/CONTRIBUTING.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Katkıda Bulunmak
|
||||
|
||||
## PHP Derleme
|
||||
|
||||
### Docker ile (Linux)
|
||||
|
||||
Geliştirme Ortamı için Docker İmajını Oluşturun:
|
||||
|
||||
```console
|
||||
docker build -t frankenphp-dev -f dev.Dockerfile .
|
||||
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -p 443:443/udp -v $PWD:/go/src/app -it frankenphp-dev
|
||||
```
|
||||
|
||||
İmaj genel geliştirme araçlarını (Go, GDB, Valgrind, Neovim...) içerir.
|
||||
|
||||
Docker sürümü 23.0'dan düşükse, derleme dockerignore [pattern issue](https://github.com/moby/moby/pull/42676) tarafından başarısız olur. Dizinleri `.dockerignore` dosyasına ekleyin.
|
||||
|
||||
```patch
|
||||
!testdata/*.php
|
||||
!testdata/*.txt
|
||||
+!caddy
|
||||
+!C-Thread-Pool
|
||||
+!internal
|
||||
```
|
||||
|
||||
### Docker olmadan (Linux ve macOS)
|
||||
|
||||
[Kaynaklardan derlemek için talimatları izleyin](https://frankenphp.dev/docs/compile/) ve `--debug` yapılandırma seçeneğini geçirin.
|
||||
|
||||
## Test senaryolarını çalıştırma
|
||||
|
||||
```console
|
||||
go test -race -v ./...
|
||||
```
|
||||
|
||||
## Caddy modülü
|
||||
|
||||
FrankenPHP Caddy modülü ile Caddy'yi oluşturun:
|
||||
|
||||
```console
|
||||
cd caddy/frankenphp/
|
||||
go build
|
||||
cd ../../
|
||||
```
|
||||
|
||||
Caddy'yi FrankenPHP Caddy modülü ile çalıştırın:
|
||||
|
||||
```console
|
||||
cd testdata/
|
||||
../caddy/frankenphp/frankenphp run
|
||||
```
|
||||
|
||||
Sunucu `127.0.0.1:8080` adresini dinliyor:
|
||||
|
||||
```console
|
||||
curl -vk https://localhost/phpinfo.php
|
||||
```
|
||||
|
||||
## Minimal test sunucusu
|
||||
|
||||
Minimal test sunucusunu oluşturun:
|
||||
|
||||
```console
|
||||
cd internal/testserver/
|
||||
go build
|
||||
cd ../../
|
||||
```
|
||||
|
||||
Test sunucusunu çalıştırın:
|
||||
|
||||
```console
|
||||
cd testdata/
|
||||
../internal/testserver/testserver
|
||||
```
|
||||
|
||||
Sunucu `127.0.0.1:8080` adresini dinliyor:
|
||||
|
||||
```console
|
||||
curl -v http://127.0.0.1:8080/phpinfo.php
|
||||
```
|
||||
|
||||
## Docker İmajlarını Yerel Olarak Oluşturma
|
||||
|
||||
Bake (pişirme) planını yazdırın:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --print
|
||||
```
|
||||
|
||||
Yerel olarak amd64 için FrankenPHP görüntüleri oluşturun:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"
|
||||
```
|
||||
|
||||
Yerel olarak arm64 için FrankenPHP görüntüleri oluşturun:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"
|
||||
```
|
||||
|
||||
FrankenPHP imajlarını arm64 ve amd64 için sıfırdan oluşturun ve Docker Hub'a gönderin:
|
||||
|
||||
```console
|
||||
docker buildx bake -f docker-bake.hcl --pull --no-cache --push
|
||||
```
|
||||
|
||||
## Statik Derlemelerle Segmentasyon Hatalarında Hata Ayıklama
|
||||
|
||||
1. FrankenPHP binary dosyasının hata ayıklama sürümünü GitHub'dan indirin veya hata ayıklama seçeneklerini kullanarak özel statik derlemenizi oluşturun:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder.args.DEBUG_SYMBOLS=1 \
|
||||
--set "static-builder.platform=linux/amd64" \
|
||||
static-builder
|
||||
docker cp $(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp
|
||||
```
|
||||
|
||||
2. Mevcut `frankenphp` sürümünüzü hata ayıklama FrankenPHP çalıştırılabilir dosyasıyla değiştirin
|
||||
3. FrankenPHP'yi her zamanki gibi başlatın (alternatif olarak FrankenPHP'yi doğrudan GDB ile başlatabilirsiniz: `gdb --args ./frankenphp run`)
|
||||
4. GDB ile sürece bağlanın:
|
||||
|
||||
```console
|
||||
gdb -p `pidof frankenphp`
|
||||
```
|
||||
|
||||
5. Gerekirse, GDB kabuğuna `continue` yazın
|
||||
6. FrankenPHP'nin çökmesini sağlayın
|
||||
7. GDB kabuğuna `bt` yazın
|
||||
8. Çıktıyı kopyalayın
|
||||
|
||||
## GitHub Eylemlerinde Segmentasyon Hatalarında Hata Ayıklama
|
||||
|
||||
1. `.github/workflows/tests.yml` dosyasını açın
|
||||
2. PHP hata ayıklama seçeneklerini etkinleştirin
|
||||
|
||||
```patch
|
||||
- uses: shivammathur/setup-php@v2
|
||||
# ...
|
||||
env:
|
||||
phpts: ts
|
||||
+ debug: true
|
||||
```
|
||||
|
||||
3. Konteynere bağlanmak için `tmate`i etkinleştirin
|
||||
|
||||
```patch
|
||||
-
|
||||
name: Set CGO flags
|
||||
run: echo "CGO_CFLAGS=$(php-config --includes)" >> "$GITHUB_ENV"
|
||||
+ -
|
||||
+ run: |
|
||||
+ sudo apt install gdb
|
||||
+ mkdir -p /home/runner/.config/gdb/
|
||||
+ printf "set auto-load safe-path /\nhandle SIG34 nostop noprint pass" > /home/runner/.config/gdb/gdbinit
|
||||
+ -
|
||||
+ uses: mxschmitt/action-tmate@v3
|
||||
```
|
||||
|
||||
4. Konteynere bağlanın
|
||||
5. `frankenphp.go` dosyasını açın
|
||||
6. `cgosymbolizer`'ı etkinleştirin
|
||||
|
||||
```patch
|
||||
- //_ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
+ _ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
```
|
||||
|
||||
7. Modülü indirin: `go get`
|
||||
8. Konteynerde GDB ve benzerlerini kullanabilirsiniz:
|
||||
|
||||
```console
|
||||
go test -c -ldflags=-w
|
||||
gdb --args ./frankenphp.test -test.run ^MyTest$
|
||||
```
|
||||
|
||||
9. Hata düzeltildiğinde, tüm bu değişiklikleri geri alın
|
||||
|
||||
## Misc Dev Resources
|
||||
|
||||
* [uWSGI içine PHP gömme](https://github.com/unbit/uwsgi/blob/master/plugins/php/php_plugin.c)
|
||||
* [NGINX Unit'te PHP gömme](https://github.com/nginx/unit/blob/master/src/nxt_php_sapi.c)
|
||||
* [Go (go-php) içinde PHP gömme](https://github.com/deuill/go-php)
|
||||
* [Go'da PHP gömme (GoEmPHP)](https://github.com/mikespook/goemphp)
|
||||
* [C++'da PHP gömme](https://gist.github.com/paresy/3cbd4c6a469511ac7479aa0e7c42fea7)
|
||||
* [Sara Golemon tarafından PHP'yi Genişletme ve Yerleştirme](https://books.google.fr/books?id=zMbGvK17_tYC&pg=PA254&lpg=PA254#v=onepage&q&f=false)
|
||||
* [TSRMLS_CC de neyin nesi?](http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html)
|
||||
* [Mac'te PHP gömme](https://gist.github.com/jonnywang/61427ffc0e8dde74fff40f479d147db4)
|
||||
* [SDL bağları](https://pkg.go.dev/github.com/veandco/go-sdl2@v0.4.21/sdl#Main)
|
||||
|
||||
## Docker ile İlgili Kaynaklar
|
||||
|
||||
* [Pişirme (bake) dosya tanımı](https://docs.docker.com/build/customize/bake/file-definition/)
|
||||
* [docker buildx build](https://docs.docker.com/engine/reference/commandline/buildx_build/)
|
||||
|
||||
## Faydalı Komut
|
||||
|
||||
```console
|
||||
apk add strace util-linux gdb
|
||||
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
|
||||
```
|
||||
77
docs/tr/README.md
Normal file
77
docs/tr/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# FrankenPHP: PHP için Modern Uygulama Sunucusu
|
||||
|
||||
<h1 align="center"><a href="https://frankenphp.dev"><img src="frankenphp.png" alt="FrankenPHP" width="600"></a></h1>
|
||||
|
||||
FrankenPHP, [Caddy](https://caddyserver.com/) web sunucusunun üzerine inşa edilmiş PHP için modern bir uygulama sunucusudur.
|
||||
|
||||
FrankenPHP, çarpıcı özellikleri sayesinde PHP uygulamalarınıza süper güçler kazandırır: [Early Hints*](https://frankenphp.dev/docs/early-hints/), [worker modu](https://frankenphp.dev/docs/worker/), [real-time yetenekleri](https://frankenphp.dev/docs/mercure/), otomatik HTTPS, HTTP/2 ve HTTP/3 desteği...
|
||||
|
||||
FrankenPHP herhangi bir PHP uygulaması ile çalışır ve worker modu ile resmi entegrasyonları sayesinde Laravel ve Symfony projelerinizi her zamankinden daha performanslı hale getirir.
|
||||
|
||||
FrankenPHP, PHP'yi `net/http` kullanarak herhangi bir uygulamaya yerleştirmek için bağımsız bir Go kütüphanesi olarak da kullanılabilir.
|
||||
|
||||
[*Frankenphp.dev*](https://frankenphp.dev) adresinden ve bu slayt üzerinden daha fazlasını öğrenin:
|
||||
|
||||
<a href="https://dunglas.dev/2022/10/frankenphp-the-modern-php-app-server-written-in-go/"><img src="https://dunglas.dev/wp-content/uploads/2022/10/frankenphp.png" alt="Slides" width="600"></a>
|
||||
|
||||
## Başlarken
|
||||
|
||||
### Docker
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
`https://localhost` adresine gidin ve keyfini çıkarın!
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> `https://127.0.0.1` kullanmaya çalışmayın. `https://localhost` kullanın ve kendinden imzalı sertifikayı kabul edin.
|
||||
> Kullanılacak alan adını değiştirmek için [`SERVER_NAME` ortam değişkenini](docs/config.md#environment-variables) kullanın.
|
||||
|
||||
### Binary Çıktısı
|
||||
|
||||
Docker kullanmayı tercih etmiyorsanız, Linux ve macOS için bağımsız FrankenPHP binary dosyası sağlıyoruz
|
||||
[PHP 8.3](https://www.php.net/releases/8.3/en.php) ve en popüler PHP eklentilerini de içermekte: [FrankenPHP](https://github.com/dunglas/frankenphp/releases) indirin
|
||||
|
||||
Geçerli dizinin içeriğini başlatmak için çalıştırın:
|
||||
|
||||
```console
|
||||
./frankenphp php-server
|
||||
```
|
||||
|
||||
Ayrıca aşağıdaki tek komut satırı ile de çalıştırabilirsiniz:
|
||||
|
||||
```console
|
||||
./frankenphp php-cli /path/to/your/script.php
|
||||
```
|
||||
|
||||
## Docs
|
||||
|
||||
* [Worker modu](https://frankenphp.dev/docs/worker/)
|
||||
* [Early Hints desteği (103 HTTP durum kodu)](https://frankenphp.dev/docs/early-hints/)
|
||||
* [Real-time](https://frankenphp.dev/docs/mercure/)
|
||||
* [Konfigürasyon](https://frankenphp.dev/docs/config/)
|
||||
* [Docker imajları](https://frankenphp.dev/docs/docker/)
|
||||
* [Production'a dağıtım](docs/production.md)
|
||||
* [**Bağımsız** kendiliğinden çalıştırılabilir PHP uygulamaları oluşturma](https://frankenphp.dev/docs/embed/)
|
||||
* [Statik binary'leri oluşturma](https://frankenphp.dev/docs/static/)
|
||||
* [Kaynak dosyalarından derleme](https://frankenphp.dev/docs/compile/)
|
||||
* [Laravel entegrasyonu](https://frankenphp.dev/docs/laravel/)
|
||||
* [Bilinen sorunlar](https://frankenphp.dev/docs/known-issues/)
|
||||
* [Demo uygulama (Symfony) ve kıyaslamalar](https://github.com/dunglas/frankenphp-demo)
|
||||
* [Go kütüphane dokümantasonu](https://pkg.go.dev/github.com/dunglas/frankenphp)
|
||||
* [Katkıda bulunma ve hata ayıklama](https://frankenphp.dev/docs/contributing/)
|
||||
|
||||
## Örnekler ve İskeletler
|
||||
|
||||
* [Symfony](https://github.com/dunglas/symfony-docker)
|
||||
* [API Platform](https://api-platform.com/docs/distribution/)
|
||||
* [Laravel](https://frankenphp.dev/docs/laravel/)
|
||||
* [Sulu](https://sulu.io/blog/running-sulu-with-frankenphp)
|
||||
* [WordPress](https://github.com/dunglas/frankenphp-wordpress)
|
||||
* [Drupal](https://github.com/dunglas/frankenphp-drupal)
|
||||
* [Joomla](https://github.com/alexandreelise/frankenphp-joomla)
|
||||
* [TYPO3](https://github.com/ochorocho/franken-typo3)
|
||||
104
docs/tr/compile.md
Normal file
104
docs/tr/compile.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Kaynak Kodlardan Derleme
|
||||
|
||||
Bu doküman, PHP'yi dinamik bir kütüphane olarak yükleyecek bir FrankenPHP yapısının nasıl oluşturulacağını açıklamaktadır.
|
||||
Önerilen yöntem bu şekildedir.
|
||||
|
||||
Alternatif olarak, [statik yapılar oluşturma](static.md) da mümkündür.
|
||||
|
||||
## PHP'yi yükleyin
|
||||
|
||||
FrankenPHP, PHP 8.2 ve üstü ile uyumludur.
|
||||
|
||||
İlk olarak, [PHP'nin kaynaklarını edinin](https://www.php.net/downloads.php) ve bunları çıkarın:
|
||||
|
||||
```console
|
||||
tar xf php-*
|
||||
cd php-*/
|
||||
```
|
||||
|
||||
Ardından, PHP'yi platformunuz için yapılandırın:
|
||||
|
||||
### Linux
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--enable-zend-max-execution-timers
|
||||
```
|
||||
|
||||
Son olarak, PHP'yi derleyin ve kurun:
|
||||
|
||||
```console
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Mac
|
||||
|
||||
Yüklemek için [Homebrew](https://brew.sh/) paket yöneticisini kullanın
|
||||
`libiconv`, `bison`, `re2c` ve `pkg-config`:
|
||||
|
||||
```console
|
||||
brew install libiconv bison re2c pkg-config
|
||||
echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
Ardından yapılandırma betiğini çalıştırın:
|
||||
|
||||
```console
|
||||
./configure \
|
||||
--enable-embed=static \
|
||||
--enable-zts \
|
||||
--disable-zend-signals \
|
||||
--disable-opcache-jit \
|
||||
--enable-static \
|
||||
--enable-shared=no \
|
||||
--with-iconv=/opt/homebrew/opt/libiconv/
|
||||
```
|
||||
|
||||
Bu şekilde yapılandırma gereklidir, ancak başka opsiyonlar da ekleyebilirsiniz (örn. ekstra uzantılar)
|
||||
İhtiyaç halinde.
|
||||
|
||||
Son olarak, PHP'yi derleyin ve yükleyin:
|
||||
|
||||
```console
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Go Uygulamasını Derleyin
|
||||
|
||||
Artık Go kütüphanesini kullanabilir ve Caddy yapımızı derleyebilirsiniz:
|
||||
|
||||
```console
|
||||
curl -L https://github.com/dunglas/frankenphp/archive/refs/heads/main.tar.gz | tar x
|
||||
cd frankenphp-main/caddy/frankenphp
|
||||
CGO_CFLAGS=$(php-config --includes) CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" go build
|
||||
```
|
||||
|
||||
### Xcaddy kullanımı
|
||||
|
||||
Alternatif olarak, FrankenPHP'yi [özel Caddy modülleri](https://caddyserver.com/docs/modules/) ile derlemek için [xcaddy](https://github.com/caddyserver/xcaddy) kullanın:
|
||||
|
||||
```console
|
||||
CGO_ENABLED=1 \
|
||||
XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'" \
|
||||
xcaddy build \
|
||||
--output frankenphp \
|
||||
--with github.com/dunglas/frankenphp/caddy \
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Add extra Caddy modules here
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Eğer musl libc (Alpine Linux'ta varsayılan) ve Symfony kullanıyorsanız,
|
||||
> varsayılan yığın boyutunu artırmanız gerekebilir.
|
||||
> Aksi takdirde, şu tarz hatalar alabilirsiniz `PHP Fatal error: Maximum call stack size of 83360 bytes reached during compilation. Try splitting expression`
|
||||
>
|
||||
> Bunu yapmak için, `XCADDY_GO_BUILD_FLAGS` ortam değişkenini bu şekilde değiştirin
|
||||
> `XCADDY_GO_BUILD_FLAGS=$'-ldflags "-w -s -extldflags \'-Wl,-z,stack-size=0x80000\'"'`
|
||||
> (yığın boyutunun değerini uygulamanızın ihtiyaçlarına göre değiştirin).
|
||||
159
docs/tr/config.md
Normal file
159
docs/tr/config.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Konfigürasyon
|
||||
|
||||
FrankenPHP, Caddy'nin yanı sıra Mercure ve Vulcain modülleri [Caddy tarafından desteklenen formatlar](https://caddyserver.com/docs/getting-started#your-first-config) kullanılarak yapılandırılabilir.
|
||||
|
||||
Docker imajında, `Caddyfile` `/etc/caddy/Caddyfile` dosyası olarak bulunur.
|
||||
|
||||
PHP'yi her zamanki gibi `php.ini` kullanarak da yapılandırabilirsiniz.
|
||||
|
||||
Docker imajında `php.ini` dosyası mevcut değildir, elle oluşturabilir veya resmi bir şablonu kopyalayabilirsiniz:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# Developement:
|
||||
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
|
||||
|
||||
# Veya production:
|
||||
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
|
||||
```
|
||||
|
||||
## Caddyfile Konfigürasyonu
|
||||
|
||||
FrankenPHP yürütücüsünü kaydetmek için `frankenphp` [global seçenek](https://caddyserver.com/docs/caddyfile/concepts#global-options) ayarlanmalıdır, ardından PHP uygulamanızı sunmak için site blokları içinde `php_server` veya `php` [HTTP yönergeleri](https://caddyserver.com/docs/caddyfile/concepts#directives) kullanılabilir.
|
||||
|
||||
Minimal örnek:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
# FrankenPHP'yi aktif et
|
||||
frankenphp
|
||||
# Yönergenin ne zaman yürütülmesi gerektiğini yapılandırma
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
localhost {
|
||||
# Sıkıştırmayı etkinleştir (isteğe bağlı)
|
||||
encode zstd br gzip
|
||||
# Geçerli dizindeki PHP dosyalarını çalıştırın ve varlıkları sunun
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
İsteğe bağlı olarak, oluşturulacak iş parçacığı sayısı ve sunucuyla birlikte başlatılacak [işçi betikleri] (worker.md) global seçenek altında belirtilebilir.
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
num_threads <num_threads> # Başlatılacak PHP iş parçacığı sayısını ayarlar. Varsayılan: Mevcut CPU çekirdek sayısının 2 katı.
|
||||
worker {
|
||||
file <path> # Çalışan komut dosyasının yolunu ayarlar.
|
||||
num <num> # Başlatılacak PHP iş parçacığı sayısını ayarlar, varsayılan değer mevcut CPU çekirdek sayısının 2 katıdır.
|
||||
env <key> <value> # Ek bir ortam değişkenini verilen değere ayarlar. Birden fazla ortam değişkeni için birden fazla kez belirtilebilir.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Alternatif olarak, `worker` seçeneğinin tek satırlık kısa formunu kullanabilirsiniz:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker <file> <num>
|
||||
}
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Aynı sunucuda birden fazla uygulamaya hizmet veriyorsanız birden fazla işçi de tanımlayabilirsiniz:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp {
|
||||
worker /path/to/app/public/index.php <num>
|
||||
worker /path/to/other/public/index.php <num>
|
||||
}
|
||||
}
|
||||
|
||||
app.example.com {
|
||||
root * /path/to/app/public
|
||||
php_server
|
||||
}
|
||||
|
||||
other.example.com {
|
||||
root * /path/to/other/public
|
||||
php_server
|
||||
}
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Genellikle ihtiyacınız olan şey `php_server` yönergesini kullanmaktır,
|
||||
ancak tam kontrole ihtiyacınız varsa, daha düşük seviyeli `php` yönergesini kullanabilirsiniz:
|
||||
|
||||
php_server` yönergesini kullanmak bu yapılandırmay ile aynıdır:
|
||||
|
||||
```caddyfile
|
||||
route {
|
||||
# Dizin istekleri için sondaki eğik çizgiyi, diğer adıyla taksim işaretini ekleyin
|
||||
@canonicalPath {
|
||||
file {path}/index.php
|
||||
not path */
|
||||
}
|
||||
redir @canonicalPath {path}/ 308
|
||||
# İstenen dosya mevcut değilse, dizin dosyalarını deneyin
|
||||
@indexFiles file {
|
||||
try_files {path} {path}/index.php index.php
|
||||
split_path .php
|
||||
}
|
||||
rewrite @indexFiles {http.matchers.file.relative}
|
||||
# FrankenPHP!
|
||||
@phpFiles path *.php
|
||||
php @phpFiles
|
||||
file_server
|
||||
}
|
||||
```
|
||||
|
||||
php_server` ve `php` yönergeleri aşağıdaki seçeneklere sahiptir:
|
||||
|
||||
```caddyfile
|
||||
php_server [<matcher>] {
|
||||
root <directory> # Sitenin kök klasörünü ayarlar. Öntanımlı: `root` yönergesi.
|
||||
split_path <delim...> # URI'yi iki parçaya bölmek için alt dizgeleri ayarlar. İlk eşleşen alt dizge "yol bilgisini" yoldan ayırmak için kullanılır. İlk parça eşleşen alt dizeyle sonlandırılır ve gerçek kaynak (CGI betiği) adı olarak kabul edilir. İkinci parça betiğin kullanması için PATH_INFO olarak ayarlanacaktır. Varsayılan: `.php`
|
||||
resolve_root_symlink false # Varsa, sembolik bir bağlantıyı değerlendirerek `root` dizininin gerçek değerine çözümlenmesini devre dışı bırakır (varsayılan olarak etkindir).
|
||||
env <key> <value> # Ek bir ortam değişkenini verilen değere ayarlar. Birden fazla ortam değişkeni için birden fazla kez belirtilebilir.
|
||||
}
|
||||
```
|
||||
|
||||
## Ortam Değişkenleri
|
||||
|
||||
Aşağıdaki ortam değişkenleri `Caddyfile` içinde değişiklik yapmadan Caddy yönergelerini entegre etmek için kullanılabilir:
|
||||
|
||||
* `SERVER_NAME`: değiştirin [dinlenecek adresleri](https://caddyserver.com/docs/caddyfile/concepts#addresses), sağlanan ana bilgisayar adları oluşturulan TLS sertifikası için de kullanılacaktır
|
||||
* `CADDY_GLOBAL_OPTIONS`: entegre edin [global seçenekler](https://caddyserver.com/docs/caddyfile/options)
|
||||
* `FRANKENPHP_CONFIG`: `frankenphp` yönergesi altına yapılandırma entegre edin
|
||||
|
||||
FPM ve CLI SAPI'lerinde olduğu gibi, ortam değişkenleri varsayılan olarak `$_SERVER` süper globalinde gösterilir.
|
||||
|
||||
[`variables_order`'a ait PHP yönergesinin](https://www.php.net/manual/en/ini.core.php#ini.variables-order) `S` değeri bu yönergede `E`'nin başka bir yere yerleştirilmesinden bağımsız olarak her zaman `ES` ile eş değerdir.
|
||||
|
||||
## PHP konfigürasyonu
|
||||
|
||||
Ek olarak [PHP yapılandırma dosyalarını](https://www.php.net/manual/en/configuration.file.php#configuration.file.scan) yüklemek için
|
||||
`PHP_INI_SCAN_DIR` ortam değişkeni kullanılabilir.
|
||||
Ayarlandığında, PHP verilen dizinlerde bulunan `.ini` uzantılı tüm dosyaları yükleyecektir.
|
||||
|
||||
## Hata Ayıklama Modunu Etkinleştirin
|
||||
|
||||
Docker imajını kullanırken, hata ayıklama modunu etkinleştirmek için `CADDY_GLOBAL_OPTIONS` ortam değişkenini `debug` olarak ayarlayın:
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public \
|
||||
-e CADDY_GLOBAL_OPTIONS=debug \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
167
docs/tr/docker.md
Normal file
167
docs/tr/docker.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Özel Docker İmajı Oluşturma
|
||||
|
||||
[Resmi PHP imajları](https://hub.docker.com/_/php/) temel alınarak [FrankenPHP Docker imajları](https://hub.docker.com/r/dunglas/frankenphp) hazırlanmıştır. Popüler mimariler için Debian ve Alpine Linux varyantları sağlanmıştır. Debian dağıtımı tavsiye edilir.
|
||||
|
||||
PHP 8.2 ve PHP 8.3 için varyantlar sağlanmıştır. [Etiketlere göz atın](https://hub.docker.com/r/dunglas/frankenphp/tags).
|
||||
|
||||
## İmajlar Nasıl Kullanılır
|
||||
|
||||
Projenizde bir `Dockerfile` oluşturun:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
COPY . /app/public
|
||||
```
|
||||
|
||||
Ardından, Docker imajını oluşturmak ve çalıştırmak için bu komutları çalıştırın:
|
||||
|
||||
```console
|
||||
docker build -t my-php-app .
|
||||
docker run -it --rm --name my-running-app my-php-app
|
||||
```
|
||||
|
||||
## Daha Fazla PHP Eklentisi Nasıl Kurulur
|
||||
|
||||
[Docker-php-extension-installer`](https://github.com/mlocati/docker-php-extension-installer) betiği temel imajda sağlanmıştır.
|
||||
Ek PHP eklentileri eklemek ise gerçekten kolaydır:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# buraya istenilen eklentileri ekleyin:
|
||||
RUN install-php-extensions \
|
||||
pdo_mysql \
|
||||
gd \
|
||||
intl \
|
||||
zip \
|
||||
opcache
|
||||
```
|
||||
|
||||
## Daha Fazla Caddy Modülü Nasıl Kurulur
|
||||
|
||||
FrankenPHP, Caddy'nin üzerine inşa edilmiştir ve tüm [Caddy modülleri](https://caddyserver.com/docs/modules/) FrankenPHP ile kullanılabilir.
|
||||
|
||||
Özel Caddy modüllerini kurmanın en kolay yolu [xcaddy](https://github.com/caddyserver/xcaddy) kullanmaktır:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp:latest-builder AS builder
|
||||
|
||||
# xcaddy'yi derleyen imaja kopyalayın
|
||||
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy
|
||||
|
||||
# FrankenPHP oluşturmak için CGO etkinleştirilmelidir
|
||||
ENV CGO_ENABLED=1 XCADDY_SETCAP=1 XCADDY_GO_BUILD_FLAGS="-ldflags '-w -s'"
|
||||
RUN xcaddy build \
|
||||
--output /usr/local/bin/frankenphp \
|
||||
--with github.com/dunglas/frankenphp=./ \
|
||||
--with github.com/dunglas/frankenphp/caddy=./caddy/ \
|
||||
# Mercure ve Vulcain resmi yapıya dahil edilmiştir, ancak bunları kaldırmaktan çekinmeyin
|
||||
--with github.com/dunglas/caddy-cbrotli \
|
||||
--with github.com/dunglas/mercure/caddy \
|
||||
--with github.com/dunglas/vulcain/caddy
|
||||
# Buraya ekstra Caddy modülleri ekleyin
|
||||
|
||||
FROM dunglas/frankenphp AS runner
|
||||
|
||||
# Resmi binary dosyayı özel modüllerinizi içeren binary dosyayla değiştirin
|
||||
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
|
||||
```
|
||||
|
||||
FrankenPHP tarafından sağlanan `builder` imajı `libphp`'nin derlenmiş bir sürümünü içerir.
|
||||
[Derleyici imajları](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder) hem Debian hem de Alpine için FrankenPHP ve PHP'nin tüm sürümleri için sağlanmıştır.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> Eğer Alpine Linux ve Symfony kullanıyorsanız,
|
||||
> [varsayılan yığın boyutunu artırmanız](compile.md#using-xcaddy) gerekebilir.
|
||||
|
||||
## Varsayılan Olarak Worker Modunun Etkinleştirilmesi
|
||||
|
||||
FrankenPHP'yi bir worker betiği ile başlatmak için `FRANKENPHP_CONFIG` ortam değişkenini ayarlayın:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# ...
|
||||
|
||||
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
|
||||
```
|
||||
|
||||
## Geliştirme Sürecinde Yığın (Volume) Kullanma
|
||||
|
||||
FrankenPHP ile kolayca geliştirme yapmak için, uygulamanın kaynak kodunu içeren dizini ana bilgisayarınızdan Docker konteynerine bir yığın (volume) olarak bağlayın:
|
||||
|
||||
```console
|
||||
docker run -v $PWD:/app/public -p 80:80 -p 443:443 -p 443:443/udp --tty my-php-app
|
||||
```
|
||||
|
||||
> ![İPUCU]
|
||||
>
|
||||
> `--tty' seçeneği JSON günlükleri yerine insan tarafından okunabilir güzel günlüklere sahip olmayı sağlar.
|
||||
|
||||
Docker Compose ile:
|
||||
|
||||
```yaml
|
||||
# compose.yaml
|
||||
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
# özel bir Dockerfile kullanmak istiyorsanız aşağıdaki yorum satırını kaldırın
|
||||
#build: .
|
||||
# bunu bir production ortamında çalıştırmak istiyorsanız aşağıdaki yorum satırını kaldırın
|
||||
# restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- ./:/app/public
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
# production ortamda aşağıdaki satırı yorum satırı yapın, geliştirme ortamında insan tarafından okunabilir güzel günlüklere sahip olmanızı sağlar
|
||||
tty: true
|
||||
|
||||
# Caddy sertifikaları ve yapılandırması için gereken yığınlar (volumes)
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
## Root Olmayan Kullanıcı Olarak Çalıştırma
|
||||
|
||||
FrankenPHP, Docker'da root olmayan kullanıcı olarak çalışabilir.
|
||||
|
||||
İşte bunu yapan örnek bir `Dockerfile`:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
ARG USER=www-data
|
||||
|
||||
RUN \
|
||||
# Alpine tabanlı dağıtımlar için "adduser -D ${USER}" kullanın
|
||||
useradd -D ${USER}; \
|
||||
# 80 ve 443 numaralı bağlantı noktalarına bağlanmak için ek özellik ekleyin
|
||||
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp; \
|
||||
# /data/caddy ve /config/caddy dosyalarına yazma erişimi verin
|
||||
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy;
|
||||
|
||||
USER ${USER}
|
||||
```
|
||||
|
||||
## Güncellemeler
|
||||
|
||||
Docker imajları oluşturulur:
|
||||
|
||||
* Yeni bir sürüm etiketlendiğinde
|
||||
* Her gün UTC ile saat 4'te Resmi PHP imajlarının yeni sürümleri mevcutsa
|
||||
|
||||
## Geliştirme Sürümleri
|
||||
|
||||
Geliştirme sürümleri [`dunglas/frankenphp-dev`](https://hub.docker.com/repository/docker/dunglas/frankenphp-dev) Docker deposunda mevcuttur.
|
||||
GitHub deposunun ana dalına her commit yapıldığında yeni bir derleme tetiklenir.
|
||||
|
||||
`latest*` etiketleri `main` dalının başına işaret eder.
|
||||
`sha-<hash-du-commit-git>` biçimindeki etiketler de kullanılabilir.
|
||||
21
docs/tr/early-hints.md
Normal file
21
docs/tr/early-hints.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Early Hints
|
||||
|
||||
FrankenPHP [103 Early Hints durum kodunu](https://developer.chrome.com/blog/early-hints/) yerel olarak destekler.
|
||||
Early Hints kullanmak web sayfalarınızın yüklenme süresini %30 oranında artırabilir.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
header('Link: </style.css>; rel=preload; as=style');
|
||||
headers_send(103);
|
||||
|
||||
// yavaş algoritmalarınız ve SQL sorgularınız 🤪
|
||||
|
||||
echo <<<'HTML'
|
||||
<!DOCTYPE html>
|
||||
<title>Hello FrankenPHP</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
HTML;
|
||||
```
|
||||
|
||||
Early Hints hem normal hem de [worker](worker.md) modları tarafından desteklenir.
|
||||
132
docs/tr/embed.md
Normal file
132
docs/tr/embed.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Binary Dosyası Olarak PHP Uygulamaları
|
||||
|
||||
FrankenPHP, PHP uygulamalarının kaynak kodunu ve varlıklarını statik, kendi kendine yeten bir binary dosyaya yerleştirme yeteneğine sahiptir.
|
||||
|
||||
Bu özellik sayesinde PHP uygulamaları, uygulamanın kendisini, PHP yorumlayıcısını ve üretim düzeyinde bir web sunucusu olan Caddy'yi içeren bağımsız bir binary dosyalar olarak çıktısı alınabilir ve dağıtılabilir.
|
||||
|
||||
Bu özellik hakkında daha fazla bilgi almak için [Kévin tarafından SymfonyCon 2023'te yapılan sunuma](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/) göz atabilirsiniz.
|
||||
|
||||
## Preparing Your App
|
||||
|
||||
Bağımsız binary dosyayı oluşturmadan önce uygulamanızın gömülmeye hazır olduğundan emin olun.
|
||||
|
||||
Örneğin muhtemelen şunları yapmak istersiniz:
|
||||
|
||||
* Uygulamanın üretim bağımlılıklarını yükleyin
|
||||
* Otomatik yükleyiciyi boşaltın
|
||||
* Uygulamanızın üretim modunu etkinleştirin (varsa)
|
||||
* Nihai binary dosyanızın boyutunu küçültmek için `.git` veya testler gibi gerekli olmayan dosyaları çıkarın
|
||||
|
||||
Örneğin, bir Symfony uygulaması için aşağıdaki komutları kullanabilirsiniz:
|
||||
|
||||
```console
|
||||
# .git/, vb. dosyalarından kurtulmak için projeyi dışa aktarın
|
||||
mkdir $TMPDIR/my-prepared-app
|
||||
git archive HEAD | tar -x -C $TMPDIR/my-prepared-app
|
||||
cd $TMPDIR/my-prepared-app
|
||||
|
||||
# Uygun ortam değişkenlerini ayarlayın
|
||||
echo APP_ENV=prod > .env.local
|
||||
echo APP_DEBUG=0 >> .env.local
|
||||
|
||||
# Testleri kaldırın
|
||||
rm -Rf tests/
|
||||
|
||||
# Bağımlılıkları yükleyin
|
||||
composer install --ignore-platform-reqs --no-dev -a
|
||||
|
||||
# .env'yi optimize edin
|
||||
composer dump-env prod
|
||||
```
|
||||
|
||||
## Linux Binary'si Oluşturma
|
||||
|
||||
Bir Linux binary çıktısı almanın en kolay yolu, sağladığımız Docker tabanlı derleyiciyi kullanmaktır.
|
||||
|
||||
1. Hazırladığınız uygulamanın deposunda `static-build.Dockerfile` adlı bir dosya oluşturun:
|
||||
|
||||
```dockerfile
|
||||
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder
|
||||
|
||||
# Uygulamanızı kopyalayın
|
||||
WORKDIR /go/src/app/dist/app
|
||||
COPY . .
|
||||
|
||||
# Statik binary dosyasını oluşturun, yalnızca istediğiniz PHP eklentilerini seçtiğinizden emin olun
|
||||
WORKDIR /go/src/app/
|
||||
RUN EMBED=dist/app/ \
|
||||
PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Bazı `.dockerignore` dosyaları (örneğin varsayılan [Symfony Docker `.dockerignore`](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))
|
||||
> `vendor/` dizinini ve `.env` dosyalarını yok sayacaktır. Derlemeden önce `.dockerignore` dosyasını ayarladığınızdan veya kaldırdığınızdan emin olun.
|
||||
|
||||
2. Derleyin:
|
||||
|
||||
```console
|
||||
docker build -t static-app -f static-build.Dockerfile .
|
||||
```
|
||||
|
||||
3. Binary dosyasını çıkarın:
|
||||
|
||||
```console
|
||||
docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp
|
||||
```
|
||||
|
||||
Elde edilen binary dosyası, geçerli dizindeki `my-app` adlı dosyadır.
|
||||
|
||||
## Diğer İşletim Sistemleri için Binary Çıktısı Alma
|
||||
|
||||
Docker kullanmak istemiyorsanız veya bir macOS binary dosyası oluşturmak istiyorsanız, sağladığımız kabuk betiğini kullanın:
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
EMBED=/path/to/your/app \
|
||||
PHP_EXTENSIONS=ctype,iconv,pdo_sqlite \
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
Elde edilen binary dosyası `dist/` dizinindeki `frankenphp-<os>-<arch>` adlı dosyadır.
|
||||
|
||||
## Binary Dosyasını Kullanma
|
||||
|
||||
İşte bu kadar! `my-app` dosyası (veya diğer işletim sistemlerinde `dist/frankenphp-<os>-<arch>`) bağımsız uygulamanızı içerir!
|
||||
|
||||
Web uygulamasını başlatmak için çalıştırın:
|
||||
|
||||
```console
|
||||
./my-app php-server
|
||||
```
|
||||
|
||||
Uygulamanız bir [worker betiği](worker.md) içeriyorsa, worker'ı aşağıdaki gibi bir şeyle başlatın:
|
||||
|
||||
```console
|
||||
./my-app php-server --worker public/index.php
|
||||
```
|
||||
|
||||
HTTPS (Let's Encrypt sertifikası otomatik olarak oluşturulur), HTTP/2 ve HTTP/3'ü etkinleştirmek için kullanılacak alan adını belirtin:
|
||||
|
||||
```console
|
||||
./my-app php-server --domain localhost
|
||||
```
|
||||
|
||||
Ayrıca binary dosyanıza gömülü PHP CLI betiklerini de çalıştırabilirsiniz:
|
||||
|
||||
```console
|
||||
./my-app php-cli bin/console
|
||||
```
|
||||
|
||||
## Yapıyı Özelleştirme
|
||||
|
||||
Binary dosyasının nasıl özelleştirileceğini (uzantılar, PHP sürümü...) görmek için [Statik derleme dokümanını okuyun](static.md).
|
||||
|
||||
## Binary Dosyasının Dağıtılması
|
||||
|
||||
Linux'ta, oluşturulan ikili dosya [UPX](https://upx.github.io) kullanılarak sıkıştırılır.
|
||||
|
||||
Mac'te, göndermeden önce dosyanın boyutunu küçültmek için sıkıştırabilirsiniz.
|
||||
Biz `xz` öneririz.
|
||||
31
docs/tr/github-actions.md
Normal file
31
docs/tr/github-actions.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# GitHub Actions Kullanma
|
||||
|
||||
Bu depo Docker imajını [Docker Hub](https://hub.docker.com/r/dunglas/frankenphp) üzerinde derler ve dağıtır.
|
||||
Bu durum onaylanan her çekme (pull) isteğinde veya çatallandıktan (fork) sonra gerçekleşir.
|
||||
|
||||
## GitHub Eylemlerini Ayarlama
|
||||
|
||||
Depo ayarlarında, gizli değerler altında aşağıdaki gizli değerleri ekleyin:
|
||||
|
||||
- `REGISTRY_LOGIN_SERVER`: Kullanılacak Docker Registry bilgisi (örneğin `docker.io`).
|
||||
- `REGISTRY_USERNAME`: Giriş yapmak için kullanılacak kullanıcı adı (örn. `dunglas`).
|
||||
- `REGISTRY_PASSWORD`: Oturum açmak için kullanılacak parola (örn. bir erişim anahtarı).
|
||||
- `IMAGE_NAME`: İmajın adı (örn. `dunglas/frankenphp`).
|
||||
|
||||
## İmajı Oluşturma ve Dağıtma
|
||||
|
||||
1. Bir Çekme (pull) İsteği oluşturun veya çatala (forka) dağıtın.
|
||||
2. GitHub Actions imajı oluşturacak ve tüm testleri çalıştıracaktır.
|
||||
3. Derleme başarılı olursa, görüntü `pr-x` (burada `x` PR numarasıdır) etiketi kullanılarak ilgili saklanan yere (registry'e) gönderilir.
|
||||
|
||||
## İmajı Dağıtma
|
||||
|
||||
1. Çekme (pull) isteği birleştirildikten sonra, GitHub Actions testleri tekrar çalıştıracak ve yeni bir imaj oluşturacaktır.
|
||||
2. Derleme başarılı olursa, `main` etiketi Docker Registry'de güncellenecektir.
|
||||
|
||||
## Bültenler
|
||||
|
||||
1. Depoda yeni bir etiket oluşturun.
|
||||
2. GitHub Actions imajı oluşturacak ve tüm testleri çalıştıracaktır.
|
||||
3. Derleme başarılı olursa, etiket adı etiket olarak kullanılarak imaj saklanan yere (registry'e) gönderilir (örneğin `v1.2.3` ve `v1.2` oluşturulur).
|
||||
4. `latest` etiketi de güncellenecektir.
|
||||
138
docs/tr/known-issues.md
Normal file
138
docs/tr/known-issues.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Bilinen Sorunlar
|
||||
|
||||
## Fibers
|
||||
|
||||
[Fibers](https://www.php.net/manual/en/language.fibers.php) içinde [cgo](https://go.dev/blog/cgo) çağrısı yapan PHP fonksiyonlarının ve dil yapılarının çağrılmasının çökmelere neden olduğu bilinmektedir.
|
||||
|
||||
Bu sorun [Go projesi tarafından üzerinde çalışılmaktadır](https://github.com/golang/go/issues/62130).
|
||||
|
||||
Bu arada, bir çözüm Fibers içinden Go'ya temsilci atayan yapıları (`echo` gibi) ve fonksiyonları (`header()` gibi) kullanmamaktır.
|
||||
|
||||
Bu kod, Fiber içinde `echo` kullandığı için büyük olasılıkla çökecektir:
|
||||
|
||||
```php
|
||||
$fiber = new Fiber(function() {
|
||||
echo 'In the Fiber'.PHP_EOL;
|
||||
echo 'Still inside'.PHP_EOL;
|
||||
});
|
||||
$fiber->start();
|
||||
```
|
||||
|
||||
Bunun yerine, değeri Fiber'den döndürün ve dışarıda kullanın:
|
||||
|
||||
```php
|
||||
$fiber = new Fiber(function() {
|
||||
Fiber::suspend('In the Fiber'.PHP_EOL));
|
||||
Fiber::suspend('Still inside'.PHP_EOL));
|
||||
});
|
||||
echo $fiber->start();
|
||||
echo $fiber->resume();
|
||||
$fiber->resume();
|
||||
```
|
||||
|
||||
## Desteklenmeyen PHP Eklentileri
|
||||
|
||||
Aşağıdaki eklentilerin FrankenPHP ile uyumlu olmadığı bilinmektedir:
|
||||
|
||||
| Adı | Nedeni | Alternatifleri |
|
||||
|-------------------------------------------------------------|----------------------------|----------------------------------------------------------------------------------------------------------------------|
|
||||
| [imap](https://www.php.net/manual/en/imap.installation.php) | İş parçacığı güvenli değil | [javanile/php-imap2](https://github.com/javanile/php-imap2), [webklex/php-imap](https://github.com/Webklex/php-imap) |
|
||||
|
||||
## Sorunlu PHP Eklentileri
|
||||
|
||||
Aşağıdaki eklentiler FrankenPHP ile kullanıldığında bilinen hatalara ve beklenmeyen davranışlara sahiptir:
|
||||
|
||||
| Adı | Problem |
|
||||
|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [Tideways](https://tideways.com/) | Worker modunda, Tideways eklentisi [worker komut dosyalarının düzgün şekilde sonlandırılmasını engelliyor](https://github.com/dunglas/frankenphp/issues/578#issuecomment-1966620351) veya CPU'nun %100'ünü tüketiyor. Bu durum Tideways'e bildirilmiştir. |
|
||||
|
||||
## get_browser
|
||||
|
||||
[get_browser()](https://www.php.net/manual/en/function.get-browser.php) fonksiyonu bir süre sonra kötü performans gösteriyor gibi görünüyor. Geçici bir çözüm, statik oldukları için User-Agent başına sonuçları önbelleğe almaktır (örneğin [APCu](https://www.php.net/manual/en/book.apcu.php) ile).
|
||||
|
||||
## Binary Çıktısı ve Alpine Tabanlı Docker İmajları
|
||||
|
||||
Binary çıktısı ve Alpine tabanlı Docker imajları (dunglas/frankenphp:*-alpine), daha küçük bir binary boyutu korumak için glibc ve arkadaşları yerine musl libc kullanır. Bu durum bazı uyumluluk sorunlarına yol açabilir. Özellikle, glob seçeneği GLOB_BRACE mevcut değildir.
|
||||
|
||||
## Docker ile `https://127.0.0.1` Kullanımı
|
||||
|
||||
FrankenPHP varsayılan olarak `localhost` için bir TLS sertifikası oluşturur.
|
||||
Bu, yerel geliştirme için en kolay ve önerilen seçenektir.
|
||||
|
||||
Bunun yerine ana bilgisayar olarak `127.0.0.1` kullanmak istiyorsanız, sunucu adını `127.0.0.1` şeklinde ayarlayarak bunun için bir sertifika oluşturacak yapılandırma yapmak mümkündür.
|
||||
|
||||
Ne yazık ki, [ağ sistemi](https://docs.docker.com/network/) nedeniyle Docker kullanırken bu yeterli değildir.
|
||||
`Curl: (35) LibreSSL/3.3.6: error:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error`'a benzer bir TLS hatası alırsınız.
|
||||
|
||||
Linux kullanıyorsanız, [ana bilgisayar ağ sürücüsünü](https://docs.docker.com/network/network-tutorial-host/) kullanmak bir çözümdür:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
--network host \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Ana bilgisayar ağ sürücüsü Mac ve Windows'ta desteklenmez. Bu platformlarda, konteynerin IP adresini tahmin etmeniz ve bunu sunucu adlarına dahil etmeniz gerekecektir.
|
||||
|
||||
`docker network inspect bridge`'i çalıştırın ve `IPv4Address` anahtarının altındaki son atanmış IP adresini belirlemek için `Containers` anahtarına bakın ve bir artırın. Eğer hiçbir konteyner çalışmıyorsa, ilk atanan IP adresi genellikle `172.17.0.2`dir.
|
||||
|
||||
Ardından, bunu `SERVER_NAME` ortam değişkenine ekleyin:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e SERVER_NAME="127.0.0.1, 172.17.0.3" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> 172.17.0.3`ü konteynerinize atanacak IP ile değiştirdiğinizden emin olun.
|
||||
|
||||
Artık ana makineden `https://127.0.0.1` adresine erişebilmeniz gerekir.
|
||||
|
||||
Eğer durum böyle değilse, sorunu anlamaya çalışmak için FrankenPHP'yi hata ayıklama modunda başlatın:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e CADDY_GLOBAL_OPTIONS="debug" \
|
||||
-e SERVER_NAME="127.0.0.1" \
|
||||
-v $PWD:/app/public \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## `@php` Referanslı Composer Betikler
|
||||
|
||||
[Composer betikleri](https://getcomposer.org/doc/articles/scripts.md) bazı görevler için bir PHP binary çalıştırmak isteyebilir, örneğin [bir Laravel projesinde](laravel.md) `@php artisan package:discover --ansi` çalıştırmak. Bu [şu anda mümkün değil](https://github.com/dunglas/frankenphp/issues/483#issuecomment-1899890915) ve 2 nedeni var:
|
||||
|
||||
* Composer FrankenPHP binary dosyasını nasıl çağıracağını bilmiyor;
|
||||
* Composer, FrankenPHP'nin henüz desteklemediği `-d` bayrağını kullanarak PHP ayarlarını komuta ekleyebilir.
|
||||
|
||||
Geçici bir çözüm olarak, `/usr/local/bin/php` içinde desteklenmeyen parametreleri silen ve ardından FrankenPHP'yi çağıran bir kabuk betiği oluşturabiliriz:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
args=("$@")
|
||||
index=0
|
||||
for i in "$@"
|
||||
do
|
||||
if [ "$i" == "-d" ]; then
|
||||
unset 'args[$index]'
|
||||
unset 'args[$index+1]'
|
||||
fi
|
||||
index=$((index+1))
|
||||
done
|
||||
|
||||
/usr/local/bin/frankenphp php-cli ${args[@]}
|
||||
```
|
||||
|
||||
Ardından `PHP_BINARY` ortam değişkenini PHP betiğimizin yoluna ayarlayın ve Composer bu yolla çalışacaktır:
|
||||
|
||||
```bash
|
||||
export PHP_BINARY=/usr/local/bin/php
|
||||
composer install
|
||||
```
|
||||
75
docs/tr/laravel.md
Normal file
75
docs/tr/laravel.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Laravel
|
||||
|
||||
## Docker
|
||||
|
||||
Bir [Laravel](https://laravel.com) web uygulamasını FrankenPHP ile çalıştırmak, projeyi resmi Docker imajının `/app` dizinine monte etmek kadar kolaydır.
|
||||
|
||||
Bu komutu Laravel uygulamanızın ana dizininden çalıştırın:
|
||||
|
||||
```console
|
||||
docker run -p 80:80 -p 443:443 -p 443:443/udp -v $PWD:/app dunglas/frankenphp
|
||||
```
|
||||
|
||||
And tadını çıkarın!
|
||||
|
||||
## Yerel Kurulum
|
||||
|
||||
Alternatif olarak, Laravel projelerinizi FrankenPHP ile yerel makinenizden çalıştırabilirsiniz:
|
||||
|
||||
1. [Sisteminize karşılık gelen binary dosyayı indirin](https://github.com/dunglas/frankenphp/releases)
|
||||
2. Aşağıdaki yapılandırmayı Laravel projenizin kök dizinindeki `Caddyfile` adlı bir dosyaya ekleyin:
|
||||
|
||||
```caddyfile
|
||||
{
|
||||
frankenphp
|
||||
order php_server before file_server
|
||||
}
|
||||
|
||||
# Sunucunuzun alan adı
|
||||
localhost {
|
||||
# Webroot'u public/ dizinine ayarlayın
|
||||
root * public/
|
||||
# Sıkıştırmayı etkinleştir (isteğe bağlı)
|
||||
encode zstd br gzip
|
||||
# PHP dosyalarını public/ dizininden çalıştırın ve varlıkları sunun
|
||||
php_server
|
||||
}
|
||||
```
|
||||
|
||||
3. FrankenPHP'yi Laravel projenizin kök dizininden başlatın: `./frankenphp run`
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
Octane, Composer paket yöneticisi aracılığıyla kurulabilir:
|
||||
|
||||
```console
|
||||
composer require laravel/octane
|
||||
```
|
||||
|
||||
Octane'ı kurduktan sonra, Octane'ın yapılandırma dosyasını uygulamanıza yükleyecek olan `octane:install` Artisan komutunu çalıştırabilirsiniz:
|
||||
|
||||
```console
|
||||
php artisan octane:install --server=frankenphp
|
||||
```
|
||||
|
||||
Octane sunucusu `octane:start` Artisan komutu aracılığıyla başlatılabilir.
|
||||
|
||||
```console
|
||||
php artisan octane:start
|
||||
```
|
||||
|
||||
`octane:start` komutu aşağıdaki seçenekleri alabilir:
|
||||
|
||||
* `--host`: Sunucunun bağlanması gereken IP adresi (varsayılan: `127.0.0.1`)
|
||||
* `--port`: Sunucunun erişilebilir olması gereken port (varsayılan: `8000`)
|
||||
* `--admin-port`: Yönetici sunucusunun erişilebilir olması gereken port (varsayılan: `2019`)
|
||||
* `--workers`: İstekleri işlemek için hazır olması gereken worker sayısı (varsayılan: `auto`)
|
||||
* `--max-requests`: Sunucu yeniden yüklenmeden önce işlenecek istek sayısı (varsayılan: `500`)
|
||||
* `--caddyfile`: FrankenPHP `Caddyfile` dosyasının yolu
|
||||
* `--https`: HTTPS, HTTP/2 ve HTTP/3'ü etkinleştirin ve sertifikaları otomatik olarak oluşturup yenileyin
|
||||
* `--http-redirect`: HTTP'den HTTPS'ye yeniden yönlendirmeyi etkinleştir (yalnızca --https geçilirse etkinleştirilir)
|
||||
* `--watch`: Uygulamada kod değişikliği olduğunda sunucuyu otomatik olarak yeniden yükle
|
||||
* `--poll`: Dosyaları bir ağ üzerinden izlemek için izleme sırasında dosya sistemi yoklamasını kullanın
|
||||
* `--log-level`: Belirtilen günlük seviyesinde veya üzerinde günlük mesajları
|
||||
|
||||
Laravel Octane hakkında daha fazla bilgi edinmek için [Laravel Octane resmi belgelerine](https://laravel.com/docs/octane) göz atın.
|
||||
12
docs/tr/mercure.md
Normal file
12
docs/tr/mercure.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Gerçek Zamanlı
|
||||
|
||||
FrankenPHP yerleşik bir [Mercure](https://mercure.rocks) hub ile birlikte gelir!
|
||||
Mercure, olayları tüm bağlı cihazlara gerçek zamanlı olarak göndermeye olanak tanır: anında bir JavaScript olayı alırlar.
|
||||
|
||||
JS kütüphanesi veya SDK gerekmez!
|
||||
|
||||

|
||||
|
||||
Mercure hub'ını etkinleştirmek için [Mercure'ün sitesinde](https://mercure.rocks/docs/hub/config) açıklandığı gibi `Caddyfile`'ı güncelleyin.
|
||||
|
||||
Mercure güncellemelerini kodunuzdan göndermek için [Symfony Mercure Bileşenini](https://symfony.com/components/Mercure) öneririz (kullanmak için Symfony tam yığın çerçevesine ihtiyacınız yoktur).
|
||||
139
docs/tr/production.md
Normal file
139
docs/tr/production.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Production Ortamına Dağıtım
|
||||
|
||||
Bu dokümanda, Docker Compose kullanarak bir PHP uygulamasını tek bir sunucuya nasıl dağıtacağımızı öğreneceğiz.
|
||||
|
||||
Symfony kullanıyorsanız, Symfony Docker projesinin (FrankenPHP kullanan) "[Production ortamına dağıtım](https://github.com/dunglas/symfony-docker/blob/main/docs/production.md)" dokümanını okumayı tercih edebilirsiniz.
|
||||
|
||||
API Platform (FrankenPHP de kullanır) tercih ediyorsanız, [çerçevenin dağıtım dokümanına](https://api-platform.com/docs/deployment/) bakabilirsiniz.
|
||||
|
||||
## Uygulamanızı Hazırlama
|
||||
|
||||
İlk olarak, PHP projenizin kök dizininde bir `Dockerfile` oluşturun:
|
||||
|
||||
```dockerfile
|
||||
FROM dunglas/frankenphp
|
||||
|
||||
# "your-domain-name.example.com" yerine kendi alan adınızı yazdığınızdan emin olun
|
||||
ENV SERVER_NAME=your-domain-name.example.com
|
||||
# HTTPS'yi devre dışı bırakmak istiyorsanız, bunun yerine bu değeri kullanın:
|
||||
#ENV SERVER_NAME=:80
|
||||
|
||||
# PHP production ayarlarını etkinleştirin
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Projenizin PHP dosyalarını genel dizine kopyalayın
|
||||
COPY . /app/public
|
||||
# Symfony veya Laravel kullanıyorsanız, bunun yerine tüm projeyi kopyalamanız gerekir:
|
||||
#COPY . /app
|
||||
```
|
||||
|
||||
Daha fazla ayrıntı ve seçenek için "[Özel Docker İmajı Oluşturma](docker.md)" bölümüne bakın,
|
||||
ve yapılandırmayı nasıl özelleştireceğinizi öğrenmek için PHP eklentilerini ve Caddy modüllerini yükleyin.
|
||||
|
||||
Projeniz Composer kullanıyorsa,
|
||||
Docker imajına dahil ettiğinizden ve bağımlılıklarınızı yüklediğinizden emin olun.
|
||||
|
||||
Ardından, bir `compose.yaml` dosyası ekleyin:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
php:
|
||||
image: dunglas/frankenphp
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "443:443/udp" # HTTP/3
|
||||
volumes:
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
|
||||
# Caddy sertifikaları ve yapılandırması için gereken yığınlar (volumes)
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Önceki örnekler production kullanımı için tasarlanmıştır.
|
||||
> Geliştirme aşamasında, bir yığın (volume), farklı bir PHP yapılandırması ve `SERVER_NAME` ortam değişkeni için farklı bir değer kullanmak isteyebilirsiniz.
|
||||
>
|
||||
> (FrankenPHP kullanan) çok aşamalı Composer, ekstra PHP eklentileri vb. içeren imajlara başvuran daha gelişmiş bir örnek için [Symfony Docker](https://github.com/dunglas/symfony-docker) projesine bir göz atın.
|
||||
|
||||
Son olarak, eğer Git kullanıyorsanız, bu dosyaları commit edin ve push edin.
|
||||
|
||||
## Sunucu Hazırlama
|
||||
|
||||
Uygulamanızı production ortamına dağıtmak için bir sunucuya ihtiyacınız vardır.
|
||||
Bu dokümanda, DigitalOcean tarafından sağlanan bir sanal makine kullanacağız, ancak herhangi bir Linux sunucusu çalışabilir.
|
||||
Docker yüklü bir Linux sunucunuz varsa, doğrudan [bir sonraki bölüme](#alan-adı-yapılandırma) geçebilirsiniz.
|
||||
|
||||
Aksi takdirde, 200 $ ücretsiz kredi almak için [bu ortaklık bağlantısını](https://m.do.co/c/5d8aabe3ab80) kullanın, bir hesap oluşturun ve ardından "Create a Droplet" seçeneğine tıklayın.
|
||||
Ardından, "Bir imaj seçin" bölümünün altındaki "Marketplace" sekmesine tıklayın ve "Docker" adlı uygulamayı bulun.
|
||||
Bu, Docker ve Docker Compose'un en son sürümlerinin zaten yüklü olduğu bir Ubuntu sunucusu sağlayacaktır!
|
||||
|
||||
Test amaçlı kullanım için en ucuz planlar yeterli olacaktır.
|
||||
Gerçek production kullanımı için, muhtemelen ihtiyaçlarınıza uyacak şekilde "genel amaçlı" bölümünden bir plan seçmek isteyeceksiniz.
|
||||
|
||||

|
||||
|
||||
Diğer ayarlar için varsayılanları koruyabilir veya ihtiyaçlarınıza göre değiştirebilirsiniz.
|
||||
SSH anahtarınızı eklemeyi veya bir parola oluşturmayı unutmayın, ardından "Sonlandır ve oluştur" düğmesine basın.
|
||||
|
||||
Ardından, Droplet'iniz hazırlanırken birkaç saniye bekleyin.
|
||||
Droplet'iniz hazır olduğunda, bağlanmak için SSH kullanın:
|
||||
|
||||
```console
|
||||
ssh root@<droplet-ip>
|
||||
```
|
||||
|
||||
## Alan Adı Yapılandırma
|
||||
|
||||
Çoğu durumda sitenizle bir alan adını ilişkilendirmek isteyeceksiniz.
|
||||
Henüz bir alan adınız yoksa, bir kayıt şirketi aracılığıyla bir alan adı satın almanız gerekir.
|
||||
|
||||
Daha sonra alan adınız için sunucunuzun IP adresini işaret eden `A` türünde bir DNS kaydı oluşturun:
|
||||
|
||||
```dns
|
||||
your-domain-name.example.com. IN A 207.154.233.113
|
||||
```
|
||||
|
||||
DigitalOcean Alan Adları hizmetiyle ilgili örnek ("Networking" > "Domains"):
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> FrankenPHP tarafından varsayılan olarak otomatik olarak TLS sertifikası oluşturmak için kullanılan hizmet olan Let's Encrypt, direkt IP adreslerinin kullanılmasını desteklemez. Let's Encrypt'i kullanmak için alan adı kullanmak zorunludur.
|
||||
|
||||
## Dağıtım
|
||||
|
||||
Projenizi `git clone`, `scp` veya ihtiyacınıza uygun başka bir araç kullanarak sunucuya kopyalayın.
|
||||
GitHub kullanıyorsanız [bir dağıtım anahtarı](https://docs.github.com/en/free-pro-team@latest/developers/overview/managing-deploy-keys#deploy-keys) kullanmak isteyebilirsiniz.
|
||||
Dağıtım anahtarları ayrıca [GitLab tarafından desteklenir](https://docs.gitlab.com/ee/user/project/deploy_keys/).
|
||||
|
||||
Git ile örnek:
|
||||
|
||||
```console
|
||||
git clone git@github.com:<username>/<project-name>.git
|
||||
```
|
||||
|
||||
Projenizi içeren dizine gidin (`<proje-adı>`) ve uygulamayı production modunda başlatın:
|
||||
|
||||
```console
|
||||
docker compose up -d --wait
|
||||
```
|
||||
|
||||
Sunucunuz hazır ve çalışıyor. Sizin için otomatik olarak bir HTTPS sertifikası oluşturuldu.
|
||||
`https://your-domain-name.example.com` adresine gidin ve keyfini çıkarın!
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Docker bir önbellek katmanına sahip olabilir, her dağıtım için doğru derlemeye sahip olduğunuzdan emin olun veya önbellek sorununu önlemek için projenizi `--no-cache` seçeneği ile yeniden oluşturun.
|
||||
|
||||
## Birden Fazla Düğümde Dağıtım
|
||||
|
||||
Uygulamanızı bir makine kümesine dağıtmak istiyorsanız, [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/) kullanabilirsiniz,
|
||||
sağlanan Compose dosyaları ile uyumludur.
|
||||
Kubernetes üzerinde dağıtım yapmak için FrankenPHP kullanan [API Platformu ile sağlanan Helm grafiğine](https://api-platform.com/docs/deployment/kubernetes/) göz atın.
|
||||
81
docs/tr/static.md
Normal file
81
docs/tr/static.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Statik Yapı Oluşturun
|
||||
|
||||
PHP kütüphanesinin yerel kurulumunu kullanmak yerine,
|
||||
harika [static-php-cli projesi](https://github.com/crazywhalecc/static-php-cli) sayesinde FrankenPHP'nin statik bir yapısını oluşturmak mümkündür (adına rağmen, bu proje sadece CLI'yi değil, tüm SAPI'leri destekler).
|
||||
|
||||
Bu yöntemle, tek, taşınabilir bir ikili PHP yorumlayıcısını, Caddy web sunucusunu ve FrankenPHP'yi içerecektir!
|
||||
|
||||
FrankenPHP ayrıca [PHP uygulamasının statik binary gömülmesini](embed.md) destekler.
|
||||
|
||||
## Linux
|
||||
|
||||
Linux statik binary dosyası oluşturmak için bir Docker imajı sağlıyoruz:
|
||||
|
||||
```console
|
||||
docker buildx bake --load static-builder
|
||||
docker cp $(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp ; docker rm static-builder
|
||||
```
|
||||
|
||||
Elde edilen statik binary `frankenphp` olarak adlandırılır ve geçerli dizinde kullanılabilir.
|
||||
|
||||
Statik binary dosyasını Docker olmadan oluşturmak istiyorsanız, Linux için de çalışan macOS talimatlarına bir göz atın.
|
||||
|
||||
### Özel Eklentiler
|
||||
|
||||
Varsayılan olarak, en popüler PHP eklentileri zaten derlenir.
|
||||
|
||||
Binary dosyanın boyutunu küçültmek ve saldırı yüzeyini azaltmak için `PHP_EXTENSIONS` Docker ARG'sini kullanarak derlenecek eklentilerin listesini seçebilirsiniz.
|
||||
|
||||
Örneğin, yalnızca `opcache` eklentisini derlemek için aşağıdaki komutu çalıştırın:
|
||||
|
||||
```console
|
||||
docker buildx bake --load --set static-builder.args.PHP_EXTENSIONS=opcache,pdo_sqlite static-builder
|
||||
# ...
|
||||
```
|
||||
|
||||
Etkinleştirdiğiniz eklentilere ek işlevler sağlayan kütüphaneler eklemek için `PHP_EXTENSION_LIBS` Docker ARG'sini kullanabilirsiniz:
|
||||
|
||||
```console
|
||||
docker buildx bake \
|
||||
--load \
|
||||
--set static-builder.args.PHP_EXTENSIONS=gd \
|
||||
--set static-builder.args.PHP_EXTENSION_LIBS=libjpeg,libwebp \
|
||||
static-builder
|
||||
```
|
||||
|
||||
Derlemeyi nasıl [özelleştireceğinize](#yapıyı-özelleştirme) de bakın.
|
||||
|
||||
### GitHub Token
|
||||
|
||||
GitHub API kullanım limitine ulaşırsanız, `GITHUB_TOKEN` adlı bir ortam değişkeninde bir GitHub Personal Access Token ayarlayın:
|
||||
|
||||
```console
|
||||
GITHUB_TOKEN="xxx" docker --load buildx bake static-builder
|
||||
# ...
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
macOS için statik bir binary oluşturmak için aşağıdaki betiği çalıştırın ([Homebrew](https://brew.sh/) yüklü olmalıdır):
|
||||
|
||||
```console
|
||||
git clone https://github.com/dunglas/frankenphp
|
||||
cd frankenphp
|
||||
./build-static.sh
|
||||
```
|
||||
|
||||
Not: Bu betik Linux'ta (ve muhtemelen diğer Unix'lerde) da çalışır ve sağladığımız Docker tabanlı statik derleyici tarafından dahili olarak kullanılır.
|
||||
|
||||
## Yapıyı Özelleştirme
|
||||
|
||||
Aşağıdaki ortam değişkenleri `docker build` ve `build-static.sh` dosyalarına aktarılabilir
|
||||
statik derlemeyi özelleştirmek için betik:
|
||||
|
||||
* `FRANKENPHP_VERSION`: kullanılacak FrankenPHP sürümü
|
||||
* `PHP_VERSION`: kullanılacak PHP sürümü
|
||||
* `PHP_EXTENSIONS`: oluşturulacak PHP eklentileri ([desteklenen eklentiler listesi](https://static-php.dev/en/guide/extensions.html))
|
||||
* `PHP_EXTENSION_LIBS`: eklentilere özellikler ekleyen oluşturulacak ekstra kütüphaneler
|
||||
* `EMBED`: binary dosyaya gömülecek PHP uygulamasının yolu
|
||||
* `CLEAN`: ayarlandığında, libphp ve tüm bağımlılıkları sıfırdan oluşturulur (önbellek yok)
|
||||
* `DEBUG_SYMBOLS`: ayarlandığında, hata ayıklama sembolleri ayıklanmayacak ve binary dosyaya eklenecektir
|
||||
* `RELEASE`: (yalnızca bakımcılar) ayarlandığında, ortaya çıkan binary dosya GitHub'a yüklenecektir
|
||||
121
docs/tr/worker.md
Normal file
121
docs/tr/worker.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# FrankenPHP Worker'ları Kullanma
|
||||
|
||||
Uygulamanızı bir kez önyükleyin ve bellekte tutun.
|
||||
FrankenPHP gelen istekleri birkaç milisaniye içinde halledecektir.
|
||||
|
||||
## Çalışan Komut Dosyalarının Başlatılması
|
||||
|
||||
### Docker
|
||||
|
||||
`FRANKENPHP_CONFIG` ortam değişkeninin değerini `worker /path/to/your/worker/script.php` olarak ayarlayın:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker /app/path/to/your/worker/script.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### Binary Çıktısı
|
||||
|
||||
Geçerli dizinin içeriğini bir worker kullanarak sunmak için `php-server` komutunun `--worker` seçeneğini kullanın:
|
||||
|
||||
```console
|
||||
./frankenphp php-server --worker /path/to/your/worker/script.php
|
||||
```
|
||||
|
||||
PHP uygulamanız [binary dosyaya gömülü](embed.md) ise, uygulamanın kök dizinine özel bir `Caddyfile` ekleyebilirsiniz.
|
||||
Otomatik olarak kullanılacaktır.
|
||||
|
||||
## Symfony Çalışma Zamanı
|
||||
|
||||
FrankenPHP'nin worker modu [Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html) tarafından desteklenmektedir.
|
||||
Herhangi bir Symfony uygulamasını bir worker'da başlatmak için [PHP Runtime](https://github.com/php-runtime/runtime)'ın FrankenPHP paketini yükleyin:
|
||||
|
||||
```console
|
||||
composer require runtime/frankenphp-symfony
|
||||
```
|
||||
|
||||
FrankenPHP Symfony Runtime'ı kullanmak için `APP_RUNTIME` ortam değişkenini tanımlayarak uygulama sunucunuzu başlatın:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
## Laravel Octane
|
||||
|
||||
Bkz. [ilgili doküman](laravel.md#laravel-octane).
|
||||
|
||||
## Özel Uygulamalar
|
||||
|
||||
Aşağıdaki örnek, üçüncü taraf bir kütüphaneye güvenmeden kendi çalışan kodunuzu nasıl oluşturacağınızı göstermektedir:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// public/index.php
|
||||
|
||||
// Bir istemci bağlantısı kesildiğinde alt komut dosyasının sonlandırılmasını önleyin
|
||||
ignore_user_abort(true);
|
||||
|
||||
// Uygulamanızı önyükleyin
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$myApp = new \App\Kernel();
|
||||
$myApp->boot();
|
||||
|
||||
// Daha iyi performans için döngü dışında işleyici (daha az iş yapıyor)
|
||||
$handler = static function () use ($myApp) {
|
||||
// Bir istek alındığında çağrılır,
|
||||
// superglobals, php://input ve benzerleri sıfırlanır
|
||||
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
};
|
||||
|
||||
for($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbRequests < ((int)$_SERVER['MAX_REQUESTS'])) && $running; ++$nbRequests) {
|
||||
$running = \frankenphp_handle_request($handler);
|
||||
|
||||
// HTTP yanıtını gönderdikten sonra bir şey yapın
|
||||
$myApp->terminate();
|
||||
|
||||
// Bir sayfa oluşturmanın ortasında tetiklenme olasılığını azaltmak için çöp toplayıcıyı çağırın
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
// Temizleme
|
||||
$myApp->shutdown();
|
||||
```
|
||||
|
||||
Ardından, uygulamanızı başlatın ve çalışanınızı yapılandırmak için `FRANKENPHP_CONFIG` ortam değişkenini kullanın:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
Varsayılan olarak, CPU başına 2 worker başlatılır.
|
||||
Başlatılacak worker sayısını da yapılandırabilirsiniz:
|
||||
|
||||
```console
|
||||
docker run \
|
||||
-e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
|
||||
-v $PWD:/app \
|
||||
-p 80:80 -p 443:443 -p 443:443/udp \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
### Belirli Sayıda İstekten Sonra Worker'ı Yeniden Başlatın
|
||||
|
||||
<!-- textlint-disable -->
|
||||
PHP başlangıçta uzun süreli işlemler için tasarlanmadığından, hala bellek sızdıran birçok kütüphane ve eski kod vardır.
|
||||
<!-- textlint-enable -->
|
||||
Bu tür kodları worker modunda kullanmak için geçici bir çözüm, belirli sayıda isteği işledikten sonra worker betiğini yeniden başlatmaktır:
|
||||
|
||||
Önceki worker kod parçacığı, `MAX_REQUESTS` adlı bir ortam değişkeni ayarlayarak işlenecek maksimum istek sayısını yapılandırmaya izin verir.
|
||||
@@ -25,6 +25,9 @@ Use the `--worker` option of the `php-server` command to serve the content of th
|
||||
./frankenphp php-server --worker /path/to/your/worker/script.php
|
||||
```
|
||||
|
||||
If your PHP app is [embeded in the binary](embed.md), you can add a custom `Caddyfile` in the root directory of the app.
|
||||
It will be used automatically.
|
||||
|
||||
## Symfony Runtime
|
||||
|
||||
The worker mode of FrankenPHP is supported by the [Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html).
|
||||
@@ -72,6 +75,7 @@ $handler = static function () use ($myApp) {
|
||||
// superglobals, php://input and the like are reset
|
||||
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
};
|
||||
|
||||
for($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbRequests < ((int)$_SERVER['MAX_REQUESTS'])) && $running; ++$nbRequests) {
|
||||
$running = \frankenphp_handle_request($handler);
|
||||
|
||||
@@ -81,6 +85,7 @@ for($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbReq
|
||||
// Call the garbage collector to reduce the chances of it being triggered in the middle of a page generation
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
$myApp->shutdown();
|
||||
```
|
||||
@@ -95,7 +100,7 @@ docker run \
|
||||
dunglas/frankenphp
|
||||
```
|
||||
|
||||
By default, one worker per CPU is started.
|
||||
By default, 2 workers per CPU are started.
|
||||
You can also configure the number of workers to start:
|
||||
|
||||
```console
|
||||
|
||||
155
frankenphp.c
155
frankenphp.c
@@ -12,6 +12,7 @@
|
||||
#include <php_output.h>
|
||||
#include <php_variables.h>
|
||||
#include <sapi/embed/php_embed.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -250,7 +251,7 @@ PHP_FUNCTION(frankenphp_request_headers) {
|
||||
|
||||
frankenphp_server_context *ctx = SG(server_context);
|
||||
struct go_apache_request_headers_return headers =
|
||||
go_apache_request_headers(ctx->current_request);
|
||||
go_apache_request_headers(ctx->current_request, ctx->main_request);
|
||||
|
||||
array_init_size(return_value, headers.r1);
|
||||
|
||||
@@ -433,6 +434,7 @@ static uintptr_t frankenphp_request_shutdown() {
|
||||
|
||||
free(ctx);
|
||||
SG(server_context) = NULL;
|
||||
ctx = NULL;
|
||||
|
||||
#if defined(ZTS)
|
||||
ts_free_thread();
|
||||
@@ -572,8 +574,23 @@ static char *frankenphp_read_cookies(void) {
|
||||
return ctx->cookie_data;
|
||||
}
|
||||
|
||||
static void frankenphp_register_known_variable(const char *key, char *value,
|
||||
zval *track_vars_array, bool f) {
|
||||
static void frankenphp_register_known_variable(const char *key, go_string value,
|
||||
zval *track_vars_array) {
|
||||
if (value.data == NULL) {
|
||||
php_register_variable_safe(key, "", 0, track_vars_array);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t new_val_len;
|
||||
if (sapi_module.input_filter(PARSE_SERVER, key, &value.data, value.len,
|
||||
&new_val_len)) {
|
||||
php_register_variable_safe(key, value.data, new_val_len, track_vars_array);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
frankenphp_register_variable_from_request_info(const char *key, char *value,
|
||||
zval *track_vars_array) {
|
||||
if (value == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -583,91 +600,80 @@ static void frankenphp_register_known_variable(const char *key, char *value,
|
||||
&new_val_len)) {
|
||||
php_register_variable_safe(key, value, new_val_len, track_vars_array);
|
||||
}
|
||||
|
||||
if (f) {
|
||||
free(value);
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void frankenphp_register_bulk_variables(char *known_variables[27],
|
||||
char **dynamic_variables, size_t size,
|
||||
zval *track_vars_array) {
|
||||
void frankenphp_register_bulk_variables(go_string known_variables[27],
|
||||
php_variable *dynamic_variables,
|
||||
size_t size, zval *track_vars_array) {
|
||||
/* Not used, but must be present */
|
||||
frankenphp_register_known_variable("AUTH_TYPE", "", track_vars_array, false);
|
||||
frankenphp_register_known_variable("REMOTE_IDENT", "", track_vars_array,
|
||||
false);
|
||||
php_register_variable_safe("AUTH_TYPE", "", 0, track_vars_array);
|
||||
php_register_variable_safe("REMOTE_IDENT", "", 0, track_vars_array);
|
||||
|
||||
/* Allocated in frankenphp_update_server_context() */
|
||||
frankenphp_register_known_variable("CONTENT_TYPE",
|
||||
(char *)SG(request_info).content_type,
|
||||
track_vars_array, false);
|
||||
frankenphp_register_known_variable("PATH_TRANSLATED",
|
||||
(char *)SG(request_info).path_translated,
|
||||
track_vars_array, false);
|
||||
frankenphp_register_known_variable(
|
||||
"QUERY_STRING", SG(request_info).query_string, track_vars_array, false);
|
||||
frankenphp_register_known_variable("REMOTE_USER",
|
||||
(char *)SG(request_info).auth_user,
|
||||
track_vars_array, false);
|
||||
frankenphp_register_known_variable("REQUEST_METHOD",
|
||||
(char *)SG(request_info).request_method,
|
||||
track_vars_array, false);
|
||||
frankenphp_register_known_variable(
|
||||
"REQUEST_URI", SG(request_info).request_uri, track_vars_array, false);
|
||||
frankenphp_register_variable_from_request_info(
|
||||
"CONTENT_TYPE", (char *)SG(request_info).content_type, track_vars_array);
|
||||
frankenphp_register_variable_from_request_info(
|
||||
"PATH_TRANSLATED", (char *)SG(request_info).path_translated,
|
||||
track_vars_array);
|
||||
frankenphp_register_variable_from_request_info(
|
||||
"QUERY_STRING", SG(request_info).query_string, track_vars_array);
|
||||
frankenphp_register_variable_from_request_info(
|
||||
"REMOTE_USER", (char *)SG(request_info).auth_user, track_vars_array);
|
||||
frankenphp_register_variable_from_request_info(
|
||||
"REQUEST_METHOD", (char *)SG(request_info).request_method,
|
||||
track_vars_array);
|
||||
frankenphp_register_variable_from_request_info(
|
||||
"REQUEST_URI", SG(request_info).request_uri, track_vars_array);
|
||||
|
||||
/* Known variables */
|
||||
frankenphp_register_known_variable("CONTENT_LENGTH", known_variables[0],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("DOCUMENT_ROOT", known_variables[1],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("DOCUMENT_URI", known_variables[2],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("GATEWAY_INTERFACE", known_variables[3],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("HTTP_HOST", known_variables[4],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("HTTPS", known_variables[5],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("PATH_INFO", known_variables[6],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("PHP_SELF", known_variables[7],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("REMOTE_ADDR", known_variables[8],
|
||||
track_vars_array,
|
||||
known_variables[8] != known_variables[9]);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("REMOTE_HOST", known_variables[9],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("REMOTE_PORT", known_variables[10],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("REQUEST_SCHEME", known_variables[11],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SCRIPT_FILENAME", known_variables[12],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SCRIPT_NAME", known_variables[13],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SERVER_NAME", known_variables[14],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SERVER_PORT", known_variables[15],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SERVER_PROTOCOL", known_variables[16],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SERVER_SOFTWARE", known_variables[17],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
frankenphp_register_known_variable("SSL_PROTOCOL", known_variables[18],
|
||||
track_vars_array, true);
|
||||
track_vars_array);
|
||||
|
||||
size_t new_val_len;
|
||||
for (size_t i = 0; i < size; i = i + 2) {
|
||||
if (sapi_module.input_filter(
|
||||
PARSE_SERVER, dynamic_variables[i], &dynamic_variables[i + 1],
|
||||
strlen(dynamic_variables[i + 1]), &new_val_len)) {
|
||||
php_register_variable_safe(dynamic_variables[i], dynamic_variables[i + 1],
|
||||
new_val_len, track_vars_array);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (sapi_module.input_filter(PARSE_SERVER, dynamic_variables[i].var,
|
||||
&dynamic_variables[i].data,
|
||||
dynamic_variables[i].data_len, &new_val_len)) {
|
||||
php_register_variable_safe(dynamic_variables[i].var,
|
||||
dynamic_variables[i].data, new_val_len,
|
||||
track_vars_array);
|
||||
}
|
||||
|
||||
free(dynamic_variables[i]);
|
||||
free(dynamic_variables[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,6 +681,11 @@ static void frankenphp_register_variables(zval *track_vars_array) {
|
||||
/* https://www.php.net/manual/en/reserved.variables.server.php */
|
||||
frankenphp_server_context *ctx = SG(server_context);
|
||||
|
||||
/* In CGI mode, we consider the environment to be a part of the server
|
||||
* variables
|
||||
*/
|
||||
php_import_environment_variables(track_vars_array);
|
||||
|
||||
go_register_variables(ctx->current_request ? ctx->current_request
|
||||
: ctx->main_request,
|
||||
track_vars_array);
|
||||
@@ -716,9 +727,27 @@ sapi_module_struct frankenphp_sapi_module = {
|
||||
STANDARD_SAPI_MODULE_PROPERTIES};
|
||||
|
||||
static void *manager_thread(void *arg) {
|
||||
// SIGPIPE must be masked in non-Go threads:
|
||||
// https://pkg.go.dev/os/signal#hdr-Go_programs_that_use_cgo_or_SWIG
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGPIPE);
|
||||
|
||||
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
|
||||
perror("failed to block SIGPIPE");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int num_threads = *((int *)arg);
|
||||
free(arg);
|
||||
arg = NULL;
|
||||
|
||||
#ifdef ZTS
|
||||
// TODO: use tsrm_startup() directly as we know the number of expected threads
|
||||
#if (PHP_VERSION_ID >= 80300)
|
||||
php_tsrm_startup_ex(num_threads);
|
||||
#else
|
||||
php_tsrm_startup();
|
||||
#endif
|
||||
/*tsrm_error_set(TSRM_ERROR_LEVEL_INFO, NULL);*/
|
||||
#ifdef PHP_WIN32
|
||||
ZEND_TSRMLS_CACHE_UPDATE();
|
||||
@@ -739,8 +768,7 @@ static void *manager_thread(void *arg) {
|
||||
|
||||
frankenphp_sapi_module.startup(&frankenphp_sapi_module);
|
||||
|
||||
threadpool thpool = thpool_init(*((int *)arg));
|
||||
free(arg);
|
||||
threadpool thpool = thpool_init(num_threads);
|
||||
|
||||
uintptr_t rh;
|
||||
while ((rh = go_fetch_request())) {
|
||||
@@ -794,6 +822,7 @@ int frankenphp_request_startup() {
|
||||
frankenphp_server_context *ctx = SG(server_context);
|
||||
SG(server_context) = NULL;
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
php_request_shutdown((void *)0);
|
||||
|
||||
@@ -803,6 +832,7 @@ int frankenphp_request_startup() {
|
||||
int frankenphp_execute_script(char *file_name) {
|
||||
if (frankenphp_request_startup() == FAILURE) {
|
||||
free(file_name);
|
||||
file_name = NULL;
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -812,6 +842,7 @@ int frankenphp_execute_script(char *file_name) {
|
||||
zend_file_handle file_handle;
|
||||
zend_stream_init_filename(&file_handle, file_name);
|
||||
free(file_name);
|
||||
file_name = NULL;
|
||||
|
||||
file_handle.primary_script = 1;
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/maypok86/otter"
|
||||
"go.uber.org/zap"
|
||||
// debug on Linux
|
||||
//_ "github.com/ianlancetaylor/cgosymbolizer"
|
||||
@@ -115,7 +116,7 @@ func (l syslogLevel) String() string {
|
||||
type FrankenPHPContext struct {
|
||||
documentRoot string
|
||||
splitPath []string
|
||||
env map[string]string
|
||||
env PreparedEnv
|
||||
logger *zap.Logger
|
||||
|
||||
docURI string
|
||||
@@ -539,50 +540,98 @@ func go_ub_write(rh C.uintptr_t, cBuf *C.char, length C.int) (C.size_t, C.bool)
|
||||
return C.size_t(i), C.bool(clientHasClosed(r))
|
||||
}
|
||||
|
||||
// There are around 60 common request headers according to https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields
|
||||
// Give some space for custom headers
|
||||
var headerKeyCache = func() otter.Cache[string, string] {
|
||||
c, err := otter.MustBuilder[string, string](256).Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}()
|
||||
|
||||
//export go_register_variables
|
||||
func go_register_variables(rh C.uintptr_t, trackVarsArray *C.zval) {
|
||||
r := cgo.Handle(rh).Value().(*http.Request)
|
||||
fc := r.Context().Value(contextKey).(*FrankenPHPContext)
|
||||
|
||||
le := (len(fc.env) + len(r.Header)) * 2
|
||||
dynamicVariables := make([]*C.char, le)
|
||||
p := &runtime.Pinner{}
|
||||
|
||||
dynamicVariables := make([]C.php_variable, len(fc.env)+len(r.Header))
|
||||
|
||||
var l int
|
||||
|
||||
var i int
|
||||
// Add all HTTP headers to env variables
|
||||
for field, val := range r.Header {
|
||||
k := "HTTP_" + headerNameReplacer.Replace(strings.ToUpper(field))
|
||||
k, ok := headerKeyCache.Get(field)
|
||||
if !ok {
|
||||
k = "HTTP_" + headerNameReplacer.Replace(strings.ToUpper(field)) + "\x00"
|
||||
headerKeyCache.SetIfAbsent(field, k)
|
||||
}
|
||||
|
||||
if _, ok := fc.env[k]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
dynamicVariables[i] = C.CString(k)
|
||||
i++
|
||||
v := strings.Join(val, ", ")
|
||||
|
||||
dynamicVariables[i] = C.CString(strings.Join(val, ", "))
|
||||
i++
|
||||
kData := unsafe.StringData(k)
|
||||
vData := unsafe.StringData(v)
|
||||
|
||||
p.Pin(kData)
|
||||
p.Pin(vData)
|
||||
|
||||
dynamicVariables[l]._var = (*C.char)(unsafe.Pointer(kData))
|
||||
dynamicVariables[l].data_len = C.size_t(len(v))
|
||||
dynamicVariables[l].data = (*C.char)(unsafe.Pointer(vData))
|
||||
|
||||
l++
|
||||
}
|
||||
|
||||
for k, v := range fc.env {
|
||||
dynamicVariables[i] = C.CString(k)
|
||||
i++
|
||||
if _, ok := knownServerKeys[k]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
dynamicVariables[i] = C.CString(v)
|
||||
i++
|
||||
kData := unsafe.StringData(k)
|
||||
vData := unsafe.Pointer(unsafe.StringData(v))
|
||||
|
||||
p.Pin(kData)
|
||||
p.Pin(vData)
|
||||
|
||||
dynamicVariables[l]._var = (*C.char)(unsafe.Pointer(kData))
|
||||
dynamicVariables[l].data_len = C.size_t(len(v))
|
||||
dynamicVariables[l].data = (*C.char)(unsafe.Pointer(vData))
|
||||
|
||||
l++
|
||||
}
|
||||
|
||||
var dynamicVariablesPtr **C.char = nil
|
||||
if le > 0 {
|
||||
dynamicVariablesPtr = &dynamicVariables[0]
|
||||
}
|
||||
knownVariables := computeKnownVariables(r, p)
|
||||
|
||||
knownVariables := computeKnownVariables(r)
|
||||
C.frankenphp_register_bulk_variables(&knownVariables[0], dynamicVariablesPtr, C.size_t(le), trackVarsArray)
|
||||
dvsd := unsafe.SliceData(dynamicVariables)
|
||||
p.Pin(dvsd)
|
||||
|
||||
C.frankenphp_register_bulk_variables(&knownVariables[0], dvsd, C.size_t(l), trackVarsArray)
|
||||
|
||||
p.Unpin()
|
||||
|
||||
fc.env = nil
|
||||
}
|
||||
|
||||
//export go_apache_request_headers
|
||||
func go_apache_request_headers(rh C.uintptr_t) (*C.go_string, C.size_t, C.uintptr_t) {
|
||||
func go_apache_request_headers(rh, mrh C.uintptr_t) (*C.go_string, C.size_t, C.uintptr_t) {
|
||||
if rh == 0 {
|
||||
// worker mode, not handling a request
|
||||
mr := cgo.Handle(mrh).Value().(*http.Request)
|
||||
mfc := mr.Context().Value(contextKey).(*FrankenPHPContext)
|
||||
|
||||
if c := mfc.logger.Check(zap.DebugLevel, "apache_request_headers() called in non-HTTP context"); c != nil {
|
||||
c.Write(zap.String("worker", mfc.scriptFilename))
|
||||
}
|
||||
|
||||
return nil, 0, 0
|
||||
}
|
||||
r := cgo.Handle(rh).Value().(*http.Request)
|
||||
|
||||
pinner := &runtime.Pinner{}
|
||||
@@ -613,6 +662,10 @@ func go_apache_request_headers(rh C.uintptr_t) (*C.go_string, C.size_t, C.uintpt
|
||||
|
||||
//export go_apache_request_cleanup
|
||||
func go_apache_request_cleanup(rh C.uintptr_t) {
|
||||
if rh == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
h := cgo.Handle(rh)
|
||||
p := h.Value().(*runtime.Pinner)
|
||||
p.Unpin()
|
||||
@@ -693,12 +746,6 @@ func go_read_post(rh C.uintptr_t, cBuf *C.char, countBytes C.size_t) (readBytes
|
||||
readBytes += C.size_t(n)
|
||||
}
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
// invalid Read on closed Body may happen because of https://github.com/golang/go/issues/15527
|
||||
fc, _ := FromContext(r.Context())
|
||||
fc.logger.Error("error while reading the request body", zap.Error(err))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
14
frankenphp.h
14
frankenphp.h
@@ -13,9 +13,15 @@
|
||||
|
||||
typedef struct go_string {
|
||||
size_t len;
|
||||
const char *data;
|
||||
char *data;
|
||||
} go_string;
|
||||
|
||||
typedef struct php_variable {
|
||||
const char *var;
|
||||
size_t data_len;
|
||||
char *data;
|
||||
} php_variable;
|
||||
|
||||
typedef struct frankenphp_version {
|
||||
unsigned char major_version;
|
||||
unsigned char minor_version;
|
||||
@@ -44,9 +50,9 @@ int frankenphp_update_server_context(
|
||||
char *auth_user, char *auth_password, int proto_num);
|
||||
int frankenphp_request_startup();
|
||||
int frankenphp_execute_script(char *file_name);
|
||||
void frankenphp_register_bulk_variables(char *known_variables[27],
|
||||
char **dynamic_variables, size_t size,
|
||||
zval *track_vars_array);
|
||||
void frankenphp_register_bulk_variables(go_string known_variables[27],
|
||||
php_variable *dynamic_variables,
|
||||
size_t size, zval *track_vars_array);
|
||||
|
||||
int frankenphp_execute_script_cli(char *script, int argc, char **argv);
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// In all tests, headers added to requests are copied on the heap using strings.Clone.
|
||||
// This was originally a workaround for https://github.com/golang/go/issues/65286#issuecomment-1920087884 (fixed in Go 1.22),
|
||||
// but this allows to catch panics occuring in real life but not when the string is in the internal binary memory.
|
||||
|
||||
package frankenphp_test
|
||||
|
||||
import (
|
||||
@@ -128,8 +132,8 @@ func TestServerVariable_worker(t *testing.T) {
|
||||
func testServerVariable(t *testing.T, opts *testOptions) {
|
||||
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
||||
req := httptest.NewRequest("POST", fmt.Sprintf("http://example.com/server-variable.php/baz/bat?foo=a&bar=b&i=%d#hash", i), strings.NewReader("foo"))
|
||||
req.SetBasicAuth("kevin", "password")
|
||||
req.Header.Add("Content-Type", "text/plain")
|
||||
req.SetBasicAuth(strings.Clone("kevin"), strings.Clone("password"))
|
||||
req.Header.Add(strings.Clone("Content-Type"), strings.Clone("text/plain"))
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, req)
|
||||
|
||||
@@ -171,13 +175,14 @@ func TestPathInfo_worker(t *testing.T) {
|
||||
testPathInfo(t, &testOptions{workerScript: "server-variable.php"})
|
||||
}
|
||||
func testPathInfo(t *testing.T, opts *testOptions) {
|
||||
cwd, _ := os.Getwd()
|
||||
testDataDir := cwd + strings.Clone("/testdata/")
|
||||
path := strings.Clone("/server-variable.php/pathinfo")
|
||||
|
||||
runTest(t, func(_ func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
cwd, _ := os.Getwd()
|
||||
testDataDir := cwd + "/testdata/"
|
||||
|
||||
requestURI := r.URL.RequestURI()
|
||||
r.URL.Path = "/server-variable.php/pathinfo"
|
||||
r.URL.Path = path
|
||||
|
||||
rewriteRequest, err := frankenphp.NewRequestWithContext(r,
|
||||
frankenphp.WithRequestDocumentRoot(testDataDir, false),
|
||||
@@ -271,7 +276,7 @@ func testPostSuperGlobals(t *testing.T, opts *testOptions) {
|
||||
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
||||
formData := url.Values{"baz": {"bat"}, "i": {fmt.Sprintf("%d", i)}}
|
||||
req := httptest.NewRequest("POST", fmt.Sprintf("http://example.com/super-globals.php?foo=bar&iG=%d", i), strings.NewReader(formData.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Content-Type", strings.Clone("application/x-www-form-urlencoded"))
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, req)
|
||||
|
||||
@@ -535,7 +540,7 @@ func testLargeRequest(t *testing.T, opts *testOptions) {
|
||||
req := httptest.NewRequest(
|
||||
"POST",
|
||||
fmt.Sprintf("http://example.com/large-request.php?i=%d", i),
|
||||
strings.NewReader(strings.Repeat("f", 1_048_576)),
|
||||
strings.NewReader(strings.Repeat("f", 6_048_576)),
|
||||
)
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, req)
|
||||
@@ -543,7 +548,7 @@ func testLargeRequest(t *testing.T, opts *testOptions) {
|
||||
resp := w.Result()
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
|
||||
assert.Contains(t, string(body), fmt.Sprintf("Request body size: 1048576 (%d)", i))
|
||||
assert.Contains(t, string(body), fmt.Sprintf("Request body size: 6048576 (%d)", i))
|
||||
}, opts)
|
||||
}
|
||||
|
||||
@@ -665,6 +670,7 @@ func BenchmarkHelloWorld(b *testing.B) {
|
||||
req := httptest.NewRequest("GET", "http://example.com/index.php", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
handler(w, req)
|
||||
}
|
||||
@@ -730,6 +736,7 @@ func BenchmarkEcho(b *testing.B) {
|
||||
req := httptest.NewRequest("POST", "http://example.com/echo.php", r)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
r.Reset(body)
|
||||
handler(w, req)
|
||||
@@ -783,8 +790,10 @@ func BenchmarkServerSuperGlobal(b *testing.B) {
|
||||
"PHP_SHA256": "4ffa3e44afc9c590e28dc0d2d31fc61f0139f8b335f11880a121b9f9b9f0634e",
|
||||
}
|
||||
|
||||
preparedEnv := frankenphp.PrepareEnv(env)
|
||||
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := frankenphp.NewRequestWithContext(r, frankenphp.WithRequestDocumentRoot(testDataDir, false), frankenphp.WithRequestEnv(env))
|
||||
req, err := frankenphp.NewRequestWithContext(r, frankenphp.WithRequestDocumentRoot(testDataDir, false), frankenphp.WithRequestPreparedEnv(preparedEnv))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -798,6 +807,7 @@ func BenchmarkServerSuperGlobal(b *testing.B) {
|
||||
req := httptest.NewRequest("GET", "http://example.com/server-variable.php", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
handler(w, req)
|
||||
}
|
||||
|
||||
16
go.mod
16
go.mod
@@ -2,20 +2,26 @@ module github.com/dunglas/frankenphp
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.22.0
|
||||
|
||||
retract v1.0.0-rc.1 // Human error
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/net v0.19.0
|
||||
github.com/maypok86/otter v1.2.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/net v0.22.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/dolthub/maphash v0.1.0 // indirect
|
||||
github.com/gammazero/deque v0.2.1 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
34
go.sum
34
go.sum
@@ -1,27 +1,39 @@
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
|
||||
github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4=
|
||||
github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
|
||||
github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/maypok86/otter v1.2.0 h1:djwBBNpp9+dyzBTY0zscIG+pyAQVXRRRMbzztf8iJ4U=
|
||||
github.com/maypok86/otter v1.2.0/go.mod h1:mKLfoI7v1HOmQMwFgX4QkRk23mX6ge3RDvjdHOWG4R4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -19,7 +19,7 @@ type opt struct {
|
||||
type workerOpt struct {
|
||||
fileName string
|
||||
num int
|
||||
env map[string]string
|
||||
env PreparedEnv
|
||||
}
|
||||
|
||||
// WithNumThreads configures the number of PHP threads to start.
|
||||
@@ -34,7 +34,7 @@ func WithNumThreads(numThreads int) Option {
|
||||
// WithWorkers configures the PHP workers to start.
|
||||
func WithWorkers(fileName string, num int, env map[string]string) Option {
|
||||
return func(o *opt) error {
|
||||
o.workers = append(o.workers, workerOpt{fileName, num, env})
|
||||
o.workers = append(o.workers, workerOpt{fileName, num, PrepareEnv(env)})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -47,8 +47,3 @@ tags=$(git tag --list --sort=-version:refname 'v*')
|
||||
previous_tag=$(awk 'NR==2 {print;exit}' <<< "${tags}")
|
||||
|
||||
gh release create --draft --generate-notes --latest --notes-start-tag "${previous_tag}" --verify-tag "v$1"
|
||||
|
||||
if [[ "$(uname -s)" = "Darwin" ]]; then
|
||||
rm -Rf dist/*
|
||||
FRANKENPHP_VERSION=$1 RELEASE=1 ./build-static.sh
|
||||
fi
|
||||
|
||||
@@ -52,9 +52,24 @@ func WithRequestSplitPath(splitPath []string) RequestOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnv set CGI-like environment variables that will be available in $_SERVER.
|
||||
type PreparedEnv = map[string]string
|
||||
|
||||
func PrepareEnv(env map[string]string) PreparedEnv {
|
||||
preparedEnv := make(PreparedEnv, len(env))
|
||||
for k, v := range env {
|
||||
preparedEnv[k+"\x00"] = v
|
||||
}
|
||||
|
||||
return preparedEnv
|
||||
}
|
||||
|
||||
// WithRequestEnv set CGI-like environment variables that will be available in $_SERVER.
|
||||
// Values set with WithEnv always have priority over automatically populated values.
|
||||
func WithRequestEnv(env map[string]string) RequestOption {
|
||||
return WithRequestPreparedEnv(PrepareEnv(env))
|
||||
}
|
||||
|
||||
func WithRequestPreparedEnv(env PreparedEnv) RequestOption {
|
||||
return func(o *FrankenPHPContext) error {
|
||||
o.env = env
|
||||
|
||||
@@ -62,7 +77,7 @@ func WithRequestEnv(env map[string]string) RequestOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogger sets the logger associated with the current request
|
||||
// WithRequestLogger sets the logger associated with the current request
|
||||
func WithRequestLogger(logger *zap.Logger) RequestOption {
|
||||
return func(o *FrankenPHPContext) error {
|
||||
o.logger = logger
|
||||
|
||||
@@ -2,19 +2,13 @@
|
||||
FROM golang-base
|
||||
|
||||
ARG FRANKENPHP_VERSION=''
|
||||
ENV FRANKENPHP_VERSION=${FRANKENPHP_VERSION}
|
||||
|
||||
ARG PHP_VERSION=''
|
||||
ENV PHP_VERSION=${PHP_VERSION}
|
||||
|
||||
ARG PHP_EXTENSIONS=''
|
||||
ENV PHP_EXTENSIONS=${PHP_EXTENSIONS}
|
||||
|
||||
ARG PHP_EXTENSION_LIBS=''
|
||||
ENV PHP_EXTENSION_LIBS=${PHP_EXTENSION_LIBS}
|
||||
|
||||
ARG CLEAN=''
|
||||
ARG EMBED=''
|
||||
ARG DEBUG_SYMBOLS=''
|
||||
|
||||
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
|
||||
|
||||
LABEL org.opencontainers.image.title=FrankenPHP
|
||||
@@ -33,6 +27,7 @@ RUN apk update; \
|
||||
bison \
|
||||
build-base \
|
||||
cmake \
|
||||
composer \
|
||||
curl \
|
||||
file \
|
||||
flex \
|
||||
@@ -47,11 +42,6 @@ RUN apk update; \
|
||||
m4 \
|
||||
make \
|
||||
pkgconfig \
|
||||
wget \
|
||||
xz ; \
|
||||
apk add --no-cache \
|
||||
--repository=https://dl-cdn.alpinelinux.org/alpine/edge/main \
|
||||
--repository=https://dl-cdn.alpinelinux.org/alpine/edge/community \
|
||||
php83 \
|
||||
php83-common \
|
||||
php83-ctype \
|
||||
@@ -66,14 +56,14 @@ RUN apk update; \
|
||||
php83-sodium \
|
||||
php83-tokenizer \
|
||||
php83-xml \
|
||||
php83-xmlwriter; \
|
||||
php83-xmlwriter \
|
||||
upx \
|
||||
wget \
|
||||
xz ; \
|
||||
ln -sf /usr/bin/php83 /usr/bin/php
|
||||
|
||||
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
|
||||
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||
ENV PATH="${PATH}:/root/.composer/vendor/bin"
|
||||
|
||||
COPY --from=composer/composer:2-bin --link /composer /usr/bin/composer
|
||||
|
||||
WORKDIR /go/src/app
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
25
testdata/load-test.js
vendored
25
testdata/load-test.js
vendored
@@ -58,7 +58,30 @@ const payload = 'foo\n'.repeat(1000)
|
||||
// about authoring k6 scripts.
|
||||
//
|
||||
export default function () {
|
||||
const res = http.post('http://localhost/echo.php', payload)
|
||||
const params = {
|
||||
headers: {
|
||||
Accept:
|
||||
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
||||
// 'Accept-Encoding': 'br',
|
||||
'Accept-Language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
|
||||
'Cache-Control': 'no-cache',
|
||||
Connection: 'keep-alive',
|
||||
Cookie:
|
||||
'user_session=myrandomuuid; __Host-user_session_same_site=myotherrandomuuid; dotcom_user=dunglas; logged_in=yes; _foo=barbarbarbarbarbar; _device_id=anotherrandomuuid; color_mode=foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar; preferred_color_mode=light; tz=Europe%2FParis; has_recent_activity=1',
|
||||
DNT: '1',
|
||||
Host: 'example.com',
|
||||
Pragma: 'no-cache',
|
||||
'Sec-Fetch-Dest': 'document',
|
||||
'Sec-Fetch-Mode': 'navigate',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-GPC': '1',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0'
|
||||
}
|
||||
}
|
||||
|
||||
const res = http.post('http://localhost/echo.php', payload, params)
|
||||
check(res, {
|
||||
'is status 200': (r) => r.status === 200,
|
||||
'is echoed': (r) => r.body === payload
|
||||
|
||||
2
testdata/request-headers.php
vendored
2
testdata/request-headers.php
vendored
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
apache_request_headers();
|
||||
|
||||
require_once __DIR__.'/_executor.php';
|
||||
|
||||
return function() {
|
||||
|
||||
@@ -30,7 +30,7 @@ func initWorkers(opt []workerOpt) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func startWorkers(fileName string, nbWorkers int, env map[string]string) error {
|
||||
func startWorkers(fileName string, nbWorkers int, env PreparedEnv) error {
|
||||
absFileName, err := filepath.Abs(fileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("workers %q: %w", fileName, err)
|
||||
@@ -50,10 +50,10 @@ func startWorkers(fileName string, nbWorkers int, env map[string]string) error {
|
||||
)
|
||||
|
||||
if env == nil {
|
||||
env = make(map[string]string, 1)
|
||||
env = make(PreparedEnv, 1)
|
||||
}
|
||||
|
||||
env["FRANKENPHP_WORKER"] = "1"
|
||||
env["FRANKENPHP_WORKER\x00"] = "1\x00"
|
||||
|
||||
l := getLogger()
|
||||
for i := 0; i < nbWorkers; i++ {
|
||||
@@ -68,7 +68,7 @@ func startWorkers(fileName string, nbWorkers int, env map[string]string) error {
|
||||
r, err = NewRequestWithContext(
|
||||
r,
|
||||
WithRequestDocumentRoot(filepath.Dir(absFileName), false),
|
||||
WithRequestEnv(env),
|
||||
WithRequestPreparedEnv(env),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestWorker(t *testing.T) {
|
||||
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
||||
formData := url.Values{"baz": {"bat"}}
|
||||
req := httptest.NewRequest("POST", "http://example.com/worker.php?foo=bar", strings.NewReader(formData.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Content-Type", strings.Clone("application/x-www-form-urlencoded"))
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, req)
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestWorker(t *testing.T) {
|
||||
|
||||
formData2 := url.Values{"baz2": {"bat2"}}
|
||||
req2 := httptest.NewRequest("POST", "http://example.com/worker.php?foo2=bar2", strings.NewReader(formData2.Encode()))
|
||||
req2.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req2.Header.Set("Content-Type", strings.Clone("application/x-www-form-urlencoded"))
|
||||
|
||||
w2 := httptest.NewRecorder()
|
||||
handler(w2, req2)
|
||||
|
||||
Reference in New Issue
Block a user