mirror of
https://github.com/dunglas/frankenphp.git
synced 2025-12-24 13:38:11 +08:00
Compare commits
9 Commits
feat/apach
...
ci/fix-doc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34262949d7 | ||
|
|
e53b1ce891 | ||
|
|
6dee113a01 | ||
|
|
fe7e9e7c79 | ||
|
|
ab7ce9cb18 | ||
|
|
5afde55ebf | ||
|
|
da63e700b0 | ||
|
|
5a8e5f9518 | ||
|
|
3d9f344a50 |
18
.github/workflows/docker.yaml
vendored
18
.github/workflows/docker.yaml
vendored
@@ -19,6 +19,7 @@ on:
|
||||
- cron: '0 4 * * *'
|
||||
env:
|
||||
IMAGE_NAME: ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/')) && 'dunglas/frankenphp' || 'dunglas/frankenphp-dev' }}
|
||||
LATEST: ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/')) && '0' || '1' }}
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -37,6 +38,8 @@ jobs:
|
||||
-
|
||||
name: Check PHP versions
|
||||
id: check
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
PHP_82_LATEST=$(skopeo inspect docker://docker.io/library/php:8.2 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
|
||||
PHP_83_LATEST=$(skopeo inspect docker://docker.io/library/php:8.3 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
|
||||
@@ -45,13 +48,13 @@ jobs:
|
||||
echo php82_version="${PHP_82_LATEST//./-}"
|
||||
echo php83_version="${PHP_83_LATEST//./-}"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
|
||||
|
||||
# Check if the Docker images must be rebuilt
|
||||
if [[ "${GITHUB_EVENT_NAME}" != "schedule" ]]; then
|
||||
echo skip=false >> "${GITHUB_OUTPUT}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
FRANKENPHP_82_LATEST=$(skopeo inspect docker://docker.io/dunglas/frankenphp:latest-php8.2 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
|
||||
FRANKENPHP_83_LATEST=$(skopeo inspect docker://docker.io/dunglas/frankenphp:latest-php8.3 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
|
||||
|
||||
@@ -59,7 +62,7 @@ jobs:
|
||||
echo skip=true >> "${GITHUB_OUTPUT}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
{
|
||||
echo ref="$(gh release view --repo dunglas/frankenphp --json tagName --jq '.tagName')"
|
||||
echo skip=false
|
||||
@@ -89,7 +92,6 @@ jobs:
|
||||
SHA: ${{ github.sha }}
|
||||
VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || steps.check.outputs.ref || github.sha }}
|
||||
PHP_VERSION: ${{ steps.check.outputs.php_version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
@@ -160,7 +162,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 }}
|
||||
@@ -229,7 +231,8 @@ jobs:
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: latest
|
||||
# Temporary fix for https://github.com/docker/buildx/issues/2229
|
||||
version: "https://github.com/docker/buildx.git#master"
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
@@ -240,9 +243,10 @@ jobs:
|
||||
name: Create manifest list and push
|
||||
working-directory: /tmp/metadata
|
||||
run: |
|
||||
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 }}
|
||||
-
|
||||
|
||||
5
.github/workflows/static.yaml
vendored
5
.github/workflows/static.yaml
vendored
@@ -19,6 +19,7 @@ on:
|
||||
- cron: '0 0 * * *'
|
||||
env:
|
||||
IMAGE_NAME: ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/')) && 'dunglas/frankenphp' || 'dunglas/frankenphp-dev' }}
|
||||
LATEST: ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/')) && '0' || '1' }}
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -113,7 +114,7 @@ jobs:
|
||||
*.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' || '' }}
|
||||
${{ 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}}
|
||||
@@ -188,7 +189,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 }}
|
||||
-
|
||||
|
||||
@@ -144,3 +144,18 @@ RUN adduser -D ${USER} \
|
||||
# Caddy requires write access to /data/caddy and /config/caddy
|
||||
RUN chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy
|
||||
```
|
||||
|
||||
## Updates
|
||||
|
||||
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
|
||||
|
||||
## Development Versions
|
||||
|
||||
Development versions are available in the [`dunglas/frankenphp-dev`](https://hub.docker.com/repository/docker/dunglas/frankenphp-dev) Docker repository.
|
||||
A new build is triggered every time a commit is pushed to the main branch of the GitHub repository.
|
||||
|
||||
The `latest*` tags point to the head of the `main` branch.
|
||||
Tags of the form `sha-<git-commit-hash>` are also available.
|
||||
|
||||
64
frankenphp.c
64
frankenphp.c
@@ -243,7 +243,7 @@ PHP_FUNCTION(frankenphp_finish_request) { /* {{{ */
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ Fetch all HTTP request headers */
|
||||
PHP_FUNCTION(apache_request_headers) {
|
||||
PHP_FUNCTION(frankenphp_request_headers) {
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -261,7 +261,59 @@ PHP_FUNCTION(apache_request_headers) {
|
||||
add_assoc_stringl_ex(return_value, key.data, key.len, val.data, val.len);
|
||||
}
|
||||
|
||||
free(headers.r0);
|
||||
go_apache_request_cleanup(headers.r2);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
// add_response_header and apache_response_headers are copied from
|
||||
// https://github.com/php/php-src/blob/master/sapi/cli/php_cli_server.c
|
||||
// Copyright (c) The PHP Group
|
||||
// Licensed under The PHP License
|
||||
// Original authors: Moriyoshi Koizumi <moriyoshi@php.net> and Xinchen Hui
|
||||
// <laruence@php.net>
|
||||
static void add_response_header(sapi_header_struct *h,
|
||||
zval *return_value) /* {{{ */
|
||||
{
|
||||
if (h->header_len > 0) {
|
||||
char *s;
|
||||
size_t len = 0;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
char *p = strchr(h->header, ':');
|
||||
if (NULL != p) {
|
||||
len = p - h->header;
|
||||
}
|
||||
if (len > 0) {
|
||||
while (len != 0 &&
|
||||
(h->header[len - 1] == ' ' || h->header[len - 1] == '\t')) {
|
||||
len--;
|
||||
}
|
||||
if (len) {
|
||||
s = do_alloca(len + 1, use_heap);
|
||||
memcpy(s, h->header, len);
|
||||
s[len] = 0;
|
||||
do {
|
||||
p++;
|
||||
} while (*p == ' ' || *p == '\t');
|
||||
add_assoc_stringl_ex(return_value, s, len, p,
|
||||
h->header_len - (p - h->header));
|
||||
free_alloca(s, use_heap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_FUNCTION(frankenphp_response_headers) /* {{{ */
|
||||
{
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
zend_llist_apply_with_argument(
|
||||
&SG(sapi_headers).headers,
|
||||
(llist_apply_with_arg_func_t)add_response_header, return_value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -784,8 +836,12 @@ static char *cli_script;
|
||||
static int cli_argc;
|
||||
static char **cli_argv;
|
||||
|
||||
// Adapted from https://github.com/php/php-src/sapi/cli/php_cli.c (The PHP
|
||||
// Group, The PHP License)
|
||||
// CLI code is adapted from
|
||||
// https://github.com/php/php-src/blob/master/sapi/cli/php_cli.c Copyright (c)
|
||||
// The PHP Group Licensed under The PHP License Original uthors: Edin Kadribasic
|
||||
// <edink@php.net>, Marcus Boerger <helly@php.net> and Johannes Schlueter
|
||||
// <johannes@php.net> Parts based on CGI SAPI Module by Rasmus Lerdorf, Stig
|
||||
// Bakken and Zeev Suraski
|
||||
static void cli_register_file_handles(bool no_close) /* {{{ */
|
||||
{
|
||||
php_stream *s_in, *s_out, *s_err;
|
||||
|
||||
@@ -582,24 +582,41 @@ func go_register_variables(rh C.uintptr_t, trackVarsArray *C.zval) {
|
||||
}
|
||||
|
||||
//export go_apache_request_headers
|
||||
func go_apache_request_headers(rh C.uintptr_t) (*C.go_string, C.size_t) {
|
||||
func go_apache_request_headers(rh C.uintptr_t) (*C.go_string, C.size_t, C.uintptr_t) {
|
||||
r := cgo.Handle(rh).Value().(*http.Request)
|
||||
|
||||
rl := len(r.Header)
|
||||
scs := unsafe.Sizeof(C.go_string{})
|
||||
pinner := &runtime.Pinner{}
|
||||
pinnerHandle := C.uintptr_t(cgo.NewHandle(pinner))
|
||||
|
||||
headers := make([]C.go_string, 0, len(r.Header)*2)
|
||||
|
||||
headers := (*C.go_string)(unsafe.Pointer(C.malloc(C.size_t(rl*2) * (C.size_t)(scs))))
|
||||
header := headers
|
||||
for field, val := range r.Header {
|
||||
*header = C.go_string{C.size_t(len(field)), (*C.char)(unsafe.Pointer(unsafe.StringData(field)))}
|
||||
header = (*C.go_string)(unsafe.Add(unsafe.Pointer(header), scs))
|
||||
fd := unsafe.StringData(field)
|
||||
pinner.Pin(fd)
|
||||
|
||||
cv := strings.Join(val, ", ")
|
||||
*header = C.go_string{C.size_t(len(cv)), (*C.char)(unsafe.Pointer(unsafe.StringData(cv)))}
|
||||
header = (*C.go_string)(unsafe.Add(unsafe.Pointer(header), scs))
|
||||
vd := unsafe.StringData(cv)
|
||||
pinner.Pin(vd)
|
||||
|
||||
headers = append(
|
||||
headers,
|
||||
C.go_string{C.size_t(len(field)), (*C.char)(unsafe.Pointer(fd))},
|
||||
C.go_string{C.size_t(len(cv)), (*C.char)(unsafe.Pointer(vd))},
|
||||
)
|
||||
}
|
||||
|
||||
return headers, C.size_t(rl)
|
||||
sd := unsafe.SliceData(headers)
|
||||
pinner.Pin(sd)
|
||||
|
||||
return sd, C.size_t(len(r.Header)), pinnerHandle
|
||||
}
|
||||
|
||||
//export go_apache_request_cleanup
|
||||
func go_apache_request_cleanup(rh C.uintptr_t) {
|
||||
h := cgo.Handle(rh)
|
||||
p := h.Value().(*runtime.Pinner)
|
||||
p.Unpin()
|
||||
h.Delete()
|
||||
}
|
||||
|
||||
func addHeader(fc *FrankenPHPContext, cString *C.char, length C.int) {
|
||||
|
||||
@@ -13,9 +13,22 @@ function frankenphp_finish_request(): bool {}
|
||||
*/
|
||||
function fastcgi_finish_request(): bool {}
|
||||
|
||||
function frankenphp_request_headers(): array {}
|
||||
|
||||
/**
|
||||
* @alias frankenphp_request_headers
|
||||
*/
|
||||
function apache_request_headers(): array {}
|
||||
|
||||
/**
|
||||
* @alias apache_request_headers
|
||||
* @alias frankenphp_response_headers
|
||||
*/
|
||||
function getallheaders(): array {}
|
||||
|
||||
function frankenphp_response_headers(): array|bool {}
|
||||
|
||||
/**
|
||||
* @alias frankenphp_response_headers
|
||||
*/
|
||||
function apache_response_headers(): array|bool {}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: f925a1c280fb955eb32d0823cbd4f360b0cbabed */
|
||||
* Stub hash: 467f1406e17d3b8ca67bba5ea367194e60d8dd27 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_handle_request, 0, 1,
|
||||
_IS_BOOL, 0)
|
||||
@@ -16,16 +16,25 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_fastcgi_finish_request arginfo_frankenphp_finish_request
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_apache_request_headers, 0, 0,
|
||||
IS_ARRAY, 0)
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_request_headers, 0,
|
||||
0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_getallheaders arginfo_apache_request_headers
|
||||
#define arginfo_apache_request_headers arginfo_frankenphp_request_headers
|
||||
|
||||
#define arginfo_getallheaders arginfo_frankenphp_request_headers
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_frankenphp_response_headers, 0,
|
||||
0, MAY_BE_ARRAY | MAY_BE_BOOL)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_apache_response_headers arginfo_frankenphp_response_headers
|
||||
|
||||
ZEND_FUNCTION(frankenphp_handle_request);
|
||||
ZEND_FUNCTION(headers_send);
|
||||
ZEND_FUNCTION(frankenphp_finish_request);
|
||||
ZEND_FUNCTION(apache_request_headers);
|
||||
ZEND_FUNCTION(frankenphp_request_headers);
|
||||
ZEND_FUNCTION(frankenphp_response_headers);
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(frankenphp_handle_request, arginfo_frankenphp_handle_request)
|
||||
@@ -33,6 +42,16 @@ static const zend_function_entry ext_functions[] = {
|
||||
frankenphp_finish_request, arginfo_frankenphp_finish_request)
|
||||
ZEND_FALIAS(fastcgi_finish_request, frankenphp_finish_request,
|
||||
arginfo_fastcgi_finish_request)
|
||||
ZEND_FE(apache_request_headers, arginfo_apache_request_headers)
|
||||
ZEND_FALIAS(getallheaders, apache_request_headers,
|
||||
arginfo_getallheaders) ZEND_FE_END};
|
||||
ZEND_FE(frankenphp_request_headers,
|
||||
arginfo_frankenphp_request_headers)
|
||||
ZEND_FALIAS(apache_request_headers,
|
||||
frankenphp_request_headers,
|
||||
arginfo_apache_request_headers)
|
||||
ZEND_FALIAS(getallheaders, frankenphp_response_headers,
|
||||
arginfo_getallheaders)
|
||||
ZEND_FE(frankenphp_response_headers,
|
||||
arginfo_frankenphp_response_headers)
|
||||
ZEND_FALIAS(apache_response_headers,
|
||||
frankenphp_response_headers,
|
||||
arginfo_apache_response_headers)
|
||||
ZEND_FE_END};
|
||||
|
||||
@@ -226,6 +226,27 @@ func testHeaders(t *testing.T, opts *testOptions) {
|
||||
}, opts)
|
||||
}
|
||||
|
||||
func TestResponseHeaders_module(t *testing.T) { testResponseHeaders(t, nil) }
|
||||
func TestResponseHeaders_worker(t *testing.T) {
|
||||
testResponseHeaders(t, &testOptions{workerScript: "response-headers.php"})
|
||||
}
|
||||
func testResponseHeaders(t *testing.T, opts *testOptions) {
|
||||
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
||||
req := httptest.NewRequest("GET", fmt.Sprintf("http://example.com/response-headers.php?i=%d", i), nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, req)
|
||||
|
||||
resp := w.Result()
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
|
||||
assert.Contains(t, string(body), "'X-Powered-By' => 'PH")
|
||||
assert.Contains(t, string(body), "'Foo' => 'bar',")
|
||||
assert.Contains(t, string(body), "'Foo2' => 'bar2',")
|
||||
assert.Contains(t, string(body), fmt.Sprintf("'I' => '%d',", i))
|
||||
assert.NotContains(t, string(body), "Invalid")
|
||||
}, opts)
|
||||
}
|
||||
|
||||
func TestInput_module(t *testing.T) { testInput(t, nil) }
|
||||
func TestInput_worker(t *testing.T) { testInput(t, &testOptions{workerScript: "input.php"}) }
|
||||
func testInput(t *testing.T, opts *testOptions) {
|
||||
@@ -553,15 +574,15 @@ func testFiberNoCgo(t *testing.T, opts *testOptions) {
|
||||
}, opts)
|
||||
}
|
||||
|
||||
func TestApacheRequestHeaders_module(t *testing.T) { testApacheRequestHeaders(t, &testOptions{}) }
|
||||
func TestApacheRequestHeaders_worker(t *testing.T) {
|
||||
testApacheRequestHeaders(t, &testOptions{workerScript: "apache-request-headers.php"})
|
||||
func TestRequestHeaders_module(t *testing.T) { testRequestHeaders(t, &testOptions{}) }
|
||||
func TestRequestHeaders_worker(t *testing.T) {
|
||||
testRequestHeaders(t, &testOptions{workerScript: "request-headers.php"})
|
||||
}
|
||||
func testApacheRequestHeaders(t *testing.T, opts *testOptions) {
|
||||
func testRequestHeaders(t *testing.T, opts *testOptions) {
|
||||
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
||||
req := httptest.NewRequest("GET", fmt.Sprintf("http://example.com/apache-request-headers.php?i=%d", i), nil)
|
||||
req.Header.Add("Content-Type", "text/plain")
|
||||
req.Header.Add("Frankenphp-I", strconv.Itoa(i))
|
||||
req := httptest.NewRequest("GET", fmt.Sprintf("http://example.com/request-headers.php?i=%d", i), nil)
|
||||
req.Header.Add(strings.Clone("Content-Type"), strings.Clone("text/plain"))
|
||||
req.Header.Add(strings.Clone("Frankenphp-I"), strings.Clone(strconv.Itoa(i)))
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, req)
|
||||
@@ -714,3 +735,70 @@ func BenchmarkEcho(b *testing.B) {
|
||||
handler(w, req)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkServerSuperGlobal(b *testing.B) {
|
||||
if err := frankenphp.Init(frankenphp.WithLogger(zap.NewNop())); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer frankenphp.Shutdown()
|
||||
cwd, _ := os.Getwd()
|
||||
testDataDir := cwd + "/testdata/"
|
||||
|
||||
// Mimicks headers of a request sent by Firefox to GitHub
|
||||
headers := http.Header{}
|
||||
headers.Add(strings.Clone("Accept"), strings.Clone("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"))
|
||||
headers.Add(strings.Clone("Accept-Encoding"), strings.Clone("gzip, deflate, br"))
|
||||
headers.Add(strings.Clone("Accept-Language"), strings.Clone("fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3"))
|
||||
headers.Add(strings.Clone("Cache-Control"), strings.Clone("no-cache"))
|
||||
headers.Add(strings.Clone("Connection"), strings.Clone("keep-alive"))
|
||||
headers.Add(strings.Clone("Cookie"), strings.Clone("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"))
|
||||
headers.Add(strings.Clone("DNT"), strings.Clone("1"))
|
||||
headers.Add(strings.Clone("Host"), strings.Clone("example.com"))
|
||||
headers.Add(strings.Clone("Pragma"), strings.Clone("no-cache"))
|
||||
headers.Add(strings.Clone("Sec-Fetch-Dest"), strings.Clone("document"))
|
||||
headers.Add(strings.Clone("Sec-Fetch-Mode"), strings.Clone("navigate"))
|
||||
headers.Add(strings.Clone("Sec-Fetch-Site"), strings.Clone("cross-site"))
|
||||
headers.Add(strings.Clone("Sec-GPC"), strings.Clone("1"))
|
||||
headers.Add(strings.Clone("Upgrade-Insecure-Requests"), strings.Clone("1"))
|
||||
headers.Add(strings.Clone("User-Agent"), strings.Clone("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0"))
|
||||
|
||||
// Env vars available in a typical Docker container
|
||||
env := map[string]string{
|
||||
"HOSTNAME": "a88e81aa22e4",
|
||||
"PHP_INI_DIR": "/usr/local/etc/php",
|
||||
"HOME": "/root",
|
||||
"GODEBUG": "cgocheck=0",
|
||||
"PHP_LDFLAGS": "-Wl,-O1 -pie",
|
||||
"PHP_CFLAGS": "-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64",
|
||||
"PHP_VERSION": "8.3.2",
|
||||
"GPG_KEYS": "1198C0117593497A5EC5C199286AF1F9897469DC C28D937575603EB4ABB725861C0779DC5C0A9DE4 AFD8691FDAEDF03BDF6E460563F15A9B715376CA",
|
||||
"PHP_CPPFLAGS": "-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64",
|
||||
"PHP_ASC_URL": "https://www.php.net/distributions/php-8.3.2.tar.xz.asc",
|
||||
"PHP_URL": "https://www.php.net/distributions/php-8.3.2.tar.xz",
|
||||
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"XDG_CONFIG_HOME": "/config",
|
||||
"XDG_DATA_HOME": "/data",
|
||||
"PHPIZE_DEPS": "autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c",
|
||||
"PWD": "/app",
|
||||
"PHP_SHA256": "4ffa3e44afc9c590e28dc0d2d31fc61f0139f8b335f11880a121b9f9b9f0634e",
|
||||
}
|
||||
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := frankenphp.NewRequestWithContext(r, frankenphp.WithRequestDocumentRoot(testDataDir, false), frankenphp.WithRequestEnv(env))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r.Header = headers
|
||||
if err := frankenphp.ServeHTTP(w, req); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
req := httptest.NewRequest("GET", "http://example.com/server-variable.php", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
handler(w, req)
|
||||
}
|
||||
}
|
||||
|
||||
13
testdata/response-headers.php
vendored
Normal file
13
testdata/response-headers.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__.'/_executor.php';
|
||||
|
||||
return function () {
|
||||
header('Foo: bar');
|
||||
header('Foo2: bar2');
|
||||
header('Invalid');
|
||||
header('I: ' . ($_GET['i'] ?? 'i not set'));
|
||||
http_response_code(201);
|
||||
|
||||
var_export(apache_response_headers());
|
||||
};
|
||||
Reference in New Issue
Block a user