mirror of
https://github.com/caddyserver/caddy.git
synced 2025-12-08 06:09:53 +00:00
Merge 01828e38bb into 31960dc998
This commit is contained in:
commit
f11c0a6159
17 changed files with 1463 additions and 0 deletions
106
.github/workflows/ci.yml
vendored
106
.github/workflows/ci.yml
vendored
|
|
@ -63,6 +63,7 @@ jobs:
|
||||||
contents: read
|
contents: read
|
||||||
pull-requests: read
|
pull-requests: read
|
||||||
actions: write # to allow uploading artifacts and cache
|
actions: write # to allow uploading artifacts and cache
|
||||||
|
checks: write
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
|
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
|
||||||
|
|
@ -152,6 +153,111 @@ jobs:
|
||||||
# echo "step_test ${{ steps.step_test.outputs.status }}\n"
|
# echo "step_test ${{ steps.step_test.outputs.status }}\n"
|
||||||
# exit 1
|
# exit 1
|
||||||
|
|
||||||
|
spec-test:
|
||||||
|
permissions:
|
||||||
|
checks: write
|
||||||
|
pull-requests: write
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
go:
|
||||||
|
- '1.25'
|
||||||
|
|
||||||
|
include:
|
||||||
|
# Set the minimum Go patch version for the given Go minor
|
||||||
|
# Usable via ${{ matrix.GO_SEMVER }}
|
||||||
|
- go: '1.25'
|
||||||
|
GO_SEMVER: '~1.25.0'
|
||||||
|
|
||||||
|
# Set some variables per OS, usable via ${{ matrix.VAR }}
|
||||||
|
# OS_LABEL: the VM label from GitHub Actions (see https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories)
|
||||||
|
# CADDY_BIN_PATH: the path to the compiled Caddy binary, for artifact publishing
|
||||||
|
# SUCCESS: the typical value for $? per OS (Windows/pwsh returns 'True')
|
||||||
|
- os: linux
|
||||||
|
OS_LABEL: ubuntu-latest
|
||||||
|
CADDY_BIN_PATH: ./cmd/caddy/caddy
|
||||||
|
SUCCESS: 0
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.OS_LABEL }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.GO_SEMVER }}
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
|
- name: Print Go version and environment
|
||||||
|
id: vars
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
printf "curl version: $(curl --version)\n"
|
||||||
|
printf "Using go at: $(which go)\n"
|
||||||
|
printf "Go version: $(go version)\n"
|
||||||
|
printf "\n\nGo environment:\n\n"
|
||||||
|
go env
|
||||||
|
printf "\n\nSystem environment:\n\n"
|
||||||
|
env
|
||||||
|
printf "Git version: $(git version)\n\n"
|
||||||
|
# Calculate the short SHA1 hash of the git commit
|
||||||
|
echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Get dependencies
|
||||||
|
run: |
|
||||||
|
go get -v -t ./...
|
||||||
|
# mkdir test-results
|
||||||
|
- name: Build Caddy
|
||||||
|
working-directory: ./cmd/caddy
|
||||||
|
env:
|
||||||
|
CGO_ENABLED: 0
|
||||||
|
run: |
|
||||||
|
go build -cover -tags nobadger,nopgx,nomysql -trimpath -ldflags="-w -s" -v
|
||||||
|
|
||||||
|
- name: Install Hurl
|
||||||
|
env:
|
||||||
|
HURL_VERSION: "7.0.0"
|
||||||
|
run: |
|
||||||
|
curl --location --remote-name https://github.com/Orange-OpenSource/hurl/releases/download/${HURL_VERSION}/hurl_${HURL_VERSION}_amd64.deb
|
||||||
|
sudo dpkg -i hurl_${HURL_VERSION}_amd64.deb
|
||||||
|
hurl --version
|
||||||
|
|
||||||
|
- name: Run Caddy
|
||||||
|
run: |
|
||||||
|
./cmd/caddy/caddy environ
|
||||||
|
mkdir coverdir
|
||||||
|
export GOCOVERDIR=./coverdir
|
||||||
|
./cmd/caddy/caddy start
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
- name: Run tests with Hurl
|
||||||
|
run: |
|
||||||
|
mkdir hurl-report
|
||||||
|
find . -name *.hurl -exec hurl --jobs 1 --variables-file caddytest/spec/hurl_vars.properties --very-verbose --verbose --test --report-junit hurl-report/junit.xml --color {} \;
|
||||||
|
|
||||||
|
- name: Publish Test Results
|
||||||
|
uses: EnricoMi/publish-unit-test-result-action@3a74b2957438d0b6e2e61d67b05318aa25c9e6c6 # v2.20.0
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
hurl-report/junit.xml
|
||||||
|
|
||||||
|
- name: Generate Coverage Data
|
||||||
|
run: |
|
||||||
|
export GOCOVERDIR=./coverdir
|
||||||
|
./cmd/caddy/caddy stop
|
||||||
|
go tool covdata textfmt -i=coverdir -o hurl-report/caddy_cover_${{ steps.vars.outputs.short_sha }}.txt
|
||||||
|
go tool cover -html hurl-report/caddy_cover_${{ steps.vars.outputs.short_sha }}.txt -o hurl-report/caddy_cover_${{ steps.vars.outputs.short_sha }}.html
|
||||||
|
|
||||||
|
|
||||||
|
- name: Publish Coverage Profile
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
path: hurl-report/caddy_cover_${{ steps.vars.outputs.short_sha }}.html
|
||||||
|
compression-level: 0
|
||||||
|
|
||||||
s390x-test:
|
s390x-test:
|
||||||
name: test (s390x on IBM Z)
|
name: test (s390x on IBM Z)
|
||||||
permissions:
|
permissions:
|
||||||
|
|
|
||||||
38
caddytest/spec/http/basicauth/spec.hurl
Normal file
38
caddytest/spec/http/basicauth/spec.hurl
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
log
|
||||||
|
basic_auth {
|
||||||
|
john $2a$14$x4HlYwA9Zeer4RkMEYbUzug9XxWmncneR.dcMs.UjalR95URnHg5.
|
||||||
|
}
|
||||||
|
respond "Hello, World!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# requests without `Authorization` header are rejected with 401
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 401
|
||||||
|
[Asserts]
|
||||||
|
header "WWW-Authenticate" == "Basic realm=\"restricted\""
|
||||||
|
|
||||||
|
|
||||||
|
# requests with `Authorization` header are accepted with 200
|
||||||
|
GET https://localhost:9443
|
||||||
|
[BasicAuth]
|
||||||
|
john:password
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
`Hello, World!`
|
||||||
150
caddytest/spec/http/error/spec.hurl
Normal file
150
caddytest/spec/http/error/spec.hurl
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
# Configure Caddy with error directive
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
error /forbidden* "Access denied" 403
|
||||||
|
respond "OK"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# error directive triggers 403 for matching paths
|
||||||
|
GET https://localhost:9443/forbidden/resource
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 403
|
||||||
|
|
||||||
|
|
||||||
|
# error directive does not trigger for non-matching paths
|
||||||
|
GET https://localhost:9443/allowed
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "OK"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with error and handle_errors
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
error /admin* "Forbidden" 403
|
||||||
|
handle_errors {
|
||||||
|
respond "Custom error: {err.status_code} - {err.status_text}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# error with handle_errors shows custom error page
|
||||||
|
GET https://localhost:9443/admin/panel
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 403
|
||||||
|
[Asserts]
|
||||||
|
body == "Custom error: 403 - Forbidden"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with conditional error
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
@admin path /admin*
|
||||||
|
error @admin 404
|
||||||
|
respond "Public content"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# error with named matcher triggers on match
|
||||||
|
GET https://localhost:9443/admin/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 404
|
||||||
|
|
||||||
|
|
||||||
|
# error with named matcher doesn't trigger on non-match
|
||||||
|
GET https://localhost:9443/public
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Public content"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with error for specific methods
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
@post method POST
|
||||||
|
error @post "Method not allowed" 405
|
||||||
|
respond "GET OK"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# error blocks POST requests
|
||||||
|
POST https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 405
|
||||||
|
|
||||||
|
|
||||||
|
# error allows GET requests
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "GET OK"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with dynamic error message
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
error /error* "Path {path} not found" 404
|
||||||
|
handle_errors {
|
||||||
|
respond "{err.message}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# error message can use placeholders
|
||||||
|
GET https://localhost:9443/error/test
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 404
|
||||||
|
[Asserts]
|
||||||
|
body == "Path /error/test not found"
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Index.html Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Index.html
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
caddytest/spec/http/file_server/assets/indexed/index.txt
Normal file
1
caddytest/spec/http/file_server/assets/indexed/index.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
index.txt
|
||||||
119
caddytest/spec/http/file_server/spec.hurl
Normal file
119
caddytest/spec/http/file_server/spec.hurl
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
# Configure Caddy with default configuration
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
root {{indexed_root}}
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# requests without specific file receive index file per
|
||||||
|
# the default index list: index.html, index.txt
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Index.html Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Index.html
|
||||||
|
</body>
|
||||||
|
</html>```
|
||||||
|
|
||||||
|
|
||||||
|
# if index.txt is specifically requested, we expect index.txt
|
||||||
|
GET https://localhost:9443/index.txt
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "index.txt"
|
||||||
|
|
||||||
|
# requests for sub-folder followed by .. result in sanitized path
|
||||||
|
GET https://localhost:9443/non-existent/../index.txt
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "index.txt"
|
||||||
|
|
||||||
|
# results out of root folder are sanitized,
|
||||||
|
# and conform to default index list sequence.
|
||||||
|
GET https://localhost:9443/../
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Index.html Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Index.html
|
||||||
|
</body>
|
||||||
|
</html>```
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with custsom index "index.txt"
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
root {{indexed_root}}
|
||||||
|
file_server {
|
||||||
|
index index.txt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "index.txt"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure with a root not containing index files
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
root {{unindexed_root}}
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 404
|
||||||
132
caddytest/spec/http/forward_auth/spec.hurl
Normal file
132
caddytest/spec/http/forward_auth/spec.hurl
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
# Configure Caddy with forward_auth directive
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
forward_auth localhost:9080 {
|
||||||
|
uri /auth
|
||||||
|
}
|
||||||
|
respond "Protected content"
|
||||||
|
}
|
||||||
|
http://localhost:9080 {
|
||||||
|
handle /auth {
|
||||||
|
respond 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# forward_auth allows request when auth endpoint returns 2xx
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
delay: 500ms
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Protected content"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with forward_auth rejecting
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
forward_auth localhost:9080 {
|
||||||
|
uri /auth
|
||||||
|
}
|
||||||
|
respond "Protected content"
|
||||||
|
}
|
||||||
|
http://localhost:9080 {
|
||||||
|
handle /auth {
|
||||||
|
respond 401
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# forward_auth blocks request when auth endpoint returns 4xx
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
delay: 500ms
|
||||||
|
insecure: true
|
||||||
|
HTTP 401
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with forward_auth copying headers
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
forward_auth localhost:9080 {
|
||||||
|
uri /auth
|
||||||
|
copy_headers X-User-ID X-User-Email
|
||||||
|
}
|
||||||
|
respond "User: {header.X-User-ID}, Email: {header.X-User-Email}"
|
||||||
|
}
|
||||||
|
http://localhost:9080 {
|
||||||
|
handle /auth {
|
||||||
|
header X-User-ID "user123"
|
||||||
|
header X-User-Email "user@example.com"
|
||||||
|
respond 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# forward_auth copies specified headers from auth response
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
delay: 500ms
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "User: user123, Email: user@example.com"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with forward_auth and custom headers
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
forward_auth localhost:9080 {
|
||||||
|
uri /auth
|
||||||
|
header_up X-Original-URL {uri}
|
||||||
|
}
|
||||||
|
respond "OK"
|
||||||
|
}
|
||||||
|
http://localhost:9080 {
|
||||||
|
handle /auth {
|
||||||
|
respond "{header.X-Original-URL}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# forward_auth can send custom headers to auth endpoint
|
||||||
|
GET https://localhost:9443/test/path
|
||||||
|
[Options]
|
||||||
|
delay: 500ms
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "OK"
|
||||||
22
caddytest/spec/http/headers/spec.hurl
Normal file
22
caddytest/spec/http/headers/spec.hurl
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
header "X-Custom-Header" "Custom-Value"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
header "X-Custom-Header" == "Custom-Value"
|
||||||
190
caddytest/spec/http/request_header/spec.hurl
Normal file
190
caddytest/spec/http/request_header/spec.hurl
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
# Configure Caddy with request_header directive
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
request_header X-Custom-Header "CustomValue"
|
||||||
|
respond "{header.X-Custom-Header}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# request_header adds headers to request
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "CustomValue"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with request_header removing headers
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
request_header -User-Agent
|
||||||
|
respond "UA: {header.User-Agent}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# request_header can remove headers
|
||||||
|
GET https://localhost:9443
|
||||||
|
User-Agent: TestAgent/1.0
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "UA: "
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with request_header replacing headers
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
request_header Host "example.com"
|
||||||
|
respond "Host: {host}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# request_header can replace Host header
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Host: example.com"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with request_header using placeholders
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
request_header X-Original-Path {path}
|
||||||
|
respond "Path: {header.X-Original-Path}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# request_header can use placeholders
|
||||||
|
GET https://localhost:9443/test/path
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Path: /test/path"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with conditional request_header
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
@api path /api/*
|
||||||
|
request_header @api X-API "true"
|
||||||
|
respond "API: {header.X-API}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# request_header applies conditionally based on matcher
|
||||||
|
GET https://localhost:9443/api/test
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "API: true"
|
||||||
|
|
||||||
|
|
||||||
|
# request_header doesn't apply when matcher doesn't match
|
||||||
|
GET https://localhost:9443/other
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "API: "
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with multiple request_header operations
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
request_header X-First "1"
|
||||||
|
request_header X-Second "2"
|
||||||
|
request_header X-Third "3"
|
||||||
|
respond "{header.X-First},{header.X-Second},{header.X-Third}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# multiple request_header directives are applied
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "1,2,3"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with request_header and reverse_proxy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
request_header X-Custom-Header "Value"
|
||||||
|
reverse_proxy localhost:9450
|
||||||
|
}
|
||||||
|
http://localhost:9450 {
|
||||||
|
respond "{header.X-Custom-Header}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# request_header adds header before reverse_proxy
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Value"
|
||||||
36
caddytest/spec/http/requestbody/spec.hurl
Normal file
36
caddytest/spec/http/requestbody/spec.hurl
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
log
|
||||||
|
request_body {
|
||||||
|
max_size 2B
|
||||||
|
}
|
||||||
|
reverse_proxy localhost:8000 # to fake body reading
|
||||||
|
handle_errors 4xx {
|
||||||
|
respond "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http://localhost:8000 {
|
||||||
|
respond "Failed"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
delay: 1s
|
||||||
|
insecure: true
|
||||||
|
```
|
||||||
|
Hello
|
||||||
|
```
|
||||||
|
HTTP 413
|
||||||
|
`OK`
|
||||||
|
|
||||||
|
# TODO: how to test{read,write}_timeout?
|
||||||
66
caddytest/spec/http/rewrite/spec.hurl
Normal file
66
caddytest/spec/http/rewrite/spec.hurl
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
User-Agent: hurl/ci
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
rewrite /from /to
|
||||||
|
respond {uri}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# simple scenario: rewriting /from to /to produces expected result of seeing /to
|
||||||
|
GET https://localhost:9443/from
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/to"
|
||||||
|
|
||||||
|
# unmatched path is passed through unchanged
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/"
|
||||||
|
|
||||||
|
# having a query parameter does not trip the rewrite and retains the query
|
||||||
|
GET https://localhost:9443/from?query_param=value
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/to?query_param=value"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
User-Agent: hurl/ci
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
rewrite /from /to?a=b
|
||||||
|
respond {uri}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# a rewrite with query parameters affects the parameters
|
||||||
|
GET https://localhost:9443/from?query_param=value
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/to?a=b"
|
||||||
171
caddytest/spec/http/route/spec.hurl
Normal file
171
caddytest/spec/http/route/spec.hurl
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
# Configure Caddy with route directive
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
route /api/* {
|
||||||
|
uri strip_prefix /api
|
||||||
|
respond "API: {uri}"
|
||||||
|
}
|
||||||
|
respond "Not API"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# route groups handlers and maintains order
|
||||||
|
GET https://localhost:9443/api/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "API: /users"
|
||||||
|
|
||||||
|
|
||||||
|
# route doesn't match non-matching paths
|
||||||
|
GET https://localhost:9443/other
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Not API"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with nested routes
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
route /api/* {
|
||||||
|
uri strip_prefix /api
|
||||||
|
route /v1/* {
|
||||||
|
uri strip_prefix /v1
|
||||||
|
respond "API v1: {uri}"
|
||||||
|
}
|
||||||
|
respond "API: {uri}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# nested routes process sequentially
|
||||||
|
GET https://localhost:9443/api/v1/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "API v1: /users"
|
||||||
|
|
||||||
|
|
||||||
|
# outer route processes when inner doesn't match
|
||||||
|
GET https://localhost:9443/api/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "API: /users"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with route and terminal handlers
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
route {
|
||||||
|
header X-First "1"
|
||||||
|
respond "Response"
|
||||||
|
header X-Second "2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# route stops at terminal handler (respond)
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
header "X-First" == "1"
|
||||||
|
header "X-Second" not exists
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with route preserving handler order
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
route {
|
||||||
|
vars step1 "done"
|
||||||
|
vars step2 "done"
|
||||||
|
vars step3 "done"
|
||||||
|
respond "{vars.step1},{vars.step2},{vars.step3}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# route preserves exact handler order
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "done,done,done"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with route and matchers
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
route {
|
||||||
|
@api path /api/*
|
||||||
|
vars @api type "api"
|
||||||
|
vars type "other"
|
||||||
|
respond "{vars.type}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# route applies matchers in sequence
|
||||||
|
GET https://localhost:9443/api/test
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "other"
|
||||||
|
|
||||||
|
|
||||||
|
# route continues when matcher doesn't match
|
||||||
|
GET https://localhost:9443/test
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "other"
|
||||||
105
caddytest/spec/http/static_response/spec.hurl
Normal file
105
caddytest/spec/http/static_response/spec.hurl
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
User-Agent: hurl/ci
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
log
|
||||||
|
respond "Hello, World!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
`Hello, World!`
|
||||||
|
|
||||||
|
|
||||||
|
GET https://localhost:9443/foo
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
`Hello, World!`
|
||||||
|
|
||||||
|
# Configure Caddy
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
User-Agent: hurl/ci
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
respond "New text!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP/2 200
|
||||||
|
[Asserts]
|
||||||
|
`New text!`
|
||||||
|
|
||||||
|
|
||||||
|
GET https://localhost:9443/foo
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP/2 200
|
||||||
|
[Asserts]
|
||||||
|
`New text!`
|
||||||
|
|
||||||
|
GET https://localhost:9443/foo
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP/2 200
|
||||||
|
[Asserts]
|
||||||
|
body != "Hello, World!"
|
||||||
|
|
||||||
|
# Configure Caddy
|
||||||
|
# The body is a placeholder
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
User-Agent: hurl/ci
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
log
|
||||||
|
respond {http.request.body}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# handler responds with the "application/json" if the response body is valid JSON
|
||||||
|
POST https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"greeting": "Hello, world!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
HTTP/2 200
|
||||||
|
[Asserts]
|
||||||
|
header "Content-Type" == "application/json"
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"greeting": "Hello, world!"
|
||||||
|
}
|
||||||
|
```
|
||||||
191
caddytest/spec/http/uri/spec.hurl
Normal file
191
caddytest/spec/http/uri/spec.hurl
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
# Configure Caddy with uri strip_prefix
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri strip_prefix /api
|
||||||
|
respond {uri}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# strip_prefix removes the prefix from the URI
|
||||||
|
GET https://localhost:9443/api/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/users"
|
||||||
|
|
||||||
|
|
||||||
|
# URI without prefix is unchanged
|
||||||
|
GET https://localhost:9443/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/users"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with uri strip_suffix
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri strip_suffix .php
|
||||||
|
respond {uri}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# strip_suffix removes the suffix from the URI
|
||||||
|
GET https://localhost:9443/index.php
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/index"
|
||||||
|
|
||||||
|
|
||||||
|
# URI without suffix is unchanged
|
||||||
|
GET https://localhost:9443/index.html
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/index.html"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with uri replace
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri replace old new
|
||||||
|
respond {uri}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# replace substitutes all occurrences
|
||||||
|
GET https://localhost:9443/old/path/old
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/new/path/new"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with uri path_regexp
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri path_regexp /([0-9]+) /$1/id
|
||||||
|
respond {uri}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# path_regexp replaces using regular expressions
|
||||||
|
GET https://localhost:9443/123
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "/123/id"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with uri query operations
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri query +foo bar
|
||||||
|
respond {query}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# query operations add parameters
|
||||||
|
GET https://localhost:9443/?existing=value
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "existing=value&foo=bar"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with uri query delete
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri query -sensitive
|
||||||
|
respond {query}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# query operations delete parameters
|
||||||
|
GET https://localhost:9443/?keep=this&sensitive=secret
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "keep=this"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with uri query rename
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
uri query old>new
|
||||||
|
respond {query}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# query operations rename parameters
|
||||||
|
GET https://localhost:9443/?old=value
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "new=value"
|
||||||
125
caddytest/spec/http/vars/spec.hurl
Normal file
125
caddytest/spec/http/vars/spec.hurl
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
# Configure Caddy with vars directive
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
vars my_var "custom_value"
|
||||||
|
vars another_var "another_value"
|
||||||
|
respond "{vars.my_var} {vars.another_var}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Variables are accessible in placeholders
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "custom_value another_value"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with vars using placeholders
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
vars request_path {path}
|
||||||
|
vars request_method {method}
|
||||||
|
respond "Path: {vars.request_path}, Method: {vars.request_method}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Variables can be set from request placeholders
|
||||||
|
GET https://localhost:9443/test/path
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Path: /test/path, Method: GET"
|
||||||
|
|
||||||
|
|
||||||
|
# POST method is captured correctly
|
||||||
|
POST https://localhost:9443/another
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Path: /another, Method: POST"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with vars in route
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
route /api/* {
|
||||||
|
vars api_version "v1"
|
||||||
|
respond "API {vars.api_version}"
|
||||||
|
}
|
||||||
|
respond "Not API"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Variables are scoped to their route
|
||||||
|
GET https://localhost:9443/api/users
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "API v1"
|
||||||
|
|
||||||
|
|
||||||
|
# Outside the route, variables are not set
|
||||||
|
GET https://localhost:9443/other
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "Not API"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure Caddy with vars overwriting
|
||||||
|
POST http://localhost:2019/load
|
||||||
|
Content-Type: text/caddyfile
|
||||||
|
```
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
http_port 9080
|
||||||
|
https_port 9443
|
||||||
|
local_certs
|
||||||
|
}
|
||||||
|
localhost {
|
||||||
|
# without `route`, middlewares are sorted an unstable sort
|
||||||
|
route {
|
||||||
|
vars my_var "2"
|
||||||
|
vars my_var "1"
|
||||||
|
}
|
||||||
|
respond "{vars.my_var}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Later vars directives overwrite earlier ones
|
||||||
|
GET https://localhost:9443
|
||||||
|
[Options]
|
||||||
|
insecure: true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
body == "1"
|
||||||
2
caddytest/spec/hurl_vars.properties
Normal file
2
caddytest/spec/hurl_vars.properties
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
indexed_root=caddytest/spec/http/file_server/assets/indexed
|
||||||
|
unindexed_root=caddytest/spec/http/file_server/assets/unindexed
|
||||||
Loading…
Add table
Add a link
Reference in a new issue