mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
vweb: document live reload
This commit is contained in:
parent
4f518c2850
commit
5355c67ebe
@ -86,6 +86,10 @@ pub enum FormatDelimiter {
|
|||||||
no_delimiter
|
no_delimiter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn Time.new(t Time) Time {
|
||||||
|
return new_time(t)
|
||||||
|
}
|
||||||
|
|
||||||
// smonth returns month name abbreviation.
|
// smonth returns month name abbreviation.
|
||||||
pub fn (t Time) smonth() string {
|
pub fn (t Time) smonth() string {
|
||||||
if t.month <= 0 || t.month > 12 {
|
if t.month <= 0 || t.month > 12 {
|
||||||
|
@ -7,7 +7,14 @@ The [gitly](https://gitly.org/) site is based on vweb.
|
|||||||
**_Some features may not be complete, and have some bugs._**
|
**_Some features may not be complete, and have some bugs._**
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
Just run **`v new <name> web`** in your terminal
|
Just run **`v new <name> web`** in your terminal.
|
||||||
|
|
||||||
|
Run your vweb app with a live reload via `v -d vweb_livereload watch run .`
|
||||||
|
|
||||||
|
Now modifying any file in your web app (whether it's a .v file with the backend logic
|
||||||
|
or a compiled .html template file) will result in an instant refresh of your app
|
||||||
|
in the browser. No need to quit the app, rebuild it, and refresh the page in the browser!
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@ -253,7 +260,7 @@ pub fn (mut app App) controller_get_user_by_id() vweb.Result {
|
|||||||
```
|
```
|
||||||
#### - Host
|
#### - Host
|
||||||
To restrict an endpoint to a specific host, you can use the `host` attribute
|
To restrict an endpoint to a specific host, you can use the `host` attribute
|
||||||
followed by a colon `:` and the host name. You can test the Host feature locally
|
followed by a colon `:` and the host name. You can test the Host feature locally
|
||||||
by adding a host to the "hosts" file of your device.
|
by adding a host to the "hosts" file of your device.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
@ -293,10 +300,10 @@ pub fn (mut app App) before_request() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Middleware functions can be passed directly when creating an App instance and is
|
Middleware functions can be passed directly when creating an App instance and is
|
||||||
executed when the url starts with the defined key.
|
executed when the url starts with the defined key.
|
||||||
|
|
||||||
In the following example, if a user navigates to `/path/to/test` the middleware
|
In the following example, if a user navigates to `/path/to/test` the middleware
|
||||||
is executed in the following order: `middleware_func`, `other_func`, `global_middleware`.
|
is executed in the following order: `middleware_func`, `other_func`, `global_middleware`.
|
||||||
The middleware is executed in the same order as they are defined and if any function in
|
The middleware is executed in the same order as they are defined and if any function in
|
||||||
the chain returns `false` the propogation is stopped.
|
the chain returns `false` the propogation is stopped.
|
||||||
@ -342,7 +349,7 @@ fn global_middleware(mut ctx vweb.Context) bool {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Middleware functions will be of type `vweb.Middleware` and are not methods of App,
|
Middleware functions will be of type `vweb.Middleware` and are not methods of App,
|
||||||
so they could also be imported from other modules.
|
so they could also be imported from other modules.
|
||||||
```v ignore
|
```v ignore
|
||||||
pub type Middleware = fn (mut Context) bool
|
pub type Middleware = fn (mut Context) bool
|
||||||
@ -374,7 +381,7 @@ The middleware is executed in the following order:
|
|||||||
3. The middleware in the `[middleware]` attribute
|
3. The middleware in the `[middleware]` attribute
|
||||||
|
|
||||||
If any function of step 2 or 3 returns `false` the middleware functions that would
|
If any function of step 2 or 3 returns `false` the middleware functions that would
|
||||||
come after it are not executed and the app handler will also not be executed. You
|
come after it are not executed and the app handler will also not be executed. You
|
||||||
can think of it as a chain.
|
can think of it as a chain.
|
||||||
|
|
||||||
### Context values
|
### Context values
|
||||||
@ -435,7 +442,7 @@ We get this key in `index` and display it to the user if the `'user'` key exists
|
|||||||
|
|
||||||
#### Changing Context values
|
#### Changing Context values
|
||||||
|
|
||||||
By default context values are immutable when retrieved with `get_value`. If you want to
|
By default context values are immutable when retrieved with `get_value`. If you want to
|
||||||
change the value later you have to set it again with `set_value`.
|
change the value later you have to set it again with `set_value`.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
@ -494,7 +501,7 @@ pub fn (mut app App) with_auth() bool {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Fallback route
|
### Fallback route
|
||||||
You can implement a fallback `not_found` route that is called when a request is made and no
|
You can implement a fallback `not_found` route that is called when a request is made and no
|
||||||
matching route is found.
|
matching route is found.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
@ -507,7 +514,7 @@ pub fn (mut app App) not_found() vweb.Result {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Databases
|
### Databases
|
||||||
The `db` field in a vweb app is reserved for database connections. The connection is
|
The `db` field in a vweb app is reserved for database connections. The connection is
|
||||||
copied to each new request.
|
copied to each new request.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
@ -536,7 +543,7 @@ fn main() {
|
|||||||
|
|
||||||
### Multithreading
|
### Multithreading
|
||||||
By default, a vweb app is multithreaded, that means that multiple requests can
|
By default, a vweb app is multithreaded, that means that multiple requests can
|
||||||
be handled in parallel by using multiple CPU's: a worker pool. You can
|
be handled in parallel by using multiple CPU's: a worker pool. You can
|
||||||
change the number of workers (maximum allowed threads) by altering the `nr_workers`
|
change the number of workers (maximum allowed threads) by altering the `nr_workers`
|
||||||
option. The default behaviour is to use the maximum number of jobs (cores in most cases).
|
option. The default behaviour is to use the maximum number of jobs (cores in most cases).
|
||||||
|
|
||||||
@ -560,7 +567,7 @@ To resolve this issue, you can use the vweb's built-in database pool. The databa
|
|||||||
will keep a number of connections open when the app is started and each worker is
|
will keep a number of connections open when the app is started and each worker is
|
||||||
assigned its own connection.
|
assigned its own connection.
|
||||||
|
|
||||||
Let's look how we can improve our previous example with database pooling and using a
|
Let's look how we can improve our previous example with database pooling and using a
|
||||||
postgresql server instead.
|
postgresql server instead.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
@ -593,14 +600,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don't use the default number of workers (`nr_workers`) you have to change
|
If you don't use the default number of workers (`nr_workers`) you have to change
|
||||||
it to the same number in `vweb.run_at` as in `vweb.database_pool`
|
it to the same number in `vweb.run_at` as in `vweb.database_pool`
|
||||||
|
|
||||||
### Extending the App struct with `[vweb_global]`
|
### Extending the App struct with `[vweb_global]`
|
||||||
You can change your `App` struct however you like, but there are some things you
|
You can change your `App` struct however you like, but there are some things you
|
||||||
have to keep in mind. Under the hood at each request a new instance of `App` is
|
have to keep in mind. Under the hood at each request a new instance of `App` is
|
||||||
constructed, and all fields are re-initialized with their default type values,
|
constructed, and all fields are re-initialized with their default type values,
|
||||||
except for the `db` field.
|
except for the `db` field.
|
||||||
|
|
||||||
This behaviour ensures that each request is treated equally and in the same context, but
|
This behaviour ensures that each request is treated equally and in the same context, but
|
||||||
problems arise when we want to provide more context than just the default `vweb.Context`.
|
problems arise when we want to provide more context than just the default `vweb.Context`.
|
||||||
@ -628,8 +635,8 @@ fn (mut app App) index() vweb.Result {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When you visit `localhost:8080/` you would expect to see the text
|
When you visit `localhost:8080/` you would expect to see the text
|
||||||
`"My secret is: my secret"`, but instead there is only the text
|
`"My secret is: my secret"`, but instead there is only the text
|
||||||
`"My secret is: "`. This is because of the way vweb works. We can override the default
|
`"My secret is: "`. This is because of the way vweb works. We can override the default
|
||||||
behaviour by adding the attribute `[vweb_global]` to the `secret` field.
|
behaviour by adding the attribute `[vweb_global]` to the `secret` field.
|
||||||
|
|
||||||
@ -647,8 +654,8 @@ Now if you visit `localhost:8080/` you see the text `"My secret is: my secret"`.
|
|||||||
> next request. You can use shared fields for this.
|
> next request. You can use shared fields for this.
|
||||||
|
|
||||||
### Shared Objects across requests
|
### Shared Objects across requests
|
||||||
We saw in the previous section that we can persist data across multiple requests,
|
We saw in the previous section that we can persist data across multiple requests,
|
||||||
but what if we want to be able to mutate the data? Since vweb works with threads,
|
but what if we want to be able to mutate the data? Since vweb works with threads,
|
||||||
we have to use `shared` fields.
|
we have to use `shared` fields.
|
||||||
|
|
||||||
Let's see how we can add a visitor counter to our `App`.
|
Let's see how we can add a visitor counter to our `App`.
|
||||||
@ -700,7 +707,7 @@ requests the next requests will have to wait for the lock to be released.
|
|||||||
It is best practice to limit the use of shared objects as much as possible.
|
It is best practice to limit the use of shared objects as much as possible.
|
||||||
|
|
||||||
### Controllers
|
### Controllers
|
||||||
Controllers can be used to split up app logic so you are able to have one struct
|
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`
|
per `"/"`. E.g. a struct `Admin` for urls starting with `"/admin"` and a struct `Foo`
|
||||||
for urls starting with `"/foo"`
|
for urls starting with `"/foo"`
|
||||||
|
|
||||||
@ -734,9 +741,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can do everything with a controller struct as with a regular `App` struct.
|
You can do everything with a controller struct as with a regular `App` struct.
|
||||||
The only difference being is that only the main app that is being passed to `vweb.run`
|
The only difference being is that only the main app that is being passed to `vweb.run`
|
||||||
is able to have controllers. If you add `vweb.Controller` on a controller struct it
|
is able to have controllers. If you add `vweb.Controller` on a controller struct it
|
||||||
will simply be ignored.
|
will simply be ignored.
|
||||||
|
|
||||||
#### Routing
|
#### Routing
|
||||||
@ -749,10 +756,10 @@ pub fn (mut app Admin) path vweb.Result {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
When we created the controller with `vweb.controller('/admin', &Admin{})` we told
|
When we created the controller with `vweb.controller('/admin', &Admin{})` we told
|
||||||
vweb that the namespace of that controller is `"/admin"` so in this example we would
|
vweb that the namespace of that controller is `"/admin"` so in this example we would
|
||||||
see the text `"Admin"` if we navigate to the url `"/admin/path"`.
|
see the text `"Admin"` if we navigate to the url `"/admin/path"`.
|
||||||
|
|
||||||
Vweb doesn't support fallback routes or duplicate routes, so if we add the following
|
Vweb doesn't support fallback routes or duplicate routes, so if we add the following
|
||||||
route to the example the code will produce an error.
|
route to the example the code will produce an error.
|
||||||
|
|
||||||
```v ignore
|
```v ignore
|
||||||
@ -1198,5 +1205,5 @@ pub fn (mut app App) error() vweb.Result {
|
|||||||
```
|
```
|
||||||
# Cross-Site Request Forgery (CSRF) protection
|
# Cross-Site Request Forgery (CSRF) protection
|
||||||
|
|
||||||
Vweb has built-in csrf protection. Go to the [csrf module](csrf/) to learn how
|
Vweb has built-in csrf protection. Go to the [csrf module](csrf/) to learn how
|
||||||
you can protect your app against CSRF.
|
you can protect your app against CSRF.
|
||||||
|
Loading…
Reference in New Issue
Block a user