Skip to content

Commit 431b558

Browse files
authored
Doc updates & linting fixes from latest Rust update (#81)
* Refine the framework buildpacks to better describe what they do, and to make their usage instructions flow with clarity * Explain more redirects * Correct Vite doc * Skip GitHub CI run for changes to only documentation (markdown files) * Fix lint errors caught by CI from newest Rust update. * cargo fmt * Clarify Route Precedence docs
1 parent 85263cb commit 431b558

File tree

13 files changed

+227
-110
lines changed

13 files changed

+227
-110
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ name: CI
33
on:
44
push:
55
branches: ["main"]
6+
paths-ignore:
7+
- '**/*.md'
68
pull_request:
9+
paths-ignore:
10+
- '**/*.md'
711

812
permissions:
913
contents: read

buildpacks/static-web-server/README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ For example, a request to `example.com/support` will be tried in the document ro
310310

311311
*Default: none*
312312

313-
Define preset HTTP responses. Supports the common HTTP redirect use-case, or any custom status, headers, and body response.
313+
Define preset HTTP responses. Supports common use-cases such as: HTTP redirects, health check endpoint, or any custom status, headers, and body response.
314314

315315
```toml
316316
[[com.heroku.static-web-server.caddy_server_opts.static_responses]]
@@ -352,7 +352,9 @@ body = "I could be anything."
352352
- `{http.request.uri.path.file}`
353353
- `{http.request.uri.query}`
354354

355-
For example, permanently redirect to a different path with status `301` and a `Location` header, using the requested filename in the new path:
355+
##### Caddy: Redirect examples
356+
357+
Permanently redirect to a different path with status `301` and a `Location` header, using the requested filename in the new path:
356358

357359
```toml
358360
[[com.heroku.static-web-server.caddy_server_opts.static_responses]]
@@ -373,6 +375,16 @@ status = 301
373375
"X-Redirected-From" = "original.example.com"
374376
```
375377

378+
##### Caddy: Health check example
379+
380+
```toml
381+
[[com.heroku.static-web-server.caddy_server_opts.static_responses]]
382+
path_matcher = "/health"
383+
body = '{"status":"ok"}'
384+
[com.heroku.static-web-server.caddy_server_opts.static_responses.headers]
385+
"Content-Type" = "application/json"
386+
```
387+
376388
#### Caddy: Basic Authorization
377389

378390
*Default: not enabled*
@@ -539,3 +551,16 @@ docker run \
539551
-it --entrypoint bash \
540552
<APP_NAME>
541553
```
554+
555+
## Route Precendence
556+
557+
The static web server is configured to handle request URLs with the following path-matched precedence:
558+
559+
1. [optional] [Caddy: Basic Authorization](#caddy-basic-authorization)
560+
2. [optional] [Caddy: Static Responses](#caddy-static-responses) (terminating)
561+
3. [optional] [Caddy: Clean URLs](#caddy-clean-urls)
562+
1. exact URL path
563+
2. URL path + `.html` (rewrite)
564+
4. File Server
565+
1. exact URL path
566+
2. for directories, URL path + default document `index.html`

buildpacks/static-web-server/tests/integration_test.rs

Lines changed: 101 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ fn default_behavior() {
1818
&mut ContainerConfig::new(),
1919
|_container, socket_addr| {
2020
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
21-
ureq::get(&format!("http://{socket_addr}")).call()
21+
ureq::get(&format!("http://{socket_addr}"))
22+
.call()
23+
.map_err(Box::new)
2224
});
2325
match response_result {
2426
Ok(response) => {
@@ -48,7 +50,9 @@ fn build_command() {
4850
|_container, socket_addr| {
4951
// Test for successful response
5052
let response = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
51-
ureq::get(&format!("http://{socket_addr}/")).call()
53+
ureq::get(&format!("http://{socket_addr}/"))
54+
.call()
55+
.map_err(Box::new)
5256
})
5357
.unwrap();
5458
let response_status = response.status();
@@ -61,7 +65,9 @@ fn build_command() {
6165

6266
// Test for default Not Found response
6367
let response = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
64-
ureq::get(&format!("http://{socket_addr}/test-output.txt")).call()
68+
ureq::get(&format!("http://{socket_addr}/test-output.txt"))
69+
.call()
70+
.map_err(Box::new)
6571
})
6672
.unwrap();
6773
let response_status = response.status();
@@ -101,7 +107,9 @@ fn top_level_doc_root() {
101107
&mut ContainerConfig::new(),
102108
|_container, socket_addr| {
103109
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
104-
ureq::get(&format!("http://{socket_addr}/")).call()
110+
ureq::get(&format!("http://{socket_addr}/"))
111+
.call()
112+
.map_err(Box::new)
105113
});
106114
match response_result {
107115
Ok(response) => {
@@ -120,22 +128,26 @@ fn top_level_doc_root() {
120128
}
121129

122130
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
123-
ureq::get(&format!("http://{socket_addr}/non-existent-path")).call()
131+
ureq::get(&format!("http://{socket_addr}/non-existent-path"))
132+
.call()
133+
.map_err(Box::new)
124134
});
125135
match response_result {
126-
Err(ureq::Error::Status(code, response)) => {
127-
assert_eq!(code, 404);
128-
let h = response.header("Content-Type").unwrap_or_default();
129-
assert_contains!(h, "text/html");
130-
let response_body = response.into_string().unwrap();
131-
assert_contains!(response_body, "Custom 404");
132-
}
133136
Ok(_) => {
134137
panic!("should respond 404 Not Found, but got 200 ok");
135138
}
136-
Err(error) => {
137-
panic!("should respond 404 Not Found, but got other error: {error:?}");
138-
}
139+
Err(err) => match *err {
140+
ureq::Error::Status(code, response) => {
141+
assert_eq!(code, 404);
142+
let h = response.header("Content-Type").unwrap_or_default();
143+
assert_contains!(h, "text/html");
144+
let response_body = response.into_string().unwrap();
145+
assert_contains!(response_body, "Custom 404");
146+
}
147+
error @ ureq::Error::Transport(_) => {
148+
panic!("should respond 404 Not Found, but got other error: {error:?}");
149+
}
150+
},
139151
}
140152
},
141153
);
@@ -152,7 +164,9 @@ fn custom_headers() {
152164
&mut ContainerConfig::new(),
153165
|_container, socket_addr| {
154166
let response = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
155-
ureq::get(&format!("http://{socket_addr}/")).call()
167+
ureq::get(&format!("http://{socket_addr}/"))
168+
.call()
169+
.map_err(Box::new)
156170
})
157171
.unwrap();
158172
let h = response.header("X-Global").unwrap_or_default();
@@ -167,7 +181,9 @@ fn custom_headers() {
167181
);
168182

169183
let response = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
170-
ureq::get(&format!("http://{socket_addr}/page2.html")).call()
184+
ureq::get(&format!("http://{socket_addr}/page2.html"))
185+
.call()
186+
.map_err(Box::new)
171187
})
172188
.unwrap();
173189
let h = response.header("X-Only-HTML").unwrap_or_default();
@@ -193,22 +209,26 @@ fn custom_errors() {
193209
&mut ContainerConfig::new(),
194210
|_container, socket_addr| {
195211
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
196-
ureq::get(&format!("http://{socket_addr}/non-existent-path")).call()
212+
ureq::get(&format!("http://{socket_addr}/non-existent-path"))
213+
.call()
214+
.map_err(Box::new)
197215
});
198216
match response_result {
199-
Err(ureq::Error::Status(code, response)) => {
200-
assert_eq!(code, 404);
201-
let h = response.header("Content-Type").unwrap_or_default();
202-
assert_contains!(h, "text/html");
203-
let response_body = response.into_string().unwrap();
204-
assert_contains!(response_body, "Custom 404");
205-
}
206217
Ok(_) => {
207218
panic!("should respond 404 Not Found, but got 200 ok");
208219
}
209-
Err(error) => {
210-
panic!("should respond 404 Not Found, but got other error: {error:?}");
211-
}
220+
Err(err) => match *err {
221+
ureq::Error::Status(code, response) => {
222+
assert_eq!(code, 404);
223+
let h = response.header("Content-Type").unwrap_or_default();
224+
assert_contains!(h, "text/html");
225+
let response_body = response.into_string().unwrap();
226+
assert_contains!(response_body, "Custom 404");
227+
}
228+
error @ ureq::Error::Transport(_) => {
229+
panic!("should respond 404 Not Found, but got other error: {error:?}");
230+
}
231+
},
212232
}
213233
},
214234
);
@@ -225,7 +245,9 @@ fn client_side_routing() {
225245
&mut ContainerConfig::new(),
226246
|_container, socket_addr| {
227247
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
228-
ureq::get(&format!("http://{socket_addr}/non-existent-path")).call()
248+
ureq::get(&format!("http://{socket_addr}/non-existent-path"))
249+
.call()
250+
.map_err(Box::new)
229251
});
230252
match response_result {
231253
Ok(response) => {
@@ -260,7 +282,9 @@ fn runtime_configuration_custom() {
260282
),
261283
|container, socket_addr| {
262284
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
263-
ureq::get(&format!("http://{socket_addr}/")).call()
285+
ureq::get(&format!("http://{socket_addr}/"))
286+
.call()
287+
.map_err(Box::new)
264288
});
265289
match response_result {
266290
Ok(response) => {
@@ -275,7 +299,9 @@ fn runtime_configuration_custom() {
275299
}
276300
}
277301
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
278-
ureq::get(&format!("http://{socket_addr}/subsection/")).call()
302+
ureq::get(&format!("http://{socket_addr}/subsection/"))
303+
.call()
304+
.map_err(Box::new)
279305
});
280306
match response_result {
281307
Ok(response) => {
@@ -333,7 +359,9 @@ fn runtime_configuration_default() {
333359
),
334360
|_container, socket_addr| {
335361
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
336-
ureq::get(&format!("http://{socket_addr}/")).call()
362+
ureq::get(&format!("http://{socket_addr}/"))
363+
.call()
364+
.map_err(Box::new)
337365
});
338366
match response_result {
339367
Ok(response) => {
@@ -362,7 +390,9 @@ fn caddy_csp_nonce() {
362390
&mut ContainerConfig::new(),
363391
|container, socket_addr| {
364392
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
365-
ureq::get(&format!("http://{socket_addr}")).call()
393+
ureq::get(&format!("http://{socket_addr}"))
394+
.call()
395+
.map_err(Box::new)
366396
});
367397
match response_result {
368398
Ok(response) => {
@@ -395,7 +425,9 @@ fn caddy_clean_urls() {
395425
&mut ContainerConfig::new(),
396426
|container, socket_addr| {
397427
let index_response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
398-
ureq::get(&format!("http://{socket_addr}")).call()
428+
ureq::get(&format!("http://{socket_addr}"))
429+
.call()
430+
.map_err(Box::new)
399431
});
400432
match index_response_result {
401433
Ok(response) => {
@@ -410,7 +442,9 @@ fn caddy_clean_urls() {
410442
}
411443
}
412444
let other_response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
413-
ureq::get(&format!("http://{socket_addr}/other")).call()
445+
ureq::get(&format!("http://{socket_addr}/other"))
446+
.call()
447+
.map_err(Box::new)
414448
});
415449
match other_response_result {
416450
Ok(response) => {
@@ -425,7 +459,9 @@ fn caddy_clean_urls() {
425459
}
426460
}
427461
let nested_response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
428-
ureq::get(&format!("http://{socket_addr}/nested")).call()
462+
ureq::get(&format!("http://{socket_addr}/nested"))
463+
.call()
464+
.map_err(Box::new)
429465
});
430466
match nested_response_result {
431467
Ok(response) => {
@@ -441,7 +477,9 @@ fn caddy_clean_urls() {
441477
}
442478
let nested_second_response_result =
443479
retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
444-
ureq::get(&format!("http://{socket_addr}/nested/second")).call()
480+
ureq::get(&format!("http://{socket_addr}/nested/second"))
481+
.call()
482+
.map_err(Box::new)
445483
});
446484
match nested_second_response_result {
447485
Ok(response) => {
@@ -457,7 +495,9 @@ fn caddy_clean_urls() {
457495
}
458496
let nested_deeper_response_result =
459497
retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
460-
ureq::get(&format!("http://{socket_addr}/nested/deeper")).call()
498+
ureq::get(&format!("http://{socket_addr}/nested/deeper"))
499+
.call()
500+
.map_err(Box::new)
461501
});
462502
match nested_deeper_response_result {
463503
Ok(response) => {
@@ -486,7 +526,9 @@ fn caddy_access_logs() {
486526
&mut ContainerConfig::new(),
487527
|container, socket_addr| {
488528
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
489-
ureq::get(&format!("http://{socket_addr}")).call()
529+
ureq::get(&format!("http://{socket_addr}"))
530+
.call()
531+
.map_err(Box::new)
490532
});
491533
match response_result {
492534
Ok(response) => {
@@ -522,17 +564,23 @@ fn caddy_basic_auth() {
522564
),
523565
|container, socket_addr| {
524566
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
525-
ureq::get(&format!("http://{socket_addr}")).call()
567+
ureq::get(&format!("http://{socket_addr}"))
568+
.call()
569+
.map_err(Box::new)
526570
});
527571
match response_result {
528-
Err(ureq::Error::Status(code, _response)) => {
529-
assert_eq!(code, 401);
530-
}
531572
Ok(_) => {
532573
panic!("should respond 401 Unauthorized, but got 200 ok");
533574
}
534-
Err(error) => {
535-
panic!("should respond 401 Unauthorized, but got other error: {error:?}");
575+
Err(err) => {
576+
match *err {
577+
ureq::Error::Status(code, _response) => {
578+
assert_eq!(code, 401);
579+
}
580+
error @ ureq::Error::Transport(_) => {
581+
panic!("should respond 401 Unauthorized, but got other error: {error:?}");
582+
}
583+
}
536584
}
537585
}
538586

@@ -545,6 +593,7 @@ fn caddy_basic_auth() {
545593
"Basic dmlzaXRvcjpvcGVuc2Vhc2FtZQ==",
546594
)
547595
.call()
596+
.map_err(Box::new)
548597
});
549598
match auth_response_result {
550599
Ok(response) => {
@@ -579,7 +628,9 @@ fn caddy_basic_auth() {
579628
),
580629
|container, socket_addr| {
581630
let response_result = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
582-
ureq::get(&format!("http://{socket_addr}")).call()
631+
ureq::get(&format!("http://{socket_addr}"))
632+
.call()
633+
.map_err(Box::new)
583634
});
584635
match response_result {
585636
Ok(response) => {
@@ -616,7 +667,10 @@ fn caddy_static_responses() {
616667
let ureq_agent: ureq::Agent = ureq::AgentBuilder::new().redirects(0).build();
617668

618669
let response = retry(DEFAULT_RETRIES, DEFAULT_RETRY_DELAY, || {
619-
ureq_agent.get(&format!("http://{socket_addr}")).call()
670+
ureq_agent
671+
.get(&format!("http://{socket_addr}"))
672+
.call()
673+
.map_err(Box::new)
620674
})
621675
.unwrap();
622676
assert_eq!(response.status(), 200);

0 commit comments

Comments
 (0)