Compare commits

..
Author SHA1 Message Date
Jeppe Bundgaard 85eb0039d1 Add department hardware workspace backend 2026-04-23 12:45:07 +02:00
798 changed files with 9594 additions and 297242 deletions
+1 -7
View File
@@ -1,7 +1 @@
/docker-compose.yml
# Runtime-generated replication bootstrap snapshots may contain infrastructure
# metadata and encrypted/plaintext credential material. They must be
# supplied at runtime via mounted storage, not baked into deployment images.
/services/nginx/app/storage/replication-bootstrap.json
/services/nginx/app/storage/replication-bootstrap-*.json
/docker-compose.yml
+1 -6
View File
@@ -31,9 +31,6 @@ CONFIG_DB_DATABASE=
CONFIG_DB_PORT=3306
CONFIG_DB_SSL_MODE=DISABLED
# Browser origins allowed to call the API. Path-like entries are normalized to origins by the PHP CORS policy.
CORS=https://truckwash.io,https://www.truckwash.io,https://api.truckwash.io,https://api.truckwash.io:4433,https://api-v2.truckwash.io,https://web.truckwash.dk,https://api.truckwash.dk,https://truckwash.dk,https://www.truckwash.dk,https://staging.truckwash.io,http://localhost,https://localhost,http://localhost:4433,https://localhost:4433,https://twdev.jeppeb.dk,http://localhost:5173
# Debug DB credentials (used when CONFIG_DB_TARGET=debug)
# Any blank debug value falls back to the live value above.
CONFIG_DB_DEBUG_HOST=mysql-debug
@@ -52,9 +49,7 @@ ECONOMIC_API_APP_SECRET_TOKEN=
# Edge broker defaults for shell relay and gateway dispatch.
EDGE_BROKER_URL=http://edge-broker:4300
EDGE_PUBLIC_BROKER_URL=http://localhost/api/edge-broker
EDGE_AUTH_MODE=strict
EDGE_BROKER_SHARED_SECRET=
EDGE_BROKER_SHARED_SECRET=truckwash-edge-dev
# Redis credentials
REDIS_CONFIG_HOST=redis
+42
View File
@@ -0,0 +1,42 @@
USE_ENV=true
# Target of the database connection. Can be either 'live' or 'debug'.
CONFIG_DB_TARGET=live
CONFIG_DB_DATABASE=nnks_db
#CONFIG_DB_HOST=94.130.142.41
CONFIG_DB_HOST=23.88.23.183
CONFIG_DB_PASSWORD=562X0Lrr7Cz6zpXZ11I
CONFIG_DB_USER=root
CONFIG_DB_PORT=5432
CONFIG_DB_DEBUG_DATABASE=nnks_db
CONFIG_DB_DEBUG_HOST=23.88.23.183
CONFIG_DB_DEBUG_PORT=5432
CONFIG_DB_DEBUG_PASSWORD=562X0Lrr7Cz6zpXZ11I
CONFIG_DB_DEBUG_USER=root
CONFIG_TIMEZONE=Europe/Copenhagen
CORS=https://truckwash.io,https://www.truckwash.io,https://api.truckwash.io,https://api.truckwash.io:4433,https://web.truckwash.dk,https://api.truckwash.dk,https://truckwash.dk,https://www.truckwash.dk,https://staging.truckwash.io,http://localhost,https://localhost,http://localhost:4433,https://localhost:4433,https://twdev.jeppeb.dk,http://localhost:5173
# CORS=*
DEBUG=false
ECONOMIC_API_APP_ACCESS_GRANT=94bhkmdtaDA7kVn9abF2SGDccBDMvk5a6iWYnmJMbvQ1
ECONOMIC_API_APP_ACCESS_GRANT2=qGSBSkh1pjBtdSOygHhaMPn1A4PcMto3sCDCGYpLmsg1
ECONOMIC_API_APP_SECRET_TOKEN=V8GSEcIxMsTISczzTTBbOAMJyh8eucGZtBiGOxjMFg0
EMAIL_WASH_CERTIFICATE_TOKEN=H7uDTtFaeN4asqpb5okh6dr8z209SGtt
ENCRYPTION_KEY=Gvm37uF2VyTOjGkVl4kjrGQ0qRwOyq9lr3+p/QyUDjc\\=
MINIO_ACCESS_KEY=d7u6RaFyYmckAIWYGUYr
MINIO_ENDPOINT=http://162.55.225.220:9000
MINIO_SECRET_KEY=a2wJUQfkOPNO3UJfXYIdpNq4r1RrthcjiUfW1gVS
REDIS_CONFIG_DATABASE=0
REDIS_CONFIG_HOST=23.88.23.183
REDIS_CONFIG_PASSWORD=BlVg5o1NwkkR1IjKxQm
REDIS_CONFIG_PORT=5433
REDIS_CONFIG_USER=default
REDIS_CONFIG_DEBUG_PORT=5433
REDIS_CONFIG_DEBUG_USER=default
SLACK_DEFAULT_WEBHOOK=https://hooks.slaCk.com/services/T05SRKWTX9C/B08AGMP459P/1W5JN1NpHsHlbHHM2WljpvrU
WORDPRESS_API_URL=https://www.truckwash.dk/wp-admin/admin-ajax.php
WORDPRESS_STATIC_TOKEN=earm8BX4MFTgS6JCNQdqW5EzHUutv2Vx
ELASTIC_APM_SERVER_URL=http://elastic-agent:8200
ELASTIC_APM_SECRET_TOKEN=apm_dev_token
ELASTIC_APM_SERVICE_NAME=api-truckwash
ELASTIC_APM_ENVIRONMENT=dev
AUTO_COMPOSER_INSTALL=false
-15
View File
@@ -1,15 +0,0 @@
* text=auto eol=lf
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.webp binary
*.woff binary
*.woff2 binary
*.ttf binary
*.otf binary
*.pdf binary
*.zip binary
*.webm binary
-56
View File
@@ -1,56 +0,0 @@
# Default branch protection
`master` is changed through pull requests. Do not push or publish directly to
the default branch, including through automation or the Git Data API.
## Normal publishing flow
1. Create a scoped `agent/*` or feature branch from the current `origin/master`.
2. Commit and push only the intended changes.
3. Open a pull request targeting `master`.
4. Wait for the `Required CI` check. If `master` moves, update the branch and
wait for the strict check to rerun.
5. Resolve every review conversation and squash-merge the pull request.
6. Confirm the post-merge `Release Manager gate` completes on `master`.
The aggregate check covers the PHP unit, integration, API, and legacy matrix,
plus Edge Agent, Edge Broker, and Edge Gateway Backend. Qodana is advisory and
the Release Manager gate is intentionally post-merge.
## Desired ruleset
[`rulesets/protect-default-branch.json`](rulesets/protect-default-branch.json)
is the importable final desired-state repository-ruleset request body. For the
initial POST, copy the file and override `enforcement` to `disabled`. Inspect
the normalized ruleset and verify a green preparation PR and post-merge run,
then PUT the exact committed file to activate it.
The desired rule targets `~DEFAULT_BRANCH`, requires pull requests with zero
approvals, conversation resolution, strict `Required CI` from GitHub Actions
integration `15368`, squash-only linear history, and blocks deletion and force
pushes. Repository administrators receive pull-request-only bypass; they do not
receive a standing direct-push bypass.
When the ruleset is activated, align repository settings at the same time:
retain squash merging, disable merge commits and rebase merging, enable
auto-merge and branch-update suggestions, delete merged branches automatically,
keep the Actions token read-only, and prevent Actions from approving reviews.
## Activation record
Repository ruleset `19041620` was activated on 2026-07-16 after preparation
PR #311 passed `Required CI` and the merged `master` commit passed both
`Required CI` and the `Release Manager gate`. This documentation update is
the after-activation canary for the normal protected pull-request path.
## Break glass
When an incident cannot wait for the normal gate:
1. Open a pull request and describe the incident, risk, and reason for bypass.
2. Have a repository administrator use the pull-request-only bypass.
3. Monitor `Required CI` and the post-merge Release Manager workflow.
4. Open a follow-up pull request for any deferred validation or remediation.
Never bypass by updating `refs/heads/master` directly. Ruleset changes and
emergency bypasses must remain visible in GitHub's audit trail.
-48
View File
@@ -1,48 +0,0 @@
USE_ENV=true
DEBUG=true
ENCRYPTION_KEY=ci-test-encryption-key
CORS=*
CONFIG_TIMEZONE=Europe/Copenhagen
CONFIG_DB_TARGET=debug
CONFIG_DB_HOST=mysql-debug
CONFIG_DB_USER=root
CONFIG_DB_PASSWORD=debug_root_password
CONFIG_DB_DATABASE=nnks_db_debug
CONFIG_DB_PORT=3306
CONFIG_DB_SSL_MODE=DISABLED
CONFIG_DB_DEBUG_HOST=mysql-debug
CONFIG_DB_DEBUG_USER=root
CONFIG_DB_DEBUG_PASSWORD=debug_root_password
CONFIG_DB_DEBUG_DATABASE=nnks_db_debug
CONFIG_DB_DEBUG_PORT=3306
CONFIG_DB_DEBUG_SSL_MODE=DISABLED
REDIS_CONFIG_HOST=redis
REDIS_CONFIG_USER=default
REDIS_CONFIG_DATABASE=0
REDIS_CONFIG_PASSWORD=
REDIS_CONFIG_PORT=6379
REDIS_CONFIG_DEBUG_HOST=redis
REDIS_CONFIG_DEBUG_USER=default
REDIS_CONFIG_DEBUG_DATABASE=0
REDIS_CONFIG_DEBUG_PASSWORD=
REDIS_CONFIG_DEBUG_PORT=6379
ECONOMIC_API_APP_ACCESS_GRANT=ci-test
ECONOMIC_API_APP_ACCESS_GRANT2=ci-test-secondary
ECONOMIC_API_APP_SECRET_TOKEN=ci-test-secret
WORDPRESS_STATIC_TOKEN=ci-test
EMAIL_WASH_CERTIFICATE_TOKEN=ci-test
WORDPRESS_API_URL=http://localhost
MINIO_ENDPOINT=
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
SLACK_DEFAULT_WEBHOOK=
EDGE_BROKER_URL=http://edge-broker:4300
EDGE_PUBLIC_BROKER_URL=http://localhost/api/edge-broker
EDGE_AUTH_MODE=manager
EDGE_BROKER_SHARED_SECRET=truckwash-edge-ci
EDGE_GATEWAY_VIEW_CACHE_TTL=0
TRUCKWASH_TEST_BLOCK_REAL_SHELLY=1
-48
View File
@@ -1,48 +0,0 @@
USE_ENV=true
DEBUG=true
ENCRYPTION_KEY=ci-test-encryption-key
CORS=*
CONFIG_TIMEZONE=Europe/Copenhagen
CONFIG_DB_TARGET=debug
CONFIG_DB_HOST=mysql-debug
CONFIG_DB_USER=root
CONFIG_DB_PASSWORD=debug_root_password
CONFIG_DB_DATABASE=nnks_db_debug
CONFIG_DB_PORT=3306
CONFIG_DB_SSL_MODE=DISABLED
CONFIG_DB_DEBUG_HOST=mysql-debug
CONFIG_DB_DEBUG_USER=root
CONFIG_DB_DEBUG_PASSWORD=debug_root_password
CONFIG_DB_DEBUG_DATABASE=nnks_db_debug
CONFIG_DB_DEBUG_PORT=3306
CONFIG_DB_DEBUG_SSL_MODE=DISABLED
REDIS_CONFIG_HOST=redis
REDIS_CONFIG_USER=default
REDIS_CONFIG_DATABASE=0
REDIS_CONFIG_PASSWORD=
REDIS_CONFIG_PORT=6379
REDIS_CONFIG_DEBUG_HOST=redis
REDIS_CONFIG_DEBUG_USER=default
REDIS_CONFIG_DEBUG_DATABASE=0
REDIS_CONFIG_DEBUG_PASSWORD=
REDIS_CONFIG_DEBUG_PORT=6379
ECONOMIC_API_APP_ACCESS_GRANT=ci-test
ECONOMIC_API_APP_ACCESS_GRANT2=ci-test-secondary
ECONOMIC_API_APP_SECRET_TOKEN=ci-test-secret
WORDPRESS_STATIC_TOKEN=ci-test
EMAIL_WASH_CERTIFICATE_TOKEN=ci-test
WORDPRESS_API_URL=http://localhost
MINIO_ENDPOINT=
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
SLACK_DEFAULT_WEBHOOK=
EDGE_BROKER_URL=http://edge-broker:4300
EDGE_PUBLIC_BROKER_URL=http://localhost/api/edge-broker
EDGE_AUTH_MODE=manager
EDGE_BROKER_SHARED_SECRET=truckwash-edge-ci
EDGE_GATEWAY_VIEW_CACHE_TTL=0
TRUCKWASH_TEST_BLOCK_REAL_SHELLY=1
-90
View File
@@ -1,90 +0,0 @@
services:
traefik:
container_name: "${COMPOSE_PROJECT_NAME:-api}-traefik"
redis:
container_name: "${COMPOSE_PROJECT_NAME:-api}-redis"
mysql-debug:
container_name: "${COMPOSE_PROJECT_NAME:-api}-mysql-debug"
ports: !reset []
edge-broker:
container_name: "${COMPOSE_PROJECT_NAME:-api}-edge-broker"
ports:
- "127.0.0.1:${EDGE_BROKER_CI_PORT:-14300}:4300"
labels:
- "traefik.http.routers.edge-broker-local-ci.rule=PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local-ci.entrypoints=web"
- "traefik.http.routers.edge-broker-local-ci.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local-ci.priority=190"
- "traefik.http.routers.edge-broker-local-ci.service=edge-broker"
caddy:
container_name: "${COMPOSE_PROJECT_NAME:-api}-caddy"
depends_on: !reset []
labels:
- "traefik.http.routers.local-api-ci.rule=PathPrefix(`/api`)"
- "traefik.http.routers.local-api-ci.entrypoints=web"
- "traefik.http.routers.local-api-ci.middlewares=strip-api-prefix@file,secure-headers@file"
- "traefik.http.routers.local-api-ci.priority=90"
- "traefik.http.routers.local-api-ci.service=caddy"
volumes:
- ci_php_app:/var/www/html
php1:
container_name: "${COMPOSE_PROJECT_NAME:-api}-php1"
depends_on: !reset []
environment:
AUTO_COMPOSER_INSTALL: "false"
USE_ENV: "true"
CONFIG_DB_TARGET: "debug"
CONFIG_DB_HOST: "mysql-debug"
CONFIG_DB_USER: "root"
CONFIG_DB_PASSWORD: "debug_root_password"
CONFIG_DB_DATABASE: "nnks_db_debug"
CONFIG_DB_PORT: "3306"
CONFIG_DB_DEBUG_HOST: "mysql-debug"
CONFIG_DB_DEBUG_USER: "root"
CONFIG_DB_DEBUG_PASSWORD: "debug_root_password"
CONFIG_DB_DEBUG_DATABASE: "nnks_db_debug"
CONFIG_DB_DEBUG_PORT: "3306"
REDIS_CONFIG_HOST: "redis"
REDIS_CONFIG_PORT: "6379"
REDIS_CONFIG_DATABASE: "0"
REDIS_CONFIG_DEBUG_HOST: "redis"
REDIS_CONFIG_DEBUG_PORT: "6379"
REDIS_CONFIG_DEBUG_DATABASE: "0"
TRUCKWASH_TEST_BLOCK_REAL_SHELLY: "1"
EDGE_GATEWAY_VIEW_CACHE_TTL: "0"
volumes:
- ci_php_app:/var/www/html
php2:
container_name: "${COMPOSE_PROJECT_NAME:-api}-php2"
volumes:
- ci_php_app:/var/www/html
php3:
container_name: "${COMPOSE_PROJECT_NAME:-api}-php3"
volumes:
- ci_php_app:/var/www/html
php4:
container_name: "${COMPOSE_PROJECT_NAME:-api}-php4"
volumes:
- ci_php_app:/var/www/html
php5:
container_name: "${COMPOSE_PROJECT_NAME:-api}-php5"
volumes:
- ci_php_app:/var/www/html
volumes:
ci_php_app:
networks:
default:
ipam:
config:
- subnet: "${CI_DOCKER_SUBNET:-10.240.0.0/24}"
@@ -1,57 +0,0 @@
{
"name": "Protect default branch",
"target": "branch",
"enforcement": "active",
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "pull_request"
}
],
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"~DEFAULT_BRANCH"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
},
{
"type": "required_linear_history"
},
{
"type": "pull_request",
"parameters": {
"allowed_merge_methods": [
"squash"
],
"dismiss_stale_reviews_on_push": false,
"require_code_owner_review": false,
"require_last_push_approval": false,
"required_approving_review_count": 0,
"required_review_thread_resolution": true
}
},
{
"type": "required_status_checks",
"parameters": {
"do_not_enforce_on_create": false,
"required_status_checks": [
{
"context": "Required CI",
"integration_id": 15368
}
],
"strict_required_status_checks_policy": true
}
}
]
}
+13 -59
View File
@@ -1,74 +1,28 @@
name: Qodana
on:
workflow_dispatch:
pull_request:
branches:
- master
- beta
- canary
- internal
types:
- opened
- reopened
- synchronize
- ready_for_review
push:
branches:
- master
- beta
- canary
- internal
concurrency:
group: qodana-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
branches: # Specify your branches here
- main # The 'main' branch
- 'releases/*' # The release branches
jobs:
qodana:
name: Qodana
if: >-
github.event_name != 'pull_request' ||
(
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name == github.repository &&
github.event.pull_request.user.login != 'dependabot[bot]'
)
runs-on: ubuntu-24.04
timeout-minutes: 60
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
contents: write
pull-requests: write
checks: write
steps:
- name: Require Qodana Cloud token
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${QODANA_TOKEN}" ]]; then
echo "::error::QODANA_TOKEN is not configured for this repository."
exit 1
fi
- name: Check out the analyzed commit
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Run Qodana
uses: JetBrains/qodana-action@4861e015da555e86a72b862892aba6c2b93e6891 # v2026.1.3
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
fetch-depth: 0 # a full history is required for pull request analysis
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@v2025.3
with:
pr-mode: ${{ github.event_name == 'pull_request' }}
use-caches: true
cache-default-branch-only: true
use-annotations: true
post-pr-comment: true
github-token: ${{ github.token }}
push-fixes: none
upload-result: false
pr-mode: false
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
QODANA_ENDPOINT: 'https://qodana.cloud'
-167
View File
@@ -1,167 +0,0 @@
name: Deploy to Hetzner (staging)
on:
push:
branches: [master]
workflow_dispatch:
inputs:
reason:
description: 'Reason for manual deploy'
required: false
default: 'manual'
concurrency:
group: deploy-${{ github.repository }}
cancel-in-progress: false
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
jobs:
test-and-deploy:
name: CI + Deploy
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Show commit info
run: |
echo "Repo: ${{ github.repository }}"
echo "Branch: ${{ github.ref }}"
echo "Commit: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
# === CI (phpunit / vitest) runs here via repo's existing CI config ===
# (Most of our repos already have a "Required CI" check; this section
# would invoke that. If your repo doesn't have a CI workflow, the
# required-check on the branch will block this workflow's deploy step.)
- name: Setup SSH
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}
- name: Add host key
run: |
mkdir -p ~/.ssh
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null
- name: Pre-deploy snapshot
id: pre
run: |
ssh "$DEPLOY_USER@$DEPLOY_HOST" '
set -e
cd /opt/${{ github.event.repository.name }}
git rev-parse HEAD > /tmp/last_deploy_sha
echo "PRE_SHA=$(cat /tmp/last_deploy_sha)"
echo "pre_sha=$(cat /tmp/last_deploy_sha)" >> $GITHUB_OUTPUT
'
- name: Deploy
id: deploy
run: |
ssh "$DEPLOY_USER@$DEPLOY_HOST" '
set -e
cd /opt/${{ github.event.repository.name }}
git fetch origin master
git reset --hard origin/master
# PHP repos: composer install + clear cache
if [ -f composer.json ]; then
composer install --no-dev --optimize-autoloader --no-interaction
php artisan cache:clear || true
php artisan config:cache || true
# Restart php-fpm if used
sudo systemctl reload php8.2-fpm || true
fi
# Node repos: npm ci + build
if [ -f package.json ]; then
npm ci --ignore-scripts
npm run build
# Restart node service
sudo systemctl reload pleno-vue || sudo systemctl reload nginx || true
fi
# Restart generic services
sudo systemctl reload nginx || true
echo "Deploy complete: $(git rev-parse --short HEAD)"
'
- name: Pre-deploy schema check (run all *_schema_bootstrap)
id: pre_schema
run: |
echo "Running schema bootstraps against the live database…"
# Idempotent — adds missing columns, never drops anything.
# Catches the "Unknown column 'invoice_email' in 'SELECT'"
# production failure mode (TRU-77) where migrations were
# merged to master but never applied to the live DB.
php scripts/run-schema-bootstraps.php
echo "Schema bootstraps complete."
- name: Alert Slack if schema-check fails (pre-deploy)
if: failure()
run: |
php scripts/schema-health-check.php > /tmp/schema.json 2>&1 || true
msg=$(jq -r '"Schema health FAILED on '$SMOKE_BASE_URL'\nMissing: " + (.missing | join(", "))' /tmp/schema.json 2>/dev/null || echo "Schema check produced no JSON")
curl -sS -X POST -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json; charset=utf-8" \
https://slack.com/api/chat.postMessage \
-d "{\"channel\":\"$AI_DAILY_CHANNEL\",\"text\":\":rotating_light: *${{ github.event.repository.name }} — schema health FAIL\n${msg}\"}"
- name: Smoke test
id: smoke
continue-on-error: true
run: |
chmod +x scripts/smoke-test.sh
./scripts/smoke-test.sh
# Also hit the new admin schema-check endpoint to verify
# no required columns are missing.
echo "::group::Schema health check"
php scripts/schema-health-check.php | tee /tmp/schema-report.json
if [ "$(jq -r .ok /tmp/schema-report.json)" != "true" ]; then
echo "::error::Schema health check FAILED — missing columns:"
jq -r '.missing[]' /tmp/schema-report.json | sed 's/^/ • /'
exit 1
fi
echo "Schema health check OK."
- name: Auto-rollback on smoke failure
if: steps.smoke.outcome == 'failure'
run: |
echo "::error::Smoke test failed — rolling back to ${{ steps.pre.outputs.pre_sha }}"
ssh "$DEPLOY_USER@$DEPLOY_HOST" '
set -e
cd /opt/${{ github.event.repository.name }}
git reset --hard ${{ steps.pre.outputs.pre_sha }}
if [ -f composer.json ]; then
composer install --no-dev --optimize-autoloader --no-interaction
sudo systemctl reload php8.2-fpm || true
fi
if [ -f package.json ]; then
npm ci --ignore-scripts
npm run build
sudo systemctl reload nginx || true
fi
'
- name: Post Slack status
if: always()
uses: slackapi/slack-github-action@v1.27.0
with:
channel-id: ${{ secrets.AI_DAILY_CHANNEL }}
payload: |
{
"text": "${{ job.status == 'success' && '✅' || '❌' }} Deploy *${{ github.repository }}@${{ github.sha[0:7] }}* — ${{ job.status }}\n${{ steps.smoke.outcome == 'failure' && '⚠️ Auto-rolled back' || '✓ Smoke test passed' }}"
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Update Linear issue
if: success() && steps.deploy.outcome == 'success'
run: |
# Find Linear issues in this commit's history and post a comment
# (uses GitHub's auto-link: if PR body contains "TRU-123" it auto-links)
# We skip this here; the OpenClaw cron `f26dfd83` handles Linear updates.
echo "Deploy notification will be picked up by OpenClaw cron."
+179 -339
View File
@@ -3,107 +3,69 @@ name: Tests
on:
pull_request:
push:
branches:
- master
- beta
- canary
- internal
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
php:
name: PHP ${{ matrix.suite }} (required)
# Docker jobs use disposable workspaces so root-owned container artifacts cannot poison later checkouts.
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
suite: [unit, integration, api, legacy]
env:
DOCKER_HOST: unix:///var/run/docker.sock
COMPOSE_PROJECT_NAME: php-${{ github.run_id }}-${{ github.job }}-${{ matrix.suite }}-${{ github.run_attempt }}
unit:
name: Unit (required)
# Match the labels exposed by the Coolify-managed GitHub runner.
runs-on: [self-hosted, Linux, X64, default]
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- name: Ensure Docker access
run: |
set -euo pipefail
docker ps >/dev/null 2>&1 || {
echo "Docker is unavailable to the runner identity. Fix the isolated runner configuration; the workflow will not weaken /var/run/docker.sock permissions." >&2
exit 1
}
uses: actions/checkout@v4
- name: Setup Node.js
if: ${{ matrix.suite == 'unit' }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
uses: actions/setup-node@v4
with:
node-version: 22
- name: Check AI workflow sync
if: ${{ matrix.suite == 'unit' }}
run: node scripts/sync-ai-workflow.mjs --check
- name: Run PHP ${{ matrix.suite }} suite
run: bash scripts/php-ci-test.sh ${{ matrix.suite }}
- name: Upload PHP suite logs
if: ${{ failure() }}
continue-on-error: true
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
name: php-${{ matrix.suite }}-logs
path: .tmp/ci-logs/${{ matrix.suite }}
php-version: '8.2'
extensions: mysqli, curl, openssl, json, redis, xdebug
coverage: xdebug
ini-values: variables_order=EGPCS,xdebug.mode=coverage
- name: Resolve dependencies
working-directory: services/nginx/app
run: composer update --no-interaction --prefer-dist
- name: Run unit tests
working-directory: services/nginx/app
run: composer test:unit
- name: Generate coverage report
working-directory: services/nginx/app
run: composer test:coverage
- name: Upload coverage artifact
if: ${{ github.event_name == 'pull_request' }}
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: unit-coverage-clover
path: services/nginx/app/build/logs/clover.xml
if-no-files-found: warn
retention-days: 3
retention-days: 1
edge-agent:
name: Edge Agent (required)
runs-on: ubuntu-24.04
runs-on: [self-hosted, Linux, X64, default]
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install native build tools
run: |
set -euo pipefail
if command -v make >/dev/null 2>&1 && command -v g++ >/dev/null 2>&1; then
exit 0
fi
if ! command -v apt-get >/dev/null 2>&1; then
echo "make and g++ are required to install node-pty, but apt-get is not available on this runner." >&2
exit 1
fi
apt_cmd=(apt-get)
if [ "$(id -u)" -ne 0 ]; then
if ! command -v sudo >/dev/null 2>&1; then
echo "make and g++ are missing, and sudo is not available to install them." >&2
exit 1
fi
apt_cmd=(sudo apt-get)
fi
"${apt_cmd[@]}" update
"${apt_cmd[@]}" install -y --no-install-recommends build-essential python3
cache: npm
cache-dependency-path: services/edge-agent/package-lock.json
- name: Install dependencies
working-directory: services/edge-agent
@@ -115,29 +77,28 @@ jobs:
edge-broker:
name: Edge Broker (required)
runs-on: ubuntu-24.04
env:
DOCKER_HOST: unix:///var/run/docker.sock
runs-on: [self-hosted, Linux, X64, default]
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
uses: actions/checkout@v4
- name: Ensure Docker access
- name: Materialize compose env files
env:
COMPOSE_ENV: ${{ secrets.COMPOSE_ENV }}
COMPOSE_ENV_STAGING: ${{ secrets.COMPOSE_ENV_STAGING }}
run: |
set -euo pipefail
docker ps >/dev/null 2>&1 || {
echo "Docker is unavailable to the runner identity. Fix the isolated runner configuration; the workflow will not weaken /var/run/docker.sock permissions." >&2
if [ -z "${COMPOSE_ENV}" ]; then
echo "Required GitHub secret COMPOSE_ENV is not configured." >&2
exit 1
}
- name: Materialize CI compose env files
run: |
set -euo pipefail
cp .github/ci.env .env
cp .github/ci.env.staging .env.staging
fi
if [ -z "${COMPOSE_ENV_STAGING}" ]; then
echo "Required GitHub secret COMPOSE_ENV_STAGING is not configured." >&2
exit 1
fi
printf '%s\n' "$COMPOSE_ENV" > .env
printf '%s\n' "$COMPOSE_ENV_STAGING" > .env.staging
- name: Validate compose contracts
run: |
@@ -145,9 +106,11 @@ jobs:
docker compose -f docker-compose.example.yml config > /dev/null
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: services/edge-broker/package-lock.json
- name: Install dependencies
working-directory: services/edge-broker
@@ -157,262 +120,139 @@ jobs:
working-directory: services/edge-broker
run: npm test
edge-gateway-backend:
name: Edge Gateway Backend (required)
runs-on: ubuntu-24.04
env:
DOCKER_HOST: unix:///var/run/docker.sock
COMPOSE_FILE: docker-compose.yml:.github/docker-compose.ci.yml
COMPOSE_PROJECT_NAME: edge-gateway-backend-${{ github.run_id }}-${{ github.run_attempt }}
COMPOSE_PROFILES: dev
TRAEFIK_WEB_PORT: "18080"
TRAEFIK_WEBSECURE_PORT: "18443"
TRAEFIK_WEBSECURE_STAGING_PORT: "18433"
TRAEFIK_METRICS_PORT: "19100"
EDGE_BROKER_CI_PORT: "14300"
EDGE_GATEWAY_E2E_BASE_URL: "http://localhost:18080/api"
integration:
name: Integration (advisory)
runs-on: [self-hosted, Linux, X64, default]
continue-on-error: true
services:
redis:
image: redis:7
ports:
- 6379:6379
mysql:
image: mysql:8
env:
MYSQL_DATABASE: app_test
MYSQL_ROOT_PASSWORD: root
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 -proot"
--health-interval=10s
--health-timeout=5s
--health-retries=10
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
persist-credentials: false
- name: Ensure Docker access
run: |
set -euo pipefail
docker ps >/dev/null 2>&1 || {
echo "Docker is unavailable to the runner identity. Fix the isolated runner configuration; the workflow will not weaken /var/run/docker.sock permissions." >&2
exit 1
}
- name: Allocate CI ports
run: |
set -euo pipefail
find_free_port() {
start="$1"
end="$2"
port="$start"
while [ "$port" -le "$end" ]; do
if ! ss -H -ltn "sport = :$port" 2>/dev/null | grep -q .; then
echo "$port"
return 0
fi
port=$((port + 1))
done
echo "No free port in range ${start}-${end}." >&2
exit 1
}
base=$((20000 + (GITHUB_RUN_ID % 20000)))
web_port="$(find_free_port "$base" "$((base + 2000))")"
websecure_port="$(find_free_port "$((web_port + 1))" "$((web_port + 2000))")"
staging_port="$(find_free_port "$((websecure_port + 1))" "$((websecure_port + 2000))")"
metrics_port="$(find_free_port "$((staging_port + 1))" "$((staging_port + 2000))")"
broker_port="$(find_free_port "$((metrics_port + 1))" "$((metrics_port + 2000))")"
checksum="$(printf '%s' "$COMPOSE_PROJECT_NAME" | cksum | awk '{print $1}')"
subnet_second=$((64 + ((checksum / 256) % 64)))
subnet_third=$((checksum % 256))
ci_docker_subnet="10.${subnet_second}.${subnet_third}.0/24"
{
echo "TRAEFIK_WEB_PORT=${web_port}"
echo "TRAEFIK_WEBSECURE_PORT=${websecure_port}"
echo "TRAEFIK_WEBSECURE_STAGING_PORT=${staging_port}"
echo "TRAEFIK_METRICS_PORT=${metrics_port}"
echo "EDGE_BROKER_CI_PORT=${broker_port}"
echo "CI_DOCKER_SUBNET=${ci_docker_subnet}"
echo "EDGE_GATEWAY_E2E_BASE_URL=http://localhost:${web_port}/api"
echo "EDGE_GATEWAY_E2E_COMPOSE_PROJECT=${COMPOSE_PROJECT_NAME}"
} >> "$GITHUB_ENV"
- name: Materialize CI compose env files
run: |
set -euo pipefail
cp .github/ci.env .env
cp .github/ci.env.staging .env.staging
printf '\nEDGE_PUBLIC_BROKER_URL=http://edge-broker:4300/edge-broker\n' >> .env
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
- name: Boot local stack
run: sh scripts/ci-docker-compose-up.sh traefik redis mysql-debug edge-broker php1 php2 php3 php4 php5 caddy
- name: Sync PHP app checkout
run: >
tar
--exclude='./vendor'
--exclude='./.phpunit.cache'
--exclude='./build/logs'
-C services/nginx/app -cf - .
| docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml exec -T php1 tar --no-same-owner -C /var/www/html -xf -
php-version: '8.2'
extensions: mysqli, curl, openssl, json, redis
ini-values: variables_order=EGPCS
- name: Resolve dependencies
run: |
set -euo pipefail
composer_install() {
install_mode="$1"
max_attempts="$2"
attempt=1
while :; do
if docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml exec -T php1 sh -lc "cd /var/www/html && composer install --no-interaction ${install_mode} --no-progress"; then
return 0
fi
if [ "$attempt" -ge "$max_attempts" ]; then
return 1
fi
sleep_seconds=$((attempt * 5))
echo "composer install ${install_mode} failed; retrying in ${sleep_seconds}s (attempt $((attempt + 1))/${max_attempts})" >&2
sleep "$sleep_seconds"
attempt=$((attempt + 1))
done
}
working-directory: services/nginx/app
run: composer update --no-interaction --prefer-dist
composer_install --prefer-dist 3 || {
echo "Composer dist install failed; retrying with --prefer-source." >&2
composer_install --prefer-source 2
}
- name: Verify edge gateway test files
run: >
docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml exec -T php1 sh -lc
"cd /var/www/html &&
php -r '\$composer = json_decode(file_get_contents(\"composer.json\"), true); echo \"Composer scripts: \", implode(\",\", array_keys(\$composer[\"scripts\"] ?? [])), PHP_EOL;' &&
find tests/Api -maxdepth 1 -type f -name 'EdgeGateway*ApiTest.php' -print &&
test -f tests/Api/EdgeGatewayAgentApiTest.php &&
test -f tests/Api/EdgeGatewayBrokerApiTest.php &&
test -f tests/Api/EdgeGatewayOperatorApiTest.php"
- name: Run edge gateway API tests
run: >
docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml exec -T php1 sh -lc
"cd /var/www/html &&
RUN_API_TESTS=1
API_TEST_BOOTSTRAP_SCHEMA=1
API_TEST_ALLOW_LIVE_DB=1
CONFIG_DB_TARGET=debug
CONFIG_DB_HOST=mysql-debug
CONFIG_DB_USER=\${CONFIG_DB_USER:-root}
CONFIG_DB_PASSWORD=\${CONFIG_DB_PASSWORD:-debug_root_password}
CONFIG_DB_DATABASE=\${CONFIG_DB_DATABASE:-nnks_db_debug}
CONFIG_DB_PORT=3306
CONFIG_DB_DEBUG_HOST=mysql-debug
CONFIG_DB_DEBUG_USER=\${CONFIG_DB_DEBUG_USER:-root}
CONFIG_DB_DEBUG_PASSWORD=\${CONFIG_DB_DEBUG_PASSWORD:-debug_root_password}
CONFIG_DB_DEBUG_DATABASE=\${CONFIG_DB_DEBUG_DATABASE:-nnks_db_debug}
CONFIG_DB_DEBUG_PORT=3306
API_TEST_REQUEST_TIMEOUT=180
EDGE_GATEWAY_VIEW_CACHE_TTL=0
EDGE_BROKER_URL=
vendor/bin/pest
tests/Api/EdgeGatewayAgentApiTest.php
tests/Api/EdgeGatewayBrokerApiTest.php
tests/Api/EdgeGatewayOperatorApiTest.php
--colors=always"
- name: Run edge gateway integration tests
run: >
docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml exec -T php1 sh -lc
"cd /var/www/html &&
RUN_INTEGRATION_TESTS=1
CONFIG_DB_TARGET=debug
CONFIG_DB_HOST=mysql-debug
CONFIG_DB_USER=\${CONFIG_DB_USER:-root}
CONFIG_DB_PASSWORD=\${CONFIG_DB_PASSWORD:-debug_root_password}
CONFIG_DB_DATABASE=\${CONFIG_DB_DATABASE:-nnks_db_debug}
CONFIG_DB_PORT=3306
CONFIG_DB_DEBUG_HOST=mysql-debug
CONFIG_DB_DEBUG_USER=\${CONFIG_DB_DEBUG_USER:-root}
CONFIG_DB_DEBUG_PASSWORD=\${CONFIG_DB_DEBUG_PASSWORD:-debug_root_password}
CONFIG_DB_DEBUG_DATABASE=\${CONFIG_DB_DEBUG_DATABASE:-nnks_db_debug}
CONFIG_DB_DEBUG_PORT=3306
EDGE_BROKER_URL=
vendor/bin/pest tests/Integration/EdgeGateway --colors=always"
- name: Run edge gateway E2E smoke
- name: Run integration tests
working-directory: services/nginx/app
env:
EDGE_GATEWAY_E2E_COPY_CONFIG: "true"
EDGE_GATEWAY_E2E_SKIP_COMPOSE_UP: "true"
run: node scripts/edge-gateway-e2e.mjs
RUN_INTEGRATION_TESTS: '1'
USE_ENV: 'true'
DEBUG: '0'
ENCRYPTION_KEY: test-key
CORS: '*'
CONFIG_TIMEZONE: Europe/Copenhagen
ECONOMIC_API_APP_ACCESS_GRANT: test
ECONOMIC_API_APP_ACCESS_GRANT2: test
ECONOMIC_API_APP_SECRET_TOKEN: test
WORDPRESS_STATIC_TOKEN: ''
EMAIL_WASH_CERTIFICATE_TOKEN: ''
WORDPRESS_API_URL: http://localhost
MINIO_ENDPOINT: ''
MINIO_ACCESS_KEY: ''
MINIO_SECRET_KEY: ''
SLACK_DEFAULT_WEBHOOK: ''
REDIS_CONFIG_HOST: 127.0.0.1
REDIS_CONFIG_DATABASE: '0'
REDIS_CONFIG_PASSWORD: ''
REDIS_CONFIG_PORT: '6379'
CONFIG_DB_HOST: 127.0.0.1
CONFIG_DB_USER: root
CONFIG_DB_PASSWORD: root
CONFIG_DB_DATABASE: app_test
CONFIG_DB_PORT: '3306'
run: composer test:integration
- name: Tear down local stack
if: always()
run: docker compose -f docker-compose.yml -f .github/docker-compose.ci.yml down -v
api:
name: API (advisory)
runs-on: [self-hosted, Linux, X64, default]
continue-on-error: true
required-ci:
name: Required CI
runs-on: ubuntu-latest
needs: [php, edge-agent, edge-broker, edge-gateway-backend]
if: ${{ always() }}
services:
redis:
image: redis:7
ports:
- 6379:6379
mysql:
image: mysql:8
env:
MYSQL_DATABASE: app_test
MYSQL_ROOT_PASSWORD: root
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 -proot"
--health-interval=10s
--health-timeout=5s
--health-retries=10
steps:
- name: Verify required jobs succeeded
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mysqli, curl, openssl, json, redis
ini-values: variables_order=EGPCS
- name: Resolve dependencies
working-directory: services/nginx/app
run: composer update --no-interaction --prefer-dist
- name: Run API tests
working-directory: services/nginx/app
env:
PHP_RESULT: ${{ needs.php.result }}
EDGE_AGENT_RESULT: ${{ needs.edge-agent.result }}
EDGE_BROKER_RESULT: ${{ needs.edge-broker.result }}
EDGE_GATEWAY_BACKEND_RESULT: ${{ needs.edge-gateway-backend.result }}
run: |
set -euo pipefail
failed=0
for dependency in \
"php=${PHP_RESULT}" \
"edge-agent=${EDGE_AGENT_RESULT}" \
"edge-broker=${EDGE_BROKER_RESULT}" \
"edge-gateway-backend=${EDGE_GATEWAY_BACKEND_RESULT}"
do
name="${dependency%%=*}"
result="${dependency#*=}"
if [ "$result" != "success" ]; then
echo "Required dependency ${name} completed with result: ${result:-missing}" >&2
failed=1
fi
done
test "$failed" -eq 0
release-manager-gate:
name: Release Manager gate
runs-on: ubuntu-24.04
needs: [required-ci]
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && needs.required-ci.result == 'success' }}
steps:
- name: Record Release Manager API gate
run: |
set -euo pipefail
test -n "$RELEASE_MANAGER_GATE_TOKEN" || (echo "RELEASE_MANAGER_GATE_TOKEN is required" >&2; exit 1)
response_file="$(mktemp)"
http_code="$(curl --show-error --silent \
--connect-timeout 10 \
--retry 5 \
--retry-all-errors \
--retry-delay 15 \
--retry-max-time 300 \
-o "$response_file" \
-w '%{http_code}' \
-X POST "$RELEASE_MANAGER_GATE_URL" \
-H "Authorization: Bearer $RELEASE_MANAGER_GATE_TOKEN" \
-H "Content-Type: application/json" \
--data "{\"channel_slug\":\"stable\",\"app\":\"api\",\"repository\":\"$RELEASE_REPOSITORY\",\"branch\":\"$RELEASE_BRANCH\",\"expected_commit\":\"$RELEASE_EXPECTED_COMMIT\",\"workflow_url\":\"$RELEASE_WORKFLOW_URL\",\"auto_sync\":true,\"wait_timeout_seconds\":300,\"poll_interval_seconds\":10,\"required_checks\":[\"api_gateway\"]}")"
response_body="$(cat "$response_file")"
rm -f "$response_file"
if [[ "$http_code" =~ ^2[0-9][0-9]$ ]]; then
printf '%s\n' "$response_body"
exit 0
fi
printf '%s\n' "$response_body"
echo "Release Manager gate failed with HTTP $http_code." >&2
exit 1
env:
RELEASE_MANAGER_GATE_URL: ${{ secrets.RELEASE_MANAGER_GATE_URL || 'https://api.truckwash.io/release/gate/test-runs' }}
RELEASE_MANAGER_GATE_TOKEN: ${{ secrets.RELEASE_MANAGER_GATE_TOKEN }}
RELEASE_REPOSITORY: ${{ github.repository }}
RELEASE_BRANCH: ${{ github.ref_name }}
RELEASE_EXPECTED_COMMIT: ${{ github.sha }}
RELEASE_WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
RUN_API_TESTS: '1'
API_TEST_BOOTSTRAP_SCHEMA: '1'
USE_ENV: 'true'
DEBUG: '0'
ENCRYPTION_KEY: test-key
CORS: '*'
CONFIG_TIMEZONE: Europe/Copenhagen
ECONOMIC_API_APP_ACCESS_GRANT: test
ECONOMIC_API_APP_ACCESS_GRANT2: test
ECONOMIC_API_APP_SECRET_TOKEN: test
WORDPRESS_STATIC_TOKEN: ''
EMAIL_WASH_CERTIFICATE_TOKEN: ''
WORDPRESS_API_URL: http://localhost
MINIO_ENDPOINT: ''
MINIO_ACCESS_KEY: ''
MINIO_SECRET_KEY: ''
SLACK_DEFAULT_WEBHOOK: ''
REDIS_CONFIG_HOST: 127.0.0.1
REDIS_CONFIG_DATABASE: '0'
REDIS_CONFIG_PASSWORD: ''
REDIS_CONFIG_PORT: '6379'
CONFIG_DB_HOST: 127.0.0.1
CONFIG_DB_USER: root
CONFIG_DB_PASSWORD: root
CONFIG_DB_DATABASE: app_test
CONFIG_DB_PORT: '3306'
run: composer test:api
-7
View File
@@ -2,7 +2,6 @@
/docker-compose.yml
/services/nginx/app/vendor/
/services/nginx/app/modules/washcertificates/vendor/
/services/nginx/app/.phpunit.cache/
/services/nginx/letsencrypt/
*.pem
*.log.gz
@@ -11,10 +10,4 @@
/.idea/
.env
/services/caddy/logs*
.env.old
/.tmp/
/.env.staging
/services/nginx/app/storage/replication-bootstrap.json
/.env_old_2
/.openclaw/
/services/nginx/app/build/phpstan/
+2 -4
View File
@@ -40,15 +40,13 @@ COPY . /var/www/html
# Copy Nginx configuration file
COPY nginx.conf /etc/nginx/nginx.conf
COPY services/php/php-fpm-pool.conf /usr/local/etc/php-fpm.d/zz-pleno-workers.conf
# Install Composer
COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer
# Runtime bootstrap: lightweight entrypoint to ensure Composer deps exist when app is bind-mounted
COPY services/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN sed -i 's/\r$//' /usr/local/bin/docker-entrypoint.sh \
&& chmod +x /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
# Install PHP dependencies through Composer (only where composer.json exists)
# Main app dependencies
@@ -74,4 +72,4 @@ EXPOSE 80 443
ENTRYPOINT ["docker-entrypoint.sh"]
# Start services when no command is provided (docker-compose overrides this with ["php-fpm"])
CMD ["php-fpm"]
CMD ["php-fpm"]
-80
View File
@@ -1,80 +0,0 @@
FROM php:8.2.15-fpm
WORKDIR /var/www/html
COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
$PHPIZE_DEPS \
ca-certificates \
curl \
default-mysql-client \
git \
imagemagick \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmagickcore-dev \
libmagickwand-dev \
libonig-dev \
libpng-dev \
libssl-dev \
libxml2-dev \
libzip-dev \
mariadb-client \
nginx \
openssl \
pkg-config \
redis-tools \
unzip \
zip; \
update-ca-certificates; \
docker-php-ext-configure gd --with-freetype --with-jpeg; \
docker-php-ext-install -j"$(nproc)" \
bcmath \
exif \
gd \
mbstring \
mysqli \
pcntl \
pdo_mysql \
sockets \
zip; \
pecl install imagick-3.7.0 redis; \
docker-php-ext-enable imagick redis; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $PHPIZE_DEPS; \
rm -rf /var/lib/apt/lists/*
COPY services/nginx/app/ /var/www/html/
COPY scripts/bird-control-plane-activate.php /var/www/html/scripts/bird-control-plane-activate.php
COPY scripts/bird-control-plane-auto-activate.php /var/www/html/scripts/bird-control-plane-auto-activate.php
COPY services/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
COPY services/php/php-fpm-pool.conf /usr/local/etc/php-fpm.d/zz-pleno-workers.conf
COPY services/coolify/api/nginx.conf /etc/nginx/nginx.conf
COPY services/coolify/api/start.sh /usr/local/bin/coolify-api-start
RUN set -eux; \
rm -f /var/www/html/storage/replication-bootstrap.json /var/www/html/storage/replication-bootstrap-*.json; \
sed -i 's/\r$//' /usr/local/bin/docker-entrypoint.sh /usr/local/bin/coolify-api-start; \
chmod +x /usr/local/bin/docker-entrypoint.sh /usr/local/bin/coolify-api-start; \
COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction -d /var/www/html; \
if [ -f /var/www/html/modules/washcertificates/composer.json ]; then \
COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction -d /var/www/html/modules/washcertificates; \
fi; \
COMPOSER_ALLOW_SUPERUSER=1 composer dump-autoload --no-dev --optimize --no-interaction -d /var/www/html; \
php -d display_errors=1 -r 'require "/var/www/html/vendor/autoload.php"; exit(interface_exists("Psr\\Http\\Message\\UriInterface") && interface_exists("Psr\\Http\\Message\\StreamInterface") ? 0 : 1);'; \
php -r 'exit(function_exists("proc_open") && extension_loaded("openssl") ? 0 : 1);'; \
test "$(openssl pkey -pubin -in /var/www/html/modules/bird/resources/control-plane-bootstrap-public.pem -outform DER | sha256sum | cut -d " " -f 1)" = "6dc63c6ffe33b8de0b1396d7f529f56aea0a685ef98168016161cf721ddc8c21"; \
chown -R www-data:www-data /var/www/html; \
chmod -R 755 /var/www/html
ENV APP_DIR=/var/www/html \
MODULE_DIR=/var/www/html/modules/washcertificates \
AUTO_COMPOSER_INSTALL=false \
COMPOSER_ALLOW_SUPERUSER=1
EXPOSE 80
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["coolify-api-start"]
-34
View File
@@ -2,11 +2,6 @@
Backend API for Copenhagen Truck Wash services.
Changes are published from a scoped feature branch through a pull request to
`master`; direct default-branch pushes are not part of the release workflow.
See [default branch protection](.github/BRANCH_PROTECTION.md) for the CI gate
and emergency procedure.
## Architecture & Stack
- **Edge Proxy:** [Traefik 2.11](https://doc.traefik.io/traefik/) (Handles TLS termination, routing, and rate limiting).
- **Web Server:** [Caddy 2.7](https://caddyserver.com/) (Serves the PHP application via FastCGI).
@@ -75,11 +70,6 @@ When updating `.env` values used by PHP containers (for example e-conomic tokens
docker compose up -d --force-recreate php1 php2 php3 php4 php5 php-cron
```
#### Edge Broker Public URL
Set `EDGE_PUBLIC_BROKER_URL` to the public route that serves the edge broker, including the path prefix handled by the proxy. Local Traefik uses `http://localhost/api/edge-broker`; production routes use the public broker prefix, for example `https://api.truckwash.dk/edge-broker`.
The browser terminal connects to the exact advertised `EDGE_PUBLIC_BROKER_URL` plus `/ws/browser-shell`. That URL must be routable through the proxy to the edge-broker service. Do not rely on derived `/api/edge-broker` fallback paths outside the local Traefik setup.
## Testing
The project now uses [Pest](https://pestphp.com/) as the primary test runner in `services/nginx/app`.
@@ -101,8 +91,6 @@ For local Docker development, run the PHP suites inside `php1`:
docker exec php1 sh -lc "cd /var/www/html && composer test:unit"
docker exec php1 sh -lc "cd /var/www/html && composer test:integration"
docker exec php1 sh -lc "cd /var/www/html && composer test:api"
docker exec php1 sh -lc "cd /var/www/html && composer run-script test:api:edge"
docker exec php1 sh -lc "cd /var/www/html && composer run-script test:integration:edge"
```
Integration tests are opt-in and should be run with required services available:
@@ -112,28 +100,6 @@ $env:RUN_INTEGRATION_TESTS='1'
composer test:integration
```
### Edge Gateway Regression Coverage
The dedicated backend regression lane for the PHP edge gateway stack is split into:
- API contract tests for operator, agent, and broker-facing routes
- DB-backed integration tests for install sessions, heartbeats, tasks, logs, statistics, and shell persistence
- a local dockerized smoke that runs the real PHP edge agent against the local backend and broker
Run the targeted PHP suites inside `php1`:
```powershell
docker exec php1 sh -lc "cd /var/www/html && composer run-script test:api:edge"
docker exec php1 sh -lc "cd /var/www/html && composer run-script test:integration:edge"
```
Run the full local smoke from `backend-php` on the host:
```powershell
node .\scripts\edge-gateway-e2e.mjs
```
The E2E smoke expects the local compose stack and Docker daemon to be available. It boots a disposable gateway container, waits for a real heartbeat, validates live operations and telemetry, and verifies browser shell transcript persistence.
### Public Staging Edge-Gateway Smoke
`api.truckwash.io:4433` is the public staging ingress. For Edge Gateways v2, the router must serve the canonical artifacts from `services/nginx/app/resources/edge-gateway-agent`, not from the legacy `dist/agent.mjs` output or a separate runtime mount.
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -10,7 +10,7 @@ $CONFIG_DB = [
$DEBUG = true; // Set to true to enable debugging (Error messages will be shown, and this should never be used in production)
$USE_PROD_ECONOMIC_IN_DEBUG = true; // Set to true to use the production economic API in debug mode
$ENCRYPTION_KEY = ''; // 44 Characters long encryption key
$CORS = '*'; // Set to comma-separated allowed origins e.g. https://example.com,https://api-v2.truckwash.io
$CORS = '*'; // Set to the domain that should be allowed to access the API e.g. https://example.com
$ECONOMIC_API = [
'app_access_grant' => '', // Economic API access grant token (1)
'app_access_grant2' => '', // Economic API access grant token (2)
@@ -31,7 +31,7 @@ $MINIO = [
'access_key' => '', // Minio access
'secret_key' => '' // Minio secret key
];
$SLACK_DEFAULT_WEBHOOK = ''; // Set through SLACK_DEFAULT_WEBHOOK; never commit a production webhook URL.
$SLACK_DEFAULT_WEBHOOK = ''; // Default Slack webhook URL e.g. https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX
$REDIS_CONFIG = [
'host' => '', // Redis host (IP address)
'user' => '', // Redis user
+6 -22
View File
@@ -52,25 +52,9 @@ services:
dockerfile: services/edge-broker/Dockerfile
container_name: edge-broker
environment:
EDGE_AUTH_MODE: ${EDGE_AUTH_MODE:-strict}
EDGE_MANAGER_URL: ${EDGE_MANAGER_URL:-http://caddy}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
labels:
- "traefik.enable=true"
- "traefik.http.routers.edge-broker-api.rule=Host(`api.example.com`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api.tls=true"
- "traefik.http.routers.edge-broker-api.tls.certresolver=le"
- "traefik.http.routers.edge-broker-api.middlewares=edge-broker-strip"
- "traefik.http.routers.edge-broker-api.service=edge-broker"
- "traefik.http.routers.edge-broker-local.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local.entrypoints=web"
- "traefik.http.routers.edge-broker-local.middlewares=edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local.service=edge-broker"
- "traefik.http.middlewares.edge-broker-strip.stripPrefix.prefixes=/edge-broker"
- "traefik.http.middlewares.edge-broker-strip-local.stripPrefix.prefixes=/api/edge-broker"
- "traefik.http.services.edge-broker.loadbalancer.server.port=4300"
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
ports:
- "4300:4300"
caddy:
image: caddy:2.7.6-alpine
@@ -114,7 +98,7 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "true"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
@@ -129,13 +113,13 @@ services:
- redis
- mysql
- edge-broker
command: ["php", "index.php", "run", "cron-worker"]
command: ["sh", "-c", "while true; do php index.php run cron; sleep 60; done"]
env_file:
- .env.example
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
-440
View File
@@ -1,440 +0,0 @@
services:
traefik:
image: traefik:2.11
container_name: traefik
ports:
- "80:80"
- "443:443"
- "4433:4433"
- "9100:9100"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./services/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- ./services/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
- ./services/traefik/acme.json:/acme.json
- ./services/traefik/acme-io.json:/acme-io.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.truckwash.dk`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=le"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.middlewares=dashboard-allow-local@file,dashboard-auth@file"
- "traefik.http.routers.traefik-http.rule=Host(`traefik.truckwash.dk`)"
- "traefik.http.routers.traefik-http.entrypoints=web"
- "traefik.http.routers.traefik-http.middlewares=redirect-to-https@file"
- "traefik.http.routers.traefik-http.service=api@internal"
- "traefik.http.routers.traefik-local.rule=Host(`traefik.localhost`)"
- "traefik.http.routers.traefik-local.entrypoints=web"
- "traefik.http.routers.traefik-local.service=api@internal"
- "traefik.http.routers.traefik-local.middlewares=dashboard-allow-local@file,dashboard-auth@file"
redis:
image: redis:7
container_name: redis
volumes:
- nnks_redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
redis-staging:
image: redis:7
container_name: redis-staging
volumes:
- nnks_redis_staging:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
mysql-debug:
image: mysql:8.4
container_name: mysql-debug
environment:
MYSQL_ROOT_PASSWORD: ${CONFIG_DB_DEBUG_PASSWORD:-debug_root_password}
MYSQL_DATABASE: ${CONFIG_DB_DEBUG_DATABASE:-nnks_db_debug}
ports:
- "3307:3306"
volumes:
- db_debug_data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "MYSQL_PWD=$$MYSQL_ROOT_PASSWORD mysqladmin -u root ping --silent"]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s
edge-broker:
build:
context: .
dockerfile: services/edge-broker/Dockerfile
container_name: edge-broker
environment:
EDGE_AUTH_MODE: ${EDGE_AUTH_MODE:-manager}
EDGE_MANAGER_URL: ${EDGE_MANAGER_URL:-http://caddy}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
labels:
- "traefik.enable=true"
- "traefik.http.routers.edge-broker-api.rule=Host(`api.truckwash.dk`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api.tls=true"
- "traefik.http.routers.edge-broker-api.tls.certresolver=le"
- "traefik.http.routers.edge-broker-api.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api.priority=200"
- "traefik.http.routers.edge-broker-api.service=edge-broker"
- "traefik.http.routers.edge-broker-api-io.rule=Host(`api.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api-io.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api-io.tls=true"
- "traefik.http.routers.edge-broker-api-io.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-api-io.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api-io.priority=200"
- "traefik.http.routers.edge-broker-api-io.service=edge-broker"
- "traefik.http.routers.edge-broker-api-v2.rule=Host(`api-v2.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api-v2.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api-v2.tls=true"
- "traefik.http.routers.edge-broker-api-v2.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-api-v2.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api-v2.priority=200"
- "traefik.http.routers.edge-broker-api-v2.service=edge-broker"
- "traefik.http.routers.edge-broker-api-staging.rule=Host(`api.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api-staging.entrypoints=websecure-staging"
- "traefik.http.routers.edge-broker-api-staging.tls=true"
- "traefik.http.routers.edge-broker-api-staging.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-api-staging.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api-staging.priority=200"
- "traefik.http.routers.edge-broker-api-staging.service=edge-broker"
- "traefik.http.routers.edge-broker-local.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local.entrypoints=web"
- "traefik.http.routers.edge-broker-local.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local.priority=200"
- "traefik.http.routers.edge-broker-local.service=edge-broker"
- "traefik.http.routers.edge-broker-local-secure.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local-secure.entrypoints=websecure"
- "traefik.http.routers.edge-broker-local-secure.tls=true"
- "traefik.http.routers.edge-broker-local-secure.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local-secure.priority=200"
- "traefik.http.routers.edge-broker-local-secure.service=edge-broker"
- "traefik.http.routers.edge-broker-local-staging.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local-staging.entrypoints=websecure-staging"
- "traefik.http.routers.edge-broker-local-staging.tls=true"
- "traefik.http.routers.edge-broker-local-staging.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local-staging.priority=200"
- "traefik.http.routers.edge-broker-local-staging.service=edge-broker"
- "traefik.http.middlewares.edge-broker-strip.stripPrefix.prefixes=/edge-broker"
- "traefik.http.middlewares.edge-broker-strip-local.stripPrefix.prefixes=/api/edge-broker"
- "traefik.http.services.edge-broker.loadbalancer.server.port=4300"
caddy:
image: caddy:2.7.6-alpine
container_name: caddy
depends_on:
- php1
- php2
- php3
- php4
- php5
volumes:
- ./services/nginx/app:/var/www/html
- ./services/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- ./services/caddy/logs:/var/log/caddy
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.truckwash.dk`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls=true"
- "traefik.http.routers.api.tls.domains[0].main=api.truckwash.dk"
- "traefik.http.routers.api.tls.certresolver=le"
- "traefik.http.routers.api.service=caddy"
- "traefik.http.routers.api.middlewares=secure-headers@file,api-ratelimit@file"
- "traefik.http.routers.api-io.rule=Host(`api.truckwash.io`)"
- "traefik.http.routers.api-io.entrypoints=websecure"
- "traefik.http.routers.api-io.tls=true"
- "traefik.http.routers.api-io.tls.domains[0].main=api.truckwash.io"
- "traefik.http.routers.api-io.tls.certresolver=le_io"
- "traefik.http.routers.api-io.service=caddy"
- "traefik.http.routers.api-io.middlewares=secure-headers@file,api-ratelimit@file"
- "traefik.http.routers.api-v2.rule=Host(`api-v2.truckwash.io`)"
- "traefik.http.routers.api-v2.entrypoints=websecure"
- "traefik.http.routers.api-v2.tls=true"
- "traefik.http.routers.api-v2.tls.domains[0].main=api-v2.truckwash.io"
- "traefik.http.routers.api-v2.tls.certresolver=le_io"
- "traefik.http.routers.api-v2.service=caddy"
- "traefik.http.routers.api-v2.middlewares=secure-headers@file,api-ratelimit@file"
- "traefik.http.routers.api-http.rule=Host(`api.truckwash.dk`) || Host(`api.truckwash.io`) || Host(`api-v2.truckwash.io`)"
- "traefik.http.routers.api-http.entrypoints=web"
- "traefik.http.routers.api-http.middlewares=redirect-to-https@file"
- "traefik.http.routers.api-http.service=caddy"
- "traefik.http.routers.local.rule=Host(`localhost`)"
- "traefik.http.routers.local.entrypoints=web"
- "traefik.http.routers.local.service=caddy"
- "traefik.http.routers.local.middlewares=secure-headers@file"
- "traefik.http.routers.local-secure.rule=Host(`localhost`)"
- "traefik.http.routers.local-secure.entrypoints=websecure"
- "traefik.http.routers.local-secure.tls=true"
- "traefik.http.routers.local-secure.service=caddy"
- "traefik.http.routers.local-secure.middlewares=secure-headers@file"
- "traefik.http.routers.local-api.rule=Host(`localhost`) && PathPrefix(`/api`)"
- "traefik.http.routers.local-api.entrypoints=web"
- "traefik.http.routers.local-api.middlewares=strip-api-prefix@file,secure-headers@file"
- "traefik.http.routers.local-api.service=caddy"
- "traefik.http.routers.local-api.priority=100"
- "traefik.http.routers.local-api-secure.rule=Host(`localhost`) && PathPrefix(`/api`)"
- "traefik.http.routers.local-api-secure.entrypoints=websecure"
- "traefik.http.routers.local-api-secure.tls=true"
- "traefik.http.routers.local-api-secure.middlewares=strip-api-prefix@file,secure-headers@file"
- "traefik.http.routers.local-api-secure.service=caddy"
- "traefik.http.routers.local-api-secure.priority=100"
- "traefik.http.services.caddy.loadbalancer.server.port=80"
caddy-staging:
image: caddy:2.7.6-alpine
container_name: caddy-staging
depends_on:
- php-staging
volumes:
- ./services/nginx/staging:/var/www/html
- ./services/caddy/Caddyfile-staging:/etc/caddy/Caddyfile:ro
- ./services/caddy/logs-staging:/var/log/caddy
labels:
- "traefik.enable=true"
- "traefik.http.routers.api-staging.rule=Host(`api.truckwash.io`)"
- "traefik.http.routers.api-staging.entrypoints=websecure-staging"
- "traefik.http.routers.api-staging.tls=true"
- "traefik.http.routers.api-staging.tls.domains[0].main=api.truckwash.io"
- "traefik.http.routers.api-staging.tls.certresolver=le_io"
- "traefik.http.routers.api-staging.service=caddy-staging"
- "traefik.http.routers.api-staging.middlewares=secure-headers@file,api-ratelimit@file"
- "traefik.http.routers.local-staging.rule=Host(`localhost`)"
- "traefik.http.routers.local-staging.entrypoints=websecure-staging"
- "traefik.http.routers.local-staging.service=caddy-staging"
- "traefik.http.routers.local-staging.middlewares=secure-headers@file"
- "traefik.http.routers.local-staging-secure.rule=Host(`localhost`)"
- "traefik.http.routers.local-staging-secure.entrypoints=websecure-staging"
- "traefik.http.routers.local-staging-secure.tls=true"
- "traefik.http.routers.local-staging-secure.service=caddy-staging"
- "traefik.http.routers.local-staging-secure.middlewares=secure-headers@file"
- "traefik.http.routers.local-staging-api.rule=Host(`localhost`) && PathPrefix(`/api`)"
- "traefik.http.routers.local-staging-api.entrypoints=websecure-staging"
- "traefik.http.routers.local-staging-api.middlewares=strip-api-prefix@file,secure-headers@file"
- "traefik.http.routers.local-staging-api.service=caddy-staging"
- "traefik.http.routers.local-staging-api.priority=100"
- "traefik.http.routers.local-staging-api-secure.rule=Host(`localhost`) && PathPrefix(`/api`)"
- "traefik.http.routers.local-staging-api-secure.entrypoints=websecure-staging"
- "traefik.http.routers.local-staging-api-secure.tls=true"
- "traefik.http.routers.local-staging-api-secure.middlewares=strip-api-prefix@file,secure-headers@file"
- "traefik.http.routers.local-staging-api-secure.service=caddy-staging"
- "traefik.http.routers.local-staging-api-secure.priority=100"
- "traefik.http.services.caddy-staging.loadbalancer.server.port=80"
php1:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php1
depends_on:
- redis
- edge-broker
command: ["php-fpm"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "true"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs:/var/log/php
php2:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php2
depends_on:
- redis
- edge-broker
command: ["php-fpm"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs:/var/log/php
php3:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php3
depends_on:
- redis
- edge-broker
command: ["php-fpm"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs:/var/log/php
php4:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php4
depends_on:
- redis
- edge-broker
command: ["php-fpm"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs:/var/log/php
php5:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php5
depends_on:
- redis
- edge-broker
command: ["php-fpm"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs:/var/log/php
php-staging:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php-staging
depends_on:
- redis-staging
- edge-broker
command: ["php-fpm"]
env_file:
- .env.staging
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/staging:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs-staging:/var/log/php
php-cron:
build:
context: .
dockerfile: services/php/Dockerfile
container_name: php-cron
depends_on:
- redis
- edge-broker
command: ["php", "index.php", "run", "cron-worker"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/edge-agent/dist:/services/edge-agent/dist:ro
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs:/var/log/php
portainer:
image: portainer/portainer-ce:2.21.4
container_name: portainer
profiles:
- dev
ports:
- "9443:9443"
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
jaeger:
image: jaegertracing/all-in-one:1.53
container_name: jaeger
profiles:
- dev
environment:
- COLLECTOR_ZIPKIN_HTTP_PORT=9411
ports:
- "16686:16686"
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: always
environment:
- N8N_HOST=n8n.truckwash.io
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://n8n.truckwash.io/
- GENERIC_TIMEZONE=${CONFIG_TIMEZONE:-Europe/Copenhagen}
volumes:
- n8n_data:/home/node/.n8n
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.truckwash.io`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls=true"
- "traefik.http.routers.n8n.tls.certresolver=le_io"
- "traefik.http.routers.n8n.service=n8n"
- "traefik.http.routers.n8n-http.rule=Host(`n8n.truckwash.io`)"
- "traefik.http.routers.n8n-http.entrypoints=web"
- "traefik.http.routers.n8n-http.middlewares=redirect-to-https@file"
- "traefik.http.routers.n8n-http.service=n8n"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
volumes:
db_data:
db_debug_data:
nnks_redis:
nnks_redis_staging:
es_data:
portainer_data:
fleet-server-data:
elastic-agent-data:
n8n_data:
+1 -1
View File
@@ -27,5 +27,5 @@ services:
## docker compose up -d traefik caddy php1 php2 php3 php4 php5 db redis
##
## Notes:
## - Traefik uses Lets Encrypt production. Ensure DNS A/AAAA records for api.truckwash.dk, api.truckwash.io, api-v2.truckwash.io and traefik.truckwash.dk point to the expected ingress and ports 80/443 are reachable.
## - Traefik uses Lets Encrypt production. Ensure DNS A/AAAA records for api.truckwash.dk, api.truckwash.io and traefik.truckwash.dk point to this host and ports 80/443 are reachable.
## - The dashboard is protected by basic auth and an IP allowlist (defined in dynamic.yml). Replace the bcrypt hash before enabling in production.
+21 -119
View File
@@ -3,14 +3,12 @@ services:
traefik:
image: traefik:2.11
container_name: traefik
group_add:
- "${DOCKER_SOCKET_GID:-65534}"
ports:
- "${TRAEFIK_WEB_PORT:-80}:80"
- "${TRAEFIK_WEBSECURE_PORT:-443}:443"
- "${TRAEFIK_WEBSECURE_STAGING_PORT:-4433}:4433"
- "80:80"
- "443:443"
- "4433:4433"
# Prometheus metrics endpoint (local dev)
- "${TRAEFIK_METRICS_PORT:-9100}:9100"
- "9100:9100"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./services/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
@@ -36,41 +34,6 @@ services:
- "traefik.http.routers.traefik-local.entrypoints=web"
- "traefik.http.routers.traefik-local.service=api@internal"
- "traefik.http.routers.traefik-local.middlewares=dashboard-allow-local@file,dashboard-auth@file"
# Broker API (handled in edge-broker service)
- "traefik.http.routers.edge-broker.rule=Host(`api.truckwash.dk`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker.entrypoints=websecure"
- "traefik.http.routers.edge-broker.tls=true"
- "traefik.http.routers.edge-broker.tls.certresolver=le"
- "traefik.http.routers.edge-broker.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker.priority=200"
- "traefik.http.routers.edge-broker.service=edge-broker"
- "traefik.http.routers.edge-broker-io.rule=Host(`api.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-io.entrypoints=websecure"
- "traefik.http.routers.edge-broker-io.tls=true"
- "traefik.http.routers.edge-broker-io.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-io.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-io.priority=200"
- "traefik.http.routers.edge-broker-io.service=edge-broker"
- "traefik.http.routers.edge-broker-v2.rule=Host(`api-v2.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-v2.entrypoints=websecure"
- "traefik.http.routers.edge-broker-v2.tls=true"
- "traefik.http.routers.edge-broker-v2.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-v2.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-v2.priority=200"
- "traefik.http.routers.edge-broker-v2.service=edge-broker"
- "traefik.http.routers.edge-broker-staging.rule=Host(`api.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-staging.entrypoints=websecure-staging"
- "traefik.http.routers.edge-broker-staging.tls=true"
- "traefik.http.routers.edge-broker-staging.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-staging.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-staging.priority=200"
- "traefik.http.routers.edge-broker-staging.service=edge-broker"
- "traefik.http.routers.edge-broker-local.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local.entrypoints=web"
- "traefik.http.routers.edge-broker-local.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local.priority=200"
- "traefik.http.routers.edge-broker-local.service=edge-broker"
- "traefik.http.routers.edge-broker-local-secure.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
redis:
image: redis:7
@@ -103,10 +66,8 @@ services:
mysql-debug:
image: mysql:8.4
container_name: mysql-debug
profiles: [dev]
command: ["mysqld", "--innodb-use-native-aio=0"]
environment:
MYSQL_ROOT_PASSWORD: ${CONFIG_DB_DEBUG_PASSWORD:?CONFIG_DB_DEBUG_PASSWORD is required for mysql-debug}
MYSQL_ROOT_PASSWORD: ${CONFIG_DB_DEBUG_PASSWORD:-debug_root_password}
MYSQL_DATABASE: ${CONFIG_DB_DEBUG_DATABASE:-nnks_db_debug}
ports:
- "3307:3306"
@@ -125,59 +86,9 @@ services:
dockerfile: services/edge-broker/Dockerfile
container_name: edge-broker
environment:
EDGE_AUTH_MODE: ${EDGE_AUTH_MODE:-strict}
EDGE_MANAGER_URL: ${EDGE_MANAGER_URL:-http://caddy}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
labels:
- "traefik.enable=true"
- "traefik.http.routers.edge-broker-api.rule=Host(`api.truckwash.dk`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api.tls=true"
- "traefik.http.routers.edge-broker-api.tls.certresolver=le"
- "traefik.http.routers.edge-broker-api.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api.priority=200"
- "traefik.http.routers.edge-broker-api.service=edge-broker"
- "traefik.http.routers.edge-broker-api-io.rule=Host(`api.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api-io.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api-io.tls=true"
- "traefik.http.routers.edge-broker-api-io.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-api-io.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api-io.priority=200"
- "traefik.http.routers.edge-broker-api-io.service=edge-broker"
- "traefik.http.routers.edge-broker-api-v2.rule=Host(`api-v2.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api-v2.entrypoints=websecure"
- "traefik.http.routers.edge-broker-api-v2.tls=true"
- "traefik.http.routers.edge-broker-api-v2.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-api-v2.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api-v2.priority=200"
- "traefik.http.routers.edge-broker-api-v2.service=edge-broker"
- "traefik.http.routers.edge-broker-api-staging.rule=Host(`api.truckwash.io`) && PathPrefix(`/edge-broker`)"
- "traefik.http.routers.edge-broker-api-staging.entrypoints=websecure-staging"
- "traefik.http.routers.edge-broker-api-staging.tls=true"
- "traefik.http.routers.edge-broker-api-staging.tls.certresolver=le_io"
- "traefik.http.routers.edge-broker-api-staging.middlewares=secure-headers@file,edge-broker-strip"
- "traefik.http.routers.edge-broker-api-staging.priority=200"
- "traefik.http.routers.edge-broker-api-staging.service=edge-broker"
- "traefik.http.routers.edge-broker-local.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local.entrypoints=web"
- "traefik.http.routers.edge-broker-local.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local.priority=200"
- "traefik.http.routers.edge-broker-local.service=edge-broker"
- "traefik.http.routers.edge-broker-local-secure.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local-secure.entrypoints=websecure"
- "traefik.http.routers.edge-broker-local-secure.tls=true"
- "traefik.http.routers.edge-broker-local-secure.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local-secure.priority=200"
- "traefik.http.routers.edge-broker-local-secure.service=edge-broker"
- "traefik.http.routers.edge-broker-local-staging.rule=Host(`localhost`) && PathPrefix(`/api/edge-broker`)"
- "traefik.http.routers.edge-broker-local-staging.entrypoints=websecure-staging"
- "traefik.http.routers.edge-broker-local-staging.tls=true"
- "traefik.http.routers.edge-broker-local-staging.middlewares=secure-headers@file,edge-broker-strip-local"
- "traefik.http.routers.edge-broker-local-staging.priority=200"
- "traefik.http.routers.edge-broker-local-staging.service=edge-broker"
- "traefik.http.middlewares.edge-broker-strip.stripPrefix.prefixes=/edge-broker"
- "traefik.http.middlewares.edge-broker-strip-local.stripPrefix.prefixes=/api/edge-broker"
- "traefik.http.services.edge-broker.loadbalancer.server.port=4300"
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
ports:
- "4300:4300"
caddy:
image: caddy:2.7.6-alpine
@@ -190,7 +101,7 @@ services:
- php5
volumes:
- ./services/nginx/app:/var/www/html
- ./services/caddy:/etc/caddy:ro
- ./services/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- ./services/caddy/logs:/var/log/caddy
labels:
- "traefik.enable=true"
@@ -210,16 +121,8 @@ services:
- "traefik.http.routers.api-io.tls.certresolver=le_io"
- "traefik.http.routers.api-io.service=caddy"
- "traefik.http.routers.api-io.middlewares=secure-headers@file,api-ratelimit@file"
# Public API (.io load-balanced gateway)
- "traefik.http.routers.api-v2.rule=Host(`api-v2.truckwash.io`)"
- "traefik.http.routers.api-v2.entrypoints=websecure"
- "traefik.http.routers.api-v2.tls=true"
- "traefik.http.routers.api-v2.tls.domains[0].main=api-v2.truckwash.io"
- "traefik.http.routers.api-v2.tls.certresolver=le_io"
- "traefik.http.routers.api-v2.service=caddy"
- "traefik.http.routers.api-v2.middlewares=secure-headers@file,api-ratelimit@file"
# HTTP to HTTPS redirect for both API domains
- "traefik.http.routers.api-http.rule=Host(`api.truckwash.dk`) || Host(`api.truckwash.io`) || Host(`api-v2.truckwash.io`)"
- "traefik.http.routers.api-http.rule=Host(`api.truckwash.dk`) || Host(`api.truckwash.io`)"
- "traefik.http.routers.api-http.entrypoints=web"
- "traefik.http.routers.api-http.middlewares=redirect-to-https@file"
- "traefik.http.routers.api-http.service=caddy"
@@ -255,10 +158,9 @@ services:
container_name: caddy-staging
depends_on:
- php-staging
command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile-staging", "--adapter", "caddyfile"]
volumes:
- ./services/nginx/staging:/var/www/html
- ./services/caddy:/etc/caddy:ro
- ./services/nginx/app:/var/www/html
- ./services/caddy/Caddyfile-staging:/etc/caddy/Caddyfile:ro
- ./services/caddy/logs-staging:/var/log/caddy
labels:
- "traefik.enable=true"
@@ -311,7 +213,7 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "true"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
@@ -331,7 +233,7 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
@@ -351,7 +253,7 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
@@ -371,7 +273,7 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
@@ -391,7 +293,7 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
@@ -411,9 +313,9 @@ services:
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/staging:/var/www/html
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./services/php/logs-staging:/var/log/php
@@ -425,13 +327,13 @@ services:
depends_on:
- redis
- edge-broker
command: ["php", "index.php", "run", "cron-worker"]
command: ["sh", "-c", "while true; do php index.php run cron; sleep 60; done"]
env_file:
- .env
environment:
AUTO_COMPOSER_INSTALL: "false"
EDGE_BROKER_URL: ${EDGE_BROKER_URL:-http://edge-broker:4300}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:?set EDGE_BROKER_SHARED_SECRET in .env}
EDGE_BROKER_SHARED_SECRET: ${EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev}
volumes:
- ./services/nginx/app:/var/www/html
- ./services/php/php.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
-4
View File
@@ -1,4 +0,0 @@
# AGENT MCP SMOKE
Generated 20260813-091957 by hermes agent to verify GitHub MCP wiring.
Safe to close.
+3 -106
View File
@@ -3357,9 +3357,6 @@
},
"email_notifications_enabled": {
"type": "boolean"
},
"superuser_new_customer_email_notifications_enabled": {
"type": "boolean"
}
}
}
@@ -9856,7 +9853,6 @@
"Orders"
],
"summary": "Create Stripe payment intent",
"description": "Creates a Stripe Terminal card payment intent with fixed 25% moms.",
"operationId": "createStripePaymentIntent",
"requestBody": {
"required": true,
@@ -9874,6 +9870,9 @@
},
"reader": {
"type": "string"
},
"tax_percentage": {
"type": "integer"
}
}
}
@@ -12956,54 +12955,6 @@
}
}
},
"/slack/config": {
"get": {
"tags": [
"Config"
],
"summary": "Get Slack config",
"operationId": "getSlackConfig",
"responses": {
"200": {
"description": "Slack configuration retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SlackConfigListResponse"
}
}
}
}
}
},
"post": {
"tags": [
"Config"
],
"summary": "Update Slack config",
"operationId": "updateSlackConfig",
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {}
}
}
},
"responses": {
"200": {
"description": "Slack configuration updated successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ModuleConfigUpdateResponse"
}
}
}
}
}
}
},
"/backups/config": {
"get": {
"tags": [
@@ -15545,39 +15496,6 @@
"value"
]
},
"SlackConfigEntry": {
"type": "object",
"properties": {
"module": {
"type": "string",
"enum": [
"Slack"
]
},
"variable": {
"type": "string",
"enum": [
"customer_registration_webhook_url"
]
},
"type": {
"type": "string",
"enum": [
"string"
]
},
"value": {
"type": "string",
"example": "https://hooks.slack.com/services/..."
}
},
"required": [
"module",
"variable",
"type",
"value"
]
},
"BackupsConfigEntry": {
"type": "object",
"properties": {
@@ -16322,27 +16240,6 @@
}
]
},
"SlackConfigListResponse": {
"allOf": [
{
"$ref": "#/components/schemas/ModuleConfigEnvelopeBase"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SlackConfigEntry"
}
}
},
"required": [
"data"
]
}
]
},
"BackupsConfigListResponse": {
"allOf": [
{
-1
View File
@@ -7,5 +7,4 @@
<!-- AUTO-GENERATED, DO NOT EDIT -->
<p>Comprehensive API reference generated from the repository root <code>openapi.yaml</code>.</p>
<p>The edge broker's <code>/api/health</code> response additionally exposes a <code>lastActivityAt</code> field (ISO 8601 timestamp). It reports the most recent successful HTTP request handled by the broker container and defaults to the container's start time when no request has been processed yet.</p>
</topic>
@@ -12,7 +12,7 @@
</chapter>
<chapter title="Operation" id="operation">
<p>Operation ID: <code>createStripePaymentIntent</code></p>
<p>Creates a Stripe Terminal card payment intent with fixed 25% moms.</p>
<p>Create Stripe payment intent</p>
</chapter>
<chapter title="Authentication" id="authentication">
<p>Security requirements:</p>
@@ -32,6 +32,9 @@
},
&quot;reader&quot;: {
&quot;type&quot;: &quot;string&quot;
},
&quot;tax_percentage&quot;: {
&quot;type&quot;: &quot;integer&quot;
}
},
&quot;required&quot;: [
-95
View File
@@ -1,95 +0,0 @@
# XL Vask Selvvask surface — inventory & simplification plan
## Scope
The XLVask surface that powers the **Superuser → Fakturaer → Periode → Selvvask**
view. Goal: remove the AI / MiniMax / autopilot pipeline, leaving only the
operator-facing review and order-creation flow.
Out of scope: any other XLVask, plate scanner, customer, or vehicle surface.
## Files removed
| Path | Reason |
| --- | --- |
| `services/nginx/app/classes/xlvask_autopilot_service.php` | AI autopilot pipeline |
| `services/nginx/app/classes/xlvask_automation_service.php` | AI automation pipeline |
| `services/nginx/app/classes/xlvask_automation_policy_service.php` | AI policy service |
| `services/nginx/app/classes/minimax.php` | MiniMax integration |
| `services/nginx/app/modules/miniMax/` | MiniMax module (config + class) |
| `services/nginx/app/modules/xlvask/AUTOMATION_RUNBOOK.md` | Runbook for removed pipeline |
| `services/nginx/app/modules/xlvask/cron/tasks.php` | Module-owned cron registry (replaced by empty `cron_task_registry` discovery) |
| `services/nginx/app/modules/xlvask/migrations/20260804_xlvask_ai_auto_policy_v2.php` | Migration for removed AI schema |
| `services/nginx/app/modules/xlvask/config/xlvask_automatic_order_attachment_enabled_c.php` | Legacy autopilot gate |
| `services/nginx/app/modules/xlvask/config/xlvask_automatic_order_creation_enabled_c.php` | Legacy autopilot gate |
| `services/nginx/app/modules/xlvask/config/xlvask_minimax_integration_enabled_c.php` | MiniMax gate |
| `services/nginx/app/modules/xlvask/config/xlvask_openai_integration_enabled_c.php` | OpenAI gate |
| `services/nginx/app/cron/EnsureXLVaskAutomationSchema.php` | Migration helper |
| `scripts/xlvask-automation-migrate.php` | CLI wrapper for migration |
| `services/nginx/app/tests/Unit/XLVask/XLVaskAutomationMigrateScriptTest.php` | Removed migration test |
| `services/nginx/app/tests/Unit/XLVask/XLVaskAutomationServiceTest.php` | Removed automation test |
| `services/nginx/app/tests/Api/XLVaskReviewApiTest.php` | Replaced by Selvvask route contract test |
## Code changes (kept & simplified)
| Path | Change |
| --- | --- |
| `services/nginx/app/cron/Cron.php` | Drop `ProcessXLVaskAutopilotQueueCron` registration + function |
| `services/nginx/app/cli.php` | Drop `xlvask-automation-migrate` case |
| `services/nginx/app/routes/moduleConfigRoute.php` | Drop `/minimax/config` GET/POST endpoints |
| `services/nginx/app/routes/moduleXLVaskRoute.php` | Drop `/modules/xlvask/tasks/import-usage` 410 stub and `/tasks/debug` route |
| `services/nginx/app/routes/xlvaskUsageLogsRoute.php` | Slim to operator-only: list, summary, ignore/unignore, accept, reject, fast-link |
| `services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php` | Drop `runScheduledAutomationIfReady`, `processAutopilotQueue`, autopilot cleanup, legacy auto-creation branch |
| `services/nginx/app/modules/xlvask/xlvask_c.php` | Drop `minimax_integration_enabled`, `automatic_order_attachment_enabled`, `automatic_order_creation_enabled`, `openai_integration_enabled` |
| `services/nginx/app/objects/xlvask_usage_logs_o.php` | Add `summarizeUsageOrdersReadOnly` (replaces autopilot summary) |
| `services/nginx/app/openapi.yaml` | Replace autopilot/automation openapi block with operator-flow endpoints |
| `services/nginx/app/tests/Unit/Cron/CronTaskRegistryTest.php` | Update count: 24 → 22, drop `xlvask.autopilot_queue` assertion |
| `services/nginx/app/tests/Unit/XLVask/XLVaskUsageRouteContractTest.php` | Replaced with end-to-end contract assertions for the new operator surface |
## New operator-facing endpoints
All under `routes/xlvaskUsageLogsRoute.php` and scoped to the operator's
`allowedHallIds` (all-scope users see every configured scanner hall; own-scope
users see only their group's halls).
| Method | Path | Permission | Purpose |
| --- | --- | --- | --- |
| `GET` | `/modules/xlvask/services/usage/orders` | `list_xlvask_usage_orders_own/all` | List usage logs with direct linked order id, amount summary, ignored metadata |
| `GET` | `/modules/xlvask/services/usage/orders/summary` | `list_xlvask_usage_orders_own/all` | Read-only per-period summary (counts + net amount) |
| `PATCH` | `/modules/xlvask/services/usage/orders/{id}/ignore` | `review_xlvask_usage_order` | Mark ignored with reason |
| `POST` | `/modules/xlvask/services/usage/orders/{id}/unignore` | `review_xlvask_usage_order` | Clear ignored metadata |
| `POST` | `/modules/xlvask/services/usage/orders/{id}/accept` | `review_xlvask_usage_order` | Convert to order via `createOrderFromWash` |
| `POST` | `/modules/xlvask/services/usage/orders/{id}/reject` | `review_xlvask_usage_order` | Mark ignored with reject reason |
| `GET` | `/modules/xlvask/services/usage/orders/fast-link` | `list_xlvask_usage_orders_own` | Cached fast-link redeem (existing) |
## Permissions
The Selvvask surface uses these permissions only:
- `list_xlvask_usage_orders_own`
- `list_xlvask_usage_orders_all`
- `review_xlvask_usage_order`
`manage_xlvask_usage_automation`, `ignore_xlvask_usage_order`,
`superuser_xlvask_automation_activate` are not referenced anywhere in the
slimmed surface.
## Persistence model
`xlvask_usage_logs_o` already exposes `ignored_at`, `ignored_by`, `ignored_reason`
columns — no migration required for the simplified flow.
`orders_o::selectByWashId(int|string $WashId)` and
`orders_o::addXLVaskOrder(users_o $user, xlvask_usage_log $xlvask_usage_log)` are
the only integration points with the order pipeline.
## Tests
- `vendor/bin/pest --testsuite=Unit --colors=never` passes 1266 tests.
- One pre-existing failure (`BirdControlPlaneActivationTest`) requires
`PLENO_REPO_ROOT_FOR_TESTS` (coolify repo) and is unrelated to this change.
## Repo scope
This inventory covers `api`. The `pleno-vue` side has not yet been updated in
this session and will be handled in a follow-up PR.
+3 -3
View File
@@ -38,14 +38,14 @@ http {
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number, X-Release-Trace, X-Release-Channel, X-Frontend-Version";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number";
add_header Access-Control-Allow-Credentials true;
# If OPTIONS method is needed for preflight
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number, X-Release-Trace, X-Release-Channel, X-Frontend-Version";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number";
return 204; # No Content
}
@@ -65,4 +65,4 @@ http {
location ~* \.(cgi|shtml|phtml)$ {
}
}
}
}
+3 -3
View File
@@ -52,14 +52,14 @@ http {
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number, X-Release-Trace, X-Release-Channel, X-Frontend-Version";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number";
add_header Access-Control-Allow-Credentials true;
# If OPTIONS method is needed for preflight
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number, X-Release-Trace, X-Release-Channel, X-Frontend-Version";
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-Customer-Number";
return 204; # No Content
}
@@ -80,4 +80,4 @@ http {
# Additional SSL options or configurations can be placed here, if necessary.
}
}
}
}
+125 -6162
View File
File diff suppressed because it is too large Load Diff
-132545
View File
File diff suppressed because one or more lines are too long
+40 -49
View File
@@ -1,55 +1,46 @@
#-------------------------------------------------------------------------------#
# Qodana analysis is configured by qodana.yaml file #
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
#-------------------------------------------------------------------------------#
#################################################################################
# WARNING: Do not store sensitive information in this file, #
# as its contents will be included in the Qodana report. #
#################################################################################
version: "1.0"
linter: jetbrains/qodana-php:2026.1
#Specify inspection profile for code analysis
profile:
name: qodana.recommended
name: qodana.starter
php:
version: "8.2"
#Enable inspections
#include:
# - name: <SomeEnabledInspectionId>
bootstrap: |+
set -eu
composer --working-dir=services/nginx/app install --no-interaction --prefer-dist --no-progress --ignore-platform-reqs
composer --working-dir=services/nginx/app/modules/washcertificates install --no-interaction --prefer-dist --no-progress --ignore-platform-reqs
npm --prefix services/edge-agent ci --ignore-scripts
npm --prefix services/edge-broker ci --ignore-scripts
#Disable inspections
#exclude:
# - name: <SomeDisabledInspectionId>
# paths:
# - <path/where/not/run/inspection>
exclude:
# This application is intentionally Composer-classmapped and keeps legacy snake_case
# classes plus multiple local test doubles in single files; PSR path rules do not apply.
- name: PhpIllegalPsrClassPathInspection
paths:
- services/nginx/app
# Unit-test doubles intentionally bypass integration-heavy parent constructors.
- name: PhpMissingParentConstructorInspection
paths:
- services/nginx/app/tests
# These focused tests configure doubles through public fields before invoking behavior.
- name: PhpObjectFieldsAreOnlyWrittenInspection
paths:
- services/nginx/app/tests/Unit/Bird/BirdGateCallFlowTest.php
- services/nginx/app/tests/Unit/Invoicing/EconomicCustomersDiscountFallbackTest.php
- services/nginx/app/tests/Unit/Selfserve/SelfserveCustomerLaneAccessTest.php
# API coverage markers are intentional statement-style calls in the Pest DSL.
# Their return value is irrelevant; the call records route/scenario coverage.
- name: PhpExpressionResultUnusedInspection
paths:
- services/nginx/app/tests/Api
- name: All
paths:
- services/nginx/app/vendor
- services/nginx/app/modules/washcertificates/vendor
- services/nginx/app/build
- services/nginx/app/.phpunit.cache
- services/nginx/app/tests/Legacy
- services/edge-agent/node_modules
- services/edge-broker/node_modules
- services/edge-agent/dist
- documentation/generated
- documentation/topics/generated
- documentation/_build
- documentation/_site_rebuild_20260317
- docs_bird_voice_calls.html
- .tmp
- .openclaw
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
#bootstrap: sh ./prepare-qodana.sh
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
#plugins:
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
# Quality gate. Will fail the CI/CD pipeline if any condition is not met
# severityThresholds - configures maximum thresholds for different problem severities
# testCoverageThresholds - configures minimum code coverage on a whole project and newly added code
# Code Coverage is available in Ultimate and Ultimate Plus plans
#failureConditions:
# severityThresholds:
# any: 15
# critical: 5
# testCoverageThresholds:
# fresh: 70
# total: 50
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
linter: jetbrains/qodana-php:2025.3
-102
View File
@@ -1,102 +0,0 @@
#!/usr/bin/env sh
set -eu
suite="${1:-}"
case "$suite" in
unit|integration|api|legacy|all)
;;
*)
echo "Usage: $0 <unit|integration|api|legacy|all>" >&2
exit 2
;;
esac
script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
repo_root="$(CDPATH= cd -- "$script_dir/.." && pwd)"
cd "$repo_root"
compose_files="-f docker-compose.yml -f .github/docker-compose.ci.yml"
project_suffix="$(date +%s)-$$"
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-php-local-${suite}-${project_suffix}}"
log_dir=".tmp/ci-logs/$suite"
mkdir -p "$log_dir"
env_backup_dir=".tmp/php-ci-env-backup-$project_suffix"
mkdir -p "$env_backup_dir"
had_env=0
had_env_staging=0
if [ -f .env ]; then
cp .env "$env_backup_dir/env"
had_env=1
fi
if [ -f .env.staging ]; then
cp .env.staging "$env_backup_dir/env.staging"
had_env_staging=1
fi
cp .github/ci.env .env
cp .github/ci.env.staging .env.staging
collect_logs() {
status="$1"
if [ "$status" -eq 0 ]; then
return
fi
mkdir -p "$log_dir"
docker compose $compose_files ps > "$log_dir/docker-compose-ps.txt" 2>&1 || true
docker compose $compose_files logs --no-color > "$log_dir/docker-compose.log" 2>&1 || true
docker compose $compose_files cp php1:/var/www/html/build/logs "$log_dir/app-build-logs" >/dev/null 2>&1 || true
docker compose $compose_files cp php1:/var/log/php "$log_dir/php-logs" >/dev/null 2>&1 || true
}
cleanup() {
status="$?"
collect_logs "$status"
docker compose $compose_files down -v >/dev/null 2>&1 || true
if [ "$had_env" -eq 1 ]; then
cp "$env_backup_dir/env" .env
else
rm -f .env
fi
if [ "$had_env_staging" -eq 1 ]; then
cp "$env_backup_dir/env.staging" .env.staging
else
rm -f .env.staging
fi
rm -rf "$env_backup_dir"
exit "$status"
}
trap cleanup EXIT INT TERM
docker compose $compose_files up -d redis mysql-debug php1
docker compose $compose_files exec -T php1 sh -lc '
set -eu
for i in $(seq 1 90); do
if MYSQL_PWD="${CONFIG_DB_PASSWORD:-debug_root_password}" mysqladmin \
-h "${CONFIG_DB_HOST:-mysql-debug}" \
-P "${CONFIG_DB_PORT:-3306}" \
-u "${CONFIG_DB_USER:-root}" \
ping --silent >/dev/null 2>&1; then
exit 0
fi
sleep 1
done
echo "Timed out waiting for mysql-debug" >&2
exit 1
'
tar \
--exclude='./vendor' \
--exclude='./.phpunit.cache' \
--exclude='./build/logs' \
-C services/nginx/app -cf - . \
| docker compose $compose_files exec -T php1 tar -C /var/www/html -xf -
docker compose $compose_files exec -T php1 sh -lc \
'cd /var/www/html && composer install --no-interaction --prefer-dist --no-progress'
docker compose $compose_files exec -T php1 sh -lc \
"cd /var/www/html && composer test:ci:$suite"
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/env php
<?php
if (PHP_SAPI !== 'cli') {
fwrite(STDERR, "This command is CLI-only.\n");
exit(2);
}
const WD = __DIR__ . '/../services/nginx/app';
require_once WD . '/vendor/autoload.php';
require_once WD . '/config.php';
require_once WD . '/classes/db.php';
require_once WD . '/classes/account_deletion_schema_bootstrap.php';
$response = null;
$db = new \classes\db($CONFIG_DB);
$db->connect();
$command = $argv[1] ?? 'check';
if ($command === 'apply') {
if (($argv[2] ?? '') !== '--yes') {
fwrite(STDERR, "Refusing schema mutation without: apply --yes\n");
exit(2);
}
\classes\account_deletion_schema_bootstrap::apply();
}
if (!in_array($command, ['check', 'apply'], true)) {
fwrite(STDERR, "Usage: scripts/account-deletion-schema.php check|apply --yes\n");
exit(2);
}
$status = \classes\account_deletion_schema_bootstrap::check();
fwrite(STDOUT, json_encode($status, JSON_UNESCAPED_SLASHES) . PHP_EOL);
exit($status['ready'] ? 0 : 1);
-58
View File
@@ -1,58 +0,0 @@
#!/usr/bin/env php
<?php
if (PHP_SAPI !== 'cli') {
fwrite(STDERR, "This command is CLI-only.\n");
exit(2);
}
$command = $argv[1] ?? 'check';
if (!in_array($command, ['check', 'apply', 'webhooks-check', 'webhooks-apply'], true)) {
fwrite(
STDERR,
"Usage: scripts/bird-control-plane-activate.php check|apply|webhooks-check|webhooks-apply [--yes]\n"
);
exit(2);
}
if (in_array($command, ['apply', 'webhooks-apply'], true) && ($argv[2] ?? '') !== '--yes') {
fwrite(STDERR, "Refusing Bird activation without: apply --yes\n");
exit(2);
}
$appDirectory = __DIR__ . '/../services/nginx/app';
if (!is_file($appDirectory . '/config.php')) {
$appDirectory = dirname(__DIR__);
}
define('WD', $appDirectory);
require_once WD . '/vendor/autoload.php';
require_once WD . '/config.php';
require_once WD . '/classes/db.php';
require_once WD . '/modules/bird/classes/bird_control_plane_activator.php';
require_once WD . '/modules/bird/classes/bird_webhook_subscription_reconciler.php';
try {
$pdo = \classes\db::getPDO();
if (str_starts_with($command, 'webhooks-')) {
$reconciler = new \bird\classes\bird_webhook_subscription_reconciler($pdo);
$organizationId = trim((string)(getenv('BIRD_ORGANIZATION_ID') ?: ''));
$status = $command === 'webhooks-apply'
? $reconciler->apply($organizationId)
: $reconciler->check($organizationId);
} else {
$activator = new \bird\classes\bird_control_plane_activator($pdo);
$status = $command === 'apply' ? $activator->apply([
'controlPlaneToken' => trim((string)(getenv('BIRD_CONTROL_PLANE_TOKEN') ?: '')),
'webhookSigningKey' => trim((string)(getenv('BIRD_WEBHOOK_SIGNING_KEY') ?: '')),
'participantId' => trim((string)(getenv('BIRD_PARTICIPANT_ID') ?: '')),
]) : $activator->check();
}
fwrite(STDOUT, json_encode($status, JSON_UNESCAPED_SLASHES) . PHP_EOL);
exit(($status['ready'] ?? false) === true ? 0 : 1);
} catch (Throwable $throwable) {
error_log('[bird-control-plane-activate] Failed: ' . get_class($throwable));
fwrite(STDOUT, json_encode([
'ready' => false,
'errorCode' => 'bird_activation_failed',
], JSON_UNESCAPED_SLASHES) . PHP_EOL);
exit(1);
}
@@ -1,28 +0,0 @@
#!/usr/bin/env php
<?php
if (PHP_SAPI !== 'cli') {
exit(2);
}
$appDirectory = __DIR__ . '/../services/nginx/app';
if (!is_file($appDirectory . '/config.php')) {
$appDirectory = dirname(__DIR__);
}
define('WD', $appDirectory);
require_once WD . '/vendor/autoload.php';
require_once WD . '/config.php';
require_once WD . '/classes/db.php';
require_once WD . '/modules/bird/classes/bird_control_plane_auto_activation.php';
try {
$status = (new \bird\classes\bird_control_plane_auto_activation(
\classes\db::getPDO()
))->run();
fwrite(STDOUT, json_encode($status, JSON_UNESCAPED_SLASHES) . PHP_EOL);
exit(($status['ready'] ?? false) === true ? 0 : 1);
} catch (Throwable $throwable) {
error_log('[bird-control-plane-auto-activate] Failed: ' . get_class($throwable));
fwrite(STDOUT, '{"ready":false,"errorCode":"bird_auto_activation_failed"}' . PHP_EOL);
exit(1);
}
@@ -1,79 +0,0 @@
#!/bin/sh
set -eu
bootstrap_url='https://api.truckwash.io:4433/bird/control-plane/v1/bootstrap'
status_url='https://api.truckwash.io:4433/bird/control-plane/v1/status'
expected_algorithm='RSA-OAEP-256'
expected_fingerprint='6dc63c6ffe33b8de0b1396d7f529f56aea0a685ef98168016161cf721ddc8c21'
private_key='/home/jeppe/.openclaw/credentials/bird.bootstrap-private.pem'
credential_dir='/home/jeppe/.openclaw/credentials'
destination="$credential_dir/bird.gateway-token"
umask 077
mkdir -p "$credential_dir"
envelope_file="$(mktemp "$credential_dir/.bird-bootstrap-envelope.XXXXXX")"
candidate_file="$(mktemp "$credential_dir/.bird-gateway-token.XXXXXX")"
payload_file="$(mktemp "$credential_dir/.bird-bootstrap-payload.XXXXXX")"
status_file="$(mktemp "$credential_dir/.bird-bootstrap-status.XXXXXX")"
cleanup() {
rm -f "$envelope_file" "$candidate_file" "$payload_file" "$status_file"
}
trap cleanup EXIT HUP INT TERM
test -r "$private_key"
test "$(stat -c '%a' "$private_key")" = '600'
curl --proto '=https' --tlsv1.2 --fail --silent --show-error \
--max-time 30 "$bootstrap_url" > "$envelope_file"
test "$(jq -r '.success // false' "$envelope_file")" = 'true'
test "$(jq -r '.data.algorithm // empty' "$envelope_file")" = "$expected_algorithm"
test "$(jq -r '.data.keyFingerprint // empty' "$envelope_file")" = "$expected_fingerprint"
jq -e '.data | keys == ["algorithm","ciphertext","keyFingerprint","tokenVersion","updatedAt"]' \
"$envelope_file" >/dev/null
jq -e '.data.tokenVersion | type == "number" and . >= 1 and floor == .' \
"$envelope_file" >/dev/null
jq -e '.data.updatedAt | type == "string" and test("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$")' \
"$envelope_file" >/dev/null
jq -e '.data.ciphertext | type == "string" and length == 512 and test("^[A-Za-z0-9+/]{512}$")' \
"$envelope_file" >/dev/null
jq -r '.data.ciphertext' "$envelope_file" \
| base64 -d \
| openssl pkeyutl -decrypt -inkey "$private_key" \
-pkeyopt rsa_padding_mode:oaep \
-pkeyopt rsa_oaep_md:sha256 \
-pkeyopt rsa_mgf1_md:sha256 > "$payload_file"
jq -e '. | keys == ["algorithm","keyFingerprint","token","tokenVersion","updatedAt"]' \
"$payload_file" >/dev/null
test "$(jq -r '.algorithm // empty' "$payload_file")" = "$expected_algorithm"
test "$(jq -r '.keyFingerprint // empty' "$payload_file")" = "$expected_fingerprint"
test "$(jq -r '.tokenVersion // empty' "$payload_file")" = \
"$(jq -r '.data.tokenVersion' "$envelope_file")"
test "$(jq -r '.updatedAt // empty' "$payload_file")" = \
"$(jq -r '.data.updatedAt' "$envelope_file")"
jq -j '.token' "$payload_file" > "$candidate_file"
test "$(wc -c < "$candidate_file")" = '64'
grep -Eq '^[A-Za-z0-9_-]{64}$' "$candidate_file"
chmod 600 "$candidate_file"
token="$(cat "$candidate_file")"
{
printf 'url = "%s"\n' "$status_url"
printf 'proto = "=https"\n'
printf 'tlsv1.2\n'
printf 'fail\nsilent\nshow-error\n'
printf 'max-time = 30\n'
printf 'header = "Authorization: Bearer %s"\n' "$token"
} | curl --config - > "$status_file"
unset token
jq -e '.success == true and .data.enabled == true and .data.webhookConfigured == true' \
"$status_file" >/dev/null
mv -f "$candidate_file" "$destination"
chmod 600 "$destination"
trap - EXIT HUP INT TERM
rm -f "$envelope_file" "$payload_file" "$status_file"
printf 'Bird gateway credential bootstrapped and authenticated.\n'
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env php
<?php
if (PHP_SAPI !== 'cli') {
fwrite(STDERR, "This command is CLI-only.\n");
exit(2);
}
const WD = __DIR__ . '/../services/nginx/app';
require_once WD . '/vendor/autoload.php';
require_once WD . '/config.php';
require_once WD . '/classes/db.php';
require_once WD . '/modules/bird/classes/bird_control_plane_schema_bootstrap.php';
$command = $argv[1] ?? 'check';
if (!in_array($command, ['check', 'apply'], true)) {
fwrite(STDERR, "Usage: scripts/bird-control-plane-schema.php check|apply --yes\n");
exit(2);
}
$pdo = \classes\db::getPDO();
if ($command === 'apply') {
if (($argv[2] ?? '') !== '--yes') {
fwrite(STDERR, "Refusing schema mutation without: apply --yes\n");
exit(2);
}
\bird\classes\bird_control_plane_schema_bootstrap::apply($pdo);
}
$status = \bird\classes\bird_control_plane_schema_bootstrap::check($pdo);
fwrite(STDOUT, json_encode($status, JSON_UNESCAPED_SLASHES) . PHP_EOL);
exit($status['ready'] ? 0 : 1);
-45
View File
@@ -1,45 +0,0 @@
#!/usr/bin/env sh
set -eu
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <service> [service ...]" >&2
exit 2
fi
compose_files="${CI_DOCKER_COMPOSE_FILES:--f docker-compose.yml -f .github/docker-compose.ci.yml}"
lock_file="${CI_DOCKER_LOCK_FILE:-/tmp/pleno-api-ci-docker-compose-up.lock}"
max_attempts="${CI_DOCKER_UP_RETRIES:-${PHP_CI_DOCKER_RETRIES:-3}}"
export COMPOSE_PROFILES="${COMPOSE_PROFILES:-dev}"
compose_up() {
attempt=1
while :; do
docker network prune -f >/dev/null 2>&1 || true
if docker compose $compose_files up -d "$@"; then
return 0
fi
status="$?"
docker compose $compose_files down -v --remove-orphans >/dev/null 2>&1 || true
if [ "$attempt" -ge "$max_attempts" ]; then
return "$status"
fi
sleep_seconds=$((attempt * 5))
echo "Docker compose up failed with status $status; retrying in ${sleep_seconds}s (attempt $((attempt + 1))/$max_attempts)." >&2
sleep "$sleep_seconds"
attempt=$((attempt + 1))
done
}
if command -v flock >/dev/null 2>&1; then
(
flock 9
compose_up "$@"
) 9>"$lock_file"
else
echo "flock is not available; running Docker compose startup without a host lock." >&2
compose_up "$@"
fi
-453
View File
@@ -1,453 +0,0 @@
import { spawn } from "node:child_process";
import crypto from "node:crypto";
import fs from "node:fs";
import http from "node:http";
import net from "node:net";
import os from "node:os";
import path from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const DEFAULT_AGENT_PATH = path.join(
repoRoot,
"services/nginx/app/resources/edge-gateway-agent/agent.php"
);
const DEFAULT_PHP_IMAGE = "php:8.2-cli-bookworm";
const DEFAULT_TIMEOUT_MS = 12000;
function parseArgs(argv = process.argv.slice(2)) {
const options = {
agentPath: DEFAULT_AGENT_PATH,
phpImage: DEFAULT_PHP_IMAGE,
timeoutMs: DEFAULT_TIMEOUT_MS,
keepTemp: false,
help: false,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
const next = argv[index + 1];
switch (arg) {
case "--agent-path":
options.agentPath = path.resolve(String(next || "").trim());
index += 1;
break;
case "--php-image":
options.phpImage = String(next || "").trim() || DEFAULT_PHP_IMAGE;
index += 1;
break;
case "--timeout-ms":
options.timeoutMs = Number.parseInt(String(next || ""), 10) || DEFAULT_TIMEOUT_MS;
index += 1;
break;
case "--keep-temp":
options.keepTemp = true;
break;
case "--help":
case "-h":
options.help = true;
break;
default:
throw new Error(`Unknown argument: ${arg}`);
}
}
return options;
}
function printUsage() {
process.stdout.write(`Usage:
node scripts/edge-agent-command-drain-proof.mjs [options]
Verifies that a broker-connected PHP compose edge agent still drains API-queued
SET_RELAY_STATE jobs to the LAN worker /relay/switch endpoint.
Options:
--agent-path <path> PHP agent artifact to execute.
Default: ${DEFAULT_AGENT_PATH}
--php-image <image> Docker PHP image with curl, sqlite3, and pdo_sqlite.
Default: ${DEFAULT_PHP_IMAGE}
--timeout-ms <ms> Proof timeout. Default: ${DEFAULT_TIMEOUT_MS}
--keep-temp Keep the temporary config/runtime directory.
--help Show this help text.
`);
}
function readJson(request) {
return new Promise((resolve) => {
let raw = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
raw += chunk;
});
request.on("end", () => {
if (raw.trim() === "") {
resolve({});
return;
}
try {
resolve(JSON.parse(raw));
} catch {
resolve({ __invalid: raw });
}
});
});
}
function sendJson(response, status, payload) {
const body = JSON.stringify(payload);
response.writeHead(status, {
"content-type": "application/json; charset=utf-8",
"content-length": Buffer.byteLength(body),
});
response.end(body);
}
function listen(server) {
return new Promise((resolve) => {
server.listen(0, "127.0.0.1", () => resolve(server.address().port));
});
}
function closeServer(server) {
return new Promise((resolve) => {
server.close(() => resolve());
});
}
function websocketAcceptKey(key) {
return crypto
.createHash("sha1")
.update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`)
.digest("base64");
}
function createBrokerServer(state) {
const sockets = new Set();
const server = net.createServer((socket) => {
sockets.add(socket);
socket.on("close", () => sockets.delete(socket));
let buffer = "";
socket.on("data", (chunk) => {
buffer += chunk.toString("binary");
if (state.brokerHandshakeSeen || !buffer.includes("\r\n\r\n")) {
return;
}
const requestText = Buffer.from(buffer, "binary").toString("utf8");
const key = requestText.match(/Sec-WebSocket-Key:\s*(.+)\r\n/i)?.[1]?.trim();
const requestLine = requestText.split("\r\n")[0] || "";
if (!requestLine.includes("/ws/agent?")) {
state.failure = new Error(`unexpected broker path: ${requestLine}`);
}
if (!key) {
state.failure = new Error("broker handshake missing Sec-WebSocket-Key");
return;
}
socket.write([
"HTTP/1.1 101 Switching Protocols",
"Upgrade: websocket",
"Connection: Upgrade",
`Sec-WebSocket-Accept: ${websocketAcceptKey(key)}`,
"",
"",
].join("\r\n"));
state.brokerHandshakeSeen = true;
buffer = "";
});
});
return { server, sockets };
}
function createWorkerServer(state) {
return http.createServer(async (request, response) => {
const url = new URL(request.url, "http://127.0.0.1");
const body = await readJson(request);
state.requests.push({ service: "worker", method: request.method, path: url.pathname, body });
if (request.method === "GET" && url.pathname === "/health") {
sendJson(response, 200, { status: "healthy", timestamp: new Date().toISOString() });
return;
}
if (request.method === "POST" && url.pathname === "/relay/switch") {
state.relaySwitchSeen = true;
if (body.local_ip !== "10.123.0.31" || body.channel !== 0 || body.on !== true) {
state.failure = new Error(`unexpected relay switch payload: ${JSON.stringify(body)}`);
}
sendJson(response, 200, {
online: true,
on: true,
output: true,
raw: { source: "fake-worker" },
});
return;
}
sendJson(response, 404, { message: "not found" });
});
}
function createApiServer(state, brokerPort, workerPort) {
return http.createServer(async (request, response) => {
const url = new URL(request.url, "http://127.0.0.1");
const body = await readJson(request);
state.requests.push({ service: "api", method: request.method, path: url.pathname, body });
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/heartbeat") {
sendJson(response, 200, { data: { ok: true, broker_url: `ws://127.0.0.1:${brokerPort}` } });
return;
}
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/selfserve/machine-signal-bindings") {
sendJson(response, 200, { data: { monitors: [] } });
return;
}
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/commands/poll") {
state.commandPollSeen = true;
if (body.wait_seconds !== 0) {
state.failure = new Error(
`broker-connected command poll should be non-blocking, got wait_seconds=${body.wait_seconds}`
);
}
if (!state.commandDelivered) {
state.commandDelivered = true;
sendJson(response, 200, {
data: {
id: 77,
command_type: "SET_RELAY_STATE",
payload: {
localIp: "10.123.0.31",
channel: 0,
on: true,
relayId: "relay-proof",
},
},
});
return;
}
sendJson(response, 200, { data: null });
return;
}
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/commands/77/result") {
state.resultSeen = true;
if (body.ok !== true || body.result?.on !== true || body.result?.raw?.source !== "fake-worker") {
state.failure = new Error(`unexpected command result: ${JSON.stringify(body)}`);
}
sendJson(response, 200, { data: { acknowledged: true } });
return;
}
sendJson(response, 404, { message: "not found", path: url.pathname, workerPort });
});
}
function writeConfig(tempDir, apiPort, brokerPort, workerPort) {
const containerProofDir = "/proof";
const runtimeDir = `${containerProofDir}/runtime`;
const config = {
apiUrl: `http://127.0.0.1:${apiPort}`,
brokerUrl: `ws://127.0.0.1:${brokerPort}`,
gatewayId: 42,
agentToken: "agent-token",
installDir: containerProofDir,
runtimeDir,
stateDatabasePath: `${runtimeDir}/gateway-state.sqlite`,
workerBaseUrl: `http://127.0.0.1:${workerPort}`,
heartbeatIntervalSeconds: 60,
operationPollTimeoutSeconds: 20,
};
const configPath = path.join(tempDir, "config.json");
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
return { configPath, containerConfigPath: `${containerProofDir}/config.json` };
}
function spawnAgent({ agentPath, phpImage, tempDir, containerConfigPath }) {
return spawn("docker", [
"run",
"--rm",
"--network",
"host",
"-v",
`${agentPath}:/agent.php:ro`,
"-v",
`${tempDir}:/proof`,
phpImage,
"php",
"/agent.php",
"--config",
containerConfigPath,
], { stdio: ["ignore", "pipe", "pipe"] });
}
async function stopChild(child) {
if (child.exitCode !== null || child.signalCode !== null) {
return;
}
child.kill("SIGTERM");
const hardKill = setTimeout(() => {
if (child.exitCode === null && child.signalCode === null) {
child.kill("SIGKILL");
}
}, 1500);
await Promise.race([
new Promise((resolve) => child.once("exit", resolve)),
new Promise((resolve) => setTimeout(resolve, 2200)),
]);
clearTimeout(hardKill);
}
function evidenceFromState(state, childExited) {
return {
brokerHandshakeSeen: state.brokerHandshakeSeen,
commandPollSeen: state.commandPollSeen,
relaySwitchSeen: state.relaySwitchSeen,
resultSeen: state.resultSeen,
agentStayedRunningUntilProofComplete: !childExited,
};
}
export async function runProof(options) {
if (process.platform !== "linux") {
throw new Error("This proof uses Docker --network host and currently expects Linux.");
}
if (!fs.existsSync(options.agentPath)) {
throw new Error(`Agent artifact not found: ${options.agentPath}`);
}
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "edge-agent-command-drain-proof-"));
fs.mkdirSync(path.join(tempDir, "runtime"), { recursive: true });
const state = {
brokerHandshakeSeen: false,
commandPollSeen: false,
relaySwitchSeen: false,
resultSeen: false,
commandDelivered: false,
failure: null,
requests: [],
};
const broker = createBrokerServer(state);
const workerServer = createWorkerServer(state);
let apiServer = null;
let child = null;
let stdout = "";
let stderr = "";
let childExited = false;
try {
const brokerPort = await listen(broker.server);
const workerPort = await listen(workerServer);
apiServer = createApiServer(state, brokerPort, workerPort);
const apiPort = await listen(apiServer);
const { containerConfigPath } = writeConfig(tempDir, apiPort, brokerPort, workerPort);
child = spawnAgent({ ...options, tempDir, containerConfigPath });
child.stdout.on("data", (chunk) => {
stdout += chunk.toString();
});
child.stderr.on("data", (chunk) => {
stderr += chunk.toString();
});
child.once("exit", () => {
childExited = true;
});
const deadline = Date.now() + options.timeoutMs;
while (Date.now() < deadline && !state.failure && !childExited) {
if (state.brokerHandshakeSeen && state.commandPollSeen && state.relaySwitchSeen && state.resultSeen) {
break;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
const evidence = evidenceFromState(state, childExited);
if (
state.failure ||
!state.brokerHandshakeSeen ||
!state.commandPollSeen ||
!state.relaySwitchSeen ||
!state.resultSeen
) {
const error = state.failure || new Error("missing proof evidence");
error.evidence = evidence;
error.requests = state.requests;
error.stdout = stdout.slice(-3000);
error.stderr = stderr.slice(-3000);
throw error;
}
return {
evidence,
agentPath: options.agentPath,
phpImage: options.phpImage,
tempDir,
requestCount: state.requests.length,
};
} finally {
if (child) {
await stopChild(child);
}
for (const socket of broker.sockets) {
socket.destroy();
}
await Promise.allSettled([
closeServer(broker.server),
closeServer(workerServer),
apiServer ? closeServer(apiServer) : Promise.resolve(),
]);
if (!options.keepTemp) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
}
}
async function main() {
const options = parseArgs();
if (options.help) {
printUsage();
return;
}
const result = await runProof(options);
process.stdout.write("PASS broker-connected API command poll triggered local relay switch and posted result\n");
process.stdout.write(`${JSON.stringify(result.evidence)}\n`);
process.stdout.write(`Agent: ${result.agentPath}\n`);
process.stdout.write(`PHP image: ${result.phpImage}\n`);
if (options.keepTemp) {
process.stdout.write(`Temp dir: ${result.tempDir}\n`);
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch((error) => {
process.stderr.write(`FAIL ${error.message}\n`);
if (error.evidence) {
process.stderr.write(`Evidence: ${JSON.stringify(error.evidence)}\n`);
}
if (error.requests) {
process.stderr.write(`Requests: ${JSON.stringify(error.requests, null, 2)}\n`);
}
if (error.stdout) {
process.stderr.write(`stdout: ${error.stdout}\n`);
}
if (error.stderr) {
process.stderr.write(`stderr: ${error.stderr}\n`);
}
process.exit(1);
});
}
-619
View File
@@ -1,619 +0,0 @@
import { spawn } from "node:child_process";
import crypto from "node:crypto";
import fs from "node:fs";
import http from "node:http";
import net from "node:net";
import os from "node:os";
import path from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const DEFAULT_AGENT_PATH = path.join(
repoRoot,
"services/nginx/app/resources/edge-gateway-agent/agent.php"
);
const DEFAULT_WORKER_PATH = path.join(
repoRoot,
"services/nginx/app/resources/edge-gateway-agent/lan-worker.php"
);
const DEFAULT_PHP_IMAGE = "php:8.2-cli-bookworm";
const DEFAULT_TIMEOUT_MS = 15000;
const AGENT_TOKEN = "agent-token";
function parseArgs(argv = process.argv.slice(2)) {
const options = {
agentPath: DEFAULT_AGENT_PATH,
workerPath: DEFAULT_WORKER_PATH,
phpImage: DEFAULT_PHP_IMAGE,
timeoutMs: DEFAULT_TIMEOUT_MS,
keepTemp: false,
help: false,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
const next = argv[index + 1];
switch (arg) {
case "--agent-path":
options.agentPath = path.resolve(String(next || "").trim());
index += 1;
break;
case "--worker-path":
options.workerPath = path.resolve(String(next || "").trim());
index += 1;
break;
case "--php-image":
options.phpImage = String(next || "").trim() || DEFAULT_PHP_IMAGE;
index += 1;
break;
case "--timeout-ms":
options.timeoutMs = Number.parseInt(String(next || ""), 10) || DEFAULT_TIMEOUT_MS;
index += 1;
break;
case "--keep-temp":
options.keepTemp = true;
break;
case "--help":
case "-h":
options.help = true;
break;
default:
throw new Error(`Unknown argument: ${arg}`);
}
}
return options;
}
function printUsage() {
process.stdout.write(`Usage:
node scripts/edge-agent-to-shelly-proof.mjs [options]
Runs the PHP edge agent and real LAN worker against fake broker, API, and
Shelly RPC endpoints. Verifies that a broker-connected SET_RELAY_STATE command
drains from the API, reaches the worker, triggers a Shelly-style Switch.Set
call, reads Switch.GetStatus, and posts the command result.
Options:
--agent-path <path> PHP agent artifact to execute.
Default: ${DEFAULT_AGENT_PATH}
--worker-path <path> PHP LAN worker artifact to execute.
Default: ${DEFAULT_WORKER_PATH}
--php-image <image> Docker PHP image with curl, sqlite3, and pdo_sqlite.
Default: ${DEFAULT_PHP_IMAGE}
--timeout-ms <ms> Proof timeout. Default: ${DEFAULT_TIMEOUT_MS}
--keep-temp Keep the temporary config/runtime directory.
--help Show this help text.
`);
}
function readJson(request) {
return new Promise((resolve) => {
let raw = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
raw += chunk;
});
request.on("end", () => {
if (raw.trim() === "") {
resolve({});
return;
}
try {
resolve(JSON.parse(raw));
} catch {
resolve({ __invalid: raw });
}
});
});
}
function sendJson(response, status, payload) {
const body = JSON.stringify(payload);
response.writeHead(status, {
"content-type": "application/json; charset=utf-8",
"content-length": Buffer.byteLength(body),
});
response.end(body);
}
function requestJson({ method = "GET", port, path: requestPath, body = null, headers = {} }) {
return new Promise((resolve, reject) => {
const payload = body === null ? null : JSON.stringify(body);
const request = http.request({
hostname: "127.0.0.1",
port,
path: requestPath,
method,
headers: {
accept: "application/json",
...(payload === null ? {} : {
"content-type": "application/json",
"content-length": Buffer.byteLength(payload),
}),
...headers,
},
timeout: 1000,
}, (response) => {
let raw = "";
response.setEncoding("utf8");
response.on("data", (chunk) => {
raw += chunk;
});
response.on("end", () => {
let decoded;
try {
decoded = raw.trim() === "" ? {} : JSON.parse(raw);
} catch {
decoded = { __invalid: raw };
}
resolve({ status: response.statusCode || 0, body: decoded });
});
});
request.on("error", reject);
request.on("timeout", () => {
request.destroy(new Error("request timed out"));
});
if (payload !== null) {
request.write(payload);
}
request.end();
});
}
function listen(server) {
return new Promise((resolve) => {
server.listen(0, "127.0.0.1", () => resolve(server.address().port));
});
}
function closeServer(server) {
return new Promise((resolve) => {
server.close(() => resolve());
});
}
async function reservePort() {
const server = net.createServer();
const port = await new Promise((resolve) => {
server.listen(0, "127.0.0.1", () => resolve(server.address().port));
});
await closeServer(server);
return port;
}
function websocketAcceptKey(key) {
return crypto
.createHash("sha1")
.update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`)
.digest("base64");
}
function createBrokerServer(state) {
const sockets = new Set();
const server = net.createServer((socket) => {
sockets.add(socket);
socket.on("close", () => sockets.delete(socket));
let buffer = "";
socket.on("data", (chunk) => {
buffer += chunk.toString("binary");
if (state.brokerHandshakeSeen || !buffer.includes("\r\n\r\n")) {
return;
}
const requestText = Buffer.from(buffer, "binary").toString("utf8");
const key = requestText.match(/Sec-WebSocket-Key:\s*(.+)\r\n/i)?.[1]?.trim();
const requestLine = requestText.split("\r\n")[0] || "";
if (!requestLine.includes("/ws/agent?")) {
state.failure = new Error(`unexpected broker path: ${requestLine}`);
}
if (!key) {
state.failure = new Error("broker handshake missing Sec-WebSocket-Key");
return;
}
socket.write([
"HTTP/1.1 101 Switching Protocols",
"Upgrade: websocket",
"Connection: Upgrade",
`Sec-WebSocket-Accept: ${websocketAcceptKey(key)}`,
"",
"",
].join("\r\n"));
state.brokerHandshakeSeen = true;
buffer = "";
});
});
return { server, sockets };
}
function createShellyServer(state) {
return http.createServer((request, response) => {
const url = new URL(request.url, "http://127.0.0.1");
state.requests.push({
service: "shelly",
method: request.method,
path: url.pathname,
query: Object.fromEntries(url.searchParams.entries()),
});
if (request.method === "GET" && url.pathname === "/rpc/Switch.Set") {
state.shellySwitchSetSeen = true;
if (url.searchParams.get("id") !== "0" || url.searchParams.get("on") !== "true") {
state.failure = new Error(`unexpected Shelly Switch.Set query: ${url.search}`);
}
sendJson(response, 200, { was_on: false, output: true });
return;
}
if (request.method === "GET" && url.pathname === "/rpc/Switch.GetStatus") {
state.shellyStatusSeen = true;
if (url.searchParams.get("id") !== "0") {
state.failure = new Error(`unexpected Shelly Switch.GetStatus query: ${url.search}`);
}
sendJson(response, 200, { id: 0, output: true, source: "fake-shelly-rpc" });
return;
}
if (url.pathname.startsWith("/relay/")) {
state.failure = new Error(`legacy Shelly endpoint should not be used for generation 2 proof: ${url.pathname}`);
}
sendJson(response, 404, { message: "not found" });
});
}
function createApiServer(state, brokerPort, shellyAddress) {
return http.createServer(async (request, response) => {
const url = new URL(request.url, "http://127.0.0.1");
const body = await readJson(request);
state.requests.push({ service: "api", method: request.method, path: url.pathname, body });
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/heartbeat") {
sendJson(response, 200, { data: { ok: true, broker_url: `ws://127.0.0.1:${brokerPort}` } });
return;
}
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/selfserve/machine-signal-bindings") {
sendJson(response, 200, { data: { monitors: [] } });
return;
}
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/commands/poll") {
state.commandPollSeen = true;
if (body.wait_seconds !== 0) {
state.failure = new Error(
`broker-connected command poll should be non-blocking, got wait_seconds=${body.wait_seconds}`
);
}
if (!state.commandDelivered) {
state.commandDelivered = true;
sendJson(response, 200, {
data: {
id: 77,
command_type: "SET_RELAY_STATE",
payload: {
localIp: shellyAddress,
local_ip: shellyAddress,
channel: 0,
on: true,
relayId: "relay-proof",
relay_id: "relay-proof",
deviceGeneration: 2,
device_generation: 2,
},
},
});
return;
}
sendJson(response, 200, { data: null });
return;
}
if (request.method === "POST" && url.pathname === "/edge-agent/gateways/42/commands/77/result") {
state.resultSeen = true;
if (
body.ok !== true ||
body.result?.on !== true ||
body.result?.output !== true ||
body.result?.raw?.source !== "fake-shelly-rpc"
) {
state.failure = new Error(`unexpected command result: ${JSON.stringify(body)}`);
}
sendJson(response, 200, { data: { acknowledged: true } });
return;
}
sendJson(response, 404, { message: "not found", path: url.pathname });
});
}
function writeConfig(tempDir, apiPort, brokerPort, workerPort) {
const containerProofDir = "/proof";
const runtimeDir = `${containerProofDir}/runtime`;
const config = {
apiUrl: `http://127.0.0.1:${apiPort}`,
brokerUrl: `ws://127.0.0.1:${brokerPort}`,
gatewayId: 42,
agentToken: AGENT_TOKEN,
installDir: containerProofDir,
runtimeDir,
stateDatabasePath: `${runtimeDir}/gateway-state.sqlite`,
workerBaseUrl: `http://127.0.0.1:${workerPort}`,
heartbeatIntervalSeconds: 60,
operationPollTimeoutSeconds: 20,
};
const configPath = path.join(tempDir, "config.json");
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
return { containerConfigPath: `${containerProofDir}/config.json` };
}
function spawnWorker({ workerPath, phpImage, workerPort }) {
return spawn("docker", [
"run",
"--rm",
"--network",
"host",
"-e",
`TRUCKWASH_WORKER_TOKEN=${AGENT_TOKEN}`,
"-v",
`${workerPath}:/lan-worker.php:ro`,
phpImage,
"php",
"-S",
`127.0.0.1:${workerPort}`,
"/lan-worker.php",
], { stdio: ["ignore", "pipe", "pipe"] });
}
function spawnAgent({ agentPath, phpImage, tempDir, containerConfigPath }) {
return spawn("docker", [
"run",
"--rm",
"--network",
"host",
"-v",
`${agentPath}:/agent.php:ro`,
"-v",
`${tempDir}:/proof`,
phpImage,
"php",
"/agent.php",
"--config",
containerConfigPath,
], { stdio: ["ignore", "pipe", "pipe"] });
}
async function waitForWorker(workerPort, child, timeoutMs) {
const deadline = Date.now() + timeoutMs;
let lastError = null;
while (Date.now() < deadline) {
if (child.exitCode !== null || child.signalCode !== null) {
throw new Error(`LAN worker exited before becoming healthy: ${child.exitCode ?? child.signalCode}`);
}
try {
const response = await requestJson({ port: workerPort, path: "/health" });
if (response.status === 200 && response.body?.service === "lan-worker") {
return;
}
} catch (error) {
lastError = error;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
throw lastError || new Error("LAN worker did not become healthy");
}
async function stopChild(child) {
if (child.exitCode !== null || child.signalCode !== null) {
return;
}
child.kill("SIGTERM");
const hardKill = setTimeout(() => {
if (child.exitCode === null && child.signalCode === null) {
child.kill("SIGKILL");
}
}, 1500);
await Promise.race([
new Promise((resolve) => child.once("exit", resolve)),
new Promise((resolve) => setTimeout(resolve, 2200)),
]);
clearTimeout(hardKill);
}
function evidenceFromState(state, agentExited, workerExited) {
return {
brokerHandshakeSeen: state.brokerHandshakeSeen,
commandPollSeen: state.commandPollSeen,
shellySwitchSetSeen: state.shellySwitchSetSeen,
shellyStatusSeen: state.shellyStatusSeen,
resultSeen: state.resultSeen,
agentStayedRunningUntilProofComplete: !agentExited,
workerStayedRunningUntilProofComplete: !workerExited,
};
}
export async function runProof(options) {
if (process.platform !== "linux") {
throw new Error("This proof uses Docker --network host and currently expects Linux.");
}
if (!fs.existsSync(options.agentPath)) {
throw new Error(`Agent artifact not found: ${options.agentPath}`);
}
if (!fs.existsSync(options.workerPath)) {
throw new Error(`LAN worker artifact not found: ${options.workerPath}`);
}
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "edge-agent-to-shelly-proof-"));
fs.mkdirSync(path.join(tempDir, "runtime"), { recursive: true });
const state = {
brokerHandshakeSeen: false,
commandPollSeen: false,
shellySwitchSetSeen: false,
shellyStatusSeen: false,
resultSeen: false,
commandDelivered: false,
failure: null,
requests: [],
};
const broker = createBrokerServer(state);
const shellyServer = createShellyServer(state);
let apiServer = null;
let agent = null;
let worker = null;
let agentStdout = "";
let agentStderr = "";
let workerStdout = "";
let workerStderr = "";
let agentExited = false;
let workerExited = false;
try {
const brokerPort = await listen(broker.server);
const shellyPort = await listen(shellyServer);
const workerPort = await reservePort();
const shellyAddress = `127.0.0.1:${shellyPort}`;
apiServer = createApiServer(state, brokerPort, shellyAddress);
const apiPort = await listen(apiServer);
const { containerConfigPath } = writeConfig(tempDir, apiPort, brokerPort, workerPort);
worker = spawnWorker({ ...options, workerPort });
worker.stdout.on("data", (chunk) => {
workerStdout += chunk.toString();
});
worker.stderr.on("data", (chunk) => {
workerStderr += chunk.toString();
});
worker.once("exit", () => {
workerExited = true;
});
await waitForWorker(workerPort, worker, 5000);
agent = spawnAgent({ ...options, tempDir, containerConfigPath });
agent.stdout.on("data", (chunk) => {
agentStdout += chunk.toString();
});
agent.stderr.on("data", (chunk) => {
agentStderr += chunk.toString();
});
agent.once("exit", () => {
agentExited = true;
});
const deadline = Date.now() + options.timeoutMs;
while (Date.now() < deadline && !state.failure && !agentExited && !workerExited) {
if (
state.brokerHandshakeSeen &&
state.commandPollSeen &&
state.shellySwitchSetSeen &&
state.shellyStatusSeen &&
state.resultSeen
) {
break;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
const evidence = evidenceFromState(state, agentExited, workerExited);
if (
state.failure ||
!state.brokerHandshakeSeen ||
!state.commandPollSeen ||
!state.shellySwitchSetSeen ||
!state.shellyStatusSeen ||
!state.resultSeen
) {
const error = state.failure || new Error("missing proof evidence");
error.evidence = evidence;
error.requests = state.requests;
error.agentStdout = agentStdout.slice(-3000);
error.agentStderr = agentStderr.slice(-3000);
error.workerStdout = workerStdout.slice(-3000);
error.workerStderr = workerStderr.slice(-3000);
throw error;
}
return {
evidence,
agentPath: options.agentPath,
workerPath: options.workerPath,
phpImage: options.phpImage,
tempDir,
requestCount: state.requests.length,
};
} finally {
if (agent) {
await stopChild(agent);
}
if (worker) {
await stopChild(worker);
}
for (const socket of broker.sockets) {
socket.destroy();
}
await Promise.allSettled([
closeServer(broker.server),
closeServer(shellyServer),
apiServer ? closeServer(apiServer) : Promise.resolve(),
]);
if (!options.keepTemp) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
}
}
async function main() {
const options = parseArgs();
if (options.help) {
printUsage();
return;
}
const result = await runProof(options);
process.stdout.write("PASS broker-connected API command triggered real LAN worker Shelly RPC signal and posted result\n");
process.stdout.write(`${JSON.stringify(result.evidence)}\n`);
process.stdout.write(`Agent: ${result.agentPath}\n`);
process.stdout.write(`LAN worker: ${result.workerPath}\n`);
process.stdout.write(`PHP image: ${result.phpImage}\n`);
if (options.keepTemp) {
process.stdout.write(`Temp dir: ${result.tempDir}\n`);
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch((error) => {
process.stderr.write(`FAIL ${error.message}\n`);
if (error.evidence) {
process.stderr.write(`Evidence: ${JSON.stringify(error.evidence)}\n`);
}
if (error.requests) {
process.stderr.write(`Requests: ${JSON.stringify(error.requests, null, 2)}\n`);
}
if (error.agentStdout) {
process.stderr.write(`agent stdout: ${error.agentStdout}\n`);
}
if (error.agentStderr) {
process.stderr.write(`agent stderr: ${error.agentStderr}\n`);
}
if (error.workerStdout) {
process.stderr.write(`worker stdout: ${error.workerStdout}\n`);
}
if (error.workerStderr) {
process.stderr.write(`worker stderr: ${error.workerStderr}\n`);
}
process.exit(1);
});
}
-980
View File
@@ -1,980 +0,0 @@
import assert from "node:assert/strict";
import { execFile as execFileCallback, spawn as spawnCallback } from "node:child_process";
import { randomUUID } from "node:crypto";
import { promises as fs } from "node:fs";
import path from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import { DEFAULT_CONFIG_FILE_NAME, DEFAULT_HOST_API_URL } from "./test-gateway.mjs";
const execFile = promisify(execFileCallback);
const COMPOSE_SERVICES = ["traefik", "redis", "mysql-debug", "edge-broker", "php1", "php2", "php3", "php4", "php5", "caddy"];
function composeArgs(projectName, args) {
return ["compose", "-p", projectName, ...args];
}
async function resolveRootDir(scriptPath) {
const cwd = process.cwd();
try {
await fs.access(path.join(cwd, "docker-compose.yml"));
return cwd;
} catch {
return path.resolve(path.dirname(scriptPath), "..");
}
}
async function runCommand(command, args, { cwd, allowFailure = false, stdio = "pipe" } = {}) {
if (stdio === "inherit") {
await new Promise((resolve, reject) => {
const child = spawnCallback(command, args, {
cwd,
stdio: "inherit",
windowsHide: true,
});
child.on("exit", (code) => {
if (code === 0 || allowFailure) {
resolve();
return;
}
reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code}`));
});
child.on("error", reject);
});
return { stdout: "", stderr: "", code: 0 };
}
try {
const result = await execFile(command, args, {
cwd,
windowsHide: true,
encoding: "utf8",
});
return { stdout: result.stdout, stderr: result.stderr, code: 0 };
} catch (error) {
if (!allowFailure) {
throw error;
}
return {
stdout: error.stdout || "",
stderr: error.stderr || "",
code: typeof error.code === "number" ? error.code : 1,
};
}
}
function normalizeBaseUrl(url) {
return String(url || "").replace(/\/+$/, "");
}
function baseUrlWithHost(baseUrl, host, port = null) {
const url = new URL(normalizeBaseUrl(baseUrl));
url.hostname = host;
if (port !== null) {
url.port = port;
}
return normalizeBaseUrl(url.toString());
}
function directCaddyBaseUrl(baseUrl) {
const url = new URL(normalizeBaseUrl(baseUrl));
url.hostname = "caddy";
url.port = "";
if (url.pathname === "/api" || url.pathname === "/api/") {
url.pathname = "/";
}
return normalizeBaseUrl(url.toString());
}
function isLocalHost(hostname) {
const normalized = String(hostname || "").toLowerCase().replace(/^\x5b|\x5d$/g, "");
return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1";
}
function resolveBrokerWebSocketUrl(rawUrl, apiBaseUrl) {
const websocketUrl = new URL(String(rawUrl));
const apiUrl = new URL(normalizeBaseUrl(apiBaseUrl));
const ciBrokerPort = String(process.env.EDGE_BROKER_CI_PORT || "").trim();
if (isLocalHost(apiUrl.hostname) && websocketUrl.hostname === "edge-broker" && ciBrokerPort !== "") {
websocketUrl.protocol = apiUrl.protocol === "https:" ? "wss:" : "ws:";
websocketUrl.hostname = apiUrl.hostname;
websocketUrl.port = ciBrokerPort;
websocketUrl.pathname = websocketUrl.pathname.replace(/^\/edge-broker(?=\/|$)/, "") || "/";
return websocketUrl.toString();
}
if (apiUrl.hostname === "caddy" && websocketUrl.hostname === "caddy") {
websocketUrl.hostname = "edge-broker";
websocketUrl.port = "4300";
websocketUrl.pathname = websocketUrl.pathname.replace(/^\/edge-broker(?=\/|$)/, "") || "/";
}
if (isLocalHost(apiUrl.hostname) && ["caddy", "edge-broker"].includes(websocketUrl.hostname)) {
const brokerPath = websocketUrl.pathname.replace(/^\/edge-broker(?=\/|$)/, "") || "/";
websocketUrl.protocol = apiUrl.protocol === "https:" ? "wss:" : "ws:";
websocketUrl.hostname = apiUrl.hostname;
websocketUrl.port = apiUrl.port;
websocketUrl.pathname = `/api/edge-broker${brokerPath}`;
}
if (isLocalHost(websocketUrl.hostname)) {
websocketUrl.pathname = websocketUrl.pathname.replace(/^\/edge-broker(?=\/|$)/, "") || "/";
}
return websocketUrl.toString();
}
async function readDefaultGatewayHost() {
if (process.platform === "win32") {
return null;
}
try {
const routeTable = await fs.readFile("/proc/net/route", "utf8");
const route = routeTable
.split(/\r?\n/)
.map((line) => line.trim().split(/\s+/))
.find((fields) => fields[1] === "00000000" && /^[0-9A-Fa-f]{8}$/.test(fields[2] || ""));
if (!route) {
return null;
}
const gateway = route[2];
const octets = [
gateway.slice(6, 8),
gateway.slice(4, 6),
gateway.slice(2, 4),
gateway.slice(0, 2),
].map((octet) => Number.parseInt(octet, 16));
if (octets.some((octet) => !Number.isInteger(octet)) || octets.every((octet) => octet === 0)) {
return null;
}
return octets.join(".");
} catch {
return null;
}
}
function composeNetworkName(composeProject) {
return `${composeProject}_default`;
}
async function readCurrentContainerRef() {
if (process.platform === "win32") {
return null;
}
const candidates = [];
const envHostname = String(process.env.HOSTNAME || "").trim();
if (envHostname !== "") {
candidates.push(envHostname);
}
try {
const hostname = (await fs.readFile("/etc/hostname", "utf8")).trim();
if (hostname !== "") {
candidates.push(hostname);
}
} catch {
// Not running in a container with /etc/hostname available.
}
try {
const cgroup = await fs.readFile("/proc/self/cgroup", "utf8");
const matches = cgroup.match(/[0-9a-f]{64}/gi) || [];
candidates.push(...matches);
} catch {
// cgroup metadata is optional in local development.
}
return candidates.find((candidate) => /^[a-zA-Z0-9][a-zA-Z0-9_.-]{1,127}$/.test(candidate)) || null;
}
async function connectCurrentContainerToComposeNetwork(rootDir, composeProject) {
const containerRef = await readCurrentContainerRef();
if (!containerRef) {
return false;
}
const inspection = await runCommand("docker", ["inspect", containerRef], {
cwd: rootDir,
allowFailure: true,
});
if (inspection.code !== 0) {
return false;
}
const networkName = composeNetworkName(composeProject);
const connection = await runCommand("docker", ["network", "connect", networkName, containerRef], {
cwd: rootDir,
allowFailure: true,
});
const stderr = String(connection.stderr || "");
if (connection.code === 0) {
process.stdout.write(`Attached runner container ${containerRef} to ${networkName}.\n`);
return true;
}
return /already exists|already connected/i.test(stderr);
}
async function disconnectCurrentContainerFromComposeNetwork(rootDir, composeProject) {
const containerRef = await readCurrentContainerRef();
if (!containerRef) {
return;
}
await runCommand("docker", ["network", "disconnect", composeNetworkName(composeProject), containerRef], {
cwd: rootDir,
allowFailure: true,
});
}
async function readComposeServiceHost(rootDir, composeProject, serviceName) {
const ps = await runCommand("docker", composeArgs(composeProject, ["ps", "-q", serviceName]), {
cwd: rootDir,
allowFailure: true,
});
const containerId = String(ps.stdout || "").trim().split(/\s+/).find(Boolean);
const containerRefs = [
...(containerId ? [containerId] : []),
serviceName,
];
for (const containerRef of [...new Set(containerRefs)]) {
const inspection = await runCommand("docker", [
"inspect",
"-f",
"{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}",
containerRef,
], {
cwd: rootDir,
allowFailure: true,
});
const host = String(inspection.stdout || "").trim().split(/\s+/).find((value) => /^\d{1,3}(?:\.\d{1,3}){3}$/.test(value));
if (host) {
return host;
}
}
return null;
}
async function candidateApiBaseUrls(baseUrl, rootDir, composeProject, useComposeNetwork = false) {
const normalized = normalizeBaseUrl(baseUrl);
const candidates = [normalized];
const url = new URL(normalized);
if (["localhost", "127.0.0.1", "::1"].includes(url.hostname)) {
if (rootDir && composeProject) {
if (useComposeNetwork) {
candidates.push(directCaddyBaseUrl(normalized));
candidates.push(baseUrlWithHost(normalized, "traefik", ""));
}
const traefikHost = await readComposeServiceHost(rootDir, composeProject, "traefik");
if (traefikHost) {
candidates.push(baseUrlWithHost(normalized, traefikHost, ""));
}
}
const gatewayHost = await readDefaultGatewayHost();
if (gatewayHost) {
candidates.push(baseUrlWithHost(normalized, gatewayHost));
}
candidates.push(baseUrlWithHost(normalized, "host.docker.internal"));
}
return [...new Set(candidates)];
}
async function waitForCondition(predicate, { timeoutMs = 30_000, intervalMs = 500, message = "Timed out" } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
if (await predicate()) {
return;
}
await new Promise((resolve) => setTimeout(resolve, intervalMs));
}
throw new Error(message);
}
async function ensureComposeServices(rootDir, composeProject) {
await runCommand("docker", composeArgs(composeProject, ["up", "-d", ...COMPOSE_SERVICES]), {
cwd: rootDir,
stdio: "inherit",
});
}
async function waitForApiReady(baseUrl, rootDir, composeProject, useComposeNetwork = false, attempts = 60) {
const candidates = await candidateApiBaseUrls(baseUrl, rootDir, composeProject, useComposeNetwork);
let lastError = "API never responded";
for (let attempt = 0; attempt < attempts; attempt += 1) {
for (const root of candidates) {
try {
const response = await fetch(`${root}/ping`, {
signal: AbortSignal.timeout(1000),
});
if (response.ok) {
return root;
}
lastError = `${root}/ping returned HTTP ${response.status}`;
} catch (error) {
lastError = `${root}/ping failed: ${error instanceof Error ? error.message : String(error)}`;
}
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
throw new Error(`API did not become ready at ${candidates.map((candidate) => `${candidate}/ping`).join(", ")}: ${lastError}`);
}
function parseLastJsonLine(output) {
const lines = String(output || "")
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean);
for (let index = lines.length - 1; index >= 0; index -= 1) {
try {
return JSON.parse(lines[index]);
} catch {
// Continue scanning backwards for the JSON payload.
}
}
throw new Error(`Unable to parse JSON from command output:\n${output}`);
}
async function runPhpFixture(rootDir, composeProject, action, payload = null) {
const encodedPayload = payload === null
? ""
: ` ${Buffer.from(JSON.stringify(payload), "utf8").toString("base64url")}`;
const command = `cd /var/www/html && CONFIG_DB_TARGET=debug php tests/Support/EdgeGatewayE2eFixture.php ${action}${encodedPayload}`;
const result = await runCommand("docker", composeArgs(composeProject, [
"exec",
"-T",
"php1",
"sh",
"-lc",
command,
]), {
cwd: rootDir,
});
return parseLastJsonLine(result.stdout);
}
async function apiRequest(baseUrl, method, endpoint, { token = null, body = null, headers = {} } = {}) {
const response = await fetch(`${normalizeBaseUrl(baseUrl)}${endpoint}`, {
method,
headers: {
...(body === null ? {} : { "content-type": "application/json" }),
...(token ? { Authorization: `Bearer ${token}` } : {}),
...headers,
},
body: body === null ? undefined : JSON.stringify(body),
});
const rawBody = await response.text();
let json = null;
if (rawBody !== "") {
try {
json = JSON.parse(rawBody);
} catch {
json = null;
}
}
if (!response.ok) {
const message =
json?.data?.message ||
json?.error ||
rawBody ||
`HTTP ${response.status}`;
throw new Error(`${method} ${endpoint} failed: ${message}`);
}
return json;
}
async function loadWebSocketImplementation() {
if (typeof WebSocket !== "undefined") {
return WebSocket;
}
const module = await import("ws");
return module.default;
}
function onSocket(socket, eventName, handler) {
if (typeof socket.addEventListener === "function") {
socket.addEventListener(eventName, (event) => {
if (eventName === "message") {
handler(event.data);
return;
}
handler(event);
});
return;
}
socket.on(eventName, handler);
}
function collectSocketMessages(socket) {
const messages = [];
onSocket(socket, "message", (payload) => {
const text = typeof payload === "string"
? payload
: Buffer.isBuffer(payload)
? payload.toString("utf8")
: typeof payload?.toString === "function"
? payload.toString()
: "";
if (text === "") {
return;
}
try {
messages.push(JSON.parse(text));
} catch {
// Ignore non-JSON frames.
}
});
return messages;
}
async function waitForSocketOpen(socket) {
if (socket.readyState === 1) {
return;
}
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject(new Error("Timed out waiting for websocket open.")), 10_000);
const socketUrl = typeof socket.url === "string" && socket.url !== "" ? ` (${socket.url})` : "";
const onOpen = () => {
clearTimeout(timeout);
resolve();
};
const onError = (error) => {
clearTimeout(timeout);
if (error instanceof Error) {
reject(error);
return;
}
const readyState = typeof socket.readyState === "number" ? socket.readyState : "unknown";
reject(new Error(`Websocket failed to open${socketUrl}; readyState=${readyState}.`));
};
const onClose = (event) => {
clearTimeout(timeout);
const code = event && typeof event === "object" && "code" in event ? event.code : "unknown";
const reason = event && typeof event === "object" && "reason" in event ? event.reason : "";
reject(new Error(`Websocket closed before open${socketUrl}; code=${code} reason=${reason || "none"}.`));
};
onSocket(socket, "open", onOpen);
onSocket(socket, "error", onError);
onSocket(socket, "close", onClose);
});
}
async function waitForSocketMessage(messages, predicate, options) {
await waitForCondition(() => messages.some(predicate), options);
}
function buildSocketUrl(wsUrl, token) {
const url = new URL(String(wsUrl));
url.searchParams.set("token", token);
return url.toString();
}
function closeSocket(socket) {
if (!socket || typeof socket.close !== "function") {
return;
}
const readyState = typeof socket.readyState === "number" ? socket.readyState : null;
if (readyState !== null && readyState >= 2) {
return;
}
socket.close();
}
function shouldCopyGatewayConfig() {
return /^(1|true|yes)$/i.test(String(process.env.EDGE_GATEWAY_E2E_COPY_CONFIG || "").trim());
}
function shouldSkipComposeUp() {
return /^(1|true|yes)$/i.test(String(process.env.EDGE_GATEWAY_E2E_SKIP_COMPOSE_UP || "").trim());
}
function collectMessages(rows) {
return Array.isArray(rows)
? rows
.map((row) => (row && typeof row === "object" ? row.message : null))
.filter((value) => typeof value === "string")
: [];
}
function summarizeStreamMessages(messages, limit = 12) {
return messages
.slice(-limit)
.map((message) => {
if (!message || typeof message !== "object") {
return null;
}
const summary = {
type: message.type || "unknown",
};
if (message.operationId !== undefined) {
summary.operationId = Number(message.operationId || 0);
}
if (message.operation && typeof message.operation === "object") {
summary.operationStatus = message.operation.status || null;
}
if (message.gateway && typeof message.gateway === "object") {
summary.gatewayStatus = message.gateway.status || null;
}
return summary;
})
.filter(Boolean);
}
async function readGatewayDiagnostics({ baseUrl, authToken, gatewayId, containerName }) {
const diagnostics = {};
if (gatewayId !== null && gatewayId > 0 && authToken) {
try {
const detail = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}`, {
token: authToken,
});
diagnostics.gateway = {
status: detail?.data?.status ?? null,
channelStatus: detail?.data?.channel_status ?? null,
brokerPresence: detail?.data?.metadata?.broker_presence ?? null,
brokerConnected: detail?.data?.metadata?.broker_connected ?? null,
brokerLastError: detail?.data?.metadata?.broker_last_error ?? null,
};
} catch (error) {
diagnostics.gatewayError = error instanceof Error ? error.message : String(error);
}
}
try {
const logs = await runCommand("docker", ["logs", "--tail", "120", containerName], {
allowFailure: true,
});
diagnostics.containerLogs = String(`${logs.stdout || ""}${logs.stderr || ""}`).trim().split(/\r?\n/).slice(-120);
} catch (error) {
diagnostics.containerLogError = error instanceof Error ? error.message : String(error);
}
return diagnostics;
}
async function main() {
const scriptPath = fileURLToPath(import.meta.url);
const rootDir = await resolveRootDir(scriptPath);
const runId = randomUUID().slice(0, 8);
const containerName = `truckwash-edge-e2e-${runId}`;
const configDir = path.join(rootDir, ".tmp", "edge-gateway-e2e", runId);
const configFilePath = path.join(configDir, DEFAULT_CONFIG_FILE_NAME);
let baseUrl = process.env.EDGE_GATEWAY_E2E_BASE_URL || DEFAULT_HOST_API_URL;
const composeProject =
process.env.EDGE_GATEWAY_E2E_COMPOSE_PROJECT
|| path.basename(rootDir);
let fixture = null;
let gatewayId = null;
let streamSocket = null;
let shellSocket = null;
let runnerNetworkAttached = false;
try {
if (!shouldSkipComposeUp()) {
await ensureComposeServices(rootDir, composeProject);
}
runnerNetworkAttached = await connectCurrentContainerToComposeNetwork(rootDir, composeProject);
baseUrl = await waitForApiReady(baseUrl, rootDir, composeProject, runnerNetworkAttached);
process.stdout.write(`Using API base URL ${baseUrl}\n`);
fixture = await runPhpFixture(rootDir, composeProject, "create");
const authToken = String(fixture.auth_token || "");
const departmentId = Number(fixture.department_id || 0);
assert.ok(authToken !== "", "Fixture helper did not return an auth token.");
assert.ok(departmentId > 0, "Fixture helper did not return a department id.");
const installTokenResponse = await apiRequest(baseUrl, "POST", "/edge-gateways/install-token", {
token: authToken,
body: {
department_id: departmentId,
label: `Edge Gateway E2E ${runId}`,
},
});
const installToken = String(installTokenResponse?.data?.token || "");
assert.ok(installToken !== "", "Install token creation did not return a token.");
await runCommand(process.execPath, [
"scripts/test-gateway.mjs",
"start",
"--install-token",
installToken,
"--host-api-url",
baseUrl,
"--container-name",
containerName,
"--config-dir",
configDir,
"--heartbeat-seconds",
"3",
"--skip-compose-up",
...(shouldCopyGatewayConfig() ? ["--copy-config"] : []),
], {
cwd: rootDir,
stdio: "inherit",
});
await waitForCondition(
async () => {
try {
await fs.access(configFilePath);
return true;
} catch {
return false;
}
},
{ message: `Gateway config file was not created at ${configFilePath}` }
);
const config = JSON.parse(await fs.readFile(configFilePath, "utf8"));
gatewayId = Number(config.gatewayId || 0);
assert.ok(gatewayId > 0, "Gateway config did not include a gateway id.");
await waitForCondition(
async () => {
const result = await runCommand("docker", [
"exec",
containerName,
"test",
"-f",
"/opt/truckwash-edge-agent/runtime/last-heartbeat-ok.txt",
], {
allowFailure: true,
});
return result.code === 0;
},
{
timeoutMs: 60_000,
message: "Gateway never wrote the successful heartbeat marker.",
}
);
await waitForCondition(
async () => {
const detail = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}`, {
token: authToken,
});
return detail?.data?.status === "ONLINE"
&& Object.keys(detail?.data?.metadata?.system_metrics || {}).length > 0;
},
{
timeoutMs: 60_000,
message: "Gateway detail never transitioned to ONLINE with fresh system metrics after install.",
}
);
try {
await waitForCondition(
async () => {
const detail = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}`, {
token: authToken,
});
return Boolean(
detail?.data?.channel_status?.broker?.connected
|| detail?.data?.metadata?.broker_connected
);
},
{
timeoutMs: 90_000,
message: "Gateway never established a live broker connection after install.",
}
);
} catch (error) {
const diagnostics = await readGatewayDiagnostics({
baseUrl,
authToken,
gatewayId,
containerName,
});
throw new Error([
error instanceof Error ? error.message : String(error),
`Broker diagnostics: ${JSON.stringify(diagnostics, null, 2)}`,
].join("\n"));
}
const WebSocketImpl = await loadWebSocketImplementation();
const streamSession = await apiRequest(baseUrl, "POST", `/edge-gateways/${gatewayId}/stream-session`, {
token: authToken,
body: {
scopes: ["overview", "tasks", "logs", "statistics"],
},
});
const streamWsUrl = buildSocketUrl(
resolveBrokerWebSocketUrl(String(streamSession?.data?.ws_url || ""), baseUrl),
String(streamSession?.data?.token || "")
);
streamSocket = new WebSocketImpl(streamWsUrl);
const streamMessages = collectSocketMessages(streamSocket);
await waitForSocketOpen(streamSocket);
await waitForSocketMessage(
streamMessages,
(message) => message?.type === "gateway.stream.ready",
{ timeoutMs: 15_000, message: "Gateway stream never became ready." }
);
await waitForSocketMessage(
streamMessages,
(message) => (
message?.type === "gateway.stream.ready" && message?.connected === true
) || (
message?.type === "presence.changed" && message?.status === "connected"
),
{ timeoutMs: 45_000, message: "Gateway stream never observed a connected broker presence." }
);
const operationResponse = await apiRequest(baseUrl, "POST", `/edge-gateways/${gatewayId}/operations`, {
token: authToken,
body: {
type: "DISCOVERY",
request: {
inventory: [{
device_id: `edge-e2e-${runId}`,
local_ip: "10.70.80.90",
model: "TruckWash Edge E2E",
channel_count: 1,
online: true,
capabilities: {
gateway_management_v2: true,
},
metadata: {
hostname: `edge-e2e-${runId}`,
},
}],
},
},
});
const operationId = Number(operationResponse?.data?.operation?.id || 0);
assert.ok(operationId > 0, "Operation creation did not return an operation id.");
try {
await waitForCondition(
async () => {
const operations = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}/operations`, {
token: authToken,
});
const operation = Array.isArray(operations?.data)
? operations.data.find((item) => Number(item?.id || 0) === operationId)
: null;
return operation?.status === "COMPLETED"
|| streamMessages.some((message) => (
message?.type === "task.updated"
&& Number(message?.operationId || 0) === operationId
&& message?.operation?.status === "COMPLETED"
));
},
{ timeoutMs: 180_000, message: "Gateway operation never completed through the live agent." }
);
} catch (error) {
let operationSnapshot;
try {
const operations = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}/operations`, {
token: authToken,
});
operationSnapshot = Array.isArray(operations?.data)
? operations.data.find((item) => Number(item?.id || 0) === operationId) || null
: null;
} catch {
operationSnapshot = null;
}
const diagnostic = [
error instanceof Error ? error.message : String(error),
`Recent stream messages: ${JSON.stringify(summarizeStreamMessages(streamMessages))}`,
`Operation snapshot: ${JSON.stringify(operationSnapshot)}`,
].join("\n");
throw new Error(diagnostic);
}
await waitForSocketMessage(
streamMessages,
(message) => message?.type === "gateway.telemetry" || message?.type === "stats.updated",
{ timeoutMs: 15_000, message: "Live gateway stream never emitted telemetry or statistics updates." }
);
await waitForCondition(
async () => {
const logs = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}/logs`, {
token: authToken,
});
const timeline = Array.isArray(logs?.data?.entries)
? logs.data.entries
: (Array.isArray(logs?.data?.timeline) ? logs.data.timeline : []);
return timeline.some((entry) => {
const nestedEntry = entry?.entry && typeof entry.entry === "object" ? entry.entry : null;
const directOperationId = Number(nestedEntry?.operation_id || 0);
const contextualOperationId = Number(nestedEntry?.context?.operation_id || 0);
return directOperationId === operationId || contextualOperationId === operationId;
});
},
{ timeoutMs: 30_000, message: "Gateway logs page never reflected the live operation timeline." }
);
const statistics = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}/statistics`, {
token: authToken,
});
assert.ok(
Object.keys(statistics?.data?.system_metrics || {}).length > 0,
"Gateway statistics page did not expose system metrics after live telemetry."
);
const shellSession = await apiRequest(baseUrl, "POST", `/edge-gateways/${gatewayId}/shell-sessions`, {
token: authToken,
body: {
reason: "Edge gateway E2E shell validation",
cwd: "/opt/truckwash-edge-agent",
cols: 120,
rows: 40,
},
});
const shellWsUrl = buildSocketUrl(
resolveBrokerWebSocketUrl(String(shellSession?.data?.ws_url || ""), baseUrl),
String(shellSession?.data?.token || "")
);
shellSocket = new WebSocketImpl(shellWsUrl);
const shellMessages = collectSocketMessages(shellSocket);
await waitForSocketOpen(shellSocket);
await waitForSocketMessage(
shellMessages,
(message) => message?.type === "opened",
{ timeoutMs: 20_000, message: "Browser shell never opened against the live gateway." }
);
shellSocket.send(JSON.stringify({
type: "input",
data: "printf 'edge-e2e-shell\\n'; exit\n",
}));
await waitForSocketMessage(
shellMessages,
(message) => message?.type === "output" && String(message?.data || "").includes("edge-e2e-shell"),
{ timeoutMs: 20_000, message: "Browser shell never returned the expected command output." }
);
await waitForSocketMessage(
shellMessages,
(message) => message?.type === "closed",
{ timeoutMs: 20_000, message: "Browser shell never closed cleanly." }
);
await waitForCondition(
async () => {
const logsAfterShell = await apiRequest(baseUrl, "GET", `/edge-gateways/${gatewayId}/logs`, {
token: authToken,
});
const shellTranscripts = Array.isArray(logsAfterShell?.data?.shell_sessions)
? logsAfterShell.data.shell_sessions.map((session) => String(session?.transcript || ""))
: [];
const timelineMessages = collectMessages(logsAfterShell?.data?.timeline || []);
return shellTranscripts.some((transcript) => transcript.includes("edge-e2e-shell"))
&& timelineMessages.includes("GATEWAY_SHELL_SESSION_CLOSED");
},
{ timeoutMs: 30_000, message: "Gateway logs page did not persist the shell transcript and close audit event." }
);
process.stdout.write("Edge gateway E2E smoke completed successfully.\n");
} finally {
closeSocket(shellSocket);
closeSocket(streamSocket);
await runCommand(process.execPath, [
"scripts/test-gateway.mjs",
"stop",
"--container-name",
containerName,
], {
cwd: rootDir,
allowFailure: true,
}).catch(() => {});
const fixtureAuthToken = fixture?.auth_token;
if (gatewayId !== null && fixtureAuthToken) {
await apiRequest(baseUrl, "DELETE", `/edge-gateways/${gatewayId}`, {
token: String(fixtureAuthToken),
}).catch(() => {});
}
if (fixture !== null) {
await runPhpFixture(rootDir, composeProject, "cleanup", fixture).catch(() => {});
}
await fs.rm(configDir, { recursive: true, force: true }).catch(() => {});
if (runnerNetworkAttached) {
await disconnectCurrentContainerFromComposeNetwork(rootDir, composeProject).catch(() => {});
}
}
}
main().catch((error) => {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
process.exitCode = 1;
});
@@ -405,10 +405,6 @@ def render_api_reference_topic() -> str:
' title="API Reference" id="API-Reference">\n'
f"\n <!-- {AUTOGEN_NOTE} -->\n"
" <p>Comprehensive API reference generated from the repository root <code>openapi.yaml</code>.</p>\n"
" <p>The edge broker's <code>/api/health</code> response additionally exposes a "
"<code>lastActivityAt</code> field (ISO 8601 timestamp). It reports the most recent "
"successful HTTP request handled by the broker container and defaults to the container's "
"start time when no request has been processed yet.</p>\n"
"</topic>\n"
)
-163
View File
@@ -1,163 +0,0 @@
#!/usr/bin/env sh
set -eu
suite="${1:-}"
case "$suite" in
unit|integration|api|legacy|all)
;;
*)
echo "Usage: $0 <unit|integration|api|legacy|all>" >&2
exit 2
;;
esac
script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
repo_root="$(CDPATH= cd -- "$script_dir/.." && pwd)"
cd "$repo_root"
compose_files="-f docker-compose.yml -f .github/docker-compose.ci.yml"
project_suffix="$(date +%s)-$$"
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-php-local-${suite}-${project_suffix}}"
export COMPOSE_PROFILES="${COMPOSE_PROFILES:-dev}"
log_dir=".tmp/ci-logs/$suite"
mkdir -p "$log_dir"
env_backup_dir=".tmp/php-ci-env-backup-$project_suffix"
mkdir -p "$env_backup_dir"
had_env=0
had_env_staging=0
if [ -f .env ]; then
cp .env "$env_backup_dir/env"
had_env=1
fi
if [ -f .env.staging ]; then
cp .env.staging "$env_backup_dir/env.staging"
had_env_staging=1
fi
cp .github/ci.env .env
cp .github/ci.env.staging .env.staging
collect_logs() {
status="$1"
if [ "$status" -eq 0 ]; then
return
fi
mkdir -p "$log_dir"
docker compose $compose_files ps > "$log_dir/docker-compose-ps.txt" 2>&1 || true
docker compose $compose_files logs --no-color > "$log_dir/docker-compose.log" 2>&1 || true
docker compose $compose_files cp php1:/var/www/html/build/logs "$log_dir/app-build-logs" >/dev/null 2>&1 || true
docker compose $compose_files cp php1:/var/log/php "$log_dir/php-logs" >/dev/null 2>&1 || true
}
retry_command() {
max_attempts="$1"
shift
attempt=1
while :; do
"$@" && return 0
status="$?"
if [ "$attempt" -ge "$max_attempts" ]; then
return "$status"
fi
sleep_seconds=$((attempt * 5))
echo "Command failed with status $status; retrying in ${sleep_seconds}s (attempt $((attempt + 1))/$max_attempts): $*" >&2
sleep "$sleep_seconds"
attempt=$((attempt + 1))
done
}
composer_install() {
dist_attempts="${PHP_CI_COMPOSER_RETRIES:-3}"
source_attempts="${PHP_CI_COMPOSER_SOURCE_RETRIES:-2}"
if retry_command "$dist_attempts" \
docker compose $compose_files exec -T php1 sh -lc \
'cd /var/www/html && composer install --no-interaction --prefer-dist --no-progress'; then
return 0
fi
echo "Composer dist install failed after ${dist_attempts} attempts; retrying with --prefer-source." >&2
retry_command "$source_attempts" \
docker compose $compose_files exec -T php1 sh -lc \
'cd /var/www/html && composer install --no-interaction --prefer-source --no-progress'
}
configure_ci_docker_subnet() {
if [ -n "${CI_DOCKER_SUBNET:-}" ]; then
return
fi
checksum="$(printf '%s' "$COMPOSE_PROJECT_NAME" | cksum | awk '{print $1}')"
subnet_second=$((64 + ((checksum / 256) % 64)))
subnet_third=$((checksum % 256))
export CI_DOCKER_SUBNET="10.${subnet_second}.${subnet_third}.0/24"
}
cleanup() {
status="$?"
collect_logs "$status"
docker compose $compose_files down -v >/dev/null 2>&1 || true
if [ "$had_env" -eq 1 ]; then
cp "$env_backup_dir/env" .env
else
rm -f .env
fi
if [ "$had_env_staging" -eq 1 ]; then
cp "$env_backup_dir/env.staging" .env.staging
else
rm -f .env.staging
fi
rm -rf "$env_backup_dir"
exit "$status"
}
trap cleanup EXIT INT TERM
configure_ci_docker_subnet
sh scripts/ci-docker-compose-up.sh redis mysql-debug php1
docker compose $compose_files exec -T php1 sh -lc '
set -eu
for i in $(seq 1 90); do
if MYSQL_PWD="${CONFIG_DB_PASSWORD:-debug_root_password}" mysqladmin \
-h "${CONFIG_DB_HOST:-mysql-debug}" \
-P "${CONFIG_DB_PORT:-3306}" \
-u "${CONFIG_DB_USER:-root}" \
ping --silent >/dev/null 2>&1; then
exit 0
fi
sleep 1
done
echo "Timed out waiting for mysql-debug" >&2
exit 1
'
tar \
--exclude='./vendor' \
--exclude='./.phpunit.cache' \
--exclude='./build/logs' \
-C services/nginx/app -cf - . \
| docker compose $compose_files exec -T php1 tar --no-same-owner -C /var/www/html -xf -
docker compose $compose_files exec -T php1 sh -lc 'rm -rf /var/www/repo-root && mkdir -p /var/www/repo-root'
tar \
-cf - \
Dockerfile \
Dockerfile.coolify-api \
docker-compose.yml \
docker-compose.example.yml \
docker-compose.prod.standalone.yml \
scripts/bird-control-plane-auto-activate.php \
scripts/bird-control-plane-bootstrap-local.sh \
scripts/xlvask-automation-migrate.php \
services/coolify/api/start.sh \
services/php/Dockerfile \
services/php/php-fpm-pool.conf \
| docker compose $compose_files exec -T php1 tar --no-same-owner -C /var/www/repo-root -xf -
composer_install
docker compose $compose_files exec -T php1 sh -lc \
"cd /var/www/html && PLENO_REPO_ROOT_FOR_TESTS=/var/www/repo-root composer test:ci:$suite"
-64
View File
@@ -1,64 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Pre-deploy schema bootstrap runner.
*
* Loads and runs every `*_schema_bootstrap` class so the production
* database has all the columns the current code expects. Each
* bootstrap is additive and idempotent — safe to run on every deploy.
*
* Run via:
* php scripts/run-schema-bootstraps.php
*
* Used in .github/workflows/deploy.yml as a pre-deploy step.
*
* When you add a new *_schema_bootstrap class, you don't need to
* edit this file — the runner auto-discovers any class whose name
* ends in `_schema_bootstrap`.
*/
namespace scripts;
// Load the app entry point so $db is wired up the same way as in
// normal request handling.
$index = __DIR__ . '/../services/nginx/app/index.php';
if (!file_exists($index)) {
fwrite(STDERR, "Cannot find app entry point at {$index}\n");
exit(2);
}
require_once $index;
$classesDir = __DIR__ . '/../services/nginx/app/classes';
$bootstraps = glob($classesDir . '/*_schema_bootstrap.php');
if (!$bootstraps) {
fwrite(STDERR, "No *_schema_bootstrap.php files found in {$classesDir}\n");
exit(0);
}
$ran = 0;
$skipped = 0;
foreach ($bootstraps as $file) {
require_once $file;
$base = basename($file, '.php');
$class = "classes\\{$base}";
if (!class_exists($class)) {
fwrite(STDERR, " [skip] {$base}: class not found\n");
$skipped++;
continue;
}
if (!method_exists($class, 'ensureSchema')) {
fwrite(STDERR, " [skip] {$base}: no ensureSchema() method\n");
$skipped++;
continue;
}
try {
$class::ensureSchema();
echo " [ok] {$base}\n";
$ran++;
} catch (\Throwable $e) {
fwrite(STDERR, " [FAIL] {$base}: " . $e->getMessage() . "\n");
exit(1);
}
}
echo "Schema bootstraps complete: {$ran} ran, {$skipped} skipped.\n";
-96
View File
@@ -1,96 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Schema health check — verifies all required DB columns exist.
*
* Run via:
* GET /api/admin/schema-check (returns JSON report)
* php scripts/schema-health-check.php (CLI, exits 0/1)
*
* Lists the columns that the code expects to find in each critical
* table. If a column is missing, the response is 503 (HTTP) or
* exit code 1 (CLI) — clearly distinct from a generic 500.
*
* Add to the list when introducing a new optional column.
*/
namespace scripts;
require_once __DIR__ . '/../services/nginx/app/classes/customer_invoice_email_schema_bootstrap.php';
use classes\customer_invoice_email_schema_bootstrap;
const SCHEMA_REQUIREMENTS = [
'users' => [
'invoice_email', // TRU-77 (added 2026-08-16)
'wash_certificate_email',
'email',
'customer_number',
],
'invoices' => [
'po_number',
'closed_at',
'customer_number',
],
'bookings' => [
'id',
'customer_number',
'department',
],
];
function check_schema(): array
{
global $db;
$report = [
'ok' => true,
'missing' => [],
'tables_checked' => 0,
'columns_checked' => 0,
'timestamp' => date('c'),
];
if (!isset($db) || !is_object($db) || !method_exists($db, 'query')) {
$report['ok'] = false;
$report['error'] = 'no_db_connection';
return $report;
}
// First: run the schema bootstrap (additive, idempotent) so we
// give the DB a chance to self-heal.
if (class_exists(customer_invoice_email_schema_bootstrap::class)) {
customer_invoice_email_schema_bootstrap::ensureSchema();
}
foreach (SCHEMA_REQUIREMENTS as $table => $columns) {
$report['tables_checked']++;
// Confirm the table itself exists
$tableSafe = str_replace('`', '', $table);
$result = $db->query("SHOW TABLES LIKE '{$tableSafe}'");
if (!$result || (int)$result->num_rows === 0) {
$report['ok'] = false;
$report['missing'][] = "table `{$table}` does not exist";
continue;
}
foreach ($columns as $column) {
$report['columns_checked']++;
$colSafe = str_replace("'", '', $column);
$r = $db->query("SHOW COLUMNS FROM `{$tableSafe}` LIKE '{$colSafe}'");
if (!$r || (int)$r->num_rows === 0) {
$report['ok'] = false;
$report['missing'][] = "{$table}.{$column}";
}
}
}
return $report;
}
// CLI mode
if (PHP_SAPI === 'cli') {
$report = check_schema();
echo json_encode($report, JSON_PRETTY_PRINT) . "\n";
exit($report['ok'] ? 0 : 1);
}
-80
View File
@@ -1,80 +0,0 @@
#!/usr/bin/env bash
# Generic smoke test for any deployed app.
#
# Usage: ./scripts/smoke-test.sh [base_url]
# Default: https://staging.truckwash.io
#
# Required env vars (set by GitHub Action):
# SMOKE_BASE_URL - base URL to test (default: https://staging.truckwash.io)
#
# Optional env vars:
# SMOKE_TOKEN - bearer token for authenticated checks
# SMOKE_TIMEOUT - curl timeout in seconds (default: 10)
#
# Exits 0 on all-pass, 1 on any failure.
set -euo pipefail
BASE_URL="${SMOKE_BASE_URL:-${1:-https://staging.truckwash.io}}"
TIMEOUT="${SMOKE_TIMEOUT:-10}"
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
FAIL=0
check() {
local name="$1"
local url="$2"
local expected="${3:-200}"
local method="${4:-GET}"
local status
status=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" --max-time "$TIMEOUT" "$url" || echo "000")
if [[ "$status" =~ ^($expected)$ ]] || [[ "$expected" == "2xx" && "$status" =~ ^2 ]]; then
echo -e " ${GREEN}${NC} $name ($status) — $url"
else
echo -e " ${RED}${NC} $name (expected $expected, got $status) — $url"
FAIL=1
fi
}
echo "Smoke test against $BASE_URL"
echo " (timeout ${TIMEOUT}s per check)"
echo
# === Health endpoints (universal) ===
check "health check" "$BASE_URL/healthz" "2xx"
check "ping" "$BASE_URL/api/ping" "2xx"
# === Authentication (should NOT 500) ===
check "login page" "$BASE_URL/login" "2xx"
# === Public endpoints (api repo) ===
check "customer list (public schema)" "$BASE_URL/api/customer" "2xx"
check "kundeoprettelse form" "$BASE_URL/kundeoprettelse" "2xx"
# === Public endpoints (pleno-vue) ===
check "self-serve program picker" "$BASE_URL/self-serve/program" "2xx"
check "vehicle step" "$BASE_URL/self-serve/vehicle" "2xx"
# === Custom 404 should not 500 ===
check "404 page" "$BASE_URL/this-route-does-not-exist" "404"
# === Optional authenticated check ===
if [ -n "${SMOKE_TOKEN:-}" ]; then
check "auth check" "$BASE_URL/api/me" "2xx"
fi
echo
if [ "$FAIL" -eq 0 ]; then
echo -e "${GREEN}✓ All smoke tests passed${NC}"
exit 0
else
echo -e "${RED}✗ Some smoke tests failed${NC}"
exit 1
fi
+3 -73
View File
@@ -1,32 +1,14 @@
import process from "node:process";
import path from "node:path";
import { createHash } from "node:crypto";
import { pathToFileURL } from "node:url";
export const DEFAULT_STAGING_BASE_URL = "https://api.truckwash.io:4433";
export const EXPECTED_INSTALL_VERSION = "compose-php-agent-v3";
export const REQUIRED_MANIFEST_ARTIFACTS = [
"agent.php",
"lan-worker.php",
"auto-updater.php",
"docker-compose.gateway.yml",
"Dockerfile.edge-agent",
"Dockerfile.lan-worker",
"Dockerfile.auto-updater",
"gateway-launcher.sh",
"truckwash-edge-gateway-stack.service",
"truckwash-edge-agent.service",
];
export const INSTALLER_SCRIPT_REQUIRED_SNIPPETS = [
"/edge-agent/install-token/status",
"/edge-agent/artifacts/manifest.json",
"report_install_status",
'begin_install_phase "VERIFY_TOKEN"',
'begin_install_phase "VERIFY_ARTIFACTS"',
'begin_install_phase "WAIT_FOR_CLAIM"',
'report_install_status "FAILED"',
"verify_manifest_artifact",
EXPECTED_INSTALL_VERSION,
];
export function normalizeBaseUrl(url) {
@@ -73,20 +55,13 @@ export function buildChecks(baseUrl, installToken) {
name: "Ping",
url: `${normalizedBaseUrl}/ping`,
},
{
name: "Artifact manifest",
url: `${normalizedBaseUrl}/edge-agent/artifacts/manifest.json`,
artifactName: "manifest.json",
},
{
name: "Agent PHP artifact",
url: `${normalizedBaseUrl}/edge-agent/artifacts/agent.php`,
artifactName: "agent.php",
},
{
name: "Service unit artifact",
url: `${normalizedBaseUrl}/edge-agent/artifacts/truckwash-edge-agent.service`,
artifactName: "truckwash-edge-agent.service",
},
{
name: "Installer script",
@@ -95,42 +70,6 @@ export function buildChecks(baseUrl, installToken) {
];
}
export function validateArtifactManifestBody(body) {
const manifest = JSON.parse(String(body || ""));
if (manifest.version !== EXPECTED_INSTALL_VERSION) {
throw new Error(`Artifact manifest version mismatch: expected ${EXPECTED_INSTALL_VERSION}, got ${manifest.version}`);
}
if (!Array.isArray(manifest.artifacts)) {
throw new Error("Artifact manifest is missing artifacts.");
}
const byName = new Map(manifest.artifacts.map((artifact) => [artifact?.name, artifact]));
const missingArtifacts = REQUIRED_MANIFEST_ARTIFACTS.filter((artifactName) => !byName.has(artifactName));
if (missingArtifacts.length) {
throw new Error(`Artifact manifest is missing required artifacts: ${missingArtifacts.join(", ")}`);
}
return manifest;
}
export function validateArtifactBodyAgainstManifest(manifest, artifactName, body) {
const artifact = manifest?.artifacts?.find((entry) => entry?.name === artifactName);
if (!artifact) {
throw new Error(`Artifact ${artifactName} is missing from manifest.`);
}
const buffer = Buffer.isBuffer(body) ? body : Buffer.from(String(body || ""));
const sha256 = createHash("sha256").update(buffer).digest("hex");
if (sha256 !== artifact.sha256) {
throw new Error(`Artifact ${artifactName} hash mismatch: ${sha256} !== ${artifact.sha256}`);
}
if (buffer.length !== artifact.bytes) {
throw new Error(`Artifact ${artifactName} size mismatch: ${buffer.length} !== ${artifact.bytes}`);
}
return artifact;
}
export function validateInstallerScriptBody(body) {
const source = String(body || "");
const missingSnippets = INSTALLER_SCRIPT_REQUIRED_SNIPPETS.filter((snippet) => !source.includes(snippet));
@@ -168,17 +107,16 @@ export async function runSmoke({ baseUrl, installToken }) {
const checks = buildChecks(baseUrl, installToken);
const results = [];
let artifactManifest = null;
for (const check of checks) {
process.stdout.write(`[staging-smoke] GET ${check.url}\n`);
const response = await fetch(check.url);
const body = Buffer.from(await response.arrayBuffer());
const body = await response.text();
const result = {
...check,
status: response.status,
ok: response.ok,
bodyPreview: previewBody(body.toString("utf8")),
bodyPreview: previewBody(body),
};
results.push(result);
@@ -189,16 +127,8 @@ export async function runSmoke({ baseUrl, installToken }) {
);
}
if (check.name === "Artifact manifest") {
artifactManifest = validateArtifactManifestBody(body.toString("utf8"));
result.version = artifactManifest.version;
result.artifactCount = artifactManifest.artifacts.length;
}
if (artifactManifest && check.artifactName && check.artifactName !== "manifest.json") {
result.verifiedArtifact = validateArtifactBodyAgainstManifest(artifactManifest, check.artifactName, body);
}
if (check.name === "Installer script") {
result.verifiedSnippets = validateInstallerScriptBody(body.toString("utf8"));
result.verifiedSnippets = validateInstallerScriptBody(body);
}
}
@@ -3,13 +3,10 @@ import assert from "node:assert/strict";
import {
DEFAULT_STAGING_BASE_URL,
EXPECTED_INSTALL_VERSION,
INSTALLER_SCRIPT_REQUIRED_SNIPPETS,
buildChecks,
normalizeBaseUrl,
parseArgs,
validateArtifactBodyAgainstManifest,
validateArtifactManifestBody,
validateInstallerScriptBody,
} from "./staging-edge-gateway-smoke.mjs";
@@ -35,58 +32,18 @@ test("buildChecks targets the public staging endpoints", () => {
assert.deepEqual(checks.map((check) => check.url), [
"https://api.truckwash.io:4433/ping",
"https://api.truckwash.io:4433/edge-agent/artifacts/manifest.json",
"https://api.truckwash.io:4433/edge-agent/artifacts/agent.php",
"https://api.truckwash.io:4433/edge-agent/artifacts/truckwash-edge-agent.service",
"https://api.truckwash.io:4433/edge-agent/install.sh?token=abc%20123",
]);
});
test("validateArtifactManifestBody requires v3 install artifacts", () => {
const artifacts = [
"agent.php",
"lan-worker.php",
"auto-updater.php",
"docker-compose.gateway.yml",
"Dockerfile.edge-agent",
"Dockerfile.lan-worker",
"Dockerfile.auto-updater",
"gateway-launcher.sh",
"truckwash-edge-gateway-stack.service",
"truckwash-edge-agent.service",
].map((name) => ({ name, sha256: "abc", bytes: 1 }));
const manifest = validateArtifactManifestBody(JSON.stringify({
version: EXPECTED_INSTALL_VERSION,
artifacts,
}));
assert.equal(manifest.version, EXPECTED_INSTALL_VERSION);
});
test("validateArtifactBodyAgainstManifest verifies size and hash", () => {
const body = Buffer.from("hello");
const manifest = {
artifacts: [{
name: "agent.php",
sha256: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
bytes: body.length,
}],
};
assert.equal(validateArtifactBodyAgainstManifest(manifest, "agent.php", body).name, "agent.php");
});
test("validateInstallerScriptBody requires install-session reporting wiring", () => {
const script = `
INSTALL_STATUS_URL="https://api.truckwash.io:4433/edge-agent/install-token/status"
fetch_http "Download artifact manifest" "https://api.truckwash.io:4433/edge-agent/artifacts/manifest.json"
report_install_status "FAILED"
begin_install_phase "VERIFY_TOKEN" "Verifying install token"
begin_install_phase "VERIFY_ARTIFACTS" "Verifying edge gateway artifacts"
begin_install_phase "WAIT_FOR_CLAIM" "Waiting for gateway heartbeat and claim"
verify_manifest_artifact
${EXPECTED_INSTALL_VERSION}
`;
assert.deepEqual(validateInstallerScriptBody(script), INSTALLER_SCRIPT_REQUIRED_SNIPPETS);
+29 -88
View File
@@ -12,7 +12,7 @@ export const DEFAULT_IMAGE_TAG = "truckwash-edge-agent:test-gateway";
export const DEFAULT_CONFIG_FILE_NAME = "test-gateway.json";
export const DEFAULT_HOST_API_URL = "http://localhost/api";
export const DEFAULT_CONTAINER_API_URL = "http://caddy";
export const DEFAULT_CONTAINER_BROKER_URL = "ws://edge-broker:4300";
export const DEFAULT_CONTAINER_BROKER_URL = "http://edge-broker:4300";
export const DEFAULT_INSTALL_DIR = "/opt/truckwash-edge-agent";
export const DEFAULT_RUNTIME_DIR = `${DEFAULT_INSTALL_DIR}/runtime`;
export const DEFAULT_STATE_DATABASE_PATH = `${DEFAULT_RUNTIME_DIR}/gateway-state.sqlite`;
@@ -21,31 +21,6 @@ export const DEFAULT_HEARTBEAT_INTERVAL_SECONDS = 15;
export const DEFAULT_INSTALLED_VERSION = "php-agent-v1";
const DEFAULT_COMPOSE_SERVICES = ["traefik", "redis", "mysql-debug", "edge-broker", "caddy"];
function composeArgs(projectName, args) {
return ["compose", "-p", projectName, ...args];
}
function usesWindowsPathSyntax(filePath) {
return /^[A-Za-z]:($|[\\/])/.test(filePath) || filePath.startsWith("\\\\") || filePath.includes("\\");
}
function pathForInputs(...filePaths) {
const hasWindowsPath = filePaths.some((filePath) => usesWindowsPathSyntax(String(filePath || "")));
return hasWindowsPath ? path.win32 : path;
}
async function resolveRootDir(scriptPath) {
const cwd = process.cwd();
try {
await fs.access(path.join(cwd, "docker-compose.yml"));
return cwd;
} catch {
return path.resolve(path.dirname(scriptPath), "..");
}
}
function printUsage() {
process.stdout.write(`Usage:
node scripts/test-gateway.mjs start [--install-token <token>] [--container-name <name>] [--hostname <hostname>]
@@ -66,7 +41,6 @@ Options:
--tail <lines> Log lines for the logs action. Default: 200
--skip-compose-up Do not start the local Docker Compose stack before start.
--skip-build Do not rebuild the test gateway image before start.
--copy-config Copy generated config into the container instead of bind mounting it.
`);
}
@@ -76,7 +50,7 @@ export function resolveComposeProjectName(rootDir, env = process.env) {
return explicit;
}
return pathForInputs(rootDir).basename(rootDir);
return path.basename(rootDir);
}
export function resolveComposeNetworkName(rootDir, env = process.env) {
@@ -84,13 +58,11 @@ export function resolveComposeNetworkName(rootDir, env = process.env) {
}
export function resolveConfigDirectory(rootDir, explicitDir = null) {
const pathModule = pathForInputs(rootDir, explicitDir);
if (explicitDir) {
return pathModule.resolve(rootDir, explicitDir);
return path.resolve(rootDir, explicitDir);
}
return pathModule.join(rootDir, ".tmp", "test-gateway");
return path.join(rootDir, ".tmp", "test-gateway");
}
export function shouldClaimGateway(existingConfig = {}, installToken = "") {
@@ -163,7 +135,6 @@ export function parseArgs(argv = process.argv.slice(2)) {
tail: "200",
skipComposeUp: false,
skipBuild: false,
copyConfig: false,
};
for (let index = 0; index < rest.length; index += 1) {
@@ -218,9 +189,6 @@ export function parseArgs(argv = process.argv.slice(2)) {
case "--skip-build":
options.skipBuild = true;
break;
case "--copy-config":
options.copyConfig = true;
break;
case "--help":
case "-h":
options.help = true;
@@ -277,7 +245,7 @@ async function ensureComposeServices(rootDir, skipComposeUp) {
return;
}
await runCommand("docker", composeArgs(resolveComposeProjectName(rootDir), ["up", "-d", ...DEFAULT_COMPOSE_SERVICES]), {
await runCommand("docker", ["compose", "up", "-d", ...DEFAULT_COMPOSE_SERVICES], {
cwd: rootDir,
stdio: "inherit",
});
@@ -378,57 +346,35 @@ async function startContainer({
containerName,
hostname,
configDir,
copyConfig,
}) {
const networkName = resolveComposeNetworkName(rootDir);
const mountedConfigDir = toDockerMountPath(configDir);
const containerConfigPath = copyConfig
? `/tmp/${DEFAULT_CONFIG_FILE_NAME}`
: `/config/${DEFAULT_CONFIG_FILE_NAME}`;
const createArgs = [
copyConfig ? "create" : "run",
...(copyConfig ? [] : ["-d"]),
"--name",
containerName,
"--hostname",
hostname,
"--restart",
"unless-stopped",
"--network",
networkName,
...(copyConfig ? [] : ["-v", `${mountedConfigDir}:/config`]),
imageTag,
"--config",
containerConfigPath,
];
await removeContainer(containerName);
await runCommand("docker", createArgs, {
cwd: rootDir,
stdio: "inherit",
});
if (copyConfig) {
const configFilePath = path.join(configDir, DEFAULT_CONFIG_FILE_NAME);
await fs.chmod(configFilePath, 0o666).catch(() => {});
try {
await runCommand("docker", [
"cp",
configFilePath,
`${containerName}:${containerConfigPath}`,
], {
cwd: rootDir,
stdio: "inherit",
});
} finally {
await fs.chmod(configFilePath, 0o600).catch(() => {});
}
await runCommand("docker", ["start", containerName], {
await runCommand(
"docker",
[
"run",
"-d",
"--name",
containerName,
"--hostname",
hostname,
"--restart",
"unless-stopped",
"--network",
networkName,
"-v",
`${mountedConfigDir}:/config`,
imageTag,
"--config",
`/config/${DEFAULT_CONFIG_FILE_NAME}`,
],
{
cwd: rootDir,
stdio: "inherit",
});
}
}
);
}
async function printStatus({ imageTag, configDir, containerName }) {
@@ -471,7 +417,7 @@ async function main() {
}
const scriptPath = fileURLToPath(import.meta.url);
const rootDir = await resolveRootDir(scriptPath);
const rootDir = path.resolve(path.dirname(scriptPath), "..");
const configDir = resolveConfigDirectory(rootDir, options.configDir);
const configFilePath = path.join(configDir, DEFAULT_CONFIG_FILE_NAME);
@@ -508,7 +454,6 @@ async function main() {
containerName: options.containerName,
hostname: options.hostname,
configDir,
copyConfig: options.copyConfig,
});
process.stdout.write(`Test gateway container started.
@@ -540,12 +485,8 @@ Gateway ID: ${config.gatewayId ?? "unclaimed"}
}
const currentFilePath = fileURLToPath(import.meta.url);
const currentRealPath = await fs.realpath(currentFilePath).catch(() => currentFilePath);
const invokedScript = process.argv[1] ? path.resolve(process.argv[1]) : "";
const invokedRealPath = invokedScript !== ""
? await fs.realpath(invokedScript).catch(() => invokedScript)
: "";
if (invokedRealPath === currentRealPath) {
if (invokedScript === path.resolve(currentFilePath)) {
main().catch((error) => {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
process.exitCode = 1;
-6
View File
@@ -52,12 +52,6 @@ test("parseArgs accepts help without an explicit action", () => {
assert.equal(options.help, true);
});
test("parseArgs accepts copy config mode", () => {
const options = parseArgs(["start", "--copy-config"]);
assert.equal(options.copyConfig, true);
});
test("buildGatewayConfig applies defaults for a dockerized gateway", () => {
const config = buildGatewayConfig({});
-5
View File
@@ -10,11 +10,6 @@
# CORS is handled at the edge by Traefik's headers middleware.
# Do not set or strip Access-Control-* headers here to avoid conflicts.
# Do not expose local replication bootstrap material from the public web root.
# Bootstrap snapshots contain sensitive failover credentials.
@replicationBootstrap path /storage/replication-bootstrap.json /storage/replication-bootstrap-*
respond @replicationBootstrap 404
# PHP handling via FastCGI to php-fpm pool
php_fastcgi php1:9000 php2:9000 php3:9000 php4:9000 php5:9000
-5
View File
@@ -10,11 +10,6 @@
# CORS is handled at the edge by Traefik's headers middleware.
# Do not set or strip Access-Control-* headers here to avoid conflicts.
# Do not expose local replication bootstrap material from the public web root.
# Bootstrap snapshots contain sensitive failover credentials.
@replicationBootstrap path /storage/replication-bootstrap.json /storage/replication-bootstrap-*
respond @replicationBootstrap 404
# PHP handling via FastCGI to php-fpm pool
php_fastcgi php-staging:9000
+578
View File
@@ -0,0 +1,578 @@
{"level":"info","ts":1773826166.9708004,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.336730715,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826169.3245327,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.125025382,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826169.3245995,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.260210293,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826169.5794039,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.500289085,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826170.0778017,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.39669069,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826171.5490258,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.069669237,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826171.9627604,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.497760546,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826173.9760478,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.070845887,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826174.2890058,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.384107891,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826174.4404097,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.39908183,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826174.8434205,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Cache-Control":["no-cache"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.323563505,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826176.69389,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.385544905,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826176.7040854,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.395716047,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826179.9976525,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.252061272,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826179.9976532,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.252032823,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826180.2976575,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.416949968,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826180.702024,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.355183735,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826182.3615072,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.213493623,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826182.3619726,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.214062164,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826184.9015193,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.309120507,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826185.0053287,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Pragma":["no-cache"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.412929425,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826185.1834722,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Pragma":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.458085374,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826185.596906,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.404400262,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826187.2444446,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.245449894,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826187.2444932,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.245510879,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826189.7901962,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.351403066,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826189.845259,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.406399188,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826190.0125787,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.436858971,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826190.1053317,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.061400822,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826191.9140744,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.067352992,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826191.9140744,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Gpc":["1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.067144351,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"]}}
{"level":"info","ts":1773826194.5529275,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.27129644,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826194.5538201,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.272200234,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826194.8282824,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.410512911,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826195.345705,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.450611072,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826196.9063478,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.223679165,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826196.907733,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.225121309,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826199.390079,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.266549333,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826199.54275,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.419228455,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826199.7448642,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.486476363,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826200.1450813,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.406705347,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826200.902575,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Headers":["authorization"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Access-Control-Request-Method":["GET"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["*/*"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.004933848,"size":0,"status":200,"resp_headers":{"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"]}}
{"level":"info","ts":1773826200.9184515,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Access-Control-Request-Method":["GET"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Headers":["authorization"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.003871461,"size":0,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826201.313931,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Authorization":[],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.408608832,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826201.314516,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.417756253,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826201.6138952,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Authorization":[],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.297119022,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826201.614594,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.298338892,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826201.6740956,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.056775832,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826201.8352685,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.309177004,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826201.835635,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.309922332,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826202.1111634,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.434629705,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826204.2307596,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.270490136,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826204.231079,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.270777164,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826204.9306307,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.834871676,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826205.0144818,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.437812131,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826206.6582522,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.296923602,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826206.7820892,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.421257269,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826209.07706,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.28168601,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826209.0780072,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.282730259,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826209.2607417,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.329227333,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826210.719875,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.336777872,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826212.4557168,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.288418347,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826212.6393747,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.457420958,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826214.6817403,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.060898725,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826214.9970322,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.376193278,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826215.119907,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.37697543,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826215.5844464,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.358253193,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826217.364804,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.336250288,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826217.3651576,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.353011792,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826219.6290405,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.168509855,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826219.6290424,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Cache-Control":["no-cache"],"Pragma":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.168515835,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826220.0472326,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.451005017,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826220.5235884,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.459100139,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826221.9169457,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.056181782,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826221.917784,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.057027708,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826222.9502344,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.668844483,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826223.49054,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.537614159,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826223.9723587,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.479864308,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826224.343807,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.368627458,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826224.856207,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Host":["localhost"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.51019735,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826225.3152466,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.212788185,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826225.3152463,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.213877297,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826225.34763,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.489283626,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826225.3848963,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.280640345,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826225.3853478,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.284002289,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"]}}
{"level":"info","ts":1773826225.8986015,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.548822248,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826226.4152071,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.514747638,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826227.3371081,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.300847773,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826227.7347972,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.698537342,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826229.322464,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.180099137,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826229.3229284,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.182328794,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826229.5229506,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.547793197,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826229.7905357,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.515788574,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826230.0126746,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.487792958,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826230.015993,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.066576546,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826230.3144436,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.486501483,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826230.409719,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.09307799,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826231.4518874,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Access-Control-Request-Headers":["authorization"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["*/*"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"Access-Control-Request-Method":["GET"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.007941754,"size":0,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Server":["Caddy"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826231.9584615,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.504336719,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826232.00635,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.11080176,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826232.393898,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.498349724,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826233.7580044,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.31107267,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826234.0281086,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.268209641,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826234.856958,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.064741677,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826235.0811856,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.410918923,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826235.0965688,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.305344393,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826235.096562,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.305286142,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826235.758473,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.96652785,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826236.2328858,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":1.149166396,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826236.734551,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Access-Control-Request-Headers":["authorization"],"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Method":["GET"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.004409892,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826236.8764596,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Sec-Fetch-Mode":["cors"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.139966551,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826236.8765473,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.146188956,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826237.1359358,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.405598041,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826238.3543074,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.069293506,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826238.6079137,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.078009457,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826239.8719676,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.23115293,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826239.936697,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.297177805,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826239.93727,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.297747795,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826240.177016,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.301852145,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826240.2603126,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.619578163,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826240.2948732,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.115473072,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826242.5489316,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["*/*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"]}},"bytes_read":0,"user_id":"","duration":0.004359668,"size":0,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826242.840928,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.294881878,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826242.8434336,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.29885309,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826243.2189693,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Authorization":[],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.667883652,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826244.6206405,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.518181713,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826244.7226462,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.099885191,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826245.7282386,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.286842731,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826245.7282357,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.286843033,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826245.729071,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.40778575,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826245.8759341,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.433985598,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"]}}
{"level":"info","ts":1773826246.0560663,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.325072718,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826246.150864,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.709473378,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826247.3969293,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Access-Control-Request-Headers":["authorization"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Access-Control-Request-Method":["GET"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.004395296,"size":0,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826247.4287875,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Cache-Control":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.047798163,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826247.4294498,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.048426199,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826247.4584892,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Authorization":[],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.059579264,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826249.377847,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.434692156,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826249.9012983,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.520719503,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826250.3366525,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.039950465,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826250.3779438,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.21601427,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826250.3779619,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.081639673,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826250.423558,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.043639415,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826250.5279162,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.231591889,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826250.5284529,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.231734683,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826252.2262323,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["*/*"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.002952425,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826252.4899101,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.266604287,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826252.4902215,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Cache-Control":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.266939348,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826252.6353197,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.406947854,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826254.0988395,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.309949283,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826254.4142804,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.313229674,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826255.1939533,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.052917017,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826255.1943216,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Pragma":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.053291772,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826255.4786673,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.474724907,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826255.5260544,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.384703087,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826255.526563,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.385158447,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826256.113922,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.632900798,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826257.084515,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["*/*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Origin":["http://localhost:5173"],"Access-Control-Request-Headers":["authorization"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.003835498,"size":0,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826257.4487476,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.362283977,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826257.4492424,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"],"Sec-Fetch-Dest":["empty"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.368815775,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826257.6348832,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.55442496,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826259.0092547,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.376877321,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826259.6307788,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.619805015,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826260.145301,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.161590542,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826260.2827036,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.30025666,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826260.3579996,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.374290372,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826260.358565,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.375673265,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826260.3591213,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.495672175,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826260.9677532,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.005428654,"size":0,"status":200,"resp_headers":{"Content-Type":["application/json"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"]}}
{"level":"info","ts":1773826261.0812206,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.719474137,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826261.131758,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.152860403,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826261.9229548,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Access-Control-Request-Headers":["authorization"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Method":["GET"],"Referer":["http://localhost:5173/"],"Accept":["*/*"],"Origin":["http://localhost:5173"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.004796388,"size":0,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826262.1808798,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.262721205,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826262.3055892,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.387411559,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826262.3256145,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.399990235,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826264.0834198,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.605018867,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826264.4656212,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.379761165,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826265.159418,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Mode":["cors"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.337052132,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826265.1599183,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.338656721,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826265.159959,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.338665488,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826265.1599865,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.457723334,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826265.1608107,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.338186345,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826265.7457488,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.58234562,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826266.760665,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.003348445,"size":0,"status":200,"resp_headers":{"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"]}}
{"level":"info","ts":1773826267.099361,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.341886103,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826267.3528302,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.589548578,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826267.3544612,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.597138218,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826268.7962244,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.471960855,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826269.3874242,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.587826508,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826269.8864343,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.340632699,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826270.0011191,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.335564386,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826270.001632,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.336146783,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826270.1797457,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.289916136,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826270.244424,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.578840314,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826270.4123607,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.746906789,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826272.5798728,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Access-Control-Request-Method":["GET"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["*/*"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Access-Control-Request-Headers":["authorization"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.004585942,"size":0,"status":200,"resp_headers":{"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"]}}
{"level":"info","ts":1773826272.9760356,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.393565183,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826272.9766512,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.401031403,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"]}}
{"level":"info","ts":1773826273.757031,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":1.18182985,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826274.6127648,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.479104184,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826275.1434913,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.528749182,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826275.6235788,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.137716661,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826275.6238408,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.259205249,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826275.7685578,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.142324079,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826275.8653605,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.379437951,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826275.8658516,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.379986088,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826275.8674288,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.381435854,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826277.4191809,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["*/*"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Headers":["authorization"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.003160298,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Server":["Caddy"],"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826277.513314,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.083039333,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826277.513765,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.083276757,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826277.839947,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Authorization":[],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.418394618,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826279.311053,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.32588745,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826279.553671,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.240337937,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826280.4236414,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.219593491,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826280.4239388,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.097175698,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826280.609539,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.282907568,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826280.6095476,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.282945769,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826280.6837862,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.357176393,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826280.9124198,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.486043498,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826282.2816343,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Referer":["http://localhost:5173/"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.004272434,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826282.5014513,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.224096667,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826282.5932522,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"Authorization":[],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.309016132,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826282.762372,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.485008109,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826284.2473116,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.419944897,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826284.7155588,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.465644762,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826285.3731148,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.33201332,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826285.382416,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.204788999,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826285.3824492,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.204646815,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826285.527407,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.349765478,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826285.5277753,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.350248889,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826286.06445,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.688880394,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826287.113801,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.004059447,"size":0,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"Server":["Caddy"]}}
{"level":"info","ts":1773826287.419412,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.309658213,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826287.4198174,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.31017131,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826287.5938196,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Authorization":[],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.6"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.477313442,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826289.0298648,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.360409759,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826289.3319452,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.299687827,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826290.3376222,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.452177689,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826290.6402397,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.300352632,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826291.9410431,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.003132931,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826292.3842604,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Authorization":[],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.440860827,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826293.9343493,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.439952281,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826294.3440604,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.407360227,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826295.1711533,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.449134138,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826295.8527117,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.679430866,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826298.575222,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.239223342,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826299.1671898,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.589304101,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826299.9768214,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.42280195,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826300.3889349,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.409451117,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826304.4682908,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.297302011,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826304.6760879,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.205166353,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826305.7035754,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.309903469,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826306.06365,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.35758992,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826309.426586,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.411602016,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826309.7365882,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.307559619,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826310.5728822,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.340467364,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826311.1087942,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.53365395,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826314.3029535,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.451387991,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826314.7390003,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.433637015,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826315.145722,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Gpc":["1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.071645191,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826315.2184045,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.07060575,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826318.9327765,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.223040782,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826319.372069,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.435527131,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826320.2377045,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.310641846,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826320.6059396,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.366049107,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826321.019666,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Headers":["authorization"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["*/*"],"Access-Control-Request-Method":["GET"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.005125441,"size":0,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826321.0330973,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["same-site"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.004094559,"size":0,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826321.065755,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.050754619,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826321.0663266,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43688","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.049707903,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826321.0714931,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.058299498,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826321.3352807,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.31271021,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826321.3353183,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.320461487,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826321.33543,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.322217999,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826321.336045,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.319932569,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826321.454813,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.115766323,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826324.1107216,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.563325744,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826324.51782,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.404870334,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826325.0767791,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.313798868,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826325.516587,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.43789269,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826328.5783246,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.192510186,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826328.9600253,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.33591841,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826329.9461956,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.343614408,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826330.0325968,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.08370118,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826333.4395497,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.203711159,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826334.8488133,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.407913962,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826336.189148,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.775229936,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826336.5129259,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.321547405,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826339.8193758,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.778237382,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826340.484483,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.661839092,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826341.052277,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.565531578,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826341.1713974,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.116995635,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826344.3424993,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.459823803,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826344.9462178,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.600610796,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826345.400256,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.298155702,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826346.0480387,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.645135856,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826349.156766,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.41996003,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826349.5705867,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.410768907,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826350.1640942,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.209420494,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826350.5521028,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.385858993,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"]}}
{"level":"info","ts":1773826354.1082847,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.532853099,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826354.7754962,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.664431534,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826355.290558,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"X-Real-Ip":["172.18.0.1"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.498205064,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826355.7959008,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.50333574,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826359.4631894,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":1.046471635,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826359.8179033,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.352511432,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826360.3723376,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.552128883,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826361.6249712,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.250746166,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826364.3044171,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":1.036105659,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826365.7734706,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.500940415,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826366.3151329,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.539422058,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826366.9041758,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.585534079,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826369.6179724,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.552731569,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826370.0349576,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.414776487,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826370.3518865,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.066909465,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826370.719497,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.365441292,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826374.2375813,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.322032518,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826374.37445,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.134229129,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"]}}
{"level":"info","ts":1773826375.2585166,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.120342752,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826375.7874947,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.526105892,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826379.1529784,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.391462836,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826379.737555,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.582494402,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826380.8159359,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.838749844,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826380.9110472,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.0926876,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826381.0814805,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Access-Control-Request-Method":["GET"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.003464438,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826381.2150488,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43688","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.135002073,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826381.353293,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.275410157,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826381.4263964,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.347429674,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826381.4263968,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Pragma":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.347228296,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826381.4269779,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.347126352,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826381.4264684,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.346251891,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826381.4288092,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["*/*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.33539058,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["*"],"Server":["Caddy"],"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826381.725631,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.640679594,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826381.8789194,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Authorization":[],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.150518915,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826384.2855997,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.68677901,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826384.419676,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.131463831,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826385.296497,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.482235259,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826385.9763112,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.677502726,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826389.0283816,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.585028881,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826389.7241693,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.693332769,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826389.9961612,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.270062312,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826390.0560722,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"],"Origin":["http://localhost:5173"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.058272897,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826394.1860425,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.905101807,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826394.8389401,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.650678782,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826396.8760483,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":1.062733619,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826397.4128597,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.533872213,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826399.3711278,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Gpc":["1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.275338328,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826399.8407238,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.467445268,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826400.8211105,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Sec-Gpc":["1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.503336673,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826401.3927042,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.568617153,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826404.9276648,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.981689797,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826405.3865352,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.45668309,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826405.7212017,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.332704571,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"]}}
{"level":"info","ts":1773826406.24432,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.520752258,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826409.4144459,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.619358427,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826409.8032606,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.386445718,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826410.3962119,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.382138844,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826410.8523376,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.453331614,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826413.9524436,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.317999654,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826414.2163806,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.261299034,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826415.6521916,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.804872582,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826416.2200892,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.56558394,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826418.6992216,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.230586771,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826419.2315469,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.528964389,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826420.1994016,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Origin":["http://localhost:5173"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.516745862,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826420.5655065,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["empty"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.364192672,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826423.6324012,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.336594454,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826424.1642637,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.529683486,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826424.9427843,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.417239584,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826425.25549,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.310120034,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826429.4322617,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.294377725,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826429.6303096,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.195912736,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826430.5558884,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.20020931,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826430.6338358,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.075953449,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826434.7283158,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.749575954,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826435.4002984,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.669408179,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826436.0852852,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.681158799,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826436.6932082,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.605147457,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826439.2860832,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.454779172,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826439.8214653,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.533406742,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826440.4660094,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.417585991,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826440.8675385,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.398997562,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826441.1522396,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.005090754,"size":0,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"]}}
{"level":"info","ts":1773826441.1626284,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43688","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["*/*"],"Access-Control-Request-Headers":["authorization"],"Access-Control-Request-Method":["GET"],"Referer":["http://localhost:5173/"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.002807514,"size":0,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826441.3849103,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.236757779,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826441.3854418,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.236391524,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826441.473212,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.326754444,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826441.4736257,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.325698639,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826441.473778,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.32471909,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826441.4738522,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.325672989,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826441.6903734,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Authorization":[],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.53561241,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826442.0301497,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.337053066,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826443.734806,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.057697718,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826444.2450626,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.328282862,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826445.1334405,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.237094723,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826445.4486778,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.312441438,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826448.7812324,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.276600283,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826449.2926083,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.509287977,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826450.3206308,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.58550417,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826450.4873588,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.163633449,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826453.6153731,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.261944392,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826453.958753,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.341302764,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826454.935746,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.358773571,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826455.1492126,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.21140475,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826459.3996916,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.239497817,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826460.007519,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.605473485,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826460.4367466,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.054840982,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826460.6668808,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.227959031,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826464.721618,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.516813632,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"error","ts":1773826464.7636774,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/departments","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.558936596,"size":111,"status":401,"resp_headers":{"Server":["Caddy"],"Status":["401 Unauthorized"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826464.8303838,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.606549241,"size":735,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"],"Server":["Caddy"]}}
{"level":"info","ts":1773826469.3836143,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.334187709,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826474.1502144,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.245024222,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826479.0968618,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.355127487,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826484.1756196,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.582159192,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826490.199057,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.804270926,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"error","ts":1773826493.4475157,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/departments","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.367623667,"size":111,"status":401,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["401 Unauthorized"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826493.652717,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Server":["0b64317da32a"]}},"bytes_read":0,"user_id":"","duration":0.572779984,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826495.118352,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":2.018611954,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1773826499.0833688,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":1.143638682,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826501.2080162,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["*/*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Headers":["authorization"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Access-Control-Request-Method":["GET"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.005821988,"size":0,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"]}}
{"level":"info","ts":1773826501.2162066,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43688","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"OPTIONS","host":"localhost","uri":"/ping","headers":{"Accept":["*/*"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Access-Control-Request-Method":["GET"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"Access-Control-Request-Headers":["authorization"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.002818669,"size":0,"status":200,"resp_headers":{"Content-Type":["application/json"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Headers":["*"],"Server":["Caddy"]}}
{"level":"info","ts":1773826501.3781483,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"55612","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.174063301,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826501.3781526,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.176308399,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826501.378165,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38484","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.174260755,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826501.5183465,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"41354","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.313467045,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826501.5187743,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"38470","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.314577812,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826501.6968036,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Authorization":[],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.486608324,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826502.2942631,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"43684","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Origin":["http://localhost:5173"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.090459252,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826502.6856973,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Authorization":[],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"]}},"bytes_read":0,"user_id":"","duration":0.986786982,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826503.1070702,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["0b64317da32a"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.329633423,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826507.9452004,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.330087892,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826512.99931,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Server":["0b64317da32a"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.545302906,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826518.1475375,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["0b64317da32a"],"X-Forwarded-Host":["localhost"],"Cache-Control":["no-cache"]}},"bytes_read":0,"user_id":"","duration":0.843202642,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"error","ts":1773826523.1225665,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"53894","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["0b64317da32a"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.007480931,"size":0,"status":502,"resp_headers":{"Server":["Caddy"]}}
{"level":"info","ts":1773826533.9554763,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Cache-Control":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":1.158905036,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826536.9338899,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":2.965340628,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1773826538.547151,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.910843089,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826543.0969942,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.629550116,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826547.7162032,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.395867947,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826554.0806224,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.934719548,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826558.3746915,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.379371845,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826561.631695,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"Cache-Control":["no-cache"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.377331413,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826561.631695,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.371442491,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826561.7586732,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.500663238,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826561.9058926,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.644824932,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826561.9058967,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.64280669,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826561.9065697,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.648565892,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826562.008113,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37104","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.744631138,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826562.745923,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Authorization":[],"Referer":["http://localhost:5173/"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.836964667,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826563.3830287,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.539581044,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826568.1970885,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.52872221,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826572.8485315,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["cf3606ea293b"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.329632635,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826577.5866983,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.246261041,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826583.649508,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.472560865,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826588.5287206,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.50213333,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826593.668152,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.794128836,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826598.0569248,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"]}},"bytes_read":0,"user_id":"","duration":0.3455446,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"]}}
{"level":"info","ts":1773826602.9588246,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.390555761,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826607.8736682,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.477587811,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826613.8135455,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.595724596,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826618.519822,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.469573999,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826621.5868504,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Cache-Control":["no-cache"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.269667338,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826621.5905738,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.273376391,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826621.7035396,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.386524533,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826621.703969,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.388962343,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826621.7040298,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.386885628,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826621.704212,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37104","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.388677708,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826621.7050414,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.387877353,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826622.5236545,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.816353161,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826623.0119357,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.108896811,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826628.1503737,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.398736135,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826633.0426946,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.458874081,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826637.766165,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.344250942,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826643.0986114,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.839096138,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826647.9172235,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37104","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Fetch-Site":["same-site"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.293915662,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826648.011681,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/departments","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.388416664,"size":111,"status":401,"resp_headers":{"Server":["Caddy"],"Status":["401 Unauthorized"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826649.156614,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":1.486069357,"size":735,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826652.7637017,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.287533254,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1773826657.6192331,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""]}},"bytes_read":0,"user_id":"","duration":0.304165869,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826662.484209,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.332249171,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826667.3339016,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.335003003,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826672.4496367,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"]}},"bytes_read":0,"user_id":"","duration":0.615472516,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"info","ts":1773826677.9462786,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.284755105,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826681.6040988,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.215791054,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"]}}
{"level":"info","ts":1773826681.604095,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.219227531,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826681.6041782,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-Server":["cf3606ea293b"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"]}},"bytes_read":0,"user_id":"","duration":0.220043092,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826681.7778602,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.391469649,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826681.7804117,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.391671889,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826681.7854679,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.398119439,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1773826682.2771666,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Authorization":[],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.496209609,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1773826682.2781265,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37104","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.893277484,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826683.178707,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37104","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.663738661,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"info","ts":1773826688.3381941,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37104","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.989881721,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826688.52026,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/departments","headers":{"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.517618677,"size":111,"status":401,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"Status":["401 Unauthorized"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"info","ts":1773826689.0678031,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["cf3606ea293b"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":1.064311318,"size":101,"status":200,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1773826689.8285036,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":1.804908345,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1773826693.5957835,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.750935948,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826697.3757653,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/departments","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"Origin":["http://localhost:5173"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.293729729,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826697.3757768,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Gpc":["1"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.293211565,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826697.7717874,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/guest/departments?include_lanes=true","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["same-site"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.666268221,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"error","ts":1773826701.5105367,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Authorization":[],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.53491044,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"error","ts":1773826701.7883804,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/auth/reCAPTCHA/public","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.816917711,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826701.853436,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"50300","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.339505529,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"error","ts":1773826701.8538113,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/auth/session","headers":{"Origin":["http://localhost:5173"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.6"],"Referer":["http://localhost:5173/"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.877614488,"size":72,"status":404,"resp_headers":{"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"error","ts":1773826701.984547,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"35502","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/guest/departments?include_lanes=true","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Cache-Control":["no-cache"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"]}},"bytes_read":0,"user_id":"","duration":0.172874076,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"Server":["Caddy"]}}
{"level":"error","ts":1773826702.0168717,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37054","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/auth/session","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Authorization":[],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.159969922,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826702.242746,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/departments","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"],"X-Forwarded-Port":["80"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Referer":["http://localhost:5173/"],"X-Forwarded-Proto":["http"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"Authorization":[],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":1.295959827,"size":72,"status":404,"resp_headers":{"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"error","ts":1773826702.3069026,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37072","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/departments","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Cache-Control":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.577721038,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826702.350668,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/auth/reCAPTCHA/public","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"]}},"bytes_read":0,"user_id":"","duration":0.555174873,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"error","ts":1773826702.8036997,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/departments","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Origin":["http://localhost:5173"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.557892356,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"error","ts":1773826702.8073766,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":1.077441848,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"error","ts":1773826703.4966028,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"]}},"bytes_read":0,"user_id":"","duration":0.684978633,"size":72,"status":404,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"error","ts":1773826708.0270803,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Fetch-Mode":["cors"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Authorization":[],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Origin":["http://localhost:5173"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.486951214,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"error","ts":1773826708.3696883,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Sec-Fetch-Mode":["cors"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.60697834,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"error","ts":1773826708.5068195,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Authorization":[],"Origin":["http://localhost:5173"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.476434872,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Server":["Caddy"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826708.6845531,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.17228174,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826713.0960047,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Server":["cf3606ea293b"],"Origin":["http://localhost:5173"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.704865696,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"]}}
{"level":"error","ts":1773826713.2229595,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""]}},"bytes_read":0,"user_id":"","duration":0.607684269,"size":72,"status":404,"resp_headers":{"Status":["404 Not Found"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"error","ts":1773826713.5119667,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Forwarded-Port":["80"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"Accept-Language":["en-GB,en;q=0.9"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"]}},"bytes_read":0,"user_id":"","duration":0.163409461,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826713.7476597,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Gpc":["1"]}},"bytes_read":0,"user_id":"","duration":0.648740312,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"error","ts":1773826717.6552675,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["cf3606ea293b"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":0.195128913,"size":72,"status":404,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"error","ts":1773826717.6557715,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Authorization":[],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.429146662,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826718.6928694,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Pragma":["no-cache"],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Cache-Control":["no-cache"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.496269746,"size":72,"status":404,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"error","ts":1773826718.6936173,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Site":["same-site"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":1.035254318,"size":72,"status":404,"resp_headers":{"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"error","ts":1773826722.7025964,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Fetch-Site":["same-site"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.6"],"X-Forwarded-Host":["localhost"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Authorization":[],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.621774556,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"]}}
{"level":"error","ts":1773826723.3734825,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.338516843,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826723.3745852,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Authorization":[],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.667566008,"size":72,"status":404,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"error","ts":1773826723.4913466,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept":["application/json, text/plain, */*"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Forwarded-Proto":["http"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":1.187267605,"size":72,"status":404,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"]}}
{"level":"error","ts":1773826727.4152093,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Gpc":["1"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Authorization":[],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Mode":["cors"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"]}},"bytes_read":0,"user_id":"","duration":0.497147953,"size":72,"status":404,"resp_headers":{"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"error","ts":1773826727.8890858,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37084","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.747295957,"size":72,"status":404,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826728.1730373,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Server":["cf3606ea293b"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Authorization":[],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Port":["80"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":0.754468923,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826728.6366873,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"X-Forwarded-For":["172.18.0.1"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["en-GB,en;q=0.9"],"Cache-Control":["no-cache"],"Origin":["http://localhost:5173"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Pragma":["no-cache"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.746952708,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"error","ts":1773826732.221285,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Server":["cf3606ea293b"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Authorization":[],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-site"],"X-Real-Ip":["172.18.0.1"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Language":["en-GB,en;q=0.6"],"Origin":["http://localhost:5173"],"Referer":["http://localhost:5173/"]}},"bytes_read":0,"user_id":"","duration":0.456508601,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1773826732.2212849,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Accept-Language":["en-GB,en;q=0.9"],"Sec-Gpc":["1"],"X-Forwarded-For":["172.18.0.1"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Origin":["http://localhost:5173"],"Sec-Ch-Ua-Mobile":["?0"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["http://localhost:5173/"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["cors"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"]}},"bytes_read":0,"user_id":"","duration":0.234413772,"size":72,"status":404,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"]}}
{"level":"error","ts":1773826732.912765,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37058","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Referer":["http://localhost:5173/"],"Sec-Fetch-Mode":["cors"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["cf3606ea293b"],"X-Real-Ip":["172.18.0.1"],"Authorization":[],"Origin":["http://localhost:5173"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Accept-Language":["en-GB,en;q=0.6"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-site"],"Sec-Gpc":["1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":0.687789355,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"error","ts":1773826733.4827838,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"37092","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/:4433/ping","headers":{"Accept":["application/json, text/plain, */*"],"Origin":["http://localhost:5173"],"Pragma":["no-cache"],"Sec-Ch-Ua":["\"Chromium\";v=\"146\", \"Not-A.Brand\";v=\"24\", \"Brave\";v=\"146\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-site"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"Sec-Fetch-Mode":["cors"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache"],"Referer":["http://localhost:5173/"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["cf3606ea293b"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Gpc":["1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Language":["en-GB,en;q=0.9"]}},"bytes_read":0,"user_id":"","duration":0.752769145,"size":72,"status":404,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization, X-Customer-Number"],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Content-Type":["application/json; charset=utf-8"],"Status":["404 Not Found"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1774359410.7662385,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"]}},"bytes_read":0,"user_id":"","duration":1.419261331,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359411.8936794,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-Server":["4513febd0e98"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":1.095823154,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359413.4743714,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"]}},"bytes_read":0,"user_id":"","duration":1.569025749,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1774359414.9427295,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["4513febd0e98"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.453042866,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359416.5113647,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":1.555332673,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1774359417.9860232,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.45695831,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359418.5943637,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.595441308,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1774359419.6813276,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"42848","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":1.075013274,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359428.338712,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.910140374,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359429.22114,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.862201927,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359429.1707215,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":1.389081049,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359429.3823278,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.194319251,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359430.8409362,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":1.437162491,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1774359431.0736253,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["4513febd0e98"]}},"bytes_read":0,"user_id":"","duration":0.21548384,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359432.5463028,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.457021421,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359433.1541202,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.593640533,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359433.7735548,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.604391296,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359434.523004,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.735703774,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359435.3819067,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["4513febd0e98"]}},"bytes_read":0,"user_id":"","duration":0.841783131,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1774359436.0587533,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.65987697,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1774359436.7292738,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.654426603,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1774359437.4872267,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"],"X-Forwarded-Host":["localhost"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.737746322,"size":101,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"]}}
{"level":"info","ts":1774359438.1417146,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":0.638910553,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1774359438.9001129,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["4513febd0e98"]}},"bytes_read":0,"user_id":"","duration":0.744432539,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1774359439.7426257,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-Server":["4513febd0e98"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":0.820541924,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359440.5554748,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"Accept-Encoding":["gzip"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"]}},"bytes_read":0,"user_id":"","duration":0.798630689,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359441.0909092,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"]}},"bytes_read":0,"user_id":"","duration":0.522440142,"size":101,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359441.87296,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/ping","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":0.768554371,"size":101,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359451.9496348,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":3.16841118,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359454.7461386,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":2.771633599,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359456.8014095,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"Accept-Encoding":["gzip"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":2.043545388,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359458.8112676,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.997627811,"size":735,"status":200,"resp_headers":{"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1774359460.0082002,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Host":["localhost"],"X-Forwarded-Server":["4513febd0e98"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"]}},"bytes_read":0,"user_id":"","duration":2.719624341,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["application/json; charset=utf-8"],"X-Powered-By":["PHP/8.2.15"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359462.1559546,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Server":["4513febd0e98"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"]}},"bytes_read":0,"user_id":"","duration":2.129318162,"size":735,"status":200,"resp_headers":{"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"],"Server":["Caddy"]}}
{"level":"info","ts":1774359464.0260193,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Port":["80"],"X-Real-Ip":["172.18.0.1"]}},"bytes_read":0,"user_id":"","duration":1.858119212,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359466.158465,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Real-Ip":["172.18.0.1"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Prefix":["/api"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"]}},"bytes_read":0,"user_id":"","duration":2.120016812,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359468.6958492,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["4513febd0e98"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Prefix":["/api"],"X-Real-Ip":["172.18.0.1"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Port":["80"]}},"bytes_read":0,"user_id":"","duration":2.523297017,"size":735,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"],"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"]}}
{"level":"info","ts":1774359470.677206,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.6","remote_port":"53830","client_ip":"172.18.0.6","proto":"HTTP/1.1","method":"GET","host":"localhost","uri":"/guest/departments?include_lanes=true","headers":{"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Real-Ip":["172.18.0.1"],"Accept-Encoding":["gzip"],"X-Forwarded-Server":["4513febd0e98"],"User-Agent":["Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.26100.7920"],"X-Forwarded-For":["172.18.0.1"],"X-Forwarded-Host":["localhost"],"X-Forwarded-Prefix":["/api"]}},"bytes_read":0,"user_id":"","duration":1.968647671,"size":735,"status":200,"resp_headers":{"Content-Encoding":["gzip"],"Vary":["Accept-Encoding"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1775042310.766326,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"49692","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"caddy","uri":"/economic/payment-terms","headers":{"User-Agent":["curl/8.14.1"],"Accept":["*/*"],"Authorization":[]}},"bytes_read":0,"user_id":"","duration":2.173924739,"size":2514,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1775042310.819993,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"49690","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"caddy","uri":"/economic/layouts","headers":{"User-Agent":["curl/8.14.1"],"Accept":["*/*"],"Authorization":[]}},"bytes_read":0,"user_id":"","duration":2.227691681,"size":721,"status":200,"resp_headers":{"Content-Type":["application/json; charset=utf-8"],"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"]}}
{"level":"info","ts":1775042311.5330641,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"49706","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"caddy","uri":"/economic/config","headers":{"User-Agent":["curl/8.14.1"],"Accept":["*/*"],"Authorization":[]}},"bytes_read":0,"user_id":"","duration":2.692967287,"size":604,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.30"],"Content-Type":["application/json; charset=utf-8"]}}
{"level":"info","ts":1775042615.6337473,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.18.0.5","remote_port":"54866","client_ip":"172.18.0.5","proto":"HTTP/1.1","method":"GET","host":"caddy","uri":"/customers?page=1&limit=100","headers":{"User-Agent":["curl/8.14.1"],"Accept":["*/*"],"Authorization":[]}},"bytes_read":0,"user_id":"","duration":10.029899933,"size":164529,"status":200,"resp_headers":{"Server":["Caddy"],"X-Powered-By":["PHP/8.2.15"],"Content-Type":["application/json; charset=utf-8"]}}
-42
View File
@@ -1,42 +0,0 @@
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /dev/stdout;
error_log /dev/stderr warn;
sendfile on;
keepalive_timeout 65;
client_max_body_size 64m;
gzip on;
gzip_types application/json application/javascript application/xml text/css text/plain;
server {
listen 80 default_server;
server_name _;
root /var/www/html;
index index.php;
location / {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_read_timeout 60s;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param X_REQUEST_ID $http_x_request_id;
}
location ~ /\.(?!well-known) {
deny all;
}
}
}
-6
View File
@@ -1,6 +0,0 @@
#!/bin/sh
set -e
mkdir -p /run/nginx
php-fpm -D
exec nginx -g "daemon off;"
+7 -1
View File
@@ -3,7 +3,13 @@ FROM php:8.2-cli
WORKDIR /opt/truckwash-edge-agent
RUN set -eux; \
php -r 'foreach (["curl", "sqlite3"] as $extension) { if (!extension_loaded($extension)) { fwrite(STDERR, "Missing PHP extension: {$extension}\n"); exit(1); } }'
apt-get update; \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev \
libsqlite3-dev \
ca-certificates; \
docker-php-ext-install curl sqlite3; \
rm -rf /var/lib/apt/lists/*
COPY services/nginx/app/resources/edge-gateway-agent/ ./
+36 -382
View File
@@ -17,8 +17,6 @@ const DEFAULT_UPDATE_VERIFICATION_TIMEOUT_SECONDS = 45;
const DEFAULT_UPDATE_VERIFY_INTERVAL_MS = 500;
const DEFAULT_UPDATE_RESTART_GRACE_MS = 150;
const DEFAULT_BROKER_RECONNECT_DELAY_MS = 1500;
const DEFAULT_SHELLY_LOCAL_HTTP_TIMEOUT_MS = 1200;
const MAX_RELAY_TOGGLE_AFTER_SECONDS = 5;
const UPDATE_VERIFY_COMMAND = "post-update-verify";
const execFile = promisify(execFileCallback);
@@ -139,23 +137,16 @@ function buildTransportHeartbeatState(brokerState = {}) {
status: "ONLINE",
metadata: {
command_transport: brokerConnected ? "BROKER_FAST_PATH" : "API_POLLING",
shell_transport: brokerConnected ? "BROKER_FAST_PATH" : "API_POLLING",
broker_connected: brokerConnected,
broker_url: brokerState.url || null,
broker_last_error: brokerState.lastError || null,
broker_last_connected_at: brokerState.lastConnectedAt || null,
broker_last_disconnected_at: brokerState.lastDisconnectedAt || null,
broker_disconnect_reason: brokerState.disconnectReason || null,
broker_last_close_code: brokerState.lastCloseCode ?? null,
broker_last_close_clean: brokerState.lastCloseClean ?? null,
},
};
}
function isShellAccessEnabled(config = {}) {
return config.enableShellAccess === true;
}
function normalizeBrokerBaseUrl(value) {
const trimmed = String(value || "").trim().replace(/\/+$/, "");
if (trimmed === "") {
@@ -186,30 +177,6 @@ function buildBrokerSocketUrl(brokerUrl, gatewayId, token) {
return `${baseUrl}/ws/agent?${search.toString()}`;
}
function redactBrokerSocketUrl(value) {
try {
const parsed = new URL(String(value || ""));
for (const key of ["token", "agentToken", "agent_token"]) {
if (parsed.searchParams.has(key)) {
parsed.searchParams.set(key, "***");
}
}
return parsed.toString();
} catch {
return String(value || "").replace(/([?&](?:token|agentToken|agent_token)=)[^&]+/gi, "$1***");
}
}
function normalizeBrokerSocketError(error, socketUrl) {
const message = error instanceof Error && error.message
? error.message
: error?.message
? String(error.message)
: "Broker connection failed";
const redactedUrl = redactBrokerSocketUrl(socketUrl);
return redactedUrl ? `${message} (${redactedUrl})` : message;
}
async function readSocketMessageText(data) {
if (typeof data === "string") {
return data;
@@ -458,64 +425,8 @@ export async function claimIfNeeded(config, configPath, fetchImpl = fetch) {
return nextConfig;
}
function makeHttpTimeoutError(timeoutMs) {
const error = new Error(`HTTP request timed out after ${timeoutMs}ms`);
error.code = "EDGE_AGENT_HTTP_TIMEOUT";
return error;
}
function isHttpTimeoutError(error) {
return error?.code === "EDGE_AGENT_HTTP_TIMEOUT";
}
function resolveShellyLocalHttpTimeoutMs(options = {}) {
const configured = Number(options.timeoutMs ?? process.env.EDGE_SHELLY_LOCAL_HTTP_TIMEOUT_MS);
if (Number.isFinite(configured) && configured > 0) {
return Math.max(50, Math.floor(configured));
}
return DEFAULT_SHELLY_LOCAL_HTTP_TIMEOUT_MS;
}
function resolveRelayToggleAfterSeconds(payload = {}) {
const configured = Number(payload.toggleAfter ?? payload.toggle_after ?? payload.timer);
if (!Number.isFinite(configured) || configured <= 0) {
return null;
}
return Math.min(Math.floor(configured), MAX_RELAY_TOGGLE_AFTER_SECONDS);
}
async function fetchJson(url, fetchImpl = fetch, options = {}) {
const timeoutMs = Number(options.timeoutMs || 0);
let timeout = null;
let controller = null;
const requestOptions = {};
if (timeoutMs > 0 && typeof AbortController !== "undefined") {
controller = new AbortController();
requestOptions.signal = controller.signal;
}
let response;
try {
const fetchPromise = Promise.resolve().then(() => fetchImpl(url, requestOptions));
response = timeoutMs > 0
? await Promise.race([
fetchPromise,
new Promise((_, reject) => {
timeout = setTimeout(() => {
controller?.abort();
reject(makeHttpTimeoutError(timeoutMs));
}, timeoutMs);
}),
])
: await fetchPromise;
} finally {
if (timeout !== null) {
clearTimeout(timeout);
}
}
async function fetchJson(url, fetchImpl = fetch) {
const response = await fetchImpl(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
@@ -540,99 +451,13 @@ function expandCandidateIps(options = {}) {
return [];
}
function normalizeShellyDeviceGeneration(value) {
if (Number.isInteger(value) && value > 0) {
return value;
}
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
return Math.trunc(value);
}
return inferShellyDeviceGenerationFromString(value);
}
function inferShellyDeviceGenerationFromString(value) {
const normalized = String(value || "").trim();
if (!normalized) {
return null;
}
const explicit = normalized.match(/\bgen(?:eration)?\s*([1-9]\d*)\b/i);
if (explicit) {
return Number(explicit[1]);
}
const upper = normalized.toUpperCase();
const sSeries = upper.match(/\bS([3-9])(?:[A-Z0-9]+)?-[A-Z0-9-]+\b/);
if (sSeries) {
return Number(sSeries[1]);
}
if (/\b(?:SHELLY\s+)?(?:PLUS|PRO)\b/i.test(normalized) || /\bSP[A-Z0-9]+-[A-Z0-9-]+\b/.test(upper)) {
return 2;
}
if (/\bSH[A-Z0-9]+-?[A-Z0-9-]*\b/.test(upper)) {
return 1;
}
return null;
}
function resolveShellyDeviceGeneration(identity = {}) {
for (const candidate of [
identity.gen,
identity.generation,
identity.device_generation,
identity.capabilities?.generation,
]) {
const generation = normalizeShellyDeviceGeneration(candidate);
if (generation !== null) {
return generation;
}
}
for (const candidate of [
identity.model,
identity.type,
identity.app,
identity.name,
identity.id,
identity.mac,
]) {
const generation = inferShellyDeviceGenerationFromString(candidate);
if (generation !== null) {
return generation;
}
}
return null;
}
function resolveShellyCommandGeneration(payload = {}) {
return resolveShellyDeviceGeneration({
gen: payload.gen ?? payload.generation ?? payload.deviceGeneration ?? payload.device_generation,
device_generation: payload.device_generation,
capabilities: payload.capabilities,
model: payload.model ?? payload.deviceModel ?? payload.device_model ?? payload.deviceType ?? payload.device_type,
type: payload.type ?? payload.deviceType ?? payload.device_type,
app: payload.app,
name: payload.name ?? payload.deviceName ?? payload.device_name,
id: payload.deviceId ?? payload.device_id ?? payload.relayId ?? payload.relay_id,
mac: payload.mac,
});
}
export async function discoverShellyDevices(options = {}, fetchImpl = fetch) {
const candidateIps = expandCandidateIps(options);
const discovered = [];
await Promise.all(candidateIps.map(async (ip) => {
try {
const identity = await fetchJson(`http://${ip}/shelly`, fetchImpl, {
timeoutMs: resolveShellyLocalHttpTimeoutMs(options),
});
const identity = await fetchJson(`http://${ip}/shelly`, fetchImpl);
discovered.push({
id: identity.mac || identity.id || ip,
device_id: identity.mac || identity.id || ip,
@@ -641,7 +466,7 @@ export async function discoverShellyDevices(options = {}, fetchImpl = fetch) {
channel_count: Number(identity.num_outputs || identity.num_switches || 1),
online: true,
capabilities: {
generation: resolveShellyDeviceGeneration(identity),
generation: identity.gen || null,
},
metadata: identity,
});
@@ -656,41 +481,24 @@ export async function discoverShellyDevices(options = {}, fetchImpl = fetch) {
export async function getRelayStatus(payload, fetchImpl = fetch) {
const ip = payload.localIp || payload.local_ip || payload.ip;
const channel = Number.isInteger(payload.channel) ? payload.channel : 0;
const timeoutMs = resolveShellyLocalHttpTimeoutMs(payload);
if (!ip) {
throw new Error("Missing relay local IP");
}
const attempts = [
async () => {
const rpc = await fetchJson(`http://${ip}/rpc/Switch.GetStatus?id=${channel}`, fetchImpl, { timeoutMs });
return {
online: true,
on: Boolean(rpc.output),
raw: rpc,
};
},
async () => {
const legacy = await fetchJson(`http://${ip}/relay/${channel}`, fetchImpl, { timeoutMs });
return {
online: true,
on: Boolean(legacy.ison ?? legacy.output),
raw: legacy,
};
},
];
try {
return await Promise.any(attempts.map((attempt) => attempt()));
} catch (error) {
const errors = Array.isArray(error?.errors) ? error.errors : [error];
const message = errors
.map((entry) => entry?.message || String(entry))
.filter(Boolean)
.join("; ");
const relayStatusError = new Error(message ? `Unable to read relay status: ${message}` : "Unable to read relay status");
relayStatusError.cause = error;
throw relayStatusError;
const rpc = await fetchJson(`http://${ip}/rpc/Switch.GetStatus?id=${channel}`, fetchImpl);
return {
online: true,
on: Boolean(rpc.output),
raw: rpc,
};
} catch {
const legacy = await fetchJson(`http://${ip}/relay/${channel}`, fetchImpl);
return {
online: true,
on: Boolean(legacy.ison ?? legacy.output),
raw: legacy,
};
}
}
@@ -698,114 +506,25 @@ export async function setRelayState(payload, fetchImpl = fetch) {
const ip = payload.localIp || payload.local_ip || payload.ip;
const channel = Number.isInteger(payload.channel) ? payload.channel : 0;
const on = Boolean(payload.on);
const timeoutMs = resolveShellyLocalHttpTimeoutMs(payload);
const toggleAfter = resolveRelayToggleAfterSeconds(payload);
const timerQuery = toggleAfter === null ? "" : `&toggle_after=${encodeURIComponent(String(toggleAfter))}`;
const legacyTimerQuery = toggleAfter === null ? "" : `&timer=${encodeURIComponent(String(toggleAfter))}`;
const deviceGeneration = resolveShellyCommandGeneration(payload);
if (!ip) {
throw new Error("Missing relay local IP");
}
const runRpcSwitch = async () => {
const rpc = await fetchJson(`http://${ip}/rpc/Switch.Set?id=${channel}&on=${on ? "true" : "false"}${timerQuery}`, fetchImpl, { timeoutMs });
try {
const rpc = await fetchJson(`http://${ip}/rpc/Switch.Set?id=${channel}&on=${on ? "true" : "false"}`, fetchImpl);
return {
online: true,
on: Boolean(rpc.output ?? on),
raw: rpc,
};
};
const runLegacySwitch = async () => {
const legacy = await fetchJson(`http://${ip}/relay/${channel}?turn=${on ? "on" : "off"}${legacyTimerQuery}`, fetchImpl, { timeoutMs });
} catch {
const legacy = await fetchJson(`http://${ip}/relay/${channel}?turn=${on ? "on" : "off"}`, fetchImpl);
return {
online: true,
on: Boolean(legacy.ison ?? legacy.output ?? on),
raw: legacy,
};
};
if (toggleAfter !== null) {
const attempts = deviceGeneration === 1
? [runLegacySwitch, runRpcSwitch]
: [runRpcSwitch, runLegacySwitch];
let lastError = null;
for (const attempt of attempts) {
try {
return await attempt();
} catch (error) {
if (isHttpTimeoutError(error)) {
throw error;
}
lastError = error;
}
}
throw lastError || new Error("Unable to switch relay");
}
try {
return await runRpcSwitch();
} catch (error) {
if (isHttpTimeoutError(error)) {
throw error;
}
return await runLegacySwitch();
}
}
async function mapWithConcurrency(items, limit, mapper) {
const results = new Array(items.length);
let nextIndex = 0;
const workerCount = Math.max(1, Math.min(Number(limit) || 1, items.length || 1));
await Promise.all(Array.from({ length: workerCount }, async () => {
while (nextIndex < items.length) {
const index = nextIndex;
nextIndex += 1;
results[index] = await mapper(items[index], index);
}
}));
return results;
}
async function executeRelayBatch(command, handler, fetchImpl = fetch) {
const commands = Array.isArray(command?.payload?.commands)
? command.payload.commands
: Array.isArray(command?.commands)
? command.commands
: [];
const concurrency = Math.max(1, Math.min(Number(command?.payload?.concurrency || command?.concurrency || 5), 5));
const results = await mapWithConcurrency(commands, concurrency, async (entry = {}) => {
const target = String(entry.target || entry.relay || "");
const relayId = String(entry.relayId || entry.relay_id || "");
try {
const payload = await handler(entry, fetchImpl);
return {
target,
relayId,
relay_id: relayId,
ok: true,
payload,
};
} catch (error) {
return {
target,
relayId,
relay_id: relayId,
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
});
return {
batchId: command?.payload?.batchId || command?.payload?.batch_id || command?.batchId || command?.batch_id || null,
batch_id: command?.payload?.batch_id || command?.payload?.batchId || command?.batch_id || command?.batchId || null,
results,
};
}
async function fetchArtifactBuffer(url, expectedSha256, label, fetchImpl = fetch) {
@@ -813,15 +532,6 @@ async function fetchArtifactBuffer(url, expectedSha256, label, fetchImpl = fetch
return null;
}
if (!expectedSha256) {
throw new Error(`${label} checksum is required`);
}
const normalizedExpectedSha256 = String(expectedSha256).toLowerCase();
if (!/^[a-f0-9]{64}$/.test(normalizedExpectedSha256)) {
throw new Error(`${label} checksum must be a valid sha256 hex digest`);
}
const response = await fetchImpl(url);
if (!response.ok) {
throw new Error(`${label} download failed: HTTP ${response.status}`);
@@ -829,7 +539,7 @@ async function fetchArtifactBuffer(url, expectedSha256, label, fetchImpl = fetch
const buffer = Buffer.from(await response.arrayBuffer());
const sha256 = createHash("sha256").update(buffer).digest("hex");
if (normalizedExpectedSha256 !== sha256.toLowerCase()) {
if (expectedSha256 && String(expectedSha256).toLowerCase() !== sha256.toLowerCase()) {
throw new Error(`${label} checksum mismatch`);
}
@@ -1412,13 +1122,12 @@ export function createShellBridge(sendMessage, { createPtyProcess = createDefaul
sessions.set(sessionId, sessionRecord);
sendMessage({ type: "SHELL_OPENED", sessionId });
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
sendMessage({
type: "SHELL_OUTPUT",
sessionId,
data: `Failed to start root shell: ${message}\r\n`,
data: `Failed to start root shell: ${error instanceof Error ? error.message : String(error)}\r\n`,
});
sendMessage({ type: "SHELL_EXIT", sessionId, code: 1, reason: "shell_spawn_failed", message });
sendMessage({ type: "SHELL_EXIT", sessionId, code: 1 });
}
};
@@ -1470,10 +1179,6 @@ export async function handleAgentCommand(command, deps = {}) {
return await getRelayStatus(command.payload || {}, fetchImpl);
case "SET_RELAY_STATE":
return await setRelayState(command.payload || {}, fetchImpl);
case "BATCH_RELAY_STATUS":
return await executeRelayBatch(command, getRelayStatus, fetchImpl);
case "BATCH_SET_RELAY_STATE":
return await executeRelayBatch(command, setRelayState, fetchImpl);
case "RUN_UPDATE":
return await runUpdate(command.payload || {}, fetchImpl, deps);
case "UNINSTALL_AGENT":
@@ -1757,15 +1462,13 @@ function normalizeShellEvent(message) {
}
if (message.type === "SHELL_EXIT") {
const reason = String(message.reason || "agent_exit");
return {
sessionId: String(sessionId),
event: {
type: "CLOSED",
payload: {
code: Number.isFinite(message.code) ? message.code : 0,
reason,
message: message.message ? String(message.message) : null,
reason: "agent_exit",
},
},
};
@@ -1857,10 +1560,6 @@ export async function processPolledShellAction(config, action, shell, fetchImpl
}
try {
if (!isShellAccessEnabled(config)) {
throw new Error("Shell access is disabled by local configuration");
}
if (actionType === "OPEN") {
await shell.open(payload);
} else if (actionType === "INPUT") {
@@ -1900,8 +1599,6 @@ function createBrokerBridge({
disconnectReason: null,
lastConnectedAt: null,
lastDisconnectedAt: null,
lastCloseCode: null,
lastCloseClean: null,
};
let stopped = false;
@@ -1959,8 +1656,6 @@ function createBrokerBridge({
state.connected = true;
state.lastError = null;
state.disconnectReason = null;
state.lastCloseCode = null;
state.lastCloseClean = null;
state.lastConnectedAt = formatUpdateTimestamp();
};
@@ -1995,30 +1690,18 @@ function createBrokerBridge({
}
if (message.type === "OPEN_ROOT_SHELL") {
if (!isShellAccessEnabled(config)) {
throw new Error("Shell access is disabled by local configuration");
}
await shell.open(message.payload || {});
return;
}
if (message.type === "SHELL_INPUT") {
if (!isShellAccessEnabled(config)) {
throw new Error("Shell access is disabled by local configuration");
}
shell.input(message.payload || {});
return;
}
if (message.type === "RESIZE_ROOT_SHELL") {
if (!isShellAccessEnabled(config)) {
throw new Error("Shell access is disabled by local configuration");
}
shell.resize(message.payload || {});
return;
}
if (message.type === "CLOSE_ROOT_SHELL") {
if (!isShellAccessEnabled(config)) {
throw new Error("Shell access is disabled by local configuration");
}
shell.close(message.payload || {});
}
} catch {
@@ -2026,19 +1709,14 @@ function createBrokerBridge({
}
};
socket.onerror = (error) => {
state.lastError = normalizeBrokerSocketError(error, socketUrl);
socket.onerror = () => {
state.lastError = "Broker connection failed";
};
socket.onclose = (event) => {
socket = null;
state.connected = false;
state.disconnectReason = event.reason || "broker_disconnected";
state.lastCloseCode = Number.isFinite(Number(event.code)) ? Number(event.code) : null;
state.lastCloseClean = typeof event.wasClean === "boolean" ? event.wasClean : null;
if (state.lastCloseCode && state.lastCloseCode !== 1000 && !state.lastError) {
state.lastError = `Broker websocket closed with code ${state.lastCloseCode}`;
}
state.lastDisconnectedAt = formatUpdateTimestamp();
if (!stopped) {
scheduleReconnect();
@@ -2086,18 +1764,19 @@ export async function startAgent({
const commandPollTimeoutSeconds = Number(config.commandPollTimeoutSeconds || 20);
const commandPollRetryDelayMs = Number(config.commandPollRetryDelayMs || 1000);
const brokerReconnectDelayMs = Number(config.brokerReconnectDelayMs || DEFAULT_BROKER_RECONNECT_DELAY_MS);
const shellActionPollTimeoutSeconds = Number(config.shellActionPollTimeoutSeconds || 20);
const shellActionPollRetryDelayMs = Number(config.shellActionPollRetryDelayMs || 1000);
let stopped = false;
let cpuSnapshot = null;
let lastHeartbeatLatencyMs = null;
void createShellBridgeImpl;
let brokerBridge = null;
const shellEventPublisher = createShellEventPublisher(config, fetchImpl);
const shell = createShellBridgeImpl((message) => {
brokerBridge?.send(message);
shellEventPublisher.publish(message);
});
const shell = {
open: async () => {},
input: () => {},
resize: () => {},
close: () => {},
dispose: () => {},
};
brokerBridge = createBrokerBridge({
config,
shell,
@@ -2162,32 +1841,8 @@ export async function startAgent({
}
};
const runShellActionPollLoop = async () => {
while (!stopped) {
try {
const action = await pollShellActionJob(config, fetchImpl, shellActionPollTimeoutSeconds);
if (stopped) {
break;
}
if (!action) {
continue;
}
await processPolledShellAction(config, action, shell, fetchImpl);
} catch {
if (stopped) {
break;
}
await new Promise((resolve) => setTimeout(resolve, shellActionPollRetryDelayMs));
}
}
};
await sendTransportHeartbeat();
const commandPollPromise = runCommandPollLoop();
const shellActionPollPromise = runShellActionPollLoop();
const timer = setInterval(() => {
sendTransportHeartbeat().catch(() => {});
@@ -2198,9 +1853,8 @@ export async function startAgent({
stopped = true;
clearInterval(timer);
brokerBridge?.stop();
await shellEventPublisher.drain();
shell.dispose();
await Promise.allSettled([commandPollPromise, shellActionPollPromise]);
await Promise.allSettled([commandPollPromise]);
};
return {
+2 -351
View File
@@ -1,7 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { execFile as execFileCallback } from "node:child_process";
import { createHash } from "node:crypto";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -12,13 +11,11 @@ import {
buildStatusReport,
claimIfNeeded,
createShellBridge,
discoverShellyDevices,
finalizePendingUpdateOnStartup,
getAgentStatus,
getRelayStatus,
loadConfig,
parseCliArgs,
processPolledShellAction,
processPolledCommand,
runCli,
runUpdate,
@@ -41,10 +38,6 @@ function makeFetchResponse(body) {
};
}
function sha256Hex(body) {
return createHash("sha256").update(body).digest("hex");
}
async function waitFor(predicate, { timeoutMs = 1000, intervalMs = 10, description = "condition" } = {}) {
const deadline = Date.now() + timeoutMs;
@@ -127,215 +120,6 @@ test("relay status and switch commands support both Shelly RPC and legacy endpoi
assert.equal(switched.on, false);
});
test("batch relay commands return per-relay results without failing the whole batch", async () => {
const fakeFetch = async (url) => {
const value = String(url);
if (value.includes("10.1.0.31")) {
return {
ok: true,
async json() {
return { output: true };
},
};
}
throw new Error("relay offline");
};
const result = await handleAgentCommand({
commandType: "BATCH_SET_RELAY_STATE",
payload: {
batch_id: "batch-1",
commands: [
{ target: "MACHINE", relayId: "relay-machine", localIp: "10.1.0.31", channel: 0, on: true },
{ target: "EXIT", relayId: "relay-out", localIp: "10.1.0.32", channel: 0, on: true },
],
},
}, { fetchImpl: fakeFetch });
assert.equal(result.batch_id, "batch-1");
assert.equal(result.results.length, 2);
assert.equal(result.results[0].ok, true);
assert.equal(result.results[0].target, "MACHINE");
assert.equal(result.results[1].ok, false);
assert.match(result.results[1].error, /relay offline/);
});
test("Shelly discovery infers Gen3 from S3 relay model codes when generation is omitted", async () => {
const inventory = await discoverShellyDevices({ candidateIps: ["192.168.1.2"] }, async (url) => {
assert.equal(String(url), "http://192.168.1.2/shelly");
return {
ok: true,
async json() {
return {
id: "shelly1minig3-e4b3231f6410",
mac: "E4B3231F6410",
model: "S3SW-001X8EU",
type: "Shelly 1 Mini Gen3",
num_switches: 1,
};
},
};
});
assert.equal(inventory.length, 1);
assert.equal(inventory[0].device_id, "E4B3231F6410");
assert.equal(inventory[0].model, "S3SW-001X8EU");
assert.equal(inventory[0].capabilities.generation, 3);
});
test("relay status reads use the legacy endpoint when the RPC status endpoint stalls", async () => {
const urls = [];
const fakeFetch = async (url) => {
urls.push(String(url));
if (String(url).includes("Switch.GetStatus")) {
return new Promise(() => {});
}
if (String(url) === "http://10.1.0.31/relay/0") {
return {
ok: true,
async json() {
return { ison: false };
},
};
}
throw new Error(`Unexpected URL: ${url}`);
};
const startedAt = Date.now();
const status = await getRelayStatus({ localIp: "10.1.0.31", channel: 0, timeoutMs: 50 }, fakeFetch);
assert.equal(status.online, true);
assert.equal(status.on, false);
assert.deepEqual(urls.sort(), [
"http://10.1.0.31/relay/0",
"http://10.1.0.31/rpc/Switch.GetStatus?id=0",
]);
assert.ok(Date.now() - startedAt < 250);
});
test("relay switch commands fail quickly when the local Shelly request stalls", async () => {
let calls = 0;
const hangingFetch = async () => {
calls += 1;
return new Promise(() => {});
};
const startedAt = Date.now();
await assert.rejects(
() => setRelayState({ localIp: "10.1.0.31", channel: 0, on: true, timeoutMs: 50 }, hangingFetch),
/HTTP request timed out after 50ms/
);
assert.equal(calls, 1);
assert.ok(Date.now() - startedAt < 500);
});
test("relay switch commands pass timer values to local Shelly APIs", async () => {
const legacyUrls = [];
const legacyFetch = async (url) => {
legacyUrls.push(String(url));
return {
ok: true,
async json() {
return { ison: true, has_timer: true, timer_duration: 3 };
},
};
};
await setRelayState({
localIp: "10.1.0.31",
channel: 0,
on: true,
toggleAfter: 3,
deviceGeneration: 1,
}, legacyFetch);
assert.equal(
legacyUrls[0],
"http://10.1.0.31/relay/0?turn=on&timer=3"
);
const gen3Urls = [];
const gen3Fetch = async (url) => {
gen3Urls.push(String(url));
return {
ok: true,
async json() {
return { output: true };
},
};
};
await setRelayState({
localIp: "10.1.0.31",
channel: 0,
on: true,
toggle_after: 3,
device_generation: 3,
}, gen3Fetch);
assert.equal(
gen3Urls[0],
"http://10.1.0.31/rpc/Switch.Set?id=0&on=true&toggle_after=3"
);
const fallbackUrls = [];
const legacyFallbackFetch = async (url) => {
fallbackUrls.push(String(url));
if (String(url).includes("/rpc/")) {
throw new Error("RPC switch endpoint unsupported");
}
return {
ok: true,
async json() {
return { ison: true, has_timer: true, timer_duration: 3 };
},
};
};
await setRelayState({
localIp: "10.1.0.31",
channel: 0,
on: true,
toggle_after: 3,
device_model: "S3SW-001X8EU",
}, legacyFallbackFetch);
assert.deepEqual(fallbackUrls, [
"http://10.1.0.31/rpc/Switch.Set?id=0&on=true&toggle_after=3",
"http://10.1.0.31/relay/0?turn=on&timer=3",
]);
const cappedUrls = [];
const cappedFetch = async (url) => {
cappedUrls.push(String(url));
return {
ok: true,
async json() {
return { output: true };
},
};
};
await setRelayState({
localIp: "10.1.0.31",
channel: 0,
on: true,
toggle_after: 999999999,
device_generation: 3,
}, cappedFetch);
assert.equal(
cappedUrls[0],
"http://10.1.0.31/rpc/Switch.Set?id=0&on=true&toggle_after=5"
);
});
test("runUpdate stages a pending verification restart after installing new artifacts", async () => {
const tempDir = await mkdtemp(path.join(os.tmpdir(), "edge-agent-update-"));
const configPath = path.join(tempDir, "config.json");
@@ -358,23 +142,19 @@ test("runUpdate stages a pending verification restart after installing new artif
execCalls.push({ command, args, options });
return { stdout: "{}" };
};
const agentBody = "// new agent\n";
const packageBody = JSON.stringify({ name: "new-edge-agent" }, null, 2);
const fakeFetch = async (url) => {
if (String(url).endsWith("/agent.mjs")) {
return makeFetchResponse(agentBody);
return makeFetchResponse("// new agent\n");
}
if (String(url).endsWith("/package.json")) {
return makeFetchResponse(packageBody);
return makeFetchResponse(JSON.stringify({ name: "new-edge-agent" }, null, 2));
}
throw new Error(`Unexpected URL: ${url}`);
};
const result = await runUpdate({
artifactUrl: "https://api.example.test/edge-agent/artifacts/agent.mjs",
sha256: sha256Hex(agentBody),
packageUrl: "https://api.example.test/edge-agent/artifacts/package.json",
packageSha256: sha256Hex(packageBody),
targetVersion: "1.1.0",
releaseChannel: "stable",
restartMode: "spawn",
@@ -402,45 +182,6 @@ test("runUpdate stages a pending verification restart after installing new artif
await rm(tempDir, { recursive: true, force: true });
});
test("runUpdate rejects artifacts without required checksums", async () => {
const tempDir = await mkdtemp(path.join(os.tmpdir(), "edge-agent-update-checksum-"));
const configPath = path.join(tempDir, "config.json");
const liveConfig = {
apiUrl: "https://api.example.test",
gatewayId: 42,
agentToken: "agent-token",
installDir: tempDir,
restartMode: "spawn",
installedVersion: "1.0.0",
targetVersion: "1.0.0",
};
await writeFile(configPath, JSON.stringify(liveConfig, null, 2));
await writeFile(path.join(tempDir, "agent.mjs"), "// old agent\n");
let fetchCalled = false;
await assert.rejects(
runUpdate({
artifactUrl: "https://api.example.test/edge-agent/artifacts/agent.mjs",
targetVersion: "1.1.0",
}, async () => {
fetchCalled = true;
return makeFetchResponse("// new agent\n");
}, {
configPath,
config: liveConfig,
liveConfig,
execFileImpl: async () => ({ stdout: "{}" }),
}),
/Agent artifact checksum is required/
);
assert.equal(fetchCalled, false);
assert.equal(await readFile(path.join(tempDir, "agent.mjs"), "utf8"), "// old agent\n");
await rm(tempDir, { recursive: true, force: true });
});
test("handleAgentCommand returns an uninstall follow-up envelope for gateway removal", async () => {
const tempDir = await mkdtemp(path.join(os.tmpdir(), "edge-agent-uninstall-envelope-"));
@@ -732,39 +473,6 @@ test("shell bridge proxies PTY output, input, resize, close, and dispose events"
assert.ok(messages.some((message) => message.type === "SHELL_EXIT" && message.code === 0));
});
test("shell bridge reports structured spawn failures", async () => {
const messages = [];
const shell = createShellBridge(
(message) => messages.push(message),
{
createPtyProcess: async () => {
throw new Error("node-pty unavailable");
},
}
);
await shell.open({ sessionId: "spawn-failure-shell" });
assert.ok(
messages.some(
(message) =>
message.type === "SHELL_OUTPUT" &&
message.sessionId === "spawn-failure-shell" &&
/Failed to start root shell: node-pty unavailable/.test(message.data)
)
);
assert.ok(
messages.some(
(message) =>
message.type === "SHELL_EXIT" &&
message.sessionId === "spawn-failure-shell" &&
message.code === 1 &&
message.reason === "shell_spawn_failed" &&
message.message === "node-pty unavailable"
)
);
});
test("startAgent reports API polling metadata, executes polled commands, and uploads shell events", async () => {
const tempDir = await mkdtemp(path.join(os.tmpdir(), "edge-agent-"));
const configPath = path.join(tempDir, "config.json");
@@ -777,7 +485,6 @@ test("startAgent reports API polling metadata, executes polled commands, and upl
commandPollRetryDelayMs: 5,
shellActionPollTimeoutSeconds: 0,
shellActionPollRetryDelayMs: 5,
enableShellAccess: true,
}));
const heartbeats = [];
@@ -1002,7 +709,6 @@ test("startAgent reports API polling metadata, executes polled commands, and upl
assert.equal(commandResultPosts[0].body.ok, true);
assert.equal(Array.isArray(commandResultPosts[0].body.payload.inventory), true);
assert.equal(commandResultPosts[0].body.payload.inventory[0].device_id, "AA:BB:CC:DD:EE:FF");
assert.equal(commandResultPosts[0].body.payload.inventory[0].capabilities.generation, 2);
assert.ok(shellCalls.some((call) => call.type === "open"));
assert.ok(shellCalls.some((call) => call.type === "close"));
@@ -1036,61 +742,6 @@ test("startAgent reports API polling metadata, executes polled commands, and upl
}
});
test("processPolledShellAction denies shell access when locally disabled", async () => {
const submissions = [];
const fakeFetch = async (url, options = {}) => {
if (/\/shell-actions\/\d+\/result$/.test(String(url))) {
submissions.push({ url, body: JSON.parse(options.body) });
return {
ok: true,
async json() {
return { data: { acknowledged: true } };
},
};
}
throw new Error(`Unexpected URL: ${url}`);
};
const shell = {
async open() {
throw new Error("should not run");
},
input() {
throw new Error("should not run");
},
resize() {
throw new Error("should not run");
},
close() {
throw new Error("should not run");
},
};
const result = await processPolledShellAction(
{
apiUrl: "https://api.example.test",
gatewayId: 42,
agentToken: "agent-token",
enableShellAccess: false,
},
{
id: 501,
actionType: "OPEN",
payload: {
sessionId: 44,
},
},
shell,
fakeFetch
);
assert.equal(result.ok, false);
assert.match(result.error, /Shell access is disabled/);
assert.equal(submissions.length, 1);
assert.equal(submissions[0].body.ok, false);
});
test("status helpers report config without exposing the agent token", async () => {
const tempDir = await mkdtemp(path.join(os.tmpdir(), "edge-agent-status-"));
const configPath = path.join(tempDir, "config.json");
+3 -3
View File
@@ -4,9 +4,9 @@
"requires": true,
"packages": {
"node_modules/ws": {
"version": "8.21.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz",
"integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
"integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
-37
View File
@@ -40,10 +40,6 @@ class Receiver extends Writable {
* extensions
* @param {Boolean} [options.isServer=false] Specifies whether to operate in
* client or server mode
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=0] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=0] The maximum allowed message length
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
* not to skip UTF-8 validation for text and close messages
@@ -58,8 +54,6 @@ class Receiver extends Writable {
this._binaryType = options.binaryType || BINARY_TYPES[0];
this._extensions = options.extensions || {};
this._isServer = !!options.isServer;
this._maxBufferedChunks = options.maxBufferedChunks | 0;
this._maxFragments = options.maxFragments | 0;
this._maxPayload = options.maxPayload | 0;
this._skipUTF8Validation = !!options.skipUTF8Validation;
this[kWebSocket] = undefined;
@@ -77,7 +71,6 @@ class Receiver extends Writable {
this._totalPayloadLength = 0;
this._messageLength = 0;
this._numFragments = 0;
this._fragments = [];
this._errored = false;
@@ -96,22 +89,6 @@ class Receiver extends Writable {
_write(chunk, encoding, cb) {
if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
if (
this._maxBufferedChunks > 0 &&
this._buffers.length >= this._maxBufferedChunks
) {
cb(
this.createError(
RangeError,
'Too many buffered chunks',
false,
1008,
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
)
);
return;
}
this._bufferedBytes += chunk.length;
this._buffers.push(chunk);
this.startLoop(cb);
@@ -501,19 +478,6 @@ class Receiver extends Writable {
return;
}
if (this._maxFragments > 0 && ++this._numFragments > this._maxFragments) {
const error = this.createError(
RangeError,
'Too many message fragments',
false,
1008,
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
);
cb(error);
return;
}
if (this._compressed) {
this._state = INFLATING;
this.decompress(data, cb);
@@ -586,7 +550,6 @@ class Receiver extends Writable {
this._totalPayloadLength = 0;
this._messageLength = 0;
this._fragmented = 0;
this._numFragments = 0;
this._fragments = [];
if (this._opcode === 2) {
+1 -6
View File
@@ -4,9 +4,6 @@
const { Duplex } = require('stream');
const { randomFillSync } = require('crypto');
const {
types: { isUint8Array }
} = require('util');
const PerMessageDeflate = require('./permessage-deflate');
const { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants');
@@ -203,10 +200,8 @@ class Sender {
if (typeof data === 'string') {
buf.write(data, 2);
} else if (isUint8Array(data)) {
buf.set(data, 2);
} else {
throw new TypeError('Second argument must be a string or a Uint8Array');
buf.set(data, 2);
}
}
-8
View File
@@ -43,10 +43,6 @@ class WebSocketServer extends EventEmitter {
* called
* @param {Function} [options.handleProtocols] A hook to handle protocols
* @param {String} [options.host] The hostname where to bind the server
* @param {Number} [options.maxBufferedChunks=262144] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=16384] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
* size
* @param {Boolean} [options.noServer=false] Enable no server mode
@@ -69,8 +65,6 @@ class WebSocketServer extends EventEmitter {
options = {
allowSynchronousEvents: true,
autoPong: true,
maxBufferedChunks: 256 * 1024,
maxFragments: 16 * 1024,
maxPayload: 100 * 1024 * 1024,
skipUTF8Validation: false,
perMessageDeflate: false,
@@ -430,8 +424,6 @@ class WebSocketServer extends EventEmitter {
ws.setSocket(socket, head, {
allowSynchronousEvents: this.options.allowSynchronousEvents,
maxBufferedChunks: this.options.maxBufferedChunks,
maxFragments: this.options.maxFragments,
maxPayload: this.options.maxPayload,
skipUTF8Validation: this.options.skipUTF8Validation
});
-14
View File
@@ -201,10 +201,6 @@ class WebSocket extends EventEmitter {
* multiple times in the same tick
* @param {Function} [options.generateMask] The function used to generate the
* masking key
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=0] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=0] The maximum allowed message size
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
* not to skip UTF-8 validation for text and close messages
@@ -216,8 +212,6 @@ class WebSocket extends EventEmitter {
binaryType: this.binaryType,
extensions: this._extensions,
isServer: this._isServer,
maxBufferedChunks: options.maxBufferedChunks,
maxFragments: options.maxFragments,
maxPayload: options.maxPayload,
skipUTF8Validation: options.skipUTF8Validation
});
@@ -646,10 +640,6 @@ module.exports = WebSocket;
* masking key
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
* handshake request
* @param {Number} [options.maxBufferedChunks=262144] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=16384] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
* size
* @param {Number} [options.maxRedirects=10] The maximum number of redirects
@@ -670,8 +660,6 @@ function initAsClient(websocket, address, protocols, options) {
autoPong: true,
closeTimeout: CLOSE_TIMEOUT,
protocolVersion: protocolVersions[1],
maxBufferedChunks: 256 * 1024,
maxFragments: 16 * 1024,
maxPayload: 100 * 1024 * 1024,
skipUTF8Validation: false,
perMessageDeflate: true,
@@ -1029,8 +1017,6 @@ function initAsClient(websocket, address, protocols, options) {
websocket.setSocket(socket, head, {
allowSynchronousEvents: opts.allowSynchronousEvents,
generateMask: opts.generateMask,
maxBufferedChunks: opts.maxBufferedChunks,
maxFragments: opts.maxFragments,
maxPayload: opts.maxPayload,
skipUTF8Validation: opts.skipUTF8Validation
});
+1 -5
View File
@@ -1,6 +1,6 @@
{
"name": "ws",
"version": "8.21.1",
"version": "8.20.0",
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
"keywords": [
"HyBi",
@@ -66,9 +66,5 @@
"nyc": "^15.0.0",
"prettier": "^3.0.0",
"utf-8-validate": "^6.0.0"
},
"allowScripts": {
"bufferutil": true,
"utf-8-validate": true
}
}
+4 -4
View File
@@ -6,13 +6,13 @@
"": {
"name": "truckwash-edge-broker",
"dependencies": {
"ws": "^8.21.1"
"ws": "^8.18.0"
}
},
"node_modules/ws": {
"version": "8.21.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz",
"integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
"integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
+1 -1
View File
@@ -7,6 +7,6 @@
"test:live": "node --test live/live-smoke.mjs"
},
"dependencies": {
"ws": "^8.21.1"
"ws": "^8.18.0"
}
}
+182 -528
View File
@@ -1,11 +1,7 @@
import http from "node:http";
import { randomUUID } from "node:crypto";
import { fileURLToPath } from "node:url";
import { WebSocketServer } from "ws";
const DEFAULT_SHELL_OPEN_TIMEOUT_MS = 15000;
const TELEMETRY_INGEST_ERROR_MESSAGE = "Telemetry ingestion failed";
function parseJsonBody(req) {
return new Promise((resolve, reject) => {
let raw = "";
@@ -49,40 +45,14 @@ function resolveManagerUrl(options = {}) {
return trimTrailingSlash(options.managerUrl || process.env.EDGE_MANAGER_URL || process.env.EDGE_PUBLIC_API_URL || "");
}
function resolveAuthMode(options = {}) {
function resolveAuthMode(options = {}, managerUrl = "") {
if (options.authMode) {
return options.authMode;
}
if (process.env.EDGE_AUTH_MODE) {
return process.env.EDGE_AUTH_MODE;
}
return "strict";
}
function resolveSharedSecret(options = {}) {
return String(options.sharedSecret ?? process.env.EDGE_BROKER_SHARED_SECRET ?? "").trim();
}
function requireSharedSecret(req, res, sharedSecret) {
if (sharedSecret === "") {
jsonResponse(res, 503, {
ok: false,
error: "Edge broker shared secret is not configured",
shared_secret_required: true,
});
return false;
}
if (req.headers["x-edge-broker-secret"] !== sharedSecret) {
jsonResponse(res, 403, {
ok: false,
error: "Forbidden",
shared_secret_required: true,
});
return false;
}
return true;
return managerUrl ? "manager" : "stub";
}
function parseScopes(value) {
@@ -135,53 +105,11 @@ function sendJson(ws, payload) {
return true;
}
function currentTimestamp() {
return new Date().toISOString();
}
function normalizeErrorMessage(error, fallback = "Connection step failed") {
if (error instanceof Error && error.message) {
return error.message;
}
const message = String(error || "").trim();
return message || fallback;
}
function rejectUpgrade(socket, statusCode, errorCode, message, details = {}) {
const statusText = {
400: "Bad Request",
401: "Unauthorized",
403: "Forbidden",
404: "Not Found",
500: "Internal Server Error",
503: "Service Unavailable",
}[statusCode] || "WebSocket Upgrade Rejected";
const body = JSON.stringify({
ok: false,
error_code: errorCode,
message,
details,
});
socket.end(
[
`HTTP/1.1 ${statusCode} ${statusText}`,
"content-type: application/json; charset=utf-8",
`content-length: ${Buffer.byteLength(body)}`,
"connection: close",
"",
body,
].join("\r\n")
);
}
export function createBrokerServer(options = {}) {
const sharedSecret = resolveSharedSecret(options);
const sharedSecret = options.sharedSecret ?? process.env.EDGE_BROKER_SHARED_SECRET ?? "";
const managerUrl = resolveManagerUrl(options);
const authMode = resolveAuthMode(options);
const authMode = resolveAuthMode(options, managerUrl);
const commandTimeoutMs = options.commandTimeoutMs ?? 10000;
const shellOpenTimeoutMs = options.shellOpenTimeoutMs ?? DEFAULT_SHELL_OPEN_TIMEOUT_MS;
const agents = new Map();
const pendingCommands = new Map();
@@ -189,8 +117,6 @@ export function createBrokerServer(options = {}) {
const browserStreamSessions = new Map();
const gatewayStreamSessions = new Map();
const inflightGatewaySyncs = new Map();
const containerStartedAt = currentTimestamp();
let lastActivityAt = containerStartedAt;
const managerRequest = async (path, body = {}, method = "POST") => {
if (!managerUrl) {
@@ -207,11 +133,7 @@ export function createBrokerServer(options = {}) {
});
const json = await parseJsonResponse(response);
if (!response.ok) {
const error = new Error(json?.data?.message || json?.message || json?.error || `HTTP ${response.status}`);
error.status = response.status;
error.code = json?.data?.error_code || json?.error_code || null;
error.details = json?.data?.diagnostics || json?.diagnostics || null;
throw error;
throw new Error(json?.data?.message || json?.message || json?.error || `HTTP ${response.status}`);
}
return json?.data ?? json;
@@ -241,12 +163,11 @@ export function createBrokerServer(options = {}) {
options.closeShellSession ||
(authMode === "stub"
? async () => ({})
: async (_id, token, transcript, reason, details = {}) =>
: async (_id, token, transcript, reason) =>
managerRequest("/edge-agent/internal/shell-sessions/close", {
token,
transcript,
reason,
...details,
}));
const validateBrowserStream =
options.validateBrowserStream ||
@@ -298,12 +219,6 @@ export function createBrokerServer(options = {}) {
? async (_gatewayId, payload = {}) => payload
: async (gatewayId, payload = {}) =>
managerRequest(`/edge-agent/internal/gateways/${gatewayId}/logs`, payload));
const ingestMachineSignal =
options.ingestMachineSignal ||
(authMode === "stub"
? async (_gatewayId, payload = {}) => payload
: async (gatewayId, payload = {}) =>
managerRequest(`/edge-agent/internal/gateways/${gatewayId}/selfserve/machine-signal`, payload));
const broadcastGatewayEvent = (gatewayId, message) => {
const sessionIds = gatewayStreamSessions.get(String(gatewayId));
@@ -325,66 +240,29 @@ export function createBrokerServer(options = {}) {
}
};
const closeBrowserShellSession = async (sessionRecord, reason, details = {}) => {
const closeBrowserShellSession = async (sessionRecord, reason) => {
try {
await closeShellSession(
sessionRecord.session.id,
sessionRecord.ws.sessionToken,
sessionRecord.transcript,
reason,
{
message: sessionRecord.closedMessage || null,
code: sessionRecord.closedCode ?? null,
stage: sessionRecord.closedStage || null,
broker_connection_id: sessionRecord.agentConnectionId || null,
details: sessionRecord.closedDetails || {},
...details,
}
reason
);
} catch {
// Preserve socket teardown even when the manager callback is unavailable.
}
};
const clearShellOpenTimer = (sessionRecord) => {
if (sessionRecord?.openTimer) {
clearTimeout(sessionRecord.openTimer);
sessionRecord.openTimer = null;
}
};
const closeBrowserShellSocket = (sessionRecord, reason, message = null, code = 1000, details = {}) => {
sessionRecord.closedReason = reason;
sessionRecord.closedMessage = message || null;
sessionRecord.closedCode = code;
sessionRecord.closedDetails = details && typeof details === "object" ? details : {};
sessionRecord.closedStage = String(sessionRecord.closedDetails.stage || (sessionRecord.opened ? "shell_active" : "shell_open"));
clearShellOpenTimer(sessionRecord);
if (sessionRecord.ws.readyState >= 2) {
return;
}
sendJson(sessionRecord.ws, {
type: "closed",
reason,
code,
...(message ? { message } : {}),
...(Object.keys(sessionRecord.closedDetails).length ? { details: sessionRecord.closedDetails } : {}),
});
sessionRecord.ws.close(code, reason);
};
const markGatewayShellSessionsClosed = (gatewayId, reason) => {
for (const sessionRecord of browserShellSessions.values()) {
if (String(sessionRecord.session.gateway_id) !== String(gatewayId)) {
continue;
}
closeBrowserShellSocket(sessionRecord, reason, "Gateway agent disconnected from the broker.", 1011, {
stage: "agent_disconnect",
gateway_id: gatewayId,
shell_session_id: sessionRecord.session.id,
});
sessionRecord.closedReason = reason;
if (sessionRecord.ws.readyState < 2) {
sessionRecord.ws.close();
}
}
};
@@ -441,75 +319,12 @@ export function createBrokerServer(options = {}) {
return syncPromise;
};
const sendAgentWelcome = (ws) =>
sendJson(ws, {
type: "WELCOME",
target: "edge-agent",
gatewayId: String(ws.gatewayId || ""),
connectionId: ws.connectionId || null,
agentInstanceId: ws.agentInstanceId || null,
serverTime: currentTimestamp(),
broker: {
authMode,
},
});
const sendAgentConnectionProgress = (ws, stage, status, message, details = {}) =>
sendJson(ws, {
type: "CONNECTION_PROGRESS",
gatewayId: String(ws.gatewayId || ""),
connectionId: ws.connectionId || null,
stage,
status,
message,
...details,
serverTime: currentTimestamp(),
});
const sendAgentConnectionError = (ws, stage, error, details = {}) =>
sendJson(ws, {
type: "CONNECTION_ERROR",
gatewayId: String(ws.gatewayId || ""),
connectionId: ws.connectionId || null,
stage,
status: "failed",
message: normalizeErrorMessage(error),
error: normalizeErrorMessage(error),
...details,
serverTime: currentTimestamp(),
});
const server = http.createServer(async (req, res) => {
try {
const url = new URL(req.url, "http://localhost");
lastActivityAt = currentTimestamp();
if (req.method === "GET" && url.pathname === "/api/health") {
jsonResponse(res, 200, {
ok: true,
service: "edge-broker",
auth_mode: authMode,
manager_url_configured: Boolean(managerUrl),
shared_secret_configured: Boolean(sharedSecret),
agents_connected: agents.size,
lastActivityAt,
});
return;
}
if (req.method === "POST" && url.pathname === "/api/diagnostics/shared-secret") {
if (!requireSharedSecret(req, res, sharedSecret)) {
return;
}
jsonResponse(res, 200, {
ok: true,
shared_secret_required: true,
});
return;
}
if (req.method === "POST" && /^\/api\/gateways\/\d+\/commands$/.test(url.pathname)) {
if (!requireSharedSecret(req, res, sharedSecret)) {
if (sharedSecret && req.headers["x-edge-broker-secret"] !== sharedSecret) {
jsonResponse(res, 403, { error: "Forbidden" });
return;
}
@@ -552,7 +367,8 @@ export function createBrokerServer(options = {}) {
}
if (req.method === "POST" && /^\/api\/gateways\/\d+\/sync$/.test(url.pathname)) {
if (!requireSharedSecret(req, res, sharedSecret)) {
if (sharedSecret && req.headers["x-edge-broker-secret"] !== sharedSecret) {
jsonResponse(res, 403, { error: "Forbidden" });
return;
}
@@ -581,18 +397,7 @@ export function createBrokerServer(options = {}) {
return;
}
let gatewayInfo;
try {
gatewayInfo = await validateAgent({ gatewayId, token, headers: req.headers });
} catch (error) {
const status = Number(error?.status) === 403 ? 403 : Number(error?.status) === 401 ? 401 : 503;
rejectUpgrade(socket, status, error?.code || "agent_validation_failed", "Gateway agent could not be validated.", {
stage: "agent_validate",
});
return;
}
const gatewayInfo = await validateAgent({ gatewayId, token, headers: req.headers });
wss.handleUpgrade(req, socket, head, (ws) => {
const existing = agents.get(gatewayId);
if (existing && existing.readyState < 2) {
@@ -604,9 +409,6 @@ export function createBrokerServer(options = {}) {
ws.agentInstanceId = agentInstanceId || null;
ws.connectionId = randomUUID();
agents.set(gatewayId, ws);
wss.emit("connection", ws, req);
sendAgentWelcome(ws);
sendAgentConnectionProgress(ws, "presence", "started", "Reporting broker presence to the edge manager.");
reportGatewayPresence(gatewayId, {
status: "connected",
connectionId: ws.connectionId,
@@ -614,30 +416,15 @@ export function createBrokerServer(options = {}) {
remote_address: req.socket.remoteAddress || null,
agent_instance_id: ws.agentInstanceId,
},
})
.then(() => {
sendAgentConnectionProgress(ws, "presence", "succeeded", "Broker presence was reported.");
})
.catch((error) => {
sendAgentConnectionError(ws, "presence", error);
});
}).catch(() => {});
broadcastGatewayEvent(gatewayId, {
type: "presence.changed",
gatewayId,
status: "connected",
connectionId: ws.connectionId,
});
sendAgentConnectionProgress(ws, "backlog", "started", "Synchronizing queued gateway work.");
syncGatewayBacklog(gatewayId, ws)
.then((result) => {
sendAgentConnectionProgress(ws, "backlog", "succeeded", "Queued gateway work was synchronized.", {
queued: Boolean(result?.queued),
dispatchCount: Array.isArray(result?.dispatch) ? result.dispatch.length : 0,
});
})
.catch((error) => {
sendAgentConnectionError(ws, "backlog", error);
});
syncGatewayBacklog(gatewayId, ws).catch(() => {});
wss.emit("connection", ws, req);
});
return;
}
@@ -645,21 +432,11 @@ export function createBrokerServer(options = {}) {
if (url.pathname === "/ws/browser-shell") {
const token = String(url.searchParams.get("token") || "");
if (token === "") {
rejectUpgrade(socket, 400, "shell_session_token_missing", "Missing shell session token.");
socket.destroy();
return;
}
let session;
try {
session = await validateShellSession({ token, headers: req.headers });
} catch (error) {
rejectUpgrade(socket, Number(error?.status) === 403 ? 403 : 401, error?.code || "shell_session_invalid", "Shell session could not be validated.", {
stage: "shell_session_validate",
});
return;
}
const session = await validateShellSession({ token, headers: req.headers });
wss.handleUpgrade(req, socket, head, (ws) => {
ws.sessionToken = token;
ws.sessionInfo = session;
@@ -668,20 +445,11 @@ export function createBrokerServer(options = {}) {
session,
transcript: "",
closedReason: null,
closedMessage: null,
closedCode: null,
closedDetails: {},
closedStage: null,
opened: false,
openTimer: null,
agentConnectionId: null,
};
browserShellSessions.set(String(session.id), sessionRecord);
wss.emit("connection", ws, req);
const agent = agents.get(String(session.gateway_id));
if (agent && agent.readyState === 1) {
sessionRecord.agentConnectionId = agent.connectionId || null;
sendJson(agent, {
type: "OPEN_ROOT_SHELL",
payload: {
@@ -694,34 +462,11 @@ export function createBrokerServer(options = {}) {
shellArgs: session.shell_args ?? session.metadata?.shell_args ?? [],
},
});
sessionRecord.openTimer = setTimeout(() => {
closeBrowserShellSocket(
sessionRecord,
"shell_open_timeout",
"Gateway agent did not confirm that the shell opened before the broker timeout.",
1011,
{
stage: "shell_open",
timeout_ms: shellOpenTimeoutMs,
gateway_id: session.gateway_id,
shell_session_id: session.id,
}
);
}, Math.max(250, shellOpenTimeoutMs));
sessionRecord.openTimer.unref?.();
} else {
closeBrowserShellSocket(
sessionRecord,
"agent_offline",
"Gateway agent is not connected to the broker.",
1011,
{
stage: "agent_lookup",
gateway_id: session.gateway_id,
shell_session_id: session.id,
}
);
sessionRecord.closedReason = "agent_offline";
ws.close();
}
wss.emit("connection", ws, req);
});
return;
}
@@ -753,8 +498,8 @@ export function createBrokerServer(options = {}) {
});
return;
}
} catch (error) {
rejectUpgrade(socket, 500, "websocket_upgrade_failed", "WebSocket upgrade failed.");
} catch {
socket.destroy();
return;
}
@@ -770,226 +515,183 @@ export function createBrokerServer(options = {}) {
return;
}
try {
if (ws.gatewayId) {
if (message.type === "COMMAND_RESULT") {
const pending = pendingCommands.get(message.commandId);
if (!pending) {
return;
}
clearTimeout(pending.timeout);
pendingCommands.delete(message.commandId);
pending.resolve({
ok: Boolean(message.ok),
payload: message.payload,
error: message.error,
});
if (ws.gatewayId) {
if (message.type === "COMMAND_RESULT") {
const pending = pendingCommands.get(message.commandId);
if (!pending) {
return;
}
if (message.type === "TELEMETRY") {
const payload = {
...(message.payload || {}),
broker_connection_id: ws.connectionId || null,
broker_agent_instance_id: ws.agentInstanceId || null,
};
let ingested = null;
let ingestError = null;
try {
ingested = await ingestTelemetry(String(ws.gatewayId), payload);
} catch {
ingestError = TELEMETRY_INGEST_ERROR_MESSAGE;
}
const fallbackStatistics = {
system_metrics: payload?.metadata?.system_metrics || {},
container_health: payload?.metadata?.container_health || {},
};
broadcastGatewayEvent(String(ws.gatewayId), {
type: "gateway.telemetry",
gatewayId: String(ws.gatewayId),
telemetry: payload,
gateway: ingested?.gateway || ingested || null,
error: ingestError,
});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "stats.updated",
gatewayId: String(ws.gatewayId),
statistics: ingested?.statistics || ingested || fallbackStatistics,
error: ingestError,
});
return;
}
if (message.type === "TASK_EVENT") {
const operationId = Number(message.operationId ?? message.payload?.operation_id ?? 0);
if (!Number.isFinite(operationId) || operationId <= 0) {
return;
}
const operation = await ingestTaskEvent(String(ws.gatewayId), operationId, message.payload || {});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "task.updated",
gatewayId: String(ws.gatewayId),
operationId,
operation,
});
return;
}
if (message.type === "TASK_RESULT") {
const operationId = Number(message.operationId ?? message.payload?.operation_id ?? 0);
if (!Number.isFinite(operationId) || operationId <= 0) {
return;
}
const operation = await ingestTaskResult(String(ws.gatewayId), operationId, message.payload || {});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "task.updated",
gatewayId: String(ws.gatewayId),
operationId,
operation,
});
await syncGatewayBacklog(String(ws.gatewayId), ws).catch(() => {});
return;
}
if (message.type === "LOG_FRAME") {
const logEntry = await ingestLogEntry(String(ws.gatewayId), message.payload || {});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "log.append",
gatewayId: String(ws.gatewayId),
entry: logEntry,
});
return;
}
if (message.type === "MACHINE_SIGNAL") {
await ingestMachineSignal(String(ws.gatewayId), message.payload || {});
return;
}
if (["SHELL_OUTPUT", "SHELL_OPENED", "SHELL_EXIT"].includes(message.type)) {
const sessionRecord = browserShellSessions.get(String(message.sessionId));
if (!sessionRecord) {
return;
}
if (message.type === "SHELL_OUTPUT") {
sessionRecord.transcript += String(message.data || "");
sendJson(sessionRecord.ws, { type: "output", data: String(message.data || "") });
return;
}
if (message.type === "SHELL_OPENED") {
sessionRecord.opened = true;
sessionRecord.agentConnectionId = ws.connectionId || sessionRecord.agentConnectionId || null;
clearShellOpenTimer(sessionRecord);
await markShellSessionOpened(sessionRecord.ws.sessionToken, ws.connectionId || null).catch(() => {});
sendJson(sessionRecord.ws, { type: "opened" });
return;
}
if (message.type === "SHELL_EXIT") {
const reason = String(message.reason || "agent_exit");
const parsedExitCode = Number(message.code);
const exitCode = Number.isFinite(parsedExitCode) ? parsedExitCode : 0;
const closeMessage = message.message ? String(message.message) : null;
clearShellOpenTimer(sessionRecord);
sendJson(sessionRecord.ws, {
type: "closed",
reason,
code: exitCode,
...(closeMessage ? { message: closeMessage } : {}),
});
await closeBrowserShellSession(sessionRecord, reason, {
message: closeMessage,
code: exitCode,
stage: sessionRecord.opened ? "shell_active" : "shell_start",
broker_connection_id: ws.connectionId || null,
});
browserShellSessions.delete(String(message.sessionId));
if (sessionRecord.ws.readyState < 2) {
sessionRecord.ws.close(1000, reason);
}
}
}
clearTimeout(pending.timeout);
pendingCommands.delete(message.commandId);
pending.resolve({
ok: Boolean(message.ok),
payload: message.payload,
error: message.error,
});
return;
}
if (ws.sessionInfo) {
const sessionId = String(ws.sessionInfo.id);
const agent = agents.get(String(ws.sessionInfo.gateway_id));
if (!agent || agent.readyState !== 1) {
return;
}
if (message.type === "input") {
sendJson(agent, {
type: "SHELL_INPUT",
payload: {
sessionId,
data: String(message.data || ""),
},
});
return;
}
if (message.type === "resize") {
sendJson(agent, {
type: "RESIZE_ROOT_SHELL",
payload: {
sessionId,
cols: Number(message.cols || 0),
rows: Number(message.rows || 0),
},
});
return;
}
if (message.type === "close") {
sendJson(agent, {
type: "CLOSE_ROOT_SHELL",
payload: { sessionId },
});
}
if (message.type === "TELEMETRY") {
const payload = message.payload || {};
const ingested = await ingestTelemetry(String(ws.gatewayId), payload);
broadcastGatewayEvent(String(ws.gatewayId), {
type: "gateway.telemetry",
gatewayId: String(ws.gatewayId),
telemetry: payload,
gateway: ingested?.gateway || ingested || null,
});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "stats.updated",
gatewayId: String(ws.gatewayId),
statistics: ingested?.statistics || ingested || null,
});
return;
}
if (ws.streamSessionInfo) {
const sessionRecord = browserStreamSessions.get(String(ws.streamSessionInfo.id));
if (message.type === "TASK_EVENT") {
const operationId = Number(message.operationId ?? message.payload?.operation_id ?? 0);
if (!Number.isFinite(operationId) || operationId <= 0) {
return;
}
const operation = await ingestTaskEvent(String(ws.gatewayId), operationId, message.payload || {});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "task.updated",
gatewayId: String(ws.gatewayId),
operationId,
operation,
});
return;
}
if (message.type === "TASK_RESULT") {
const operationId = Number(message.operationId ?? message.payload?.operation_id ?? 0);
if (!Number.isFinite(operationId) || operationId <= 0) {
return;
}
const operation = await ingestTaskResult(String(ws.gatewayId), operationId, message.payload || {});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "task.updated",
gatewayId: String(ws.gatewayId),
operationId,
operation,
});
await syncGatewayBacklog(String(ws.gatewayId), ws).catch(() => {});
return;
}
if (message.type === "LOG_FRAME") {
const logEntry = await ingestLogEntry(String(ws.gatewayId), message.payload || {});
broadcastGatewayEvent(String(ws.gatewayId), {
type: "log.append",
gatewayId: String(ws.gatewayId),
entry: logEntry,
});
return;
}
if (["SHELL_OUTPUT", "SHELL_OPENED", "SHELL_EXIT"].includes(message.type)) {
const sessionRecord = browserShellSessions.get(String(message.sessionId));
if (!sessionRecord) {
return;
}
if (message.type === "SUBSCRIBE") {
for (const scope of parseScopes(message.scopes || message.subscriptions || [])) {
sessionRecord.subscriptions.add(scope);
}
sendJson(sessionRecord.ws, {
type: "subscribed",
subscriptions: Array.from(sessionRecord.subscriptions.values()),
});
if (message.type === "SHELL_OUTPUT") {
sessionRecord.transcript += String(message.data || "");
sendJson(sessionRecord.ws, { type: "output", data: String(message.data || "") });
return;
}
if (message.type === "UNSUBSCRIBE") {
for (const scope of parseScopes(message.scopes || message.subscriptions || [])) {
sessionRecord.subscriptions.delete(scope);
}
sendJson(sessionRecord.ws, {
type: "unsubscribed",
subscriptions: Array.from(sessionRecord.subscriptions.values()),
});
if (message.type === "SHELL_OPENED") {
await markShellSessionOpened(sessionRecord.ws.sessionToken, ws.connectionId || null).catch(() => {});
sendJson(sessionRecord.ws, { type: "opened" });
return;
}
if (message.type === "PING") {
sendJson(sessionRecord.ws, { type: "PONG" });
if (message.type === "SHELL_EXIT") {
sendJson(sessionRecord.ws, { type: "closed", code: message.code ?? 0 });
await closeBrowserShellSession(sessionRecord, "agent_exit");
browserShellSessions.delete(String(message.sessionId));
if (sessionRecord.ws.readyState < 2) {
sessionRecord.ws.close();
}
}
}
} catch {
// Ignore stale gateway/session delivery errors without killing the broker process.
return;
}
if (ws.sessionInfo) {
const sessionId = String(ws.sessionInfo.id);
const agent = agents.get(String(ws.sessionInfo.gateway_id));
if (!agent || agent.readyState !== 1) {
return;
}
if (message.type === "input") {
sendJson(agent, {
type: "SHELL_INPUT",
payload: {
sessionId,
data: String(message.data || ""),
},
});
return;
}
if (message.type === "resize") {
sendJson(agent, {
type: "RESIZE_ROOT_SHELL",
payload: {
sessionId,
cols: Number(message.cols || 0),
rows: Number(message.rows || 0),
},
});
return;
}
if (message.type === "close") {
sendJson(agent, {
type: "CLOSE_ROOT_SHELL",
payload: { sessionId },
});
}
return;
}
if (ws.streamSessionInfo) {
const sessionRecord = browserStreamSessions.get(String(ws.streamSessionInfo.id));
if (!sessionRecord) {
return;
}
if (message.type === "SUBSCRIBE") {
for (const scope of parseScopes(message.scopes || message.subscriptions || [])) {
sessionRecord.subscriptions.add(scope);
}
sendJson(sessionRecord.ws, {
type: "subscribed",
subscriptions: Array.from(sessionRecord.subscriptions.values()),
});
return;
}
if (message.type === "UNSUBSCRIBE") {
for (const scope of parseScopes(message.scopes || message.subscriptions || [])) {
sessionRecord.subscriptions.delete(scope);
}
sendJson(sessionRecord.ws, {
type: "unsubscribed",
subscriptions: Array.from(sessionRecord.subscriptions.values()),
});
return;
}
if (message.type === "PING") {
sendJson(sessionRecord.ws, { type: "PONG" });
}
}
});
ws.on("close", async (code, buffer) => {
ws.on("close", async (_code, buffer) => {
const closeReason = buffer?.toString?.("utf8") || null;
if (ws.gatewayId) {
@@ -1025,11 +727,7 @@ export function createBrokerServer(options = {}) {
}
const sessionRecord = browserShellSessions.get(sessionId);
if (sessionRecord) {
await closeBrowserShellSession(sessionRecord, sessionRecord.closedReason || "browser_closed", {
code,
stage: sessionRecord.closedStage || "browser_socket_close",
message: sessionRecord.closedMessage || null,
});
await closeBrowserShellSession(sessionRecord, sessionRecord.closedReason || "browser_closed");
browserShellSessions.delete(sessionId);
}
return;
@@ -1087,50 +785,6 @@ export function createBrokerServer(options = {}) {
pendingCommands,
managerUrl,
authMode,
containerStartedAt,
get lastActivityAt() {
return lastActivityAt;
},
},
};
}
async function runBrokerFromCli() {
const broker = createBrokerServer();
let shuttingDown = false;
const shutdown = async (signal) => {
if (shuttingDown) {
return;
}
shuttingDown = true;
try {
await broker.close();
process.exit(0);
} catch (error) {
console.error(`Failed to shut down broker after ${signal}:`, error);
process.exit(1);
}
};
process.on("SIGINT", () => {
void shutdown("SIGINT");
});
process.on("SIGTERM", () => {
void shutdown("SIGTERM");
});
const requestedPort = Number(process.env.PORT || 4300);
const address = await broker.listen(Number.isFinite(requestedPort) ? requestedPort : 4300);
const normalizedPort =
typeof address === "object" && address !== null && "port" in address
? address.port
: requestedPort;
console.log(`TruckWash edge broker listening on ${normalizedPort}`);
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
runBrokerFromCli().catch((error) => {
console.error("TruckWash edge broker failed to start:", error);
process.exit(1);
});
}
+10 -602
View File
@@ -1,10 +1,15 @@
import test from "node:test";
import assert from "node:assert/strict";
import net from "node:net";
import WebSocket from "ws";
import { createBrokerServer } from "../server.mjs";
function waitForMessage(socket) {
return new Promise((resolve) => {
socket.once("message", (raw) => resolve(JSON.parse(raw.toString())));
});
}
function collectMessages(socket) {
const messages = [];
socket.on("message", (raw) => {
@@ -19,44 +24,6 @@ function waitForClose(socket) {
});
}
function waitForCloseOrError(socket) {
return new Promise((resolve) => {
const onDone = () => {
socket.off("error", onDone);
socket.off("close", onDone);
resolve();
};
socket.once("error", onDone);
socket.once("close", onDone);
});
}
function rawUpgradeRequest(port, path) {
return new Promise((resolve, reject) => {
const socket = net.createConnection({ host: "127.0.0.1", port }, () => {
socket.write(
[
`GET ${path} HTTP/1.1`,
`Host: 127.0.0.1:${port}`,
"Connection: Upgrade",
"Upgrade: websocket",
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==",
"Sec-WebSocket-Version: 13",
"",
"",
].join("\r\n")
);
});
let response = "";
socket.setEncoding("utf8");
socket.on("data", (chunk) => {
response += chunk;
});
socket.on("end", () => resolve(response));
socket.on("error", reject);
});
}
async function waitFor(predicate, { timeoutMs = 1000, intervalMs = 10, description = "condition" } = {}) {
const deadline = Date.now() + timeoutMs;
@@ -71,100 +38,6 @@ async function waitFor(predicate, { timeoutMs = 1000, intervalMs = 10, descripti
throw new Error(`Timed out waiting for ${description}`);
}
test("broker defaults to strict auth and fails closed when manager URL is missing", async () => {
const previousEnv = {
EDGE_AUTH_MODE: process.env.EDGE_AUTH_MODE,
EDGE_MANAGER_URL: process.env.EDGE_MANAGER_URL,
EDGE_PUBLIC_API_URL: process.env.EDGE_PUBLIC_API_URL,
};
delete process.env.EDGE_AUTH_MODE;
delete process.env.EDGE_MANAGER_URL;
delete process.env.EDGE_PUBLIC_API_URL;
let broker;
try {
broker = createBrokerServer({ sharedSecret: "secret" });
assert.equal(broker.state.authMode, "strict");
assert.equal(broker.state.managerUrl, "");
const address = await broker.listen(0);
const port = address.port;
const shellResponse = await rawUpgradeRequest(port, "/ws/browser-shell?token=session-token");
const agentResponse = await rawUpgradeRequest(port, "/ws/agent?gatewayId=701&token=agent-token");
assert.doesNotMatch(shellResponse, /101 Switching Protocols/);
assert.match(shellResponse, /^HTTP\/1\.1 401 Unauthorized/m);
assert.match(shellResponse, /"error_code":"shell_session_invalid"/);
assert.match(shellResponse, /"message":"Shell session could not be validated\."/);
assert.doesNotMatch(shellResponse, /Edge manager URL is not configured/);
assert.doesNotMatch(agentResponse, /101 Switching Protocols/);
assert.match(agentResponse, /^HTTP\/1\.1 503 Service Unavailable/m);
assert.match(agentResponse, /"error_code":"agent_validation_failed"/);
assert.match(agentResponse, /"stage":"agent_validate"/);
assert.match(agentResponse, /"message":"Gateway agent could not be validated\."/);
assert.doesNotMatch(agentResponse, /Edge manager URL is not configured/);
} finally {
if (broker) {
await broker.close();
}
for (const [key, value] of Object.entries(previousEnv)) {
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
}
});
test("broker rejects protected HTTP endpoints when shared secret is missing", async () => {
const broker = createBrokerServer({ authMode: "stub", sharedSecret: "", commandTimeoutMs: 2000 });
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
await new Promise((resolve) => agent.once("open", resolve));
const agentMessages = collectMessages(agent);
const commandResponse = await fetch(`http://127.0.0.1:${port}/api/gateways/701/commands`, {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({
commandType: "SET_RELAY_STATE",
payload: { relayId: "M-7", on: true },
}),
});
const commandJson = await commandResponse.json();
assert.equal(commandResponse.status, 503);
assert.equal(commandJson.ok, false);
assert.equal(commandJson.shared_secret_required, true);
assert.match(commandJson.error, /shared secret is not configured/);
assert.equal(agentMessages.some((message) => message.type === "COMMAND"), false);
const diagnosticsResponse = await fetch(`http://127.0.0.1:${port}/api/diagnostics/shared-secret`, {
method: "POST",
});
const diagnosticsJson = await diagnosticsResponse.json();
assert.equal(diagnosticsResponse.status, 503);
assert.equal(diagnosticsJson.shared_secret_required, true);
const syncResponse = await fetch(`http://127.0.0.1:${port}/api/gateways/701/sync`, {
method: "POST",
});
const syncJson = await syncResponse.json();
assert.equal(syncResponse.status, 503);
assert.equal(syncJson.shared_secret_required, true);
agent.terminate();
await broker.close();
});
test("broker dispatches commands to connected agents", async () => {
const broker = createBrokerServer({ authMode: "stub", sharedSecret: "secret", commandTimeoutMs: 2000 });
const address = await broker.listen(0);
@@ -205,87 +78,6 @@ test("broker dispatches commands to connected agents", async () => {
await broker.close();
});
test("broker exposes health and shared-secret diagnostics", async () => {
const broker = createBrokerServer({ authMode: "manager", sharedSecret: "secret", managerUrl: "http://manager.test" });
const address = await broker.listen(0);
const port = address.port;
const healthResponse = await fetch(`http://127.0.0.1:${port}/api/health`);
const healthJson = await healthResponse.json();
assert.equal(healthResponse.status, 200);
assert.equal(healthJson.ok, true);
assert.equal(healthJson.service, "edge-broker");
assert.equal(healthJson.auth_mode, "manager");
assert.equal(healthJson.manager_url_configured, true);
assert.equal(healthJson.shared_secret_configured, true);
assert.equal(typeof healthJson.lastActivityAt, "string");
assert.match(healthJson.lastActivityAt, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
assert.ok(healthJson.lastActivityAt >= broker.state.containerStartedAt);
assert.equal(healthJson.lastActivityAt, broker.state.lastActivityAt);
const invalidSecretResponse = await fetch(`http://127.0.0.1:${port}/api/diagnostics/shared-secret`, {
method: "POST",
headers: {
"x-edge-broker-secret": "wrong-secret",
},
});
const invalidSecretJson = await invalidSecretResponse.json();
assert.equal(invalidSecretResponse.status, 403);
assert.equal(invalidSecretJson.ok, false);
assert.equal(invalidSecretJson.shared_secret_required, true);
const validSecretResponse = await fetch(`http://127.0.0.1:${port}/api/diagnostics/shared-secret`, {
method: "POST",
headers: {
"x-edge-broker-secret": "secret",
},
});
const validSecretJson = await validSecretResponse.json();
assert.equal(validSecretResponse.status, 200);
assert.equal(validSecretJson.ok, true);
assert.equal(validSecretJson.shared_secret_required, true);
await broker.close();
});
test("broker updates lastActivityAt after each successful request", async () => {
const broker = createBrokerServer({ authMode: "manager", sharedSecret: "secret", managerUrl: "http://manager.test" });
const address = await broker.listen(0);
const port = address.port;
assert.equal(broker.state.lastActivityAt, broker.state.containerStartedAt);
const firstResponse = await fetch(`http://127.0.0.1:${port}/api/health`);
const firstJson = await firstResponse.json();
const firstActivityAt = broker.state.lastActivityAt;
assert.equal(typeof firstJson.lastActivityAt, "string");
assert.equal(firstJson.lastActivityAt, firstActivityAt);
assert.ok(firstActivityAt >= broker.state.containerStartedAt);
await new Promise((resolve) => setTimeout(resolve, 5));
await fetch(`http://127.0.0.1:${port}/api/diagnostics/shared-secret`, {
method: "POST",
headers: {
"x-edge-broker-secret": "secret",
},
});
assert.notEqual(broker.state.lastActivityAt, firstActivityAt);
assert.ok(broker.state.lastActivityAt > firstActivityAt);
const secondResponse = await fetch(`http://127.0.0.1:${port}/api/health`);
const secondJson = await secondResponse.json();
assert.equal(secondJson.lastActivityAt, broker.state.lastActivityAt);
await broker.close();
});
test("broker bridges browser shell sessions through the connected agent", async () => {
const closedSessions = [];
const broker = createBrokerServer({
@@ -317,7 +109,7 @@ test("broker bridges browser shell sessions through the connected agent", async
assert.ok(browserMessages.some((message) => message.type === "opened"));
assert.ok(browserMessages.some((message) => message.type === "output" && /root@pi/.test(message.data)));
assert.ok(browserMessages.some((message) => message.type === "closed" && message.reason === "agent_exit" && message.code === 0));
assert.ok(browserMessages.some((message) => message.type === "closed" && message.code === 0));
assert.equal(closedSessions.length, 1);
assert.equal(closedSessions[0].reason, "agent_exit");
@@ -340,10 +132,7 @@ test("broker forwards browser shell input, resize, and close events to the agent
const agentMessages = collectMessages(agent);
const browser = new WebSocket(`ws://127.0.0.1:${port}/ws/browser-shell?token=session-token`);
await new Promise((resolve) => browser.once("open", resolve));
await waitFor(
() => agentMessages.some((message) => message.type === "OPEN_ROOT_SHELL" && message.payload.sessionId === "shell-2"),
{ description: "agent shell open request" }
);
await waitForMessage(agent);
browser.send(JSON.stringify({ type: "input", data: "ls\r" }));
browser.send(JSON.stringify({ type: "resize", cols: 140, rows: 44 }));
@@ -388,124 +177,15 @@ test("broker closes browser shell sessions immediately when no agent is connecte
const port = address.port;
const browser = new WebSocket(`ws://127.0.0.1:${port}/ws/browser-shell?token=session-token`);
const browserMessages = collectMessages(browser);
await new Promise((resolve) => browser.once("open", resolve));
await waitForClose(browser);
await waitFor(() => closedSessions.length === 1, { description: "offline shell session close callback" });
assert.ok(
browserMessages.some(
(message) =>
message.type === "closed" &&
message.reason === "agent_offline" &&
/not connected to the broker/i.test(message.message)
)
);
assert.deepEqual(closedSessions, [{ transcript: "", reason: "agent_offline" }]);
await broker.close();
});
test("broker rejects browser shell upgrades without a token using HTTP diagnostics", async () => {
const broker = createBrokerServer({ authMode: "stub" });
const address = await broker.listen(0);
const port = address.port;
const response = await rawUpgradeRequest(port, "/ws/browser-shell");
assert.match(response, /^HTTP\/1\.1 400 Bad Request/m);
assert.match(response, /"error_code":"shell_session_token_missing"/);
assert.match(response, /"message":"Missing shell session token\."/);
await broker.close();
});
test("broker rejects invalid browser shell upgrades without leaking the token", async () => {
const broker = createBrokerServer({
authMode: "stub",
validateShellSession: async () => {
const error = new Error("Shell session expired");
error.status = 401;
error.code = "shell_session_expired";
throw error;
},
});
const address = await broker.listen(0);
const port = address.port;
const rawToken = "session-token-secret";
const response = await rawUpgradeRequest(port, `/ws/browser-shell?token=${rawToken}`);
assert.match(response, /^HTTP\/1\.1 401 Unauthorized/m);
assert.match(response, /"error_code":"shell_session_expired"/);
assert.match(response, /"message":"Shell session could not be validated\."/);
assert.doesNotMatch(response, /Shell session expired/);
assert.doesNotMatch(response, new RegExp(rawToken));
await broker.close();
});
test("broker rejects websocket upgrade errors without exposing exception text", async () => {
const broker = createBrokerServer({
authMode: "stub",
validateBrowserStream: async () => {
throw new Error("UPSTREAM-SENSITIVE: redis://cache.internal:6379 timeout");
},
});
const address = await broker.listen(0);
const port = address.port;
const response = await rawUpgradeRequest(port, "/ws/browser-gateway-stream?token=session-token");
assert.match(response, /^HTTP\/1\.1 500 Internal Server Error/m);
assert.match(response, /"error_code":"websocket_upgrade_failed"/);
assert.match(response, /"message":"WebSocket upgrade failed\."/);
assert.doesNotMatch(response, /UPSTREAM-SENSITIVE/);
assert.doesNotMatch(response, /redis:\/\/cache\.internal/);
await broker.close();
});
test("broker closes browser shell sessions when the agent never reports shell opened", async () => {
const closedSessions = [];
const broker = createBrokerServer({
authMode: "stub",
shellOpenTimeoutMs: 30,
validateShellSession: async () => ({ id: "shell-timeout", gateway_id: "701", reason: "diagnostic" }),
closeShellSession: async (_id, _token, transcript, reason, details) => {
closedSessions.push({ transcript, reason, details });
},
});
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
const agentMessages = collectMessages(agent);
await new Promise((resolve) => agent.once("open", resolve));
const browser = new WebSocket(`ws://127.0.0.1:${port}/ws/browser-shell?token=session-token`);
const browserMessages = collectMessages(browser);
await new Promise((resolve) => browser.once("open", resolve));
await waitFor(
() =>
agentMessages.some(
(message) => message.type === "OPEN_ROOT_SHELL" && message.payload.sessionId === "shell-timeout"
),
{ description: "agent shell open request before timeout" }
);
await waitForClose(browser);
await waitFor(() => closedSessions.length === 1, { description: "timeout shell session close callback" });
assert.ok(browserMessages.some((message) => message.type === "closed" && message.reason === "shell_open_timeout"));
assert.equal(closedSessions[0].reason, "shell_open_timeout");
assert.equal(closedSessions[0].details.stage, "shell_open");
assert.equal(closedSessions[0].details.code, 1011);
agent.terminate();
await broker.close();
});
test("broker closes browser shell sessions when the agent disconnects before shell open", async () => {
const closedSessions = [];
const broker = createBrokerServer({
@@ -523,148 +203,19 @@ test("broker closes browser shell sessions when the agent disconnects before she
const agentMessages = collectMessages(agent);
const browser = new WebSocket(`ws://127.0.0.1:${port}/ws/browser-shell?token=session-token`);
const browserMessages = collectMessages(browser);
await new Promise((resolve) => browser.once("open", resolve));
await waitFor(
() => agentMessages.some((message) => message.type === "OPEN_ROOT_SHELL" && message.payload.sessionId === "shell-4"),
{ description: "agent shell open request before disconnect" }
);
await waitForMessage(agent);
agent.terminate();
await waitForClose(browser);
await waitFor(() => closedSessions.length === 1, { description: "disconnect shell session close callback" });
assert.ok(agentMessages.some((message) => message.type === "OPEN_ROOT_SHELL" && message.payload.sessionId === "shell-4"));
assert.ok(browserMessages.some((message) => message.type === "closed" && message.reason === "agent_disconnected"));
assert.deepEqual(closedSessions, [{ transcript: "", reason: "agent_disconnected" }]);
await broker.close();
});
test("broker defaults to strict auth when no validators are configured", async () => {
const broker = createBrokerServer();
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
await waitForCloseOrError(agent);
await broker.close();
});
test("broker sends an agent welcome before connection progress and backlog dispatch", async () => {
const broker = createBrokerServer({
authMode: "stub",
reportGatewayPresence: async () => ({}),
requestGatewayBacklog: async () => ({
dispatch: [
{
type: "TASK_DISPATCH",
taskType: "OPERATION",
operation: {
id: 91,
type: "DISCOVERY",
request: {},
},
},
],
}),
});
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
const messages = collectMessages(agent);
await new Promise((resolve) => agent.once("open", resolve));
await waitFor(
() => messages.some((message) => message.type === "TASK_DISPATCH" && message.operation?.id === 91),
{ description: "backlog dispatch after connection welcome" }
);
assert.equal(messages[0].type, "WELCOME");
assert.equal(messages[0].gatewayId, "701");
assert.equal(typeof messages[0].connectionId, "string");
assert.ok(messages[0].connectionId.length > 0);
const firstProgressIndex = messages.findIndex((message) => message.type === "CONNECTION_PROGRESS");
const dispatchIndex = messages.findIndex((message) => message.type === "TASK_DISPATCH");
assert.ok(firstProgressIndex > 0);
assert.ok(dispatchIndex > firstProgressIndex);
assert.ok(
messages.some(
(message) =>
message.type === "CONNECTION_PROGRESS" &&
message.stage === "presence" &&
message.status === "started"
)
);
assert.ok(
messages.some(
(message) =>
message.type === "CONNECTION_PROGRESS" &&
message.stage === "backlog" &&
message.status === "started"
)
);
assert.ok(
messages.some(
(message) =>
message.type === "CONNECTION_PROGRESS" &&
message.stage === "backlog" &&
message.status === "succeeded" &&
message.dispatchCount === 1
)
);
agent.terminate();
await broker.close();
});
test("broker sends connection errors to agents after the welcome message", async () => {
const broker = createBrokerServer({
authMode: "stub",
reportGatewayPresence: async () => {
throw new Error("presence callback unavailable");
},
requestGatewayBacklog: async () => {
throw new Error("backlog sync unavailable");
},
});
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
const messages = collectMessages(agent);
await new Promise((resolve) => agent.once("open", resolve));
await waitFor(
() => messages.filter((message) => message.type === "CONNECTION_ERROR").length >= 2,
{ description: "agent connection error notifications" }
);
assert.equal(messages[0].type, "WELCOME");
assert.ok(
messages.some(
(message) =>
message.type === "CONNECTION_ERROR" &&
message.stage === "presence" &&
message.error === "presence callback unavailable"
)
);
assert.ok(
messages.some(
(message) =>
message.type === "CONNECTION_ERROR" &&
message.stage === "backlog" &&
message.error === "backlog sync unavailable"
)
);
agent.terminate();
await broker.close();
});
test("broker syncs queued gateway backlog on agent connect and manual sync", async () => {
const backlogRequests = [];
const broker = createBrokerServer({
@@ -723,7 +274,6 @@ test("broker syncs queued gateway backlog on agent connect and manual sync", asy
});
test("broker fans out telemetry, task, log, and presence updates to browser gateway streams", async () => {
const telemetryPayloads = [];
const broker = createBrokerServer({
authMode: "stub",
validateAgent: async () => ({ id: "701", gateway_id: "701", label: "CPH Edge 01" }),
@@ -732,10 +282,7 @@ test("broker fans out telemetry, task, log, and presence updates to browser gate
gateway_id: "701",
scopes: ["overview", "tasks", "logs", "statistics"],
}),
ingestTelemetry: async (_gatewayId, payload) => {
telemetryPayloads.push(payload);
return { gateway: { id: 701, metadata: payload.metadata || {} } };
},
ingestTelemetry: async (_gatewayId, payload) => ({ gateway: { id: 701, metadata: payload.metadata || {} } }),
ingestTaskEvent: async (_gatewayId, operationId, payload) => ({
id: operationId,
status: "IN_PROGRESS",
@@ -798,145 +345,6 @@ test("broker fans out telemetry, task, log, and presence updates to browser gate
assert.ok(browserMessages.some((message) => message.type === "stats.updated"));
assert.ok(browserMessages.some((message) => message.type === "task.updated" && message.operationId === 41));
assert.ok(browserMessages.some((message) => message.type === "log.append" && /heartbeat/.test(message.entry?.message)));
assert.equal(telemetryPayloads[0]?.broker_connection_id?.length > 0, true);
browser.terminate();
agent.terminate();
await broker.close();
});
test("broker ingests self-serve machine signals from connected agents", async () => {
const machineSignals = [];
const broker = createBrokerServer({
authMode: "stub",
validateAgent: async () => ({ id: "701", gateway_id: "701", label: "CPH Edge 01" }),
ingestMachineSignal: async (gatewayId, payload) => {
machineSignals.push({ gatewayId, payload });
return { recorded: true, lane_id: payload.lane_id };
},
});
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
await new Promise((resolve) => agent.once("open", resolve));
agent.send(
JSON.stringify({
type: "MACHINE_SIGNAL",
payload: {
lane_id: 3,
relay_id: "machine-relay",
component: "input",
channel: 0,
event: "input.toggle_on",
state: true,
},
})
);
await waitFor(() => machineSignals.length === 1, { description: "machine signal ingestion" });
assert.equal(machineSignals[0].gatewayId, "701");
assert.deepEqual(machineSignals[0].payload, {
lane_id: 3,
relay_id: "machine-relay",
component: "input",
channel: 0,
event: "input.toggle_on",
state: true,
});
agent.terminate();
await broker.close();
});
test("broker survives telemetry ingestion failures for stale gateways", async () => {
const broker = createBrokerServer({
authMode: "stub",
validateAgent: async () => ({ id: "701", gateway_id: "701", label: "CPH Edge 01" }),
ingestTelemetry: async () => {
throw new Error("Edge gateway not found");
},
});
const address = await broker.listen(0);
const port = address.port;
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
await new Promise((resolve) => agent.once("open", resolve));
agent.send(
JSON.stringify({
type: "TELEMETRY",
payload: {
status: "ONLINE",
},
})
);
await new Promise((resolve) => setTimeout(resolve, 100));
assert.equal(broker.server.listening, true);
agent.terminate();
await broker.close();
});
test("broker still fans out telemetry when manager ingestion fails", async () => {
const broker = createBrokerServer({
authMode: "stub",
validateAgent: async () => ({ id: "701", gateway_id: "701", label: "CPH Edge 01" }),
validateBrowserStream: async () => ({
id: "stream-telemetry-fallback",
gateway_id: "701",
scopes: ["overview", "statistics"],
}),
ingestTelemetry: async () => {
throw new Error("manager unavailable");
},
});
const address = await broker.listen(0);
const port = address.port;
const browser = new WebSocket(`ws://127.0.0.1:${port}/ws/browser-gateway-stream?token=stream-token`);
const browserMessages = collectMessages(browser);
await new Promise((resolve) => browser.once("open", resolve));
const agent = new WebSocket(`ws://127.0.0.1:${port}/ws/agent?gatewayId=701&token=agent-token`);
await new Promise((resolve) => agent.once("open", resolve));
agent.send(
JSON.stringify({
type: "TELEMETRY",
payload: {
status: "ONLINE",
metadata: {
system_metrics: {
cpu_usage_pct: 31,
},
container_health: {
state: "ONLINE",
summary: "6/6 containers healthy",
},
},
},
})
);
await waitFor(
() =>
browserMessages.some(
(message) => message.type === "gateway.telemetry" && message.error === "Telemetry ingestion failed"
),
{ description: "telemetry fanout after ingest failure" }
);
assert.ok(
browserMessages.every((message) => message.error !== "manager unavailable"),
"raw manager errors must not be sent to browser streams"
);
assert.ok(
browserMessages.some(
(message) => message.type === "stats.updated" && message.statistics?.system_metrics?.cpu_usage_pct === 31
)
);
browser.terminate();
agent.terminate();
+12 -43
View File
@@ -15,7 +15,6 @@ function readRequiredSource(...pathSegments) {
const baseComposeSource = readRequiredSource("docker-compose.yml");
const exampleComposeSource = readRequiredSource("docker-compose.example.yml");
const standaloneProdComposeSource = readRequiredSource("docker-compose.prod.standalone.yml");
const traefikSource = [
readRequiredSource("services", "traefik", "traefik.yml"),
readRequiredSource("services", "traefik", "traefik.prod.yml"),
@@ -24,7 +23,7 @@ const traefikSource = [
function readComposeServiceBlock(composeSource, serviceName) {
const escapedServiceName = serviceName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const servicePattern = new RegExp(
`^[ ]{2}${escapedServiceName}:\\r?\\n([\\s\\S]*?)(?=^[ ]{2}[A-Za-z0-9_-]+:|^volumes:|^networks:|(?![\\s\\S]))`,
`^\\s{2}${escapedServiceName}:\\n([\\s\\S]*?)(?=^\\s{2}[A-Za-z0-9_-]+:|^volumes:|^networks:|\\Z)`,
"m"
);
const match = composeSource.match(servicePattern);
@@ -36,50 +35,20 @@ test("traefik does not expose a dedicated public edge broker port", () => {
assert.doesNotMatch(traefikSource, /edge-broker:\s*\n\s*address:\s*":4300"/);
});
test("base docker compose routes edge broker traffic through traefik", () => {
const serviceBlock = readComposeServiceBlock(baseComposeSource, "edge-broker");
assert.doesNotMatch(serviceBlock, /\n\s+ports:\s*\n[\s\S]*?\n\s+- "4300:4300"/);
assert.match(serviceBlock, /EDGE_AUTH_MODE:\s*\$\x7bEDGE_AUTH_MODE:-strict\x7d/);
assert.match(serviceBlock, /EDGE_MANAGER_URL:\s*\$\x7bEDGE_MANAGER_URL:-http:\/\/caddy\x7d/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api\.priority=200/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-local\.priority=200/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api\.rule=Host\(`api\.truckwash\.dk`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api-io\.rule=Host\(`api\.truckwash\.io`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api-v2\.rule=Host\(`api-v2\.truckwash\.io`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-local\.rule=Host\(`localhost`\) && PathPrefix\(`\/api\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.middlewares\.edge-broker-strip\.stripPrefix\.prefixes=\/edge-broker/);
assert.match(serviceBlock, /traefik\.http\.middlewares\.edge-broker-strip-local\.stripPrefix\.prefixes=\/api\/edge-broker/);
assert.match(serviceBlock, /traefik\.http\.services\.edge-broker\.loadbalancer\.server\.port=4300/);
test("base docker compose exposes the edge broker service on port 4300", () => {
assert.match(baseComposeSource, /\bedge-broker:\b/);
assert.match(baseComposeSource, /edge-broker:\s*\n[\s\S]*?\n\s+ports:\s*\n\s+- "4300:4300"/);
});
test("example docker compose routes edge broker traffic through traefik", () => {
const serviceBlock = readComposeServiceBlock(exampleComposeSource, "edge-broker");
assert.doesNotMatch(serviceBlock, /\n\s+ports:\s*\n[\s\S]*?\n\s+- "4300:4300"/);
assert.match(serviceBlock, /EDGE_AUTH_MODE:\s*\$\x7bEDGE_AUTH_MODE:-strict\x7d/);
assert.match(serviceBlock, /EDGE_MANAGER_URL:\s*\$\x7bEDGE_MANAGER_URL:-http:\/\/caddy\x7d/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api\.rule=Host\(`api\.example\.com`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-local\.rule=Host\(`localhost`\) && PathPrefix\(`\/api\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.services\.edge-broker\.loadbalancer\.server\.port=4300/);
test("example docker compose exposes the edge broker service on port 4300", () => {
assert.match(exampleComposeSource, /\bedge-broker:\b/);
assert.match(exampleComposeSource, /edge-broker:\s*\n[\s\S]*?\n\s+ports:\s*\n\s+- "4300:4300"/);
});
test("standalone production compose routes edge broker traffic through traefik", () => {
const serviceBlock = readComposeServiceBlock(standaloneProdComposeSource, "edge-broker");
assert.doesNotMatch(serviceBlock, /\n\s+ports:\s*\n[\s\S]*?\n\s+- "4300:4300"/);
assert.match(serviceBlock, /EDGE_AUTH_MODE:\s*\$\x7bEDGE_AUTH_MODE:-manager\x7d/);
assert.match(serviceBlock, /EDGE_MANAGER_URL:\s*\$\x7bEDGE_MANAGER_URL:-http:\/\/caddy\x7d/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api\.priority=200/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-local\.priority=200/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api\.rule=Host\(`api\.truckwash\.dk`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api-io\.rule=Host\(`api\.truckwash\.io`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-api-v2\.rule=Host\(`api-v2\.truckwash\.io`\) && PathPrefix\(`\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.routers\.edge-broker-local\.rule=Host\(`localhost`\) && PathPrefix\(`\/api\/edge-broker`\)/);
assert.match(serviceBlock, /traefik\.http\.services\.edge-broker\.loadbalancer\.server\.port=4300/);
});
test("compose config does not provide insecure broker secret defaults", () => {
test("php services receive broker websocket environment defaults", () => {
for (const composeSource of [baseComposeSource, exampleComposeSource]) {
assert.match(composeSource, /EDGE_BROKER_URL:\s*\$\x7bEDGE_BROKER_URL:-http:\/\/edge-broker:4300\x7d/);
assert.match(composeSource, /EDGE_BROKER_SHARED_SECRET:\s*\$\x7bEDGE_BROKER_SHARED_SECRET:\?set EDGE_BROKER_SHARED_SECRET in \.env\x7d/);
assert.match(composeSource, /EDGE_BROKER_URL:\s*\$\{EDGE_BROKER_URL:-http:\/\/edge-broker:4300\}/);
assert.match(composeSource, /EDGE_BROKER_SHARED_SECRET:\s*\$\{EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev\}/);
}
});
@@ -87,7 +56,7 @@ test("base docker compose wires the broker into each php worker", () => {
for (const serviceName of ["php1", "php2", "php3", "php4", "php5", "php-staging", "php-cron"]) {
const serviceBlock = readComposeServiceBlock(baseComposeSource, serviceName);
assert.match(serviceBlock, /\n\s+depends_on:\s*\n[\s\S]*?\n\s+- edge-broker/);
assert.match(serviceBlock, /EDGE_BROKER_URL:\s*\$\x7bEDGE_BROKER_URL:-http:\/\/edge-broker:4300\x7d/);
assert.match(serviceBlock, /EDGE_BROKER_SHARED_SECRET:\s*\$\x7bEDGE_BROKER_SHARED_SECRET:\?set EDGE_BROKER_SHARED_SECRET in \.env\x7d/);
assert.match(serviceBlock, /EDGE_BROKER_URL:\s*\$\{EDGE_BROKER_URL:-http:\/\/edge-broker:4300\}/);
assert.match(serviceBlock, /EDGE_BROKER_SHARED_SECRET:\s*\$\{EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev\}/);
}
});
@@ -1,62 +0,0 @@
import test from "node:test";
import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
const testDirectory = path.dirname(fileURLToPath(import.meta.url));
const brokerEntryPath = path.resolve(testDirectory, "../server.mjs");
test("server entrypoint starts the broker and stays alive until terminated", async () => {
const child = spawn(process.execPath, [brokerEntryPath], {
env: {
...process.env,
PORT: "0",
EDGE_AUTH_MODE: "stub",
},
stdio: ["ignore", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
child.stdout.setEncoding("utf8");
child.stderr.setEncoding("utf8");
child.stdout.on("data", (chunk) => {
stdout += chunk;
});
child.stderr.on("data", (chunk) => {
stderr += chunk;
});
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error(`Broker entrypoint did not report readiness.\nstdout:\n${stdout}\nstderr:\n${stderr}`));
}, 10_000);
child.once("exit", (code, signal) => {
clearTimeout(timeout);
reject(new Error(`Broker entrypoint exited early with code=${code} signal=${signal}.\nstdout:\n${stdout}\nstderr:\n${stderr}`));
});
const poll = () => {
if (/TruckWash edge broker listening on \d+/.test(stdout)) {
clearTimeout(timeout);
resolve();
return;
}
setTimeout(poll, 25);
};
poll();
});
assert.equal(child.exitCode, null, `Broker exited unexpectedly.\nstdout:\n${stdout}\nstderr:\n${stderr}`);
const exitResult = await new Promise((resolve, reject) => {
child.once("exit", (code, signal) => resolve({ code, signal }));
child.kill("SIGTERM");
setTimeout(() => reject(new Error("Broker did not exit after SIGTERM.")), 10_000);
});
const exitedCleanly = exitResult.code === 0 || exitResult.signal === "SIGTERM";
assert.equal(exitedCleanly, true, `Broker exited unsuccessfully.\nstdout:\n${stdout}\nstderr:\n${stderr}`);
});
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -1,13 +0,0 @@
<?php
namespace classes;
use RuntimeException;
class account_deletion_http_exception extends RuntimeException
{
public function __construct(string $message, public readonly int $status)
{
parent::__construct($message);
}
}
@@ -1,127 +0,0 @@
<?php
namespace classes;
/**
* Explicit account-deletion schema management.
*
* apply() must only be invoked by the dedicated CLI. Web requests and cron jobs
* are deliberately limited to the read-only check().
*/
class account_deletion_schema_bootstrap
{
/** @return array{ready:bool,missing:array<int,string>} */
public static function check(): array
{
global $db;
$missing = [];
foreach (['account_deletion_requests', 'account_deletion_credential_attempts', 'account_deletion_outbox'] as $table) {
$tableSql = $db->escape_string($table);
$result = $db->query("SHOW TABLES LIKE '$tableSql'");
if ($result === false || $result->num_rows === 0) {
$missing[] = 'table:' . $table;
}
}
foreach (['users' => 'deleted_at', 'subusers' => 'deleted_at'] as $table => $column) {
$result = $db->query("SHOW COLUMNS FROM `$table` LIKE '$column'");
if ($result === false || $result->num_rows === 0) {
$missing[] = 'column:' . $table . '.' . $column;
}
}
if (!in_array('table:account_deletion_requests', $missing, true)) {
$result = $db->query("SHOW COLUMNS FROM account_deletion_requests LIKE 'manual_review_required_at'");
if ($result === false || $result->num_rows === 0) {
$missing[] = 'column:account_deletion_requests.manual_review_required_at';
}
}
return ['ready' => $missing === [], 'missing' => $missing];
}
public static function apply(): void
{
if (PHP_SAPI !== 'cli') {
throw new \RuntimeException('Account deletion schema changes are CLI-only.');
}
global $db;
self::execute("CREATE TABLE IF NOT EXISTS account_deletion_requests (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
request_id CHAR(36) NOT NULL,
principal_type VARCHAR(16) NOT NULL,
principal_id BIGINT UNSIGNED NOT NULL,
customer_number_snapshot INT NULL,
active_principal_key VARCHAR(191) NULL,
status VARCHAR(32) NOT NULL DEFAULT 'requested',
policy_version VARCHAR(32) NOT NULL,
retained_data_json LONGTEXT NOT NULL,
request_ip VARCHAR(45) NULL,
request_user_agent VARCHAR(512) NULL,
retry_count INT UNSIGNED NOT NULL DEFAULT 0,
failure_code VARCHAR(191) NULL,
requested_at DATETIME NOT NULL,
processing_at DATETIME NULL,
completed_at DATETIME NULL,
next_attempt_at DATETIME NULL,
manual_review_required_at DATETIME NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uniq_account_deletion_request_id (request_id),
UNIQUE KEY uniq_account_deletion_active_principal (active_principal_key),
INDEX idx_account_deletion_worker (status, next_attempt_at, requested_at),
INDEX idx_account_deletion_principal (principal_type, principal_id, requested_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
self::ensureColumn('account_deletion_requests', 'manual_review_required_at', 'DATETIME NULL AFTER `next_attempt_at`');
self::execute("CREATE TABLE IF NOT EXISTS account_deletion_credential_attempts (
throttle_key CHAR(64) NOT NULL,
attempt_count INT UNSIGNED NOT NULL DEFAULT 1,
window_started_at DATETIME NOT NULL,
blocked_until DATETIME NULL,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (throttle_key), INDEX idx_account_deletion_throttle_expiry (updated_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
self::execute("CREATE TABLE IF NOT EXISTS account_deletion_outbox (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
request_id CHAR(36) NOT NULL,
event_type VARCHAR(64) NOT NULL,
payload_json LONGTEXT NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'pending',
attempts INT UNSIGNED NOT NULL DEFAULT 0,
available_at DATETIME NOT NULL,
processing_at DATETIME NULL,
delivered_at DATETIME NULL,
last_error VARCHAR(191) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id), UNIQUE KEY uniq_account_deletion_outbox_event (request_id, event_type),
INDEX idx_account_deletion_outbox_delivery (status, available_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
self::ensureColumn('account_deletion_outbox', 'processing_at', 'DATETIME NULL AFTER `available_at`');
self::ensureColumn('users', 'deleted_at', 'DATETIME NULL AFTER `updated_at`');
self::ensureColumn('subusers', 'deleted_at', 'DATETIME NULL AFTER `suspended_at`');
self::ensureIndex('users', 'idx_users_deleted_at', '`deleted_at`');
self::ensureIndex('subusers', 'idx_subusers_deleted_at', '`deleted_at`');
}
private static function execute(string $sql): void
{
global $db;
if ($db->query($sql) === false) {
throw new \RuntimeException('Account deletion schema operation failed.');
}
}
private static function ensureColumn(string $table, string $column, string $definition): void
{
global $db;
$result = $db->query("SHOW COLUMNS FROM `$table` LIKE '$column'");
if ($result === false) throw new \RuntimeException('Unable to inspect account deletion schema.');
if ($result->num_rows === 0) self::execute("ALTER TABLE `$table` ADD COLUMN `$column` $definition");
}
private static function ensureIndex(string $table, string $index, string $columns): void
{
global $db;
$result = $db->query("SHOW INDEX FROM `$table` WHERE Key_name = '$index'");
if ($result === false) throw new \RuntimeException('Unable to inspect account deletion indexes.');
if ($result->num_rows === 0) self::execute("ALTER TABLE `$table` ADD INDEX `$index` ($columns)");
}
}
File diff suppressed because it is too large Load Diff
@@ -1,110 +0,0 @@
<?php
namespace classes;
use RuntimeException;
class application_write_freeze
{
public static function freeze(string $reason, string $owner, int $ttlSeconds = 300): void
{
$payload = [
'reason' => $reason,
'owner' => $owner,
'created_at' => date('c'),
'expires_at' => date('c', time() + max(30, $ttlSeconds)),
];
self::writeState($payload);
}
public static function unfreeze(?string $owner = null): void
{
$state = self::state();
if ($owner !== null && isset($state['owner']) && $state['owner'] !== $owner) {
return;
}
$path = self::statePath();
if (is_file($path)) {
@unlink($path);
}
}
public static function state(): array
{
$path = self::statePath();
if (!is_file($path)) {
return [];
}
$state = json_decode((string)file_get_contents($path), true);
if (!is_array($state)) {
@unlink($path);
return [];
}
$expiresAt = strtotime((string)($state['expires_at'] ?? ''));
if ($expiresAt !== false && $expiresAt < time()) {
@unlink($path);
return [];
}
return $state;
}
public static function isFrozen(): bool
{
return self::state() !== [];
}
public static function shouldBlock(string $method, string $uri, bool $isCronOrCli): bool
{
if (!self::isFrozen()) {
return false;
}
if ($isCronOrCli) {
return true;
}
$method = strtoupper($method);
if (in_array($method, ['GET', 'HEAD', 'OPTIONS'], true)) {
return false;
}
$path = parse_url($uri, PHP_URL_PATH) ?: '';
return !str_starts_with($path, '/superuser/replication');
}
private static function writeState(array $state): void
{
$path = self::statePath();
$dir = dirname($path);
if (!is_dir($dir) && !mkdir($dir, 0770, true) && !is_dir($dir)) {
throw new RuntimeException('Could not create write-freeze directory.');
}
$tempPath = tempnam($dir, 'write-freeze-');
if ($tempPath === false) {
throw new RuntimeException('Could not create write-freeze temp file.');
}
try {
file_put_contents($tempPath, json_encode($state, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL, LOCK_EX);
if (!rename($tempPath, $path)) {
throw new RuntimeException('Could not atomically replace write-freeze state.');
}
} finally {
if (is_file($tempPath)) {
@unlink($tempPath);
}
}
}
private static function statePath(): string
{
$root = defined('WD') ? WD : dirname(__DIR__);
return $root . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'application-write-freeze.json';
}
}
@@ -37,21 +37,8 @@ class attachment_store implements minio_uploads_i
*/
public function isValidFilePath(string $filePath): bool
{
if (
$filePath === ''
|| str_starts_with($filePath, '/')
|| preg_match('/^[a-zA-Z0-9_\-\/.]+$/', $filePath) !== 1
) {
return false;
}
foreach (explode('/', $filePath) as $segment) {
if ($segment === '' || $segment === '.' || $segment === '..') {
return false;
}
}
return true;
// Check if the file path is valid
return preg_match('/^[a-zA-Z0-9_\-\/.]+$/', $filePath) === 1;
}
/**
@@ -95,10 +82,7 @@ class attachment_store implements minio_uploads_i
{
$host = 'https://api.truckwash.io';
$this->requireValidFilePath($fileName);
$encodedPath = implode('/', array_map('rawurlencode', explode('/', $fileName)));
// Generate a direct download URL for the given file name
return $host . '/files/' . $encodedPath;
return $host . '/files/' . $fileName;
}
}
}
+1 -7
View File
@@ -133,14 +133,8 @@ class attachments implements attachments_i
protected function fetchAttachmentRows(string $type, array $object_ids, array $options = []): array
{
$options = $this->normalizeAttachmentOptions($options);
$rawType = trim($type, '`');
$objectTypes = array_values(array_unique([
$rawType,
'`' . $rawType . '`',
]));
return (new object_attachments_o())->getFieldsWhereIn([
'object_type' => $objectTypes,
'object_type' => $type,
'object_id' => $object_ids,
'deleted_at' => null
], $options);
+13 -55
View File
@@ -2,13 +2,10 @@
namespace classes;
require_once WD . '/classes/account_deletion_service.php';
use classes\totp;
use Exception;
use interfaces\authentication_i;
use objects\plate_scanners_o;
use objects\subuser_grants_o;
use objects\tokens_o;
use objects\users_o;
use objects\subusers_o;
@@ -71,10 +68,6 @@ class authentication implements authentication_i
public function create_2fa_token(int $id, string $type): string
{
$principalType = $type === '2FA_VERIFICATION_SUBUSER' ? 'subuser' : 'customer';
if (account_deletion_service::principalIsBlocked($principalType, $id)) {
throw new Exception('Account unavailable');
}
// Create a temporary 2FA token
$token = bin2hex(random_bytes(32));
(new tokens_o())->create($id, $token, $type);
@@ -106,9 +99,6 @@ class authentication implements authentication_i
throw new \Exception('User not found for customer number: ' . $customer_number);
}
$user_id = $user->id;
if (account_deletion_service::principalIsBlocked('customer', (int)$user_id)) {
throw new Exception('Account unavailable');
}
// Save the token in the database
(new tokens_o())->create($user_id, $token, 'AUTH_TOKEN');
return $token;
@@ -116,9 +106,6 @@ class authentication implements authentication_i
public function create_token_by_user_id(int $user_id): string
{
if (account_deletion_service::principalIsBlocked('customer', $user_id)) {
throw new Exception('Account unavailable');
}
// Create a token
$token = bin2hex(random_bytes(32));
// Save the token in the database
@@ -128,9 +115,6 @@ class authentication implements authentication_i
public function create_employee_token(int $employee_id): string
{
if (account_deletion_service::principalIsBlocked('customer', $employee_id)) {
throw new Exception('Account unavailable');
}
// Create a token
$token = bin2hex(random_bytes(32));
// Save the token in the database
@@ -138,34 +122,17 @@ class authentication implements authentication_i
return $token;
}
public function create_impersonation_token(int $target_user_id, int $actor_user_id): string
{
if ($actor_user_id <= 0 || account_deletion_service::principalIsBlocked('customer', $target_user_id)) {
throw new Exception('Account unavailable');
}
$token = bin2hex(random_bytes(32));
(new tokens_o())->create($target_user_id, $token, 'AUTH_TOKEN_IMPERSONATION:' . $actor_user_id);
return $token;
}
public function validate_token(string $token): bool
{
// First: try validating as a classic user auth token
try {
$dbToken = (new tokens_o())->getToken($token);
if ($dbToken && $dbToken->id && $this->isClassicAuthTokenType((string)$dbToken->type->value())) {
return !account_deletion_service::principalIsBlocked(
'customer',
(int)$dbToken->user_id->value()
);
}
} catch (Exception) {
// Ignore and continue to subuser session validation
$dbToken = (new tokens_o())->getToken($token);
if ($dbToken && $dbToken->id) {
return true;
}
// Fallback: try validating as a subuser session token
$subuser = (new subusers_o())->getSubuserBySessionToken($token);
if ($subuser !== null) {
return !account_deletion_service::principalIsBlocked('subuser', (int)$subuser->id);
return true;
}
return false;
}
@@ -187,20 +154,19 @@ class authentication implements authentication_i
// Strip the Bearer prefix
$rawToken = str_replace('Bearer ', '', $rawToken);
// Get the token from the database
try {
$token = (new tokens_o())->getToken($rawToken);
} catch (Exception) {
return false;
}
$token = (new tokens_o())->getToken($rawToken);
// Check if the token exists
if (!$token->id) {
return false;
}
if (!$this->isClassicAuthTokenType((string)$token->type->value())) {
return false;
}
if (account_deletion_service::principalIsBlocked('customer', (int)$token->user_id->value())) {
return false;
if ($token->type->value() === "AUTH_TOKEN_SUBUSER") {
// Get the customer number from the headers
if (!isset($headers['X-Customer-Number'])) {
return false;
}
$customer_number = (int)$headers['X-Customer-Number'];
// Get the user by the customer number
return (new users_o())->getUserByCustomerNumber($customer_number);
}
// Get the user from the database
$user = (new users_o())->getUserById($token->user_id->value());
@@ -208,11 +174,6 @@ class authentication implements authentication_i
return $user;
}
private function isClassicAuthTokenType(string $type): bool
{
return $type === 'AUTH_TOKEN' || str_starts_with($type, 'AUTH_TOKEN_IMPERSONATION:');
}
public function get_plate_scanner(): plate_scanners_o|false
{
// Get the token from the headers
@@ -263,9 +224,6 @@ class authentication implements authentication_i
if ($subuser === null) {
return false;
}
if (account_deletion_service::principalIsBlocked('subuser', (int)$subuser->id)) {
return false;
}
$customerNumberContext = null;
if (isset($headers['X-Customer-Number'])) {
$customerNumberContext = (int)$headers['X-Customer-Number'];
@@ -1,127 +0,0 @@
<?php
namespace classes;
class backup_schema_bootstrap
{
private static bool $initialized = false;
public static function ensureTables(): void
{
if (self::$initialized) {
return;
}
global $db;
if (!isset($db) || !is_object($db) || !method_exists($db, 'query')) {
return;
}
$db->query(
"CREATE TABLE IF NOT EXISTS backup_records (
backup_uuid VARCHAR(64) NOT NULL PRIMARY KEY,
name VARCHAR(191) NOT NULL,
description TEXT NULL,
source VARCHAR(32) NOT NULL DEFAULT 'manual',
status VARCHAR(32) NOT NULL DEFAULT 'queued',
schema_version INT UNSIGNED NOT NULL DEFAULT 2,
storage_bucket VARCHAR(191) NOT NULL DEFAULT 'backups',
storage_prefix VARCHAR(255) NOT NULL,
manifest_key VARCHAR(255) NULL,
manifest_sha256 CHAR(64) NULL,
encryption_key_id VARCHAR(191) NULL,
component_count INT UNSIGNED NOT NULL DEFAULT 0,
object_count INT UNSIGNED NOT NULL DEFAULT 0,
total_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0,
requested_by_user_id INT NULL,
started_at DATETIME NULL,
completed_at DATETIME NULL,
verified_at DATETIME NULL,
expires_at DATETIME NULL,
last_error TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_backup_records_status_created (status, created_at),
KEY idx_backup_records_verified (verified_at),
KEY idx_backup_records_expires (expires_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$db->query(
"CREATE TABLE IF NOT EXISTS backup_components (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
backup_uuid VARCHAR(64) NOT NULL,
component_type VARCHAR(32) NOT NULL,
logical_name VARCHAR(191) NOT NULL,
source_bucket VARCHAR(191) NULL,
source_prefix VARCHAR(255) NULL,
storage_key VARCHAR(255) NULL,
manifest_key VARCHAR(255) NULL,
object_count INT UNSIGNED NOT NULL DEFAULT 0,
byte_size BIGINT UNSIGNED NOT NULL DEFAULT 0,
content_sha256 CHAR(64) NULL,
encrypted_sha256 CHAR(64) NULL,
encryption_key_id VARCHAR(191) NULL,
status VARCHAR(32) NOT NULL DEFAULT 'pending',
error_message TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_backup_components_backup (backup_uuid),
KEY idx_backup_components_status (status),
KEY idx_backup_components_type_name (component_type, logical_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$db->query(
"CREATE TABLE IF NOT EXISTS backup_jobs (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
job_type VARCHAR(32) NOT NULL,
backup_uuid VARCHAR(64) NULL,
status VARCHAR(32) NOT NULL DEFAULT 'queued',
progress_percent TINYINT UNSIGNED NOT NULL DEFAULT 0,
progress_message VARCHAR(255) NULL,
payload_json LONGTEXT NULL,
result_json LONGTEXT NULL,
actor_user_id INT NULL,
locked_at DATETIME NULL,
lock_owner VARCHAR(191) NULL,
started_at DATETIME NULL,
completed_at DATETIME NULL,
error_message TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_backup_jobs_status_created (status, created_at),
KEY idx_backup_jobs_backup (backup_uuid),
KEY idx_backup_jobs_type_status (job_type, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$db->query(
"CREATE TABLE IF NOT EXISTS backup_restore_audit (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
restore_job_id BIGINT UNSIGNED NULL,
preview_job_id BIGINT UNSIGNED NULL,
backup_uuid VARCHAR(64) NOT NULL,
actor_user_id INT NULL,
target_environment VARCHAR(64) NOT NULL DEFAULT 'production',
confirmation_fingerprint CHAR(64) NULL,
reason TEXT NULL,
ip_address VARCHAR(64) NULL,
user_agent VARCHAR(255) NULL,
pre_restore_backup_uuid VARCHAR(64) NULL,
status VARCHAR(32) NOT NULL DEFAULT 'queued',
started_at DATETIME NULL,
completed_at DATETIME NULL,
error_message TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_backup_restore_audit_backup (backup_uuid),
KEY idx_backup_restore_audit_job (restore_job_id),
KEY idx_backup_restore_audit_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
self::$initialized = true;
}
}
File diff suppressed because it is too large Load Diff
+13
View File
@@ -212,7 +212,19 @@ class bird implements bird_i
throw new Exception('cURL error: ' . $err);
}
curl_close($ch);
// Debug slack
$data = json_decode($body, true) ?? [];
$resp = $resp === false ? 'cURL error with no response' : $resp;
$slack_debug_message = "*Bird API Request Debug:*"
. "\nEndpoint: $url"
. "\nMethod: $method"
. "\nStatus: $code"
. "\nPayload Keys: " . implode(',', array_keys($data))
. "\nResponse: $resp";
// Send slack notification for every request for easier debugging of issues in production (can be removed later if too noisy)
$slack = new \classes\slack();
$slack->send_message($slack_debug_message);
return [
'status_code' => (int)$code,
'body' => $resp,
@@ -1061,3 +1073,4 @@ class bird implements bird_i
}
}
@@ -9,11 +9,7 @@ use interfaces\shelly_transport_i;
class cloud_shelly_transport implements shelly_transport_i
{
public function __construct(
private readonly ?shelly $client = null,
private readonly bool $logRelaySignals = true,
private readonly ?edge_gateway_manager $manager = null
)
public function __construct(private readonly ?shelly $client = null)
{
}
@@ -34,47 +30,6 @@ class cloud_shelly_transport implements shelly_transport_i
public function sendPostRequest(string $endpoint, array $data, ?int $department_id = null): array|object|null
{
try {
$response = $this->client()->sendPostRequest($endpoint, $data);
$this->logRelaySignal($endpoint, $data, $department_id, $response, null);
return $response;
} catch (\Throwable $exception) {
$this->logRelaySignal($endpoint, $data, $department_id, null, $exception);
throw $exception;
}
}
private function logRelaySignal(
string $endpoint,
array $data,
?int $department_id,
array|object|null $response,
?\Throwable $exception
): void {
if (!$this->logRelaySignals || $department_id === null || $department_id <= 0 || !$this->isRelayEndpoint($endpoint)) {
return;
}
try {
$this->manager()->appendRelayTransportLog(
$department_id,
$endpoint,
$data,
$response,
'cloud',
$exception?->getMessage()
);
} catch (\Throwable) {
}
}
private function isRelayEndpoint(string $endpoint): bool
{
return in_array($endpoint, ['/v2/devices/api/get', '/v2/devices/api/set/switch'], true);
}
private function manager(): edge_gateway_manager
{
return $this->manager ?? new edge_gateway_manager();
return $this->client()->sendPostRequest($endpoint, $data);
}
}
-39
View File
@@ -1,39 +0,0 @@
<?php
namespace classes;
require_once WD . '/interfaces/universal_module_i.php';
require_once WD . '/modules/coolify/coolify_c.php';
use Exception;
use interfaces\universal_module_i;
use modules\coolify\coolify_c;
class coolify implements universal_module_i
{
public coolify_c $config;
public function __construct()
{
$this->config = new coolify_c();
}
/**
* @throws Exception
*/
public function requireModuleEnabled(): void
{
if (!$this->config->enabled->isTrue()) {
throw new Exception('The Coolify module is not enabled');
}
}
public function isEnabled(): bool
{
try {
return $this->config->enabled->isTrue();
} catch (Exception) {
return false;
}
}
}
@@ -1,294 +0,0 @@
<?php
namespace classes;
use RuntimeException;
class coolify_api_client
{
private string $baseUrl;
private string $token;
private int $timeoutSeconds;
public function __construct(string $baseUrl, string $token, int $timeoutSeconds = 4)
{
$this->baseUrl = self::normalizeBaseUrl($baseUrl);
$this->token = trim($token);
$this->timeoutSeconds = max(1, $timeoutSeconds);
if ($this->baseUrl === '' || $this->token === '') {
throw new RuntimeException('Coolify base URL and API token are required.');
}
}
public static function normalizeBaseUrl(string $baseUrl): string
{
$baseUrl = rtrim(trim($baseUrl), '/');
if ($baseUrl === '') {
return '';
}
if (preg_match('#/api/v[0-9]+$#i', $baseUrl) === 1) {
return $baseUrl;
}
return $baseUrl . '/api/v1';
}
public function healthcheck(): array
{
return $this->request('GET', '/health', null, false);
}
public function version(): array
{
return $this->request('GET', '/version');
}
public function listServers(): array
{
return $this->request('GET', '/servers');
}
public function listProjects(): array
{
return $this->request('GET', '/projects');
}
public function listProjectEnvironments(string $projectUuid): array
{
return $this->request('GET', '/projects/' . rawurlencode($projectUuid) . '/environments');
}
public function listServices(): array
{
return $this->request('GET', '/services');
}
public function listApplications(): array
{
return $this->request('GET', '/applications');
}
public function listGithubApps(): array
{
return $this->request('GET', '/github-apps');
}
public function getService(string $uuid): array
{
return $this->request('GET', '/services/' . rawurlencode($uuid));
}
public function createService(array $payload): array
{
return $this->request('POST', '/services', $payload);
}
public function createPrivateGithubAppApplication(array $payload): array
{
return $this->request('POST', '/applications/private-github-app', $payload);
}
public function getApplication(string $uuid): array
{
return $this->request('GET', '/applications/' . rawurlencode($uuid));
}
public function updateApplication(string $uuid, array $payload): array
{
return $this->request('PATCH', '/applications/' . rawurlencode($uuid), $payload);
}
public function updateService(string $uuid, array $payload): array
{
return $this->request('PATCH', '/services/' . rawurlencode($uuid), $payload);
}
public function updateServiceEnvsBulk(string $uuid, array $env): array
{
if ($env === []) {
return [];
}
return $this->request('PATCH', '/services/' . rawurlencode($uuid) . '/envs/bulk', [
'data' => self::bulkEnvData($env),
]);
}
public function updateApplicationEnvsBulk(string $uuid, array $env): array
{
if ($env === []) {
return [];
}
return $this->request('PATCH', '/applications/' . rawurlencode($uuid) . '/envs/bulk', [
'data' => self::bulkEnvData($env),
]);
}
public function listApplicationEnvs(string $uuid): array
{
return $this->request('GET', '/applications/' . rawurlencode($uuid) . '/envs');
}
public function deleteApplicationEnv(string $uuid, string $envUuid): array
{
return $this->request('DELETE', '/applications/' . rawurlencode($uuid) . '/envs/' . rawurlencode($envUuid));
}
private static function bulkEnvData(array $env): array
{
$data = [];
foreach ($env as $key => $value) {
$data[] = [
'key' => (string)$key,
'value' => (string)$value,
'is_preview' => false,
'is_literal' => true,
'is_multiline' => str_contains((string)$value, "\n"),
'is_shown_once' => false,
];
}
return $data;
}
public function deployResource(string $uuid, bool $force = false): array
{
$path = '/deploy?uuid=' . rawurlencode($uuid) . '&force=' . ($force ? 'true' : 'false');
return $this->request('GET', $path);
}
public function startService(string $uuid): array
{
return $this->request('GET', '/services/' . rawurlencode($uuid) . '/start');
}
public function restartService(string $uuid): array
{
return $this->request('GET', '/services/' . rawurlencode($uuid) . '/restart');
}
public function restartApplication(string $uuid): array
{
return $this->request('GET', '/applications/' . rawurlencode($uuid) . '/restart');
}
public function stopService(string $uuid): array
{
return $this->request('GET', '/services/' . rawurlencode($uuid) . '/stop');
}
public function stopApplication(string $uuid): array
{
return $this->request('GET', '/applications/' . rawurlencode($uuid) . '/stop');
}
public function deleteService(string $uuid): array
{
return $this->request('DELETE', '/services/' . rawurlencode($uuid));
}
public function deleteApplication(string $uuid): array
{
return $this->request('DELETE', '/applications/' . rawurlencode($uuid));
}
public function listDeployments(): array
{
return $this->request('GET', '/deployments');
}
protected function request(string $method, string $path, ?array $payload = null, bool $versionedApi = true): array
{
$url = ($versionedApi ? $this->baseUrl : $this->apiRootUrl()) . '/' . ltrim($path, '/');
$curl = curl_init($url);
if ($curl === false) {
throw new RuntimeException('Could not initialize Coolify API request.');
}
$headers = [
'Accept: application/json',
'Authorization: Bearer ' . $this->token,
];
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, min(2, $this->timeoutSeconds));
curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeoutSeconds);
curl_setopt($curl, CURLOPT_NOSIGNAL, true);
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
if ($payload !== null) {
$body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($body === false) {
throw new RuntimeException('Could not encode Coolify API payload.');
}
$headers[] = 'Content-Type: application/json';
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$raw = curl_exec($curl);
$error = curl_error($curl);
$status = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($raw === false) {
throw new RuntimeException('Coolify API request failed: ' . $error);
}
$decoded = null;
if (trim((string)$raw) !== '') {
$decoded = json_decode((string)$raw, true);
if (!is_array($decoded)) {
$decoded = ['raw' => (string)$raw];
}
}
if ($status < 200 || $status >= 300) {
$message = is_array($decoded)
? (string)($decoded['message'] ?? $decoded['error'] ?? ('HTTP ' . $status))
: ('HTTP ' . $status);
if (is_array($decoded)) {
$details = self::validationErrorSummary($decoded);
if ($details !== '') {
$message .= ': ' . $details;
}
}
throw new RuntimeException('Coolify API request failed: ' . $message);
}
return is_array($decoded) ? $decoded : [];
}
private static function validationErrorSummary(array $decoded): string
{
$errors = $decoded['errors'] ?? $decoded['data']['errors'] ?? null;
if (!is_array($errors)) {
return '';
}
$parts = [];
foreach ($errors as $field => $messages) {
$fieldName = trim((string)$field);
$fieldPrefix = $fieldName !== '' ? $fieldName . ': ' : '';
if (is_array($messages)) {
$messages = implode(', ', array_filter(array_map(static fn(mixed $message): string => trim((string)$message), $messages)));
} else {
$messages = trim((string)$messages);
}
if ($messages !== '') {
$parts[] = $fieldPrefix . $messages;
}
}
return implode('; ', array_slice($parts, 0, 5));
}
private function apiRootUrl(): string
{
return preg_replace('#/v[0-9]+$#i', '', $this->baseUrl) ?: $this->baseUrl;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,243 +0,0 @@
<?php
namespace classes;
/**
* Additive schema bootstrap for the Coolify infrastructure integration.
*
* The legacy stack has no centralized migration runner, so this class must be
* safe to call from request handlers, cron, and tests.
*/
class coolify_schema_bootstrap
{
private static bool $initialized = false;
private static ?bool $tablesExist = null;
public static function ensureTables(): void
{
if (self::$initialized) {
return;
}
global $db;
$queries = [
"CREATE TABLE IF NOT EXISTS coolify_instances (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
label VARCHAR(128) NOT NULL,
base_url VARCHAR(512) NOT NULL,
api_token_secret TEXT NOT NULL,
default_project_uuid VARCHAR(128) NULL,
default_environment_uuid VARCHAR(128) NULL,
default_environment_name VARCHAR(128) NULL,
default_server_uuid VARCHAR(128) NULL,
default_destination_uuid VARCHAR(128) NULL,
status VARCHAR(32) NOT NULL DEFAULT 'unknown',
last_checked_at DATETIME NULL,
last_error TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME NULL,
INDEX idx_coolify_instances_status (status),
INDEX idx_coolify_instances_deleted_at (deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS coolify_targets (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
instance_id BIGINT UNSIGNED NOT NULL,
replication_host_id BIGINT UNSIGNED NULL,
kind VARCHAR(16) NOT NULL,
label VARCHAR(128) NOT NULL,
role VARCHAR(16) NOT NULL DEFAULT 'replica',
server_uuid VARCHAR(128) NULL,
project_uuid VARCHAR(128) NULL,
environment_uuid VARCHAR(128) NULL,
environment_name VARCHAR(128) NULL,
destination_uuid VARCHAR(128) NULL,
resource_uuid VARCHAR(128) NULL,
resource_type VARCHAR(32) NOT NULL DEFAULT 'service',
resource_name VARCHAR(128) NULL,
deployment_status VARCHAR(32) NOT NULL DEFAULT 'pending',
availability_state VARCHAR(32) NOT NULL DEFAULT 'degraded',
desired_compose_hash CHAR(64) NULL,
last_reconcile_status VARCHAR(32) NULL,
last_reconcile_json LONGTEXT NULL,
last_reconciled_at DATETIME NULL,
options_json LONGTEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME NULL,
INDEX idx_coolify_targets_instance (instance_id),
INDEX idx_coolify_targets_replication_host (replication_host_id),
INDEX idx_coolify_targets_kind_status (kind, deployment_status),
INDEX idx_coolify_targets_availability (availability_state),
INDEX idx_coolify_targets_resource_uuid (resource_uuid),
INDEX idx_coolify_targets_deleted_at (deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS coolify_operations (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
target_id BIGINT UNSIGNED NULL,
instance_id BIGINT UNSIGNED NULL,
operation VARCHAR(32) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'running',
guarded TINYINT(1) NOT NULL DEFAULT 1,
message VARCHAR(512) NULL,
error_message TEXT NULL,
context_json LONGTEXT NULL,
actor_user_id INT NULL,
started_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
completed_at DATETIME NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_coolify_operations_target (target_id),
INDEX idx_coolify_operations_instance (instance_id),
INDEX idx_coolify_operations_status (status),
INDEX idx_coolify_operations_operation (operation)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS coolify_audit_logs (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
target_id BIGINT UNSIGNED NULL,
instance_id BIGINT UNSIGNED NULL,
replication_host_id BIGINT UNSIGNED NULL,
action VARCHAR(64) NOT NULL,
actor_user_id INT NULL,
severity VARCHAR(16) NOT NULL DEFAULT 'info',
context_json LONGTEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_coolify_audit_target (target_id),
INDEX idx_coolify_audit_instance (instance_id),
INDEX idx_coolify_audit_replication_host (replication_host_id),
INDEX idx_coolify_audit_action (action),
INDEX idx_coolify_audit_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
"CREATE TABLE IF NOT EXISTS coolify_instance_gateways (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
instance_id BIGINT UNSIGNED NULL,
hostname VARCHAR(255) NOT NULL,
target_ip VARCHAR(64) NOT NULL,
enabled TINYINT(1) NOT NULL DEFAULT 1,
priority INT NOT NULL DEFAULT 100,
health_state VARCHAR(32) NOT NULL DEFAULT 'unknown',
lb_state VARCHAR(32) NOT NULL DEFAULT 'unknown',
last_probe_json LONGTEXT NULL,
last_probed_at DATETIME NULL,
last_reconciled_at DATETIME NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME NULL,
UNIQUE KEY uniq_coolify_instance_gateways_target_ip (target_ip),
INDEX idx_coolify_instance_gateways_instance (instance_id),
INDEX idx_coolify_instance_gateways_enabled (enabled),
INDEX idx_coolify_instance_gateways_lb_state (lb_state),
INDEX idx_coolify_instance_gateways_deleted_at (deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
];
foreach ($queries as $sql) {
$db->query($sql);
}
self::ensureColumn('coolify_instances', 'default_destination_uuid', 'VARCHAR(128) NULL');
self::ensureColumn('coolify_targets', 'availability_state', "VARCHAR(32) NOT NULL DEFAULT 'degraded'");
self::ensureColumn('coolify_targets', 'desired_compose_hash', 'CHAR(64) NULL');
self::ensureColumn('coolify_targets', 'last_reconcile_json', 'LONGTEXT NULL');
self::ensureColumn('coolify_operations', 'guarded', 'TINYINT(1) NOT NULL DEFAULT 1');
self::ensureColumn('coolify_instance_gateways', 'last_reconciled_at', 'DATETIME NULL');
self::ensureModuleConfigDefault('Coolify', 'enabled', 'false', 'bool');
self::ensureModuleConfigDefault('Coolify', 'lb_automation_enabled', 'false', 'bool');
self::ensureModuleConfigDefault('Coolify', 'lb_automation_mode', 'report_only', 'string');
self::ensureModuleConfigDefault('Coolify', 'hetzner_load_balancer_id', '', 'string');
self::ensureModuleConfigDefault('Coolify', 'hetzner_cloud_api_token', '', 'string');
self::ensureModuleConfigDefault('Coolify', 'public_gateway_host', 'api-v2.truckwash.io', 'string');
self::ensureModuleConfigDefault('Coolify', 'public_gateway_probe_path', '', 'string');
self::ensureModuleConfigDefault('Coolify', 'github_runner_token', '', 'string');
self::ensureModuleConfigDefault('Coolify', 'github_runner_service_uuid', '', 'string');
self::ensureModuleConfigDefault('Coolify', 'github_runner_frontend_repository', 'copenhagentruckwash/pleno-vue', 'string');
self::ensureModuleConfigDefault('Coolify', 'github_runner_backend_repository', 'copenhagentruckwash/api', 'string');
self::ensureModuleConfigDefault('Coolify', 'github_runner_labels', 'self-hosted,Linux,X64,default', 'string');
self::ensureModuleConfigDefault('Coolify', 'github_runner_count_per_repo', '1', 'int');
self::ensureDefaultGateway('node1.truckwash.io', '94.130.142.41', 10);
self::ensureDefaultGateway('node2.truckwash.io', '65.21.214.30', 20);
self::ensureDefaultGateway('node3.truckwash.io', '23.88.23.183', 30);
self::$initialized = true;
self::$tablesExist = true;
}
public static function tablesExist(): bool
{
if (self::$tablesExist !== null) {
return self::$tablesExist;
}
global $db;
foreach (['coolify_instances', 'coolify_targets', 'coolify_operations', 'coolify_audit_logs', 'coolify_instance_gateways'] as $table) {
$tableSql = $db->escape_string($table);
$result = $db->query("SHOW TABLES LIKE '$tableSql'");
if ($result === false || $result->num_rows === 0) {
self::$tablesExist = false;
return false;
}
}
self::$tablesExist = true;
return self::$tablesExist;
}
private static function ensureColumn(string $table, string $column, string $definition): void
{
global $db;
$table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
$column = preg_replace('/[^a-zA-Z0-9_]/', '', $column);
if ($table === '' || $column === '') {
return;
}
$result = $db->query("SHOW COLUMNS FROM `$table` LIKE '$column'");
if ($result !== false && $result->num_rows > 0) {
return;
}
$db->query("ALTER TABLE `$table` ADD COLUMN `$column` $definition");
}
private static function ensureModuleConfigDefault(string $module, string $variable, string $value, string $type): void
{
global $db;
$moduleSql = $db->escape_string($module);
$variableSql = $db->escape_string($variable);
$result = $db->query("SELECT value FROM module_config WHERE module = '$moduleSql' AND variable = '$variableSql' LIMIT 1");
if ($result !== false && $result->num_rows > 0) {
return;
}
$valueSql = $db->escape_string($value);
$typeSql = $db->escape_string($type);
$db->query("INSERT INTO module_config (module, variable, value, type) VALUES ('$moduleSql', '$variableSql', '$valueSql', '$typeSql')");
}
private static function ensureDefaultGateway(string $hostname, string $targetIp, int $priority): void
{
global $db;
$targetIpSql = $db->escape_string($targetIp);
$result = $db->query("SELECT id FROM coolify_instance_gateways WHERE target_ip = '$targetIpSql' LIMIT 1");
if ($result !== false && $result->num_rows > 0) {
return;
}
$hostnameSql = $db->escape_string($hostname);
$db->query(
"INSERT INTO coolify_instance_gateways (hostname, target_ip, enabled, priority)
VALUES ('$hostnameSql', '$targetIpSql', 1, " . (int)$priority . ")"
);
}
}
-249
View File
@@ -1,249 +0,0 @@
<?php
namespace classes;
class cors_policy
{
public const ALLOWED_HEADERS = 'Content-Type, Authorization, X-Customer-Number, X-Release-Trace, X-Release-Channel, X-Frontend-Version, Cache-Control, Pragma, *';
public const ALLOWED_METHODS = 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
public const EXPOSED_HEADERS = 'Server-Timing';
public const MAX_AGE_SECONDS = '86400';
private const REQUIRED_ALLOWED_ORIGINS = [
'https://truckwash.io',
'https://www.truckwash.io',
'https://api.truckwash.io',
'https://api.truckwash.io:4433',
'https://api-v2.truckwash.io',
'https://web.truckwash.dk',
'https://api.truckwash.dk',
'https://truckwash.dk',
'https://www.truckwash.dk',
'https://staging.truckwash.io',
'http://localhost',
'https://localhost',
'http://localhost:4433',
'https://localhost:4433',
'https://twdev.jeppeb.dk',
'http://localhost:5173',
'http://localhost:5174',
'http://127.0.0.1:5173',
'http://127.0.0.1:5174',
'capacitor://localhost',
];
public static function normalizeOrigin(?string $value): string
{
$value = trim((string)$value);
if ($value === '' || $value === '*') {
return $value;
}
if (preg_match('#^[a-z][a-z0-9+.-]*://#i', $value) !== 1) {
return '';
}
$parts = parse_url($value);
if (!is_array($parts) || empty($parts['scheme']) || empty($parts['host'])) {
return '';
}
$scheme = strtolower((string)$parts['scheme']);
if (!in_array($scheme, ['http', 'https', 'capacitor'], true)) {
return '';
}
$host = strtolower((string)$parts['host']);
$port = isset($parts['port']) ? ':' . (int)$parts['port'] : '';
return $scheme . '://' . $host . $port;
}
public static function normalizeRequestOrigin(?string $value): string
{
$value = trim((string)$value);
if ($value === '' || $value === '*') {
return '';
}
$parts = parse_url($value);
if (!is_array($parts)) {
return '';
}
foreach (['user', 'pass', 'path', 'query', 'fragment'] as $disallowedPart) {
if (array_key_exists($disallowedPart, $parts)) {
return '';
}
}
return self::normalizeOrigin($value);
}
/**
* @return array<int,string>
*/
public static function requiredAllowedOrigins(): array
{
return self::REQUIRED_ALLOWED_ORIGINS;
}
/**
* @return array<int,string>
*/
public static function traefikHeadersMiddlewareLabels(string $middlewareName, string $corsConfig = ''): array
{
$middlewareName = trim($middlewareName);
if ($middlewareName === '' || preg_match('/^[a-zA-Z0-9-]+$/', $middlewareName) !== 1) {
return [];
}
$allowedHeaders = array_values(array_filter(
array_map('trim', explode(',', self::ALLOWED_HEADERS)),
static fn(string $header): bool => $header !== '' && $header !== '*'
));
$allowedMethods = array_values(array_filter(array_map('trim', explode(',', self::ALLOWED_METHODS))));
$exposedHeaders = array_values(array_filter(array_map('trim', explode(',', self::EXPOSED_HEADERS))));
$prefix = "traefik.http.middlewares.{$middlewareName}.headers";
$allowedOrigins = self::allowedOrigins($corsConfig);
$originLabel = $allowedOrigins === ['*']
? "{$prefix}.accesscontrolalloworiginlistregex=^(https?://[^/]+|capacitor://[^/]+)$"
: "{$prefix}.accesscontrolalloworiginlist=" . implode(',', $allowedOrigins);
return [
"{$prefix}.accesscontrolallowcredentials=true",
"{$prefix}.accesscontrolallowheaders=" . implode(',', $allowedHeaders),
"{$prefix}.accesscontrolallowmethods=" . implode(',', $allowedMethods),
$originLabel,
"{$prefix}.accesscontrolexposeheaders=" . implode(',', $exposedHeaders),
"{$prefix}.accesscontrolmaxage=" . self::MAX_AGE_SECONDS,
"{$prefix}.addvaryheader=true",
];
}
/**
* @return array<int,string>
*/
public static function allowedOrigins(string $corsConfig): array
{
$origins = [];
foreach (self::splitOrigins($corsConfig) as $configuredOrigin) {
if ($configuredOrigin === '*') {
return ['*'];
}
$origin = self::normalizeOrigin($configuredOrigin);
if ($origin !== '') {
$origins[$origin] = true;
}
}
foreach (self::REQUIRED_ALLOWED_ORIGINS as $requiredOrigin) {
$origin = self::normalizeOrigin($requiredOrigin);
if ($origin !== '') {
$origins[$origin] = true;
}
}
return array_keys($origins);
}
public static function withRequiredOrigins(string $corsConfig): string
{
$allowedOrigins = self::allowedOrigins($corsConfig);
if ($allowedOrigins === ['*']) {
return '*';
}
return implode(',', $allowedOrigins);
}
public static function isOriginAllowed(?string $origin, string $corsConfig): bool
{
$origin = self::normalizeRequestOrigin($origin);
if ($origin === '') {
return false;
}
$allowedOrigins = self::allowedOrigins($corsConfig);
return in_array('*', $allowedOrigins, true) || in_array($origin, $allowedOrigins, true);
}
/**
* @return array<string,string>
*/
public static function responseHeaders(?string $origin, string $corsConfig): array
{
$origin = self::normalizeRequestOrigin($origin);
if ($origin === '' || !self::isOriginAllowed($origin, $corsConfig)) {
return [];
}
return [
'Access-Control-Allow-Origin' => $origin,
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Headers' => self::ALLOWED_HEADERS,
'Access-Control-Allow-Methods' => self::ALLOWED_METHODS,
'Access-Control-Expose-Headers' => self::EXPOSED_HEADERS,
'Access-Control-Max-Age' => self::MAX_AGE_SECONDS,
'Timing-Allow-Origin' => $origin,
'Vary' => 'Origin',
];
}
/**
* @return array{allowed:bool,status:int,headers:array<string,string>,body:string}
*/
public static function preflightResponse(?string $origin, string $corsConfig): array
{
$headers = self::responseHeaders($origin, $corsConfig);
if ($headers === []) {
return [
'allowed' => false,
'status' => 403,
'headers' => ['Content-Type' => 'application/json'],
'body' => json_encode(['success' => false, 'message' => 'CORS origin not allowed']) ?: '',
];
}
$headers['Content-Type'] = 'application/json';
return [
'allowed' => true,
'status' => 200,
'headers' => $headers,
'body' => '',
];
}
public static function applyResponseHeaders(string $corsConfig, ?string $origin = null): bool
{
$headers = self::responseHeaders($origin ?? ($_SERVER['HTTP_ORIGIN'] ?? ''), $corsConfig);
if ($headers === []) {
return false;
}
self::emitHeaders($headers);
return true;
}
/**
* @param array<string,string> $headers
*/
public static function emitHeaders(array $headers): void
{
foreach ($headers as $name => $value) {
header($name . ': ' . $value, strtolower((string)$name) !== 'vary');
}
}
/**
* @return array<int,string>
*/
private static function splitOrigins(string $corsConfig): array
{
return array_values(array_filter(
array_map('trim', explode(',', $corsConfig)),
static fn(string $origin): bool => $origin !== ''
));
}
}
@@ -1,58 +0,0 @@
<?php
namespace classes;
use InvalidArgumentException;
class cron_schedule
{
public static function normalize(array $schedule): array
{
$type = strtolower(trim((string)($schedule['type'] ?? 'interval')));
if ($type !== 'interval') {
throw new InvalidArgumentException('Unsupported cron schedule type: ' . $type);
}
$seconds = (int)($schedule['seconds'] ?? $schedule['interval'] ?? 0);
if ($seconds < 30 || $seconds > 2678400) {
throw new InvalidArgumentException('Cron interval must be between 30 seconds and 31 days.');
}
return [
'type' => 'interval',
'seconds' => $seconds,
];
}
public static function nextRunAt(array $schedule, ?string $anchorDateTime, int $now): string
{
$normalized = self::normalize($schedule);
$anchor = $anchorDateTime !== null && trim($anchorDateTime) !== ''
? strtotime($anchorDateTime)
: false;
$base = $anchor !== false ? (int)$anchor : $now;
$next = $base + (int)$normalized['seconds'];
if ($next <= $now) {
$missed = (int)floor(($now - $next) / (int)$normalized['seconds']) + 1;
$next += $missed * (int)$normalized['seconds'];
}
return date('Y-m-d H:i:s', $next);
}
public static function dueAt(array $schedule, ?string $lastRunAt, int $now, ?int $legacyLastRun = null): string
{
$normalized = self::normalize($schedule);
if ($lastRunAt !== null && trim($lastRunAt) !== '') {
return self::nextRunAt($normalized, $lastRunAt, $now);
}
if ($legacyLastRun !== null && $legacyLastRun > 0) {
return date('Y-m-d H:i:s', $legacyLastRun + (int)$normalized['seconds']);
}
return date('Y-m-d H:i:s', $now);
}
}
@@ -1,702 +0,0 @@
<?php
namespace classes;
use RuntimeException;
use Throwable;
class cron_scheduler
{
private cron_task_registry $registry;
private string $lock_owner;
public function __construct(?cron_task_registry $registry = null)
{
$this->registry = $registry ?? new cron_task_registry();
$this->lock_owner = gethostname() . ':' . getmypid() . ':' . bin2hex(random_bytes(4));
}
public function listTasks(): array
{
$this->ensureReady();
$this->syncDefinitions();
$states = $this->stateRows();
$estimates = $this->durationEstimates();
$tasks = [];
$now = time();
foreach ($this->registry->definitions() as $definition) {
$state = $states[$definition->id] ?? [];
$schedule = is_array($state['schedule'] ?? null) && $state['schedule'] !== []
? $state['schedule']
: $definition->schedule;
$nextRunAt = $state['next_run_at'] ?? null;
if ($nextRunAt === null || trim((string)$nextRunAt) === '') {
$nextRunAt = cron_schedule::dueAt($schedule, $state['last_run_at'] ?? null, $now);
}
$task = $definition->asArray($state + ['next_run_at' => $nextRunAt], $estimates[$definition->id] ?? null);
$task['due'] = strtotime($nextRunAt) !== false && strtotime($nextRunAt) <= $now;
$task['seconds_until_due'] = max(0, (int)strtotime($nextRunAt) - $now);
$tasks[] = $task;
}
return [
'tasks' => $tasks,
'summary' => [
'total' => count($tasks),
'enabled' => count(array_filter($tasks, static fn(array $task): bool => (bool)$task['enabled'])),
'due' => count(array_filter($tasks, static fn(array $task): bool => (bool)$task['due'] && (bool)$task['enabled'])),
],
];
}
public function listRuns(?string $task_id = null, int $limit = 50): array
{
$this->ensureReady();
$limit = max(1, min(200, $limit));
$where = '';
if ($task_id !== null && trim($task_id) !== '') {
$where = "WHERE task_id = " . $this->sql($task_id);
}
return $this->fetchAll(
"SELECT * FROM cron_task_runs $where ORDER BY id DESC LIMIT $limit"
);
}
public function queueTaskRun(string $task_id_or_legacy_name, ?int $actor_user_id = null, bool $force = false): array
{
$this->ensureReady();
$this->syncDefinitions();
$definition = $this->registry->get($task_id_or_legacy_name);
if ($definition === null) {
throw new RuntimeException('Cron task not found.');
}
$state = $this->stateRows()[$definition->id] ?? [];
$enabled = (bool)($state['enabled'] ?? $definition->enabled);
if (!$enabled && !$force) {
throw new RuntimeException('Cron task is disabled.');
}
if ($this->taskIsLocked($state)) {
throw new RuntimeException('Cron task is already running.');
}
$existing = $this->fetchOne(
"SELECT * FROM cron_task_runs
WHERE task_id = " . $this->sql($definition->id) . " AND status = 'queued'
ORDER BY id DESC LIMIT 1"
);
if ($existing !== null) {
$this->markTaskQueued($definition);
return $this->publicRun($existing);
}
$scheduled_for = date('Y-m-d H:i:s');
$this->query(
"INSERT INTO cron_task_runs
(task_id, module, source, status, actor_user_id, scheduled_for, force_run)
VALUES ("
. $this->sql($definition->id) . ', '
. $this->sql($definition->module) . ", 'manual', 'queued', "
. ($actor_user_id === null ? 'NULL' : (string)(int)$actor_user_id) . ', '
. $this->sql($scheduled_for) . ', '
. ($force ? '1' : '0')
. ")"
);
$run_id = (int)$this->insertId();
$this->markTaskQueued($definition);
return $this->publicRun($this->fetchOne("SELECT * FROM cron_task_runs WHERE id = $run_id") ?? []);
}
public function runDue(string $source = 'automatic'): array
{
$this->ensureReady();
$this->syncDefinitions();
$ran = [];
foreach ($this->queuedRuns() as $queuedRun) {
try {
$run = $this->runQueuedRun($queuedRun);
if ($run !== null) {
$ran[] = $run;
}
} catch (Throwable $throwable) {
$ran[] = [
'task_id' => (string)($queuedRun['task_id'] ?? ''),
'module' => (string)($queuedRun['module'] ?? ''),
'source' => (string)($queuedRun['source'] ?? 'manual'),
'status' => 'skipped',
'error_message' => $throwable->getMessage(),
];
}
}
$now = time();
$states = $this->stateRows();
foreach ($this->registry->definitions() as $definition) {
$state = $states[$definition->id] ?? [];
if (!(bool)($state['enabled'] ?? $definition->enabled)) {
continue;
}
$nextRunAt = (string)($state['next_run_at'] ?? '');
if ($nextRunAt === '' || strtotime($nextRunAt) === false || strtotime($nextRunAt) > $now) {
continue;
}
try {
$ran[] = $this->runTask($definition->id, $source, null, false, $nextRunAt);
} catch (Throwable $throwable) {
$ran[] = [
'task_id' => $definition->id,
'module' => $definition->module,
'source' => $source,
'status' => 'skipped',
'error_message' => $throwable->getMessage(),
];
}
}
return [
'ran' => $ran,
'count' => count($ran),
];
}
public function markExpiredRunningRuns(): int
{
$this->ensureReady();
$now = date('Y-m-d H:i:s');
$message = 'Task lock expired before completion.';
$this->query(
"UPDATE cron_task_runs r
INNER JOIN cron_task_state s ON s.task_id = r.task_id AND s.current_run_id = r.id
SET r.status = 'timed_out',
r.completed_at = COALESCE(s.locked_until, " . $this->sql($now) . "),
r.error_message = COALESCE(r.error_message, " . $this->sql($message) . "),
s.current_run_id = NULL,
s.locked_until = NULL,
s.lock_owner = NULL,
s.last_status = 'timed_out',
s.last_error = " . $this->sql($message) . "
WHERE r.status = 'running'
AND s.locked_until IS NOT NULL
AND s.locked_until < " . $this->sql($now)
);
return $this->affectedRows();
}
public function runTask(
string $task_id_or_legacy_name,
string $source = 'manual',
?int $actor_user_id = null,
bool $force = false,
?string $scheduled_for = null
): array {
$this->ensureReady();
$this->syncDefinitions();
$definition = $this->registry->get($task_id_or_legacy_name);
if ($definition === null) {
throw new RuntimeException('Cron task not found.');
}
$state = $this->stateRows()[$definition->id] ?? [];
$enabled = (bool)($state['enabled'] ?? $definition->enabled);
if (!$enabled && !$force) {
throw new RuntimeException('Cron task is disabled.');
}
if (!$this->claimLock($definition)) {
throw new RuntimeException('Cron task is already running.');
}
$started = microtime(true);
$started_at = date('Y-m-d H:i:s', (int)$started);
$run_id = $this->createRun($definition, $source, $actor_user_id, $scheduled_for, $started_at, $force);
$this->query(
"UPDATE cron_task_state SET current_run_id = $run_id WHERE task_id = " . $this->sql($definition->id)
);
return $this->executeClaimedRun($definition, $run_id, $started, $scheduled_for);
}
private function executeClaimedRun(
cron_task_definition $definition,
int $run_id,
float $started,
?string $scheduled_for = null
): array
{
$status = 'succeeded';
$summary = [];
$error_message = null;
$output = '';
try {
if (function_exists('set_time_limit')) {
@set_time_limit($definition->timeout_seconds + 30);
}
$this->ensureLegacyFunctionsLoaded($definition);
if (!is_callable($definition->handler)) {
throw new RuntimeException('Cron task handler is not callable: ' . $definition->handler);
}
ob_start();
$result = call_user_func($definition->handler);
$output = (string)ob_get_clean();
$summary = is_array($result) ? $result : [];
} catch (Throwable $throwable) {
if (ob_get_level() > 0) {
$output .= (string)ob_get_clean();
}
$status = 'failed';
$error_message = $throwable->getMessage();
}
$completed = microtime(true);
$duration_ms = (int)round(($completed - $started) * 1000);
if ($duration_ms > ($definition->timeout_seconds * 1000) && $status === 'succeeded') {
$status = 'timed_out';
$error_message = 'Task exceeded its configured timeout window.';
}
if ($output !== '') {
$summary['output'] = substr($output, 0, 8000);
}
$completed_at = date('Y-m-d H:i:s', (int)$completed);
$this->completeRun($run_id, $status, $completed_at, $duration_ms, $summary, $error_message);
$this->releaseLock($definition, $status, $error_message, $completed_at, $scheduled_for);
return $this->publicRun($this->fetchOne("SELECT * FROM cron_task_runs WHERE id = $run_id") ?? []);
}
public function updateTaskConfig(string $task_id, array $config): array
{
$this->ensureReady();
$this->syncDefinitions();
$definition = $this->registry->get($task_id);
if ($definition === null) {
throw new RuntimeException('Cron task not found.');
}
$updates = [];
if (array_key_exists('enabled', $config)) {
$updates[] = 'enabled = ' . ((bool)$config['enabled'] ? '1' : '0');
}
if (array_key_exists('schedule', $config)) {
$schedule = $config['schedule'] === null ? null : cron_schedule::normalize((array)$config['schedule']);
$updates[] = 'schedule_json = ' . ($schedule === null ? 'NULL' : $this->sql(json_encode($schedule)));
$anchor = (string)($this->fetchOne("SELECT last_run_at FROM cron_task_state WHERE task_id = " . $this->sql($definition->id))['last_run_at'] ?? '');
$updates[] = 'next_run_at = ' . $this->sql(cron_schedule::dueAt($schedule ?? $definition->schedule, $anchor !== '' ? $anchor : null, time()));
}
if ($updates !== []) {
$this->query(
"UPDATE cron_task_state SET " . implode(', ', $updates) . " WHERE task_id = " . $this->sql($definition->id)
);
}
return $this->listTasks();
}
private function ensureReady(): void
{
cron_schema_bootstrap::ensureTables();
}
private function syncDefinitions(): void
{
$now = time();
foreach ($this->registry->definitions() as $definition) {
$row = $this->fetchOne(
"SELECT * FROM cron_task_state WHERE task_id = " . $this->sql($definition->id)
);
if ($row !== null) {
continue;
}
$legacyLastRun = $this->legacyLastRun($definition);
$nextRunAt = cron_schedule::dueAt($definition->schedule, null, $now, $legacyLastRun);
$this->query(
"INSERT INTO cron_task_state (task_id, module, enabled, schedule_json, next_run_at)
VALUES ("
. $this->sql($definition->id) . ', '
. $this->sql($definition->module) . ', '
. ($definition->enabled ? '1' : '0') . ', NULL, '
. $this->sql($nextRunAt)
. ")"
);
}
}
private function legacyLastRun(cron_task_definition $definition): ?int
{
if ($definition->legacy_name === null || !defined('redis')) {
return null;
}
try {
$last_run = redis->get_last_crond_run($definition->legacy_name);
return $last_run !== null ? (int)$last_run : null;
} catch (Throwable) {
return null;
}
}
private function claimLock(cron_task_definition $definition): bool
{
$now = date('Y-m-d H:i:s');
$locked_until = date('Y-m-d H:i:s', time() + $definition->timeout_seconds + 60);
$this->query(
"UPDATE cron_task_state
SET locked_until = " . $this->sql($locked_until) . ",
lock_owner = " . $this->sql($this->lock_owner) . "
WHERE task_id = " . $this->sql($definition->id) . "
AND (locked_until IS NULL OR locked_until < " . $this->sql($now) . ")"
);
return $this->affectedRows() === 1;
}
private function taskIsLocked(array $state): bool
{
$lockedUntil = (string)($state['locked_until'] ?? '');
return $lockedUntil !== ''
&& strtotime($lockedUntil) !== false
&& strtotime($lockedUntil) >= time();
}
private function markTaskQueued(cron_task_definition $definition): void
{
$now = date('Y-m-d H:i:s');
$this->query(
"UPDATE cron_task_state
SET last_status = 'queued',
last_error = NULL,
next_run_at = CASE
WHEN next_run_at IS NULL OR next_run_at > " . $this->sql($now) . " THEN " . $this->sql($now) . "
ELSE next_run_at
END
WHERE task_id = " . $this->sql($definition->id)
);
}
/**
* @return array<int, array<string, mixed>>
*/
private function queuedRuns(): array
{
return $this->fetchAll("SELECT * FROM cron_task_runs WHERE status = 'queued' ORDER BY id ASC LIMIT 50");
}
private function runQueuedRun(array $queuedRun): ?array
{
$run_id = (int)($queuedRun['id'] ?? 0);
$definition = $this->registry->get((string)($queuedRun['task_id'] ?? ''));
if ($run_id < 1 || $definition === null) {
if ($run_id > 0) {
$this->skipQueuedRun($run_id, 'Cron task not found.');
return $this->publicRun($this->fetchOne("SELECT * FROM cron_task_runs WHERE id = $run_id") ?? []);
}
return null;
}
$force = (bool)($queuedRun['force_run'] ?? false);
$state = $this->stateRows()[$definition->id] ?? [];
$enabled = (bool)($state['enabled'] ?? $definition->enabled);
if (!$enabled && !$force) {
$this->skipQueuedRun($run_id, 'Cron task is disabled.', $definition);
return $this->publicRun($this->fetchOne("SELECT * FROM cron_task_runs WHERE id = $run_id") ?? []);
}
if (!$this->claimLock($definition)) {
return null;
}
$started = microtime(true);
$started_at = date('Y-m-d H:i:s', (int)$started);
$this->query(
"UPDATE cron_task_runs
SET status = 'running',
started_at = " . $this->sql($started_at) . ",
lock_owner = " . $this->sql($this->lock_owner) . "
WHERE id = $run_id AND status = 'queued'"
);
if ($this->affectedRows() !== 1) {
$this->clearClaimedLock($definition);
return null;
}
$this->query(
"UPDATE cron_task_state SET current_run_id = $run_id WHERE task_id = " . $this->sql($definition->id)
);
return $this->executeClaimedRun(
$definition,
$run_id,
$started,
isset($queuedRun['scheduled_for']) ? (string)$queuedRun['scheduled_for'] : null
);
}
private function skipQueuedRun(int $run_id, string $message, ?cron_task_definition $definition = null): void
{
$completed_at = date('Y-m-d H:i:s');
$this->query(
"UPDATE cron_task_runs
SET status = 'skipped',
completed_at = " . $this->sql($completed_at) . ",
duration_ms = 0,
error_message = " . $this->sql($message) . "
WHERE id = $run_id AND status = 'queued'"
);
$updated = $this->affectedRows() === 1;
if (!$updated || $definition === null) {
return;
}
$this->query(
"UPDATE cron_task_state
SET last_status = 'skipped',
last_error = " . $this->sql($message) . "
WHERE task_id = " . $this->sql($definition->id)
);
}
private function clearClaimedLock(cron_task_definition $definition): void
{
$this->query(
"UPDATE cron_task_state
SET locked_until = NULL,
lock_owner = NULL
WHERE task_id = " . $this->sql($definition->id) . "
AND lock_owner = " . $this->sql($this->lock_owner)
);
}
private function releaseLock(
cron_task_definition $definition,
string $status,
?string $error_message,
string $completed_at,
?string $scheduled_for = null
): void
{
$state = $this->fetchOne("SELECT schedule_json FROM cron_task_state WHERE task_id = " . $this->sql($definition->id));
$schedule = $this->decodeJson($state['schedule_json'] ?? null);
if ($schedule === []) {
$schedule = $definition->schedule;
}
// Automatic runs stay anchored to their intended schedule slot. Anchoring
// to completion time causes every task to drift by its execution time.
$scheduleAnchor = $scheduled_for !== null && strtotime($scheduled_for) !== false
? $scheduled_for
: $completed_at;
$nextRunAt = cron_schedule::nextRunAt($schedule, $scheduleAnchor, time());
if ($status !== 'succeeded') {
$retrySeconds = min(300, max(60, (int)$schedule['seconds']));
$nextRunAt = date('Y-m-d H:i:s', time() + $retrySeconds);
}
$this->query(
"UPDATE cron_task_state
SET last_run_at = " . $this->sql($completed_at) . ",
next_run_at = " . $this->sql($nextRunAt) . ",
locked_until = NULL,
lock_owner = NULL,
current_run_id = NULL,
last_status = " . $this->sql($status) . ",
last_error = " . $this->nullableSql($error_message) . "
WHERE task_id = " . $this->sql($definition->id) . "
AND lock_owner = " . $this->sql($this->lock_owner)
);
if ($definition->legacy_name !== null && defined('redis')) {
try {
redis->set_last_crond_run($definition->legacy_name, time());
} catch (Throwable) {
}
}
}
private function createRun(
cron_task_definition $definition,
string $source,
?int $actor_user_id,
?string $scheduled_for,
string $started_at,
bool $force = false
): int {
$this->query(
"INSERT INTO cron_task_runs
(task_id, module, source, status, actor_user_id, scheduled_for, started_at, lock_owner, force_run)
VALUES ("
. $this->sql($definition->id) . ', '
. $this->sql($definition->module) . ', '
. $this->sql($source) . ", 'running', "
. ($actor_user_id === null ? 'NULL' : (string)(int)$actor_user_id) . ', '
. $this->nullableSql($scheduled_for) . ', '
. $this->sql($started_at) . ', '
. $this->sql($this->lock_owner) . ', '
. ($force ? '1' : '0')
. ")"
);
return $this->insertId();
}
private function completeRun(
int $run_id,
string $status,
string $completed_at,
int $duration_ms,
array $summary,
?string $error_message
): void {
$this->query(
"UPDATE cron_task_runs
SET status = " . $this->sql($status) . ",
completed_at = " . $this->sql($completed_at) . ",
duration_ms = " . (string)$duration_ms . ",
summary_json = " . $this->sql(json_encode($summary, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) . ",
error_message = " . $this->nullableSql($error_message) . "
WHERE id = " . (string)$run_id
);
}
private function ensureLegacyFunctionsLoaded(cron_task_definition $definition): void
{
if (function_exists($definition->handler)) {
return;
}
if (!defined('WD')) {
return;
}
if (!defined('CRON_LOAD_LEGACY_FUNCTIONS_ONLY')) {
define('CRON_LOAD_LEGACY_FUNCTIONS_ONLY', true);
}
require_once WD . '/cron/Cron.php';
}
/**
* @return array<string, array<string, mixed>>
*/
private function stateRows(): array
{
$rows = $this->fetchAll("SELECT * FROM cron_task_state");
$states = [];
foreach ($rows as $row) {
$row['enabled'] = (bool)$row['enabled'];
$row['schedule'] = $this->decodeJson($row['schedule_json'] ?? null);
$states[(string)$row['task_id']] = $row;
}
return $states;
}
/**
* @return array<string, int>
*/
private function durationEstimates(): array
{
$rows = $this->fetchAll(
"SELECT task_id, AVG(duration_ms) AS avg_duration_ms
FROM (
SELECT task_id, duration_ms
FROM cron_task_runs
WHERE status = 'succeeded' AND duration_ms IS NOT NULL
ORDER BY id DESC
LIMIT 500
) recent_runs
GROUP BY task_id"
);
$estimates = [];
foreach ($rows as $row) {
$estimates[(string)$row['task_id']] = (int)round((float)$row['avg_duration_ms']);
}
return $estimates;
}
private function decodeJson(mixed $json): array
{
if (!is_string($json) || trim($json) === '') {
return [];
}
$decoded = json_decode($json, true);
return is_array($decoded) ? $decoded : [];
}
private function publicRun(array $run): array
{
if ($run === []) {
return [];
}
$run['force_run'] = (bool)($run['force_run'] ?? false);
$run['summary'] = $this->decodeJson($run['summary_json'] ?? null);
return $run;
}
private function fetchOne(string $sql): ?array
{
$rows = $this->fetchAll($sql);
return $rows[0] ?? null;
}
private function fetchAll(string $sql): array
{
$result = $this->query($sql);
if ($result === false || $result === true) {
return [];
}
return $result->fetch_all(MYSQLI_ASSOC);
}
private function query(string $sql): \mysqli_result|bool
{
global $db;
return $db->query($sql);
}
private function sql(string $value): string
{
global $db;
return "'" . $db->escape_string($value) . "'";
}
private function nullableSql(?string $value): string
{
return $value === null ? 'NULL' : $this->sql($value);
}
private function affectedRows(): int
{
global $db;
return (int)$db->conn()->affected_rows;
}
private function insertId(): int
{
global $db;
return (int)$db->insert_id();
}
}
@@ -1,121 +0,0 @@
<?php
namespace classes;
class cron_schema_bootstrap
{
private static bool $initialized = false;
public static function ensureTables(): void
{
if (self::$initialized) {
return;
}
global $db;
if (!isset($db) || !is_object($db) || !method_exists($db, 'query')) {
return;
}
$db->query(
"CREATE TABLE IF NOT EXISTS cron_task_state (
task_id VARCHAR(191) NOT NULL PRIMARY KEY,
module VARCHAR(64) NOT NULL,
enabled TINYINT(1) NOT NULL DEFAULT 1,
schedule_json LONGTEXT NULL,
last_run_at DATETIME NULL,
next_run_at DATETIME NULL,
locked_until DATETIME NULL,
lock_owner VARCHAR(191) NULL,
current_run_id BIGINT UNSIGNED NULL,
last_status VARCHAR(32) NULL,
last_error TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_cron_task_state_next_run (enabled, next_run_at),
KEY idx_cron_task_state_lock (locked_until)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$db->query(
"CREATE TABLE IF NOT EXISTS cron_task_runs (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
task_id VARCHAR(191) NOT NULL,
module VARCHAR(64) NOT NULL,
source VARCHAR(32) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'running',
actor_user_id INT NULL,
scheduled_for DATETIME NULL,
started_at DATETIME NULL,
completed_at DATETIME NULL,
duration_ms INT UNSIGNED NULL,
summary_json LONGTEXT NULL,
error_message TEXT NULL,
lock_owner VARCHAR(191) NULL,
force_run TINYINT(1) NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_cron_task_runs_task_created (task_id, created_at),
KEY idx_cron_task_runs_status_created (status, created_at),
KEY idx_cron_task_runs_module_created (module, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
self::ensureColumn('cron_task_runs', 'force_run', 'TINYINT(1) NOT NULL DEFAULT 0 AFTER lock_owner');
$db->query(
"CREATE TABLE IF NOT EXISTS cron_worker_state (
worker_id VARCHAR(191) NOT NULL PRIMARY KEY,
name VARCHAR(191) NOT NULL,
hostname VARCHAR(191) NULL,
pid INT UNSIGNED NULL,
source VARCHAR(64) NOT NULL DEFAULT 'coolify_worker',
status VARCHAR(32) NOT NULL DEFAULT 'starting',
release_channel_id BIGINT UNSIGNED NULL,
release_target_id BIGINT UNSIGNED NULL,
coolify_resource_uuid VARCHAR(128) NULL,
coolify_resource_type VARCHAR(32) NULL,
commit_sha VARCHAR(64) NULL,
poll_seconds INT UNSIGNED NOT NULL DEFAULT 15,
last_run_count INT UNSIGNED NOT NULL DEFAULT 0,
last_stale_run_count INT UNSIGNED NOT NULL DEFAULT 0,
last_error TEXT NULL,
started_at DATETIME NULL,
last_heartbeat_at DATETIME NULL,
last_loop_started_at DATETIME NULL,
last_loop_finished_at DATETIME NULL,
last_loop_gap_seconds INT UNSIGNED NULL,
consecutive_minute_loops INT UNSIGNED NOT NULL DEFAULT 0,
stopped_at DATETIME NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
KEY idx_cron_worker_state_heartbeat (last_heartbeat_at),
KEY idx_cron_worker_state_status (status),
KEY idx_cron_worker_state_release_target (release_target_id),
KEY idx_cron_worker_state_coolify_resource (coolify_resource_uuid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
self::ensureColumn('cron_worker_state', 'last_loop_gap_seconds', 'INT UNSIGNED NULL AFTER last_loop_finished_at');
self::ensureColumn('cron_worker_state', 'consecutive_minute_loops', 'INT UNSIGNED NOT NULL DEFAULT 0 AFTER last_loop_gap_seconds');
self::$initialized = true;
}
private static function ensureColumn(string $table, string $column, string $definition): void
{
global $db;
$table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
$column = preg_replace('/[^a-zA-Z0-9_]/', '', $column);
if ($table === '' || $column === '') {
return;
}
$result = $db->query("SHOW COLUMNS FROM `{$table}` LIKE '{$column}'");
if ($result && $result->num_rows > 0) {
return;
}
$db->query("ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definition}");
}
}
@@ -1,85 +0,0 @@
<?php
namespace classes;
use InvalidArgumentException;
class cron_task_definition
{
public string $id;
public string $name;
public string $description;
public string $module;
public string $handler;
public array $schedule;
public bool $enabled;
public int $timeout_seconds;
public int $estimated_duration_ms;
public int $priority;
public ?string $legacy_name;
public function __construct(array $definition)
{
$this->id = self::requiredString($definition, 'id');
$this->name = self::requiredString($definition, 'name');
$this->description = (string)($definition['description'] ?? '');
$this->module = self::requiredString($definition, 'module');
$this->handler = self::requiredString($definition, 'handler');
$this->schedule = cron_schedule::normalize($definition['schedule'] ?? []);
$this->enabled = (bool)($definition['enabled'] ?? true);
$this->timeout_seconds = max(30, (int)($definition['timeout_seconds'] ?? 600));
$this->estimated_duration_ms = max(0, (int)($definition['estimated_duration_ms'] ?? 0));
$this->priority = (int)($definition['priority'] ?? 100);
$legacy_name = trim((string)($definition['legacy_name'] ?? ''));
$this->legacy_name = $legacy_name !== '' ? $legacy_name : null;
if (!preg_match('/^[a-z0-9][a-z0-9_.-]{1,190}$/', $this->id)) {
throw new InvalidArgumentException('Invalid cron task id: ' . $this->id);
}
if (!preg_match('/^[a-z0-9][a-z0-9_-]{1,63}$/', $this->module)) {
throw new InvalidArgumentException('Invalid cron task module: ' . $this->module);
}
}
public function asArray(?array $state = null, ?int $estimatedDurationMs = null): array
{
$schedule = is_array($state['schedule'] ?? null) && ($state['schedule'] ?? []) !== []
? $state['schedule']
: $this->schedule;
$enabled = array_key_exists('enabled', $state ?? [])
? (bool)$state['enabled']
: $this->enabled;
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'module' => $this->module,
'handler' => $this->handler,
'schedule' => $schedule,
'default_schedule' => $this->schedule,
'enabled' => $enabled,
'default_enabled' => $this->enabled,
'timeout_seconds' => $this->timeout_seconds,
'estimated_duration_ms' => $estimatedDurationMs ?? $this->estimated_duration_ms,
'priority' => $this->priority,
'legacy_name' => $this->legacy_name,
'last_run_at' => $state['last_run_at'] ?? null,
'next_run_at' => $state['next_run_at'] ?? null,
'locked_until' => $state['locked_until'] ?? null,
'lock_owner' => $state['lock_owner'] ?? null,
'current_run_id' => $state['current_run_id'] ?? null,
'last_status' => $state['last_status'] ?? null,
'last_error' => $state['last_error'] ?? null,
];
}
private static function requiredString(array $definition, string $key): string
{
$value = trim((string)($definition[$key] ?? ''));
if ($value === '') {
throw new InvalidArgumentException('Missing cron task definition field: ' . $key);
}
return $value;
}
}
@@ -1,85 +0,0 @@
<?php
namespace classes;
use InvalidArgumentException;
class cron_task_registry
{
private string $modules_root;
/** @var array<string, cron_task_definition>|null */
private ?array $definitions = null;
public function __construct(?string $modules_root = null)
{
$this->modules_root = $modules_root ?? (defined('WD') ? WD . '/modules' : dirname(__DIR__) . '/modules');
}
/**
* @return array<string, cron_task_definition>
*/
public function definitions(): array
{
if ($this->definitions !== null) {
return $this->definitions;
}
$definitions = [];
foreach ($this->definitionFiles() as $file) {
$module_definitions = require $file;
if (!is_array($module_definitions)) {
throw new InvalidArgumentException('Cron definition file must return an array: ' . $file);
}
foreach ($module_definitions as $definition) {
$task = new cron_task_definition($definition);
if (isset($definitions[$task->id])) {
throw new InvalidArgumentException('Duplicate cron task id: ' . $task->id);
}
$definitions[$task->id] = $task;
}
}
uasort($definitions, static function (cron_task_definition $left, cron_task_definition $right): int {
if ($left->priority !== $right->priority) {
return $left->priority <=> $right->priority;
}
return strcmp($left->id, $right->id);
});
$this->definitions = $definitions;
return $definitions;
}
public function get(string $id_or_legacy_name): ?cron_task_definition
{
$normalized = trim($id_or_legacy_name);
if ($normalized === '') {
return null;
}
$definitions = $this->definitions();
if (isset($definitions[$normalized])) {
return $definitions[$normalized];
}
foreach ($definitions as $definition) {
if ($definition->legacy_name !== null && hash_equals($definition->legacy_name, $normalized)) {
return $definition;
}
}
return null;
}
/**
* @return array<int, string>
*/
private function definitionFiles(): array
{
$files = glob($this->modules_root . '/*/cron/tasks.php') ?: [];
sort($files, SORT_STRING);
return $files;
}
}
-361
View File
@@ -1,361 +0,0 @@
<?php
namespace classes;
use Throwable;
use traits\boolean_normalization_t;
require_once __DIR__ . '/../traits/boolean_normalization_t.php';
class cron_worker
{
use boolean_normalization_t;
private cron_scheduler $scheduler;
private string $worker_id;
private string $name;
private string $source;
private int $poll_seconds;
private int $heartbeat_seconds;
private int $max_runtime_seconds;
private bool $should_stop = false;
private int $last_heartbeat = 0;
public function __construct(?cron_scheduler $scheduler = null, array $options = [])
{
$this->scheduler = $scheduler ?? new cron_scheduler();
$this->name = $this->stringOption($options, 'name', 'CRON_WORKER_NAME', 'cron-worker');
$this->worker_id = $this->stringOption($options, 'worker_id', 'CRON_WORKER_ID', $this->name);
$this->source = $this->stringOption($options, 'source', 'CRON_WORKER_SOURCE', 'coolify_worker');
$this->poll_seconds = $this->intOption($options, 'poll_seconds', 'CRON_WORKER_POLL_SECONDS', 15, 1, 300);
$this->heartbeat_seconds = $this->intOption($options, 'heartbeat_seconds', 'CRON_WORKER_HEARTBEAT_SECONDS', 30, 5, 300);
$this->max_runtime_seconds = $this->intOption($options, 'max_runtime_seconds', 'CRON_WORKER_MAX_RUNTIME_SECONDS', 0, 0, 86400);
}
public function run(): int
{
if (!$this->boolOption('CRON_WORKER_ENABLED', true)) {
$this->heartbeat('disabled', 0, 0, null, true);
return 0;
}
$this->registerSignalHandlers();
$started = time();
$this->heartbeat('starting', 0, 0, null, true);
while (!$this->should_stop) {
$pollStarted = microtime(true);
$result = $this->tick();
$this->writeStatusLine($result);
if ($this->max_runtime_seconds > 0 && time() - $started >= $this->max_runtime_seconds) {
$this->should_stop = true;
break;
}
$this->sleepUntilNextPoll($pollStarted + $this->poll_seconds);
}
$this->heartbeat('stopped', 0, 0, null, true, true);
return 0;
}
public function tick(): array
{
$this->heartbeat('running');
$loopStartedAt = date('Y-m-d H:i:s');
$staleRuns = 0;
$ran = ['count' => 0, 'ran' => []];
$error = null;
$status = 'running';
try {
$staleRuns = $this->scheduler->markExpiredRunningRuns();
$ran = $this->scheduler->runDue($this->source);
} catch (Throwable $throwable) {
$status = 'failed';
$error = $throwable->getMessage();
}
$this->heartbeat($status, (int)($ran['count'] ?? 0), $staleRuns, $error, true, false, $loopStartedAt);
return [
'worker_id' => $this->worker_id,
'status' => $status,
'ran' => (int)($ran['count'] ?? 0),
'stale_runs' => $staleRuns,
'error' => $error,
];
}
public function listWorkers(): array
{
cron_schema_bootstrap::ensureTables();
$rows = $this->fetchAll('SELECT * FROM cron_worker_state ORDER BY last_heartbeat_at DESC, worker_id');
$workers = [];
foreach ($rows as $row) {
$workers[] = $this->publicWorker($row);
}
return [
'workers' => $workers,
'summary' => [
'total' => count($workers),
'running' => count(array_filter($workers, static fn(array $worker): bool => ($worker['status'] ?? '') === 'running')),
'stale' => count(array_filter($workers, static fn(array $worker): bool => (bool)($worker['stale'] ?? false))),
],
];
}
private function registerSignalHandlers(): void
{
if (!function_exists('pcntl_signal')) {
return;
}
if (function_exists('pcntl_async_signals')) {
pcntl_async_signals(true);
}
pcntl_signal(SIGTERM, function (): void {
$this->should_stop = true;
});
pcntl_signal(SIGINT, function (): void {
$this->should_stop = true;
});
}
private function sleepUntilNextPoll(float $nextPollAt): void
{
while (!$this->should_stop) {
$remaining = $nextPollAt - microtime(true);
if ($remaining <= 0) {
return;
}
usleep((int)(min(1.0, $remaining) * 1000000));
if (time() - $this->last_heartbeat >= $this->heartbeat_seconds) {
$this->heartbeat('running');
}
}
}
private function heartbeat(
string $status,
int $runCount = 0,
int $staleRunCount = 0,
?string $error = null,
bool $force = false,
bool $stopped = false,
?string $loopStartedAt = null
): void {
if (!$force && time() - $this->last_heartbeat < $this->heartbeat_seconds) {
return;
}
cron_schema_bootstrap::ensureTables();
$this->last_heartbeat = time();
$now = date('Y-m-d H:i:s');
$workerId = $this->sql($this->worker_id);
$name = $this->sql($this->name);
$hostname = $this->nullableSql(gethostname() ?: null);
$pid = getmypid() ?: 0;
$source = $this->sql($this->source);
$statusSql = $this->sql($status);
$releaseChannelId = $this->nullableInt($this->env('CRON_WORKER_RELEASE_CHANNEL_ID'));
$releaseTargetId = $this->nullableInt($this->env('CRON_WORKER_RELEASE_TARGET_ID'));
$resourceUuid = $this->nullableSql($this->env('COOLIFY_RESOURCE_UUID') ?: $this->env('CRON_WORKER_COOLIFY_RESOURCE_UUID'));
$resourceType = $this->nullableSql($this->env('COOLIFY_RESOURCE_TYPE') ?: $this->env('CRON_WORKER_COOLIFY_RESOURCE_TYPE') ?: 'application');
$commitSha = $this->nullableSql($this->commitSha());
$errorSql = $this->nullableSql($error);
$loopStarted = $this->nullableSql($loopStartedAt);
$stoppedAt = $stopped ? $this->sql($now) : 'NULL';
$nowSql = $this->sql($now);
$this->query(
"INSERT INTO cron_worker_state (
worker_id, name, hostname, pid, source, status, release_channel_id, release_target_id,
coolify_resource_uuid, coolify_resource_type, commit_sha, poll_seconds, last_run_count,
last_stale_run_count, last_error, started_at, last_heartbeat_at, last_loop_started_at,
last_loop_finished_at, last_loop_gap_seconds, consecutive_minute_loops, stopped_at
) VALUES (
$workerId, $name, $hostname, $pid, $source, $statusSql, $releaseChannelId, $releaseTargetId,
$resourceUuid, $resourceType, $commitSha, $this->poll_seconds, $runCount,
$staleRunCount, $errorSql, $nowSql, $nowSql, $loopStarted,
$nowSql, NULL, " . ($loopStartedAt !== null ? '1' : '0') . ", $stoppedAt
)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
hostname = VALUES(hostname),
pid = VALUES(pid),
source = VALUES(source),
status = VALUES(status),
release_channel_id = VALUES(release_channel_id),
release_target_id = VALUES(release_target_id),
coolify_resource_uuid = VALUES(coolify_resource_uuid),
coolify_resource_type = VALUES(coolify_resource_type),
commit_sha = VALUES(commit_sha),
poll_seconds = VALUES(poll_seconds),
last_run_count = VALUES(last_run_count),
last_stale_run_count = VALUES(last_stale_run_count),
last_error = VALUES(last_error),
last_heartbeat_at = VALUES(last_heartbeat_at),
last_loop_gap_seconds = CASE
WHEN VALUES(last_loop_started_at) IS NULL OR last_loop_started_at IS NULL THEN last_loop_gap_seconds
ELSE GREATEST(0, TIMESTAMPDIFF(SECOND, last_loop_started_at, VALUES(last_loop_started_at)))
END,
consecutive_minute_loops = CASE
WHEN VALUES(last_loop_started_at) IS NULL THEN consecutive_minute_loops
WHEN last_loop_started_at IS NULL THEN 1
WHEN TIMESTAMPDIFF(SECOND, last_loop_started_at, VALUES(last_loop_started_at)) BETWEEN 0 AND 60
THEN consecutive_minute_loops + 1
ELSE 1
END,
last_loop_started_at = COALESCE(VALUES(last_loop_started_at), last_loop_started_at),
last_loop_finished_at = VALUES(last_loop_finished_at),
stopped_at = VALUES(stopped_at)"
);
}
private function publicWorker(array $row): array
{
$heartbeatAt = (string)($row['last_heartbeat_at'] ?? '');
$heartbeatTs = strtotime($heartbeatAt);
$threshold = max(60, ((int)($row['poll_seconds'] ?? 15) * 4) + 30);
$age = $heartbeatTs !== false ? max(0, time() - $heartbeatTs) : null;
$loopStartedAt = (string)($row['last_loop_started_at'] ?? '');
$loopStartedTs = strtotime($loopStartedAt);
$loopAge = $loopStartedTs !== false ? max(0, time() - $loopStartedTs) : null;
$loopGap = isset($row['last_loop_gap_seconds']) ? (int)$row['last_loop_gap_seconds'] : null;
$consecutiveMinuteLoops = (int)($row['consecutive_minute_loops'] ?? 0);
$minuteCadenceVerified = ($row['status'] ?? '') === 'running'
&& $loopAge !== null
&& $loopAge <= 60
&& $loopGap !== null
&& $loopGap <= 60
&& $consecutiveMinuteLoops >= 2;
return [
'worker_id' => (string)($row['worker_id'] ?? ''),
'name' => (string)($row['name'] ?? ''),
'hostname' => $row['hostname'] ?? null,
'pid' => isset($row['pid']) ? (int)$row['pid'] : null,
'source' => (string)($row['source'] ?? ''),
'status' => (string)($row['status'] ?? 'unknown'),
'release_channel_id' => isset($row['release_channel_id']) ? (int)$row['release_channel_id'] : null,
'release_target_id' => isset($row['release_target_id']) ? (int)$row['release_target_id'] : null,
'coolify_resource_uuid' => $row['coolify_resource_uuid'] ?? null,
'coolify_resource_type' => $row['coolify_resource_type'] ?? null,
'commit_sha' => $row['commit_sha'] ?? null,
'poll_seconds' => (int)($row['poll_seconds'] ?? 0),
'last_run_count' => (int)($row['last_run_count'] ?? 0),
'last_stale_run_count' => (int)($row['last_stale_run_count'] ?? 0),
'last_error' => $row['last_error'] ?? null,
'started_at' => $row['started_at'] ?? null,
'last_heartbeat_at' => $heartbeatAt !== '' ? $heartbeatAt : null,
'last_heartbeat_age_seconds' => $age,
'last_loop_started_at' => $row['last_loop_started_at'] ?? null,
'last_loop_finished_at' => $row['last_loop_finished_at'] ?? null,
'last_loop_age_seconds' => $loopAge,
'last_loop_gap_seconds' => $loopGap,
'consecutive_minute_loops' => $consecutiveMinuteLoops,
'minute_cadence' => [
'verified' => $minuteCadenceVerified,
'maximum_gap_seconds' => 60,
'last_gap_seconds' => $loopGap,
'consecutive_loops' => $consecutiveMinuteLoops,
],
'stopped_at' => $row['stopped_at'] ?? null,
'stale' => $age === null || $age > $threshold,
'stale_after_seconds' => $threshold,
];
}
private function writeStatusLine(array $result): void
{
echo '[' . date('Y-m-d H:i:s') . '][CRON_WORKER] '
. json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
. PHP_EOL;
}
private function stringOption(array $options, string $key, string $env, string $default): string
{
$value = trim((string)($options[$key] ?? $this->env($env) ?? ''));
return $value !== '' ? $value : $default;
}
private function intOption(array $options, string $key, string $env, int $default, int $min, int $max): int
{
$value = (int)($options[$key] ?? $this->env($env) ?? $default);
return max($min, min($max, $value));
}
private function boolOption(string $env, bool $default): bool
{
$value = $this->env($env);
if ($value === null || trim($value) === '') {
return $default;
}
return self::normalizeBoolean($value);
}
private function commitSha(): string
{
foreach (['CRON_WORKER_COMMIT_SHA', 'API_COMMIT_SHA', 'RELEASE_COMMIT_SHA', 'COMMIT_SHA', 'GITHUB_SHA'] as $key) {
$value = trim((string)($this->env($key) ?? ''));
if ($value !== '') {
return $value;
}
}
return '';
}
private function env(string $key): ?string
{
$value = getenv($key);
if ($value !== false) {
return (string)$value;
}
return isset($_SERVER[$key]) ? (string)$_SERVER[$key] : null;
}
private function nullableInt(?string $value): string
{
$value = trim((string)$value);
if ($value === '' || filter_var($value, FILTER_VALIDATE_INT) === false) {
return 'NULL';
}
return (string)max(0, (int)$value);
}
private function nullableSql(?string $value): string
{
$value = $value !== null ? trim($value) : '';
return $value === '' ? 'NULL' : $this->sql($value);
}
private function fetchAll(string $sql): array
{
$result = $this->query($sql);
if ($result === false || $result === true) {
return [];
}
return $result->fetch_all(MYSQLI_ASSOC);
}
private function query(string $sql): \mysqli_result|bool
{
global $db;
return $db->query($sql);
}
private function sql(string $value): string
{
global $db;
return "'" . $db->escape_string($value) . "'";
}
}
@@ -1,93 +0,0 @@
<?php
namespace classes;
/**
* Ensures additive schema for the customer `invoice_email` field
* (TRU-77 / DRIFT 16). The field is optional and stores an
* e-mail address that should receive the customer's invoices
* separately from the customer's primary `email`.
*/
class customer_invoice_email_schema_bootstrap
{
private static bool $initialized = false;
private const TABLE = 'users';
private const COLUMN = 'invoice_email';
public static function ensureSchema(): void
{
if (self::$initialized) {
return;
}
global $db;
if (!isset($db) || !is_object($db) || !method_exists($db, 'query')) {
return;
}
self::ensureUsersTable($db);
self::ensureInvoiceEmailColumn($db);
self::$initialized = true;
}
private static function ensureUsersTable(object $db): void
{
$db->query(
"CREATE TABLE IF NOT EXISTS users (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
customer_number INT NOT NULL,
display_name VARCHAR(255) NULL,
email VARCHAR(255) NULL,
phone_country_code INT NULL,
phone BIGINT NULL,
password VARCHAR(255) NULL,
group_id INT NOT NULL DEFAULT 0,
xlvask_customer_id VARCHAR(255) NULL,
sms_notifications_enabled TINYINT(1) NOT NULL DEFAULT 0,
email_notifications_enabled TINYINT(1) NOT NULL DEFAULT 0,
wash_certificate_email VARCHAR(255) NULL,
invoice_email VARCHAR(255) NULL,
two_factor_enabled TINYINT(1) NOT NULL DEFAULT 0,
two_factor_secret VARCHAR(255) NULL,
created_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME NULL,
KEY idx_users_customer_number (customer_number),
KEY idx_users_group_id (group_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
}
private static function ensureInvoiceEmailColumn(object $db): void
{
if (!self::tableExists($db, self::TABLE)) {
return;
}
if (self::columnExists($db, self::TABLE, self::COLUMN)) {
return;
}
$safeTable = str_replace('`', '', self::TABLE);
$db->query(
"ALTER TABLE `{$safeTable}`
ADD COLUMN " . self::COLUMN . " VARCHAR(255) NULL
AFTER wash_certificate_email"
);
}
private static function tableExists(object $db, string $table): bool
{
$safeTable = str_replace('`', '', $table);
$result = $db->query("SHOW TABLES LIKE '{$safeTable}'");
return $result && (int)$result->num_rows > 0;
}
private static function columnExists(object $db, string $table, string $column): bool
{
$safeTable = str_replace('`', '', $table);
$safeColumn = str_replace("'", '', $column);
$result = $db->query("SHOW COLUMNS FROM `{$safeTable}` LIKE '{$safeColumn}'");
return $result && (int)$result->num_rows > 0;
}
}
@@ -1,560 +0,0 @@
<?php
namespace classes;
use objects\logs_o;
use objects\users_o;
class customer_mass_import_service
{
/**
* Import or create a company customer from one normalized spreadsheet row.
*
* @throws \RuntimeException
*/
public function import(array $payload): array
{
// TRU-77 / DRIFT 16: ensure the invoice_email column exists before we
// attempt to populate it on a local customer.
customer_invoice_email_schema_bootstrap::ensureSchema();
$normalized = $this->normalizePayload($payload);
$this->assertValidNormalizedPayload($normalized);
$customerNumber = (int)$normalized['customer_number'];
$cvr = (string)$normalized['cvr'];
$warnings = [];
$economicCustomers = $this->searchEconomicCustomersByCvr($cvr);
$localUserExistsBefore = $this->localCustomerNumberExists($customerNumber);
$localUser = $localUserExistsBefore ? $this->loadLocalCustomerByNumber($customerNumber) : null;
$matchingEconomicCustomer = $this->findEconomicCustomerByNumber($economicCustomers, $customerNumber);
if ($matchingEconomicCustomer !== null) {
$customer = $this->resolveLocalCustomer($customerNumber, $localUserExistsBefore, $localUser);
$this->syncLocalCustomer($customer, $normalized, $warnings);
[$action, $message] = $this->resolveExistingCustomerOutcome($localUserExistsBefore, $this->hasLocalAccount($customer));
return $this->buildSuccessResult(
$normalized,
$customer,
$action,
$message,
$localUserExistsBefore,
true,
false,
$warnings
);
}
if (count($economicCustomers) > 0) {
$existingEconomicCustomerNumber = $this->extractEconomicCustomerNumber($economicCustomers[0]);
$this->logIssue('CUSTOMER_MASS_IMPORT_CONFLICT', [
'phase' => 'search',
'cvr' => $cvr,
'requestedCustomerNumber' => $customerNumber,
'existingCustomerNumber' => $existingEconomicCustomerNumber,
]);
throw new \RuntimeException(
'CVR already registered under customer number '
. $existingEconomicCustomerNumber
. '. The submitted phone number must match the customer id. Manual cleanup or reassignment is required before retrying.',
409
);
}
$normalized['name'] = $this->resolveCreateName($normalized);
// TRU-77 / DRIFT 16: resolve the e-conomic delivery address into a
// local variable instead of overwriting $normalized['email']. The
// primary customer email must remain intact for the result payload
// and for downstream local-customer sync; the create call needs the
// dedicated invoice address (or the primary as a fallback) on its
// own.
$createEmail = $this->resolveCreateEmail($normalized, $warnings);
$createResponse = $this->createEconomicCustomer($normalized, $createEmail);
$createdCustomerNumber = $this->extractEconomicCustomerNumber($createResponse);
if ($createdCustomerNumber !== $customerNumber) {
$this->logIssue('CUSTOMER_MASS_IMPORT_CONFLICT', [
'phase' => 'create',
'cvr' => $cvr,
'requestedCustomerNumber' => $customerNumber,
'createdCustomerNumber' => $createdCustomerNumber,
'response' => $createResponse,
]);
throw new \RuntimeException(
'E-conomic created the customer under customer number '
. $createdCustomerNumber
. ' instead of the submitted phone number '
. $customerNumber
. '. Manual cleanup or reassignment is required before retrying.',
409
);
}
$customer = $this->resolveLocalCustomer($customerNumber, $localUserExistsBefore, $localUser);
$this->syncLocalCustomer($customer, $normalized, $warnings);
[$action, $message] = $this->resolveCreatedCustomerOutcome($localUserExistsBefore, $this->hasLocalAccount($customer));
return $this->buildSuccessResult(
$normalized,
$customer,
$action,
$message,
$localUserExistsBefore,
false,
true,
$warnings
);
}
protected function normalizePayload(array $payload): array
{
return [
'customer_number' => $this->normalizePositiveInt($payload['customer_number'] ?? $payload['phone'] ?? null),
'phone' => $this->normalizePositiveInt($payload['phone'] ?? $payload['customer_number'] ?? null),
'cvr' => $this->normalizeDigitString($payload['cvr'] ?? null),
'name' => $this->normalizeText($payload['name'] ?? $payload['company_name'] ?? null),
'email' => $this->normalizeEmail($payload['email'] ?? null),
'invoice_email' => $this->normalizeInvoiceEmail($payload['invoice_email'] ?? null),
'ean' => $this->normalizeDigitString($payload['ean'] ?? null),
];
}
protected function assertValidNormalizedPayload(array $normalized): void
{
$customerNumber = $normalized['customer_number'];
$cvr = $normalized['cvr'];
if ($customerNumber === null) {
throw new \RuntimeException('Phone number is required.', 400);
}
$customerNumberLength = strlen((string)$customerNumber);
if ($customerNumberLength < 8 || $customerNumberLength > 10) {
throw new \RuntimeException('Phone number must be between 8 and 10 digits.', 400);
}
if ($cvr === null) {
throw new \RuntimeException('CVR is required.', 400);
}
$cvrLength = strlen($cvr);
if ($cvrLength < 8 || $cvrLength > 20) {
throw new \RuntimeException('CVR must be between 8 and 20 digits.', 400);
}
if ($normalized['ean'] !== null && strlen((string)$normalized['ean']) > 13) {
throw new \RuntimeException('EAN must be at most 13 digits.', 400);
}
}
protected function normalizePositiveInt(mixed $value): ?int
{
$digits = $this->normalizeDigitString($value);
if ($digits === null) {
return null;
}
$normalized = (int)$digits;
return $normalized > 0 ? $normalized : null;
}
protected function normalizeDigitString(mixed $value): ?string
{
if ($value === null) {
return null;
}
$digits = preg_replace('/\D+/', '', (string)$value);
if (!is_string($digits)) {
return null;
}
$digits = trim($digits);
return $digits !== '' ? $digits : null;
}
protected function normalizeText(mixed $value): ?string
{
if ($value === null) {
return null;
}
$normalized = trim((string)$value);
return $normalized !== '' ? $normalized : null;
}
protected function normalizeEmail(mixed $value): ?string
{
$email = $this->normalizeText($value);
if ($email === null) {
return null;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \RuntimeException('Invalid email address.', 400);
}
return $email;
}
/**
* Normalize the optional dedicated invoice email (TRU-77 / DRIFT 16).
* Empty/whitespace values collapse to null. An explicit non-empty value
* must be a syntactically valid email address; an invalid value is
* rejected to keep invoices from being routed to a malformed address.
*/
protected function normalizeInvoiceEmail(mixed $value): ?string
{
$email = $this->normalizeText($value);
if ($email === null) {
return null;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \RuntimeException('Invalid invoice email address.', 400);
}
return $email;
}
/**
* Resolve the e-mail address that e-conomic should use to deliver
* invoices for the customer (TRU-77 / DRIFT 16). Prefers the dedicated
* `invoice_email` when provided, falling back to the customer's primary
* `email`.
*/
protected function resolveInvoiceEmail(array $normalized, array &$warnings): string
{
if (!empty($normalized['invoice_email'])) {
return (string)$normalized['invoice_email'];
}
if (!empty($normalized['email'])) {
return (string)$normalized['email'];
}
$warnings[] = 'No invoice email was provided, defaulted to jb@truckwash.dk for the new e-conomic customer.';
return 'jb@truckwash.dk';
}
protected function resolveCreateName(array $normalized): string
{
if ($normalized['name'] !== null) {
return $normalized['name'];
}
$name = trim($this->fetchCompanyNameByCvr((string)$normalized['cvr']));
if ($name === '') {
throw new \RuntimeException('Customer name is required to create a new company.', 400);
}
return $name;
}
protected function resolveCreateEmail(array $normalized, array &$warnings): string
{
// TRU-77 / DRIFT 16: invoices must be routed to the dedicated
// invoice_email when provided, otherwise to the customer's email.
return $this->resolveInvoiceEmail($normalized, $warnings);
}
protected function searchEconomicCustomersByCvr(string $cvr): array
{
$response = (new economic())->customers->customers->search([
'corporateIdentificationNumber' => $cvr,
], [
'skipPages' => 0,
'pageSize' => 1000,
])->collection ?? [];
return is_array($response) ? $response : [];
}
protected function createEconomicCustomer(array $normalized, string $createEmail): object
{
$payload = [
'customerNumber' => (int)$normalized['customer_number'],
'corporateIdentificationNumber' => (string)$normalized['cvr'],
'customerGroup' => [
'customerGroupNumber' => 1,
],
'paymentTerms' => [
'paymentTermsNumber' => 12,
],
'name' => (string)$normalized['name'],
// TRU-77 / DRIFT 16: the dedicated invoice_email (or the
// primary email as a fallback) is passed in explicitly so the
// caller's $normalized['email'] is never mutated here.
'email' => $createEmail,
'phone' => (int)$normalized['phone'],
'telephoneAndFaxNumber' => (string)$normalized['phone'],
'mobilePhone' => (string)$normalized['phone'],
'currency' => 'DKK',
'vatZone' => [
'vatZoneNumber' => 1,
],
];
if ($normalized['ean'] !== null) {
$payload['ean'] = (string)$normalized['ean'];
}
return (new economic())->customers->customers->create($payload);
}
protected function localCustomerNumberExists(int $customerNumber): bool
{
$rows = (new users_o())->getFieldsWhere([
'customer_number' => (string)$customerNumber,
], ['id']);
return count($rows) > 0;
}
protected function loadLocalCustomerByNumber(int $customerNumber): ?object
{
$customer = (new users_o())->getUserByCustomerNumber($customerNumber);
return $this->localUserExists($customer) ? $customer : null;
}
protected function resolveLocalCustomer(int $customerNumber, bool $localUserExistsBefore, ?object $localUser): object
{
if ($localUserExistsBefore && $this->localUserExists($localUser)) {
return $localUser;
}
return $this->bootstrapLocalCustomerOrFail($customerNumber);
}
protected function bootstrapLocalCustomerOrFail(int $customerNumber): object
{
$customer = (new users_o())->getUserByCustomerNumber($customerNumber);
if ($this->localUserExists($customer)) {
return $customer;
}
$this->logIssue('CUSTOMER_MASS_IMPORT_LOCAL_BOOTSTRAP_FAILED', [
'customerNumber' => $customerNumber,
]);
throw new \RuntimeException('Customer was created in e-conomic but could not be imported locally.', 500);
}
protected function fetchCompanyNameByCvr(string $cvr): string
{
return (string)((new virkdata())->getCompanyInformation($cvr, '', [])->name ?? '');
}
protected function logIssue(string $action, array $context): void
{
$message = json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($message === false) {
$message = 'Unable to encode customer mass import context';
}
(new logs_o())->add('customers', 'global', 0, 0, $action, $message);
}
protected function findEconomicCustomerByNumber(array $customers, int $customerNumber): ?object
{
foreach ($customers as $customer) {
if (!is_object($customer)) {
continue;
}
if ($this->extractEconomicCustomerNumber($customer) === $customerNumber) {
return $customer;
}
}
return null;
}
protected function extractEconomicCustomerNumber(object $customer): int
{
if (!isset($customer->customerNumber) || !is_numeric($customer->customerNumber)) {
return 0;
}
return (int)$customer->customerNumber;
}
protected function resolveExistingCustomerOutcome(bool $localUserExistsBefore, bool $hasAccount): array
{
if ($localUserExistsBefore && $hasAccount) {
return [
'account_already_exists',
'Customer already exists locally and already has a login account.',
];
}
if ($localUserExistsBefore) {
return [
'customer_already_exists',
'Customer already exists locally but does not have a login password yet.',
];
}
return [
'imported_existing_customer',
'Imported an existing e-conomic customer into the local customer database.',
];
}
protected function resolveCreatedCustomerOutcome(bool $localUserExistsBefore, bool $hasAccount): array
{
if ($localUserExistsBefore && $hasAccount) {
return [
'economic_customer_created_for_existing_account',
'Created the e-conomic customer for an existing local login account.',
];
}
if ($localUserExistsBefore) {
return [
'economic_customer_created_for_existing_customer',
'Created the e-conomic customer for an existing local customer record.',
];
}
return [
'created_customer',
'Created the customer in e-conomic and imported it locally.',
];
}
protected function buildSuccessResult(
array $normalized,
object $customer,
string $action,
string $message,
bool $existingLocalCustomer,
bool $existingEconomicCustomer,
bool $createdEconomicCustomer,
array $warnings
): array {
$customerName = $this->extractLocalUserDisplayName($customer) ?? $normalized['name'];
return [
'customer_number' => (int)$normalized['customer_number'],
'cvr' => (string)$normalized['cvr'],
'name' => $customerName,
'email' => $normalized['email'],
'invoice_email' => $normalized['invoice_email'] ?? null,
'ean' => $normalized['ean'],
'action' => $action,
'message' => $message,
'user_id' => $this->extractLocalUserId($customer),
'has_account' => $this->hasLocalAccount($customer),
'existing_local_customer' => $existingLocalCustomer,
'existing_economic_customer' => $existingEconomicCustomer,
'created_economic_customer' => $createdEconomicCustomer,
'warnings' => array_values(array_filter($warnings, static fn(mixed $warning): bool => is_string($warning) && trim($warning) !== '')),
];
}
protected function syncLocalCustomer(object $customer, array $normalized, array &$warnings): void
{
if (!$customer instanceof users_o || !$customer->exists()) {
return;
}
$name = $normalized['name'] ?? null;
$email = $normalized['email'] ?? null;
$invoice_email = $normalized['invoice_email'] ?? null;
$phone = $normalized['phone'] ?? null;
$displayName = trim((string)($customer->display_name->value() ?? ''));
if ($name !== null && ($displayName === '' || strtolower($displayName) === 'unnamed')) {
$customer->display_name->set($name);
}
if ($email !== null && trim((string)($customer->email->value() ?? '')) === '') {
try {
$customer->setEmail($email);
} catch (\Throwable $throwable) {
$warnings[] = 'Unable to update local email: ' . $throwable->getMessage();
}
}
// TRU-77 / DRIFT 16: persist the dedicated invoice email override
// when provided so invoice routing survives subsequent local edits.
if ($invoice_email !== null && $customer->getInvoiceEmailOverride() === null) {
try {
$customer->setInvoiceEmail($invoice_email);
} catch (\Throwable $throwable) {
$warnings[] = 'Unable to update local invoice email: ' . $throwable->getMessage();
}
}
if ($phone !== null && empty($customer->phone->value())) {
try {
$customer->setPhoneNumber((int)$phone);
} catch (\Throwable $throwable) {
$warnings[] = 'Unable to update local phone number: ' . $throwable->getMessage();
}
}
}
protected function localUserExists(?object $user): bool
{
if (!is_object($user)) {
return false;
}
if (method_exists($user, 'exists')) {
try {
return (bool)$user->exists();
} catch (\Throwable) {
return false;
}
}
return isset($user->id) && is_numeric($user->id) && (int)$user->id > 0;
}
protected function hasLocalAccount(?object $user): bool
{
if (!$this->localUserExists($user)) {
return false;
}
if (method_exists($user, 'hasPassword')) {
try {
return (bool)$user->hasPassword();
} catch (\Throwable) {
return false;
}
}
return (bool)($user->has_password ?? false);
}
protected function extractLocalUserId(?object $user): ?int
{
if (!is_object($user) || !isset($user->id) || !is_numeric($user->id)) {
return null;
}
$userId = (int)$user->id;
return $userId > 0 ? $userId : null;
}
protected function extractLocalUserDisplayName(?object $user): ?string
{
if (!is_object($user)) {
return null;
}
if ($user instanceof users_o) {
$name = trim((string)($user->display_name->value() ?? ''));
return $name !== '' ? $name : null;
}
$name = trim((string)($user->display_name ?? $user->name ?? ''));
return $name !== '' ? $name : null;
}
}
@@ -1,94 +0,0 @@
<?php
namespace classes;
class customer_name_cache_payload_builder
{
/**
* @return array{name:string}|null
*/
public static function build(mixed $cached_name, ?string $fallback_name): ?array
{
$cached_name = self::normalizePayload($cached_name);
$name = self::extractName($cached_name);
if ($name !== null) {
return ['name' => $name];
}
$fallback_name = self::normalizeName($fallback_name);
if ($fallback_name !== null) {
return ['name' => $fallback_name];
}
return null;
}
private static function normalizePayload(mixed $payload): mixed
{
if (!is_string($payload)) {
return $payload;
}
$trimmed = trim($payload);
if ($trimmed === '') {
return null;
}
$decoded = json_decode($trimmed);
if (json_last_error() === JSON_ERROR_NONE) {
return $decoded;
}
return $trimmed;
}
private static function extractName(mixed $payload): ?string
{
if (is_string($payload)) {
return self::normalizeName($payload);
}
if (!is_object($payload) && !is_array($payload)) {
return null;
}
foreach (['name', 'customerName', 'customer_name', 'displayName', 'display_name'] as $key) {
$name = self::normalizeName(self::payloadValue($payload, $key));
if ($name !== null) {
return $name;
}
}
foreach (['customer', 'data', 'economic_customer'] as $key) {
$name = self::extractName(self::payloadValue($payload, $key));
if ($name !== null) {
return $name;
}
}
return null;
}
private static function payloadValue(mixed $payload, string $key): mixed
{
if (is_object($payload) && property_exists($payload, $key)) {
return $payload->{$key};
}
if (is_array($payload) && array_key_exists($key, $payload)) {
return $payload[$key];
}
return null;
}
private static function normalizeName(mixed $name): ?string
{
if (!is_string($name)) {
return null;
}
$name = trim($name);
return $name === '' ? null : $name;
}
}
@@ -1,46 +0,0 @@
<?php
namespace classes;
use RuntimeException;
class customer_order_product_policy
{
public static function assertOrderAllowsProduct(int $orderId, int $productId): void
{
$message = self::orderProductViolationMessage($orderId, $productId);
if ($message !== null) {
throw new RuntimeException($message);
}
}
public static function orderProductViolationMessage(int $orderId, int $productId): ?string
{
$customerNumber = self::loadOrderCustomerNumber($orderId);
if ($customerNumber === null) {
return null;
}
$violation = (new customer_rule_product_restriction_service())
->violationForCustomerProduct($customerNumber, $productId);
return $violation === null ? null : (string)$violation['message'];
}
private static function loadOrderCustomerNumber(int $orderId): ?int
{
global $db;
if ($orderId < 1) {
return null;
}
$result = $db->query("SELECT customer_id FROM orders WHERE id = {$orderId} LIMIT 1");
if (!$result || $result->num_rows < 1) {
return null;
}
$row = $result->fetch_assoc();
$customerNumber = (int)($row['customer_id'] ?? 0);
return $customerNumber > 0 ? $customerNumber : null;
}
}
@@ -1,33 +0,0 @@
<?php
namespace classes;
use objects\orders_o;
class customer_product_rule_service
{
public const BLOCK_MESSAGE = 'This product is not allowed for the selected customer';
/**
* @return array{rule:string,rules:list<string>,collections:list<int>,product_id:int,code:string,message:string}|null
*/
public function firstViolationForOrderItem(int $orderId, int $productId, ?int $relatedItemId): ?array
{
$order = (new orders_o())->getOrderById($orderId);
if (!$order->exists()) {
return null;
}
$violation = (new customer_rule_product_restriction_service())->violationForCustomerProduct(
(int)$order->customer_id->value(),
$productId
);
if ($violation === null) {
return null;
}
// Keep the singular key during the API migration for existing invoice
// and logging consumers while also returning every matching rule.
return ['rule' => (string)$violation['rules'][0]] + $violation;
}
}

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