diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 31c9f1b9c..705c3f0f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -137,15 +137,14 @@ jobs:
- name: Run Caddy
if: matrix.os == 'linux' && matrix.go == '1.22'
- working-directory: ./cmd/caddy
run: |
- ./caddy start
+ ./cmd/caddy/caddy start
- name: Run tests with Hurl
if: matrix.os == 'linux' && matrix.go == '1.22'
run: |
mkdir hurl-report
- find . -name *.hurl -exec hurl --very-verbose --verbose --test --report-junit hurl-report/junit.xml --color {} \;
+ find . -name *.hurl -exec hurl --variables-file caddytest/spec/hurl_vars.properties --very-verbose --verbose --test --report-junit hurl-report/junit.xml --color {} \;
- name: Publish Test Results
if: matrix.os == 'linux' && matrix.go == '1.22'
diff --git a/caddytest/spec/http/file_server/assets/indexed/index.html b/caddytest/spec/http/file_server/assets/indexed/index.html
new file mode 100644
index 000000000..da5de44a0
--- /dev/null
+++ b/caddytest/spec/http/file_server/assets/indexed/index.html
@@ -0,0 +1,9 @@
+
+
+
+ Index.html Title
+
+
+ Index.html
+
+
\ No newline at end of file
diff --git a/caddytest/spec/http/file_server/assets/indexed/index.txt b/caddytest/spec/http/file_server/assets/indexed/index.txt
new file mode 100644
index 000000000..21fc0c67e
--- /dev/null
+++ b/caddytest/spec/http/file_server/assets/indexed/index.txt
@@ -0,0 +1 @@
+index.txt
\ No newline at end of file
diff --git a/caddytest/spec/http/file_server/assets/unindexed/.gitkeep b/caddytest/spec/http/file_server/assets/unindexed/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/caddytest/spec/http/file_server/spec.hurl b/caddytest/spec/http/file_server/spec.hurl
new file mode 100644
index 000000000..be9504e15
--- /dev/null
+++ b/caddytest/spec/http/file_server/spec.hurl
@@ -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]
+```
+
+
+
+ Index.html Title
+
+
+ Index.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]
+```
+
+
+
+ Index.html Title
+
+
+ Index.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
\ No newline at end of file
diff --git a/caddytest/spec/hurl_vars.properties b/caddytest/spec/hurl_vars.properties
new file mode 100644
index 000000000..a3832eaea
--- /dev/null
+++ b/caddytest/spec/hurl_vars.properties
@@ -0,0 +1,2 @@
+indexed_root=caddytest/spec/http/file_server/assets/indexed
+unindexed_root=caddytest/spec/http/file_server/assets/unindexed
\ No newline at end of file