Skip to content

Commit

Permalink
vweb: add an overridable .not_found() method, for making a custom 404…
Browse files Browse the repository at this point in the history
… page + tests fixes (#17936)
  • Loading branch information
Casper64 authored Apr 11, 2023
1 parent f9c186a commit 838083e
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 16 deletions.
13 changes: 13 additions & 0 deletions vlib/vweb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,19 @@ pub fn (mut app App) with_auth() bool {
}
```

### Fallback route
You can implement a fallback `not_found` route that is called when a request is made and no
matching route is found.

**Example:**

``` v ignore
pub fn (mut app App) not_found() vweb.Result {
app.set_status(404, 'Not Found')
return app.html('<h1>Page not found</h1>')
}
```

### Controllers
Controllers can be used to split up app logic so you are able to have one struct
per `"/"`. E.g. a struct `Admin` for urls starting with `"/admin"` and a struct `Foo`
Expand Down
2 changes: 1 addition & 1 deletion vlib/vweb/tests/controller_duplicate_server.v
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct Admin {
}

['/admin/duplicate']
fn (mut app App) duplicate() vweb.Result {
pub fn (mut app App) duplicate() vweb.Result {
return app.text('duplicate')
}

Expand Down
18 changes: 15 additions & 3 deletions vlib/vweb/tests/controller_test.v
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import os
import time
import json
import net
import net.http
import io

const (
sport = 12382
Expand Down Expand Up @@ -91,6 +88,21 @@ fn test_other_path() {
assert x.body == 'Other path'
}

fn test_different_404() {
res_app := http.get('http://${localserver}/zxcnbnm') or { panic(err) }
assert res_app.status() == .not_found
assert res_app.body == '404 From App'

res_admin := http.get('http://${localserver}/admin/JHKAJA') or { panic(err) }
assert res_admin.status() == .not_found
assert res_admin.body == '404 From Admin'

// Other doesn't have a custom 404 so the vweb.Context's not_found is expected
res_other := http.get('http://${localserver}/other/unknown') or { panic(err) }
assert res_other.status() == .not_found
assert res_other.body == '404 Not Found'
}

fn test_shutdown() {
// This test is guaranteed to be called last.
// It sends a request to the server to shutdown.
Expand Down
22 changes: 16 additions & 6 deletions vlib/vweb/tests/controller_test_server.v
Original file line number Diff line number Diff line change
Expand Up @@ -46,32 +46,42 @@ fn main() {
}

['/']
fn (mut app App) home() vweb.Result {
pub fn (mut app App) home() vweb.Result {
return app.text('App')
}

['/path']
fn (mut app App) app_path() vweb.Result {
pub fn (mut app App) app_path() vweb.Result {
return app.text('App path')
}

pub fn (mut app App) not_found() vweb.Result {
app.set_status(404, 'Not Found')
return app.text('404 From App')
}

['/']
fn (mut app Admin) admin_home() vweb.Result {
pub fn (mut app Admin) admin_home() vweb.Result {
return app.text('Admin')
}

['/path']
fn (mut app Admin) admin_path() vweb.Result {
pub fn (mut app Admin) admin_path() vweb.Result {
return app.text('Admin path')
}

pub fn (mut app Admin) not_found() vweb.Result {
app.set_status(404, 'Not Found')
return app.text('404 From Admin')
}

['/']
fn (mut app Other) other_home() vweb.Result {
pub fn (mut app Other) other_home() vweb.Result {
return app.text('Other')
}

['/path']
fn (mut app Other) other_path() vweb.Result {
pub fn (mut app Other) other_path() vweb.Result {
return app.text('Other path')
}

Expand Down
11 changes: 6 additions & 5 deletions vlib/vweb/tests/vweb_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,16 @@ fn test_http_client_index() {
}

fn test_http_client_404() {
server := 'http://${localserver}'
url_404_list := [
'http://${localserver}/zxcnbnm',
'http://${localserver}/JHKAJA',
'http://${localserver}/unknown',
'/zxcnbnm',
'/JHKAJA',
'/unknown',
]
for url in url_404_list {
res := http.get(url) or { panic(err) }
res := http.get('${server}${url}') or { panic(err) }
assert res.status() == .not_found
assert res.body == '404 on "${url}"'
}
}

Expand Down Expand Up @@ -234,7 +236,6 @@ fn test_http_client_shutdown_does_not_work_without_a_cookie() {
return
}
assert x.status() == .not_found
assert x.body == '404 Not Found'
}

fn testsuite_end() {
Expand Down
6 changes: 6 additions & 0 deletions vlib/vweb/tests/vweb_test_server.v
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ pub fn (mut app App) json() vweb.Result {
return app.ok(app.req.data)
}

// Custom 404 page
pub fn (mut app App) not_found() vweb.Result {
app.set_status(404, 'Not Found')
return app.html('404 on "${app.req.url}"')
}

pub fn (mut app App) shutdown() vweb.Result {
session_key := app.get_cookie('skey') or { return app.not_found() }
if session_key != 'superman' {
Expand Down
2 changes: 1 addition & 1 deletion vlib/vweb/vweb.v
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ fn handle_route[T](mut app T, url urllib.URL, routes &map[string]Route, tid int)
}
}
// Route not found
app.conn.write(vweb.http_404.bytes()) or {}
app.not_found()
}

// validate_middleware validates and fires all middlewares that are defined in the global app instance
Expand Down

0 comments on commit 838083e

Please sign in to comment.