Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation #16

Merged
merged 2 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/background-jobs/cron.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Cron jobs, or scheduled jobs, are background jobs that are performed automatical

## Defining scheduled jobs

A scheduled job is a regular [background job](../), for example:
A scheduled job is a regular [background job](index.md), for example:

```rust
use rwf::prelude::*;
Expand Down
8 changes: 4 additions & 4 deletions docs/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ Rwf will automatically load configuration settings from that file, as they are n

The configuration file is using the [TOML language](https://toml.io/). If you're not familiar with TOML, it's pretty simple and expressive language commonly used in the world of Rust programming.

Rwf configuration file is split into multiple sections. The `[general]` section controls various options such as logging settings, and which secret key to use for [encryption](../encryption). The `[database]`
Rwf configuration file is split into multiple sections. The `[general]` section controls various options such as logging settings, and which secret key to use for [encryption](encryption.md). The `[database]`
section configures database connection settings, like the database URL, connection pool size, and others.

### `[general]`

| Setting | Description | Default |
|---------|-------------|---------|
| `log_queries` | Toggles logging of all SQL queries executed by the [ORM](../models/). | `false` |
| `secret_key` | Secret key, encoded using base64, used for [encryption](../encryption). | Randomly generated |
| `cache_templates` | Toggle caching of [dynamic templates](/views/templates/). | `false` in debug, `true` in release |
| `log_queries` | Toggles logging of all SQL queries executed by the [ORM](models/index.md). | `false` |
| `secret_key` | Secret key, encoded using base64, used for [encryption](encryption.md). | Randomly generated |
| `cache_templates` | Toggle caching of [dynamic templates](views/templates/index.md). | `false` in debug, `true` in release |

#### Secret key

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/controllers/REST/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ The delete method, implemented using the HTTP `DELETE /endpoint/<id>` call, dele

## REST controller

Rwf comes with a REST [controller](../), which has the six aforementioned methods separated into individual functions. For example, writing a `/users` endpoint controller could be done like so:
Rwf comes with a REST [controller](../index.md), which has the six aforementioned methods separated into individual functions. For example, writing a `/users` endpoint controller could be done like so:

```rust
use rwf::prelude::*;
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/controllers/authentication.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Authentication

Rwf has multiple authentication and authorization mechanisms. Different kinds of authentication require their own kinds of user-supplied credentials. The most commonly used mechanism is [Session](../sessions) authentication, which has built-in methods for easy use in [controllers](../).
Rwf has multiple authentication and authorization mechanisms. Different kinds of authentication require their own kinds of user-supplied credentials. The most commonly used mechanism is [Session](sessions.md) authentication, which has built-in methods for easy use in [controllers](index.md).

## Session authentication

[Session](../sessions) authentication checks that the user-supplied session cookie is valid (not expired) and contains an authenticated session. If that's not the case, the request is either rejected with a `403 - Forbidden` or provided an endpoint to re-authenticate, e.g., using a username and password, with a `302 - Found` redirect.
[Session](sessions.md) authentication checks that the user-supplied session cookie is valid (not expired) and contains an authenticated session. If that's not the case, the request is either rejected with a `403 - Forbidden` or provided an endpoint to re-authenticate, e.g., using a username and password, with a `302 - Found` redirect.

### Enable session authentication

Expand Down Expand Up @@ -43,4 +43,4 @@ impl Controller for Private {
## Basic authentication

HTTP Basic is a form of authentication using a global username and password. It's not particularly secure, but it's good enough to protect an endpoint quickly against random visitors. Enabling basic authentication is as simple
as setting an [`AuthHandler`](https://docs.rs/rwf/latest/rwf/controller/auth/struct.AuthHandler.html) with [`BasicAuth`](https://docs.rs/rwf/latest/rwf/controller/auth/struct.BasicAuth.html) on your [controller](../). See [examples/auth](https://github.com/levkk/rwf/tree/main/examples/auth) for examples on how to do this.
as setting an [`AuthHandler`](https://docs.rs/rwf/latest/rwf/controller/auth/struct.AuthHandler.html) with [`BasicAuth`](https://docs.rs/rwf/latest/rwf/controller/auth/struct.BasicAuth.html) on your [controller](index.md). See [examples/auth](https://github.com/levkk/rwf/tree/main/examples/auth) for examples on how to do this.
6 changes: 3 additions & 3 deletions docs/docs/controllers/cookies.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Cookies allow persisting information between what are otherwise stateless HTTP r

## Read cookies

Cookies sent by the browser can be read inside a [controller](../) by calling the [`cookies`](https://docs.rs/rwf/latest/rwf/http/request/struct.Request.html#method.cookies) method:
Cookies sent by the browser can be read inside a [controller](index.md) by calling the [`cookies`](https://docs.rs/rwf/latest/rwf/http/request/struct.Request.html#method.cookies) method:

```rust
let cookies = request.cookies();
Expand All @@ -26,7 +26,7 @@ More often than not, cookies are used to store plain text information, so no spe

## Set cookies

Setting cookies on the server can be done when crafting a [response](../response):
Setting cookies on the server can be done when crafting a [response](response.md):

```rust
use rwf::prelude::*;
Expand Down Expand Up @@ -61,7 +61,7 @@ response
.add_private(cookie)?;
```

Cookies are [encrypted](../../encryption) with AES-128, using the security key set in the [configuration](../../configuration).
Cookies are [encrypted](../encryption.md) with AES-128, using the security key set in the [configuration](../configuration.md).


### Read private cookies
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/controllers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ The `Controller` trait is asynchronous. Support for async traits in Rust is stil

#### `handle`

The `handle` method accepts a [`Request`](request) and must return a [`Response`](response). The response can be any valid HTTP response, including `404` or even `500`.
The `handle` method accepts a [`Request`](request.md) and must return a [`Response`](response.md). The response can be any valid HTTP response, including `404` or even `500`.

##### Errors

Expand Down Expand Up @@ -124,5 +124,5 @@ impl PageController for Login {

Read more about working with controllers, requests, and responses:

- [Requests](request)
- [Responses](response)
- [Requests](request.md)
- [Responses](response.md)
6 changes: 3 additions & 3 deletions docs/docs/controllers/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Middleware needs to be specified on each controller. By default, all controllers

### Define middleware

Middleware, similar to [controllers](../), is any struct which implements the [`Middleware`](https://docs.rs/rwf/latest/rwf/controller/middleware/trait.Middleware.html) trait. The only method that needs
implementation is the [`async fn handle_request`](https://docs.rs/rwf/latest/rwf/controller/middleware/trait.Middleware.html#tymethod.handle_request) method, which accepts a [`Request`](../request) and must return an [`Outcome`](https://docs.rs/rwf/latest/rwf/controller/middleware/enum.Outcome.html).
Middleware, similar to [controllers](index.md), is any struct which implements the [`Middleware`](https://docs.rs/rwf/latest/rwf/controller/middleware/trait.Middleware.html) trait. The only method that needs
implementation is the [`async fn handle_request`](https://docs.rs/rwf/latest/rwf/controller/middleware/trait.Middleware.html#tymethod.handle_request) method, which accepts a [`Request`](request.md) and must return an [`Outcome`](https://docs.rs/rwf/latest/rwf/controller/middleware/enum.Outcome.html).

If the request is allowed to proceed, [`Outcome::Forward`](https://docs.rs/rwf/latest/rwf/controller/middleware/enum.Outcome.html#variant.Forward) is returned, containing the request, in its modified or unchanged form.
If on the other hand, the request failed some kind of validation, [`Outcome::Stop`](https://docs.rs/rwf/latest/rwf/controller/middleware/enum.Outcome.html#variant.Stop) must be returned with a [`Response`](../response), for example:
If on the other hand, the request failed some kind of validation, [`Outcome::Stop`](https://docs.rs/rwf/latest/rwf/controller/middleware/enum.Outcome.html#variant.Stop) must be returned with a [`Response`](response.md), for example:

```rust
use rwf::controller::middleware::prelude::*;
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/controllers/request.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Requests

For each HTTP request served by Rwf, a new [`Request`](https://docs.rs/rwf/latest/rwf/http/request/struct.Request.html) struct is created. It contains the client IP address,
browser headers, [cookies](../cookies), [session](../sessions) information, and the request body.
browser headers, [cookies](cookies.md), [session](sessions.md) information, and the request body.

## Headers

Expand Down Expand Up @@ -32,7 +32,7 @@ impl Controller for Index {
Headers in Rwf are case-insensitive, so `accept` and `Accept` are equivalent.

Most browsers send required headers like `Origin`, `Accept`, and `User-Agent`, but that doesn't mean all HTTP clients will.
Checking for valid headers is good practice to avoid bad actors like bots. Read more about intercepting HTTP requests with [Middleware](../middleware).
Checking for valid headers is good practice to avoid bad actors like bots. Read more about intercepting HTTP requests with [Middleware](middleware.md).

## Request body

Expand Down
8 changes: 4 additions & 4 deletions docs/docs/controllers/response.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Responses

Each HTTP request served by Rwf is expected to return a response. If your app is using a [REST](../REST/) API, responses
are typically JSON. If you prefer [HTML over the wire](../../views/turbo/) or plain old websites, the responses will contain HTML or text.
Each HTTP request served by Rwf is expected to return a response. If your app is using a [REST](REST/index.md) API, responses
are typically JSON. If you prefer [HTML over the wire](../views/turbo/index.md) or plain old websites, the responses will contain HTML or text.

## Creating responses

Expand Down Expand Up @@ -56,5 +56,5 @@ let response = Response::new()

## Learn more

- [Cookies](../cookies)
- [Sessions](../sessions)
- [Cookies](cookies.md)
- [Sessions](sessions.md)
10 changes: 5 additions & 5 deletions docs/docs/controllers/sessions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sessions

A session is an [encrypted](../../encryption) [cookie](../cookies) managed by Rwf. It contains a unique identifier for each browser using your web app. All standard-compliant browsers connecting to Rwf-powered apps will have a Rwf session set automatically, and should send it back on each request.
A session is an [encrypted](../encryption.md) [cookie](cookies.md) managed by Rwf. It contains a unique identifier for each browser using your web app. All standard-compliant browsers connecting to Rwf-powered apps will have a Rwf session set automatically, and should send it back on each request.

## Session types

Expand Down Expand Up @@ -29,7 +29,7 @@ async fn handle(&self, request: &Request) -> Result<Response, Error> {

## Check for valid session

All [controllers](../) can check for the presence of a valid session:
All [controllers](index.md) can check for the presence of a valid session:

```rust
let session = request.session();
Expand All @@ -46,11 +46,11 @@ If the session is expired, it's advisable not to trust its point of origin. Whil

### Session authentication

Rwf can ensure all requests have valid and current (not expired) sessions. To enable this feature, enable the [`SessionAuth`](https://docs.rs/rwf/latest/rwf/controller/auth/struct.SessionAuth.html) [authentication](../authentication) on your controllers. Guest sessions will be refused access, while authenticated sessions will be allowed through.
Rwf can ensure all requests have valid and current (not expired) sessions. To enable this feature, enable the [`SessionAuth`](https://docs.rs/rwf/latest/rwf/controller/auth/struct.SessionAuth.html) [authentication](authentication.md) on your controllers. Guest sessions will be refused access, while authenticated sessions will be allowed through.

## Store data in session

Rwf sessions allow you to privately store arbitrary JSON-encoded data. Since browsers place limits on cookie sizes, this data should be relatively small. To store some data in the session, you can set it on the [response](../response):
Rwf sessions allow you to privately store arbitrary JSON-encoded data. Since browsers place limits on cookie sizes, this data should be relatively small. To store some data in the session, you can set it on the [response](response.md):

```rust
let session = Session::new(
Expand All @@ -65,6 +65,6 @@ let response = Response::new()

## Renew sessions

Sessions are automatically renewed on each request. This allows your active users to remain "logged in", while inactive ones would be redirected to a login page if session [authentication](../authentication) is enabled.
Sessions are automatically renewed on each request. This allows your active users to remain "logged in", while inactive ones would be redirected to a login page if session [authentication](authentication.md) is enabled.

Expired sessions are not renewed, so a user holding an expired session will need to use an authentication controller to get a new valid session.
2 changes: 1 addition & 1 deletion docs/docs/controllers/static-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ and will automatically return the right `Content-Type` header (also known as [MI

## Serve static files

The static files server is just another [controller](../), implemented internally. To add it to your app, you can
The static files server is just another [controller](index.md), implemented internally. To add it to your app, you can
add it to the server at startup:

```rust
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/controllers/websockets.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ to send a [`Message`](https://docs.rs/rwf/latest/rwf/http/websocket/enum.Message

## Sending messages to clients

All WebSocket clients have a unique [session](../sessions) identifier. Sending a message to a client only requires that you know their session ID, which you can obtain from the [`Request`](../request), for example:
All WebSocket clients have a unique [session](sessions.md) identifier. Sending a message to a client only requires that you know their session ID, which you can obtain from the [`Request`](request.md), for example:

```rust
if let Some(session_id) = request.session_id() {
Expand All @@ -103,7 +103,7 @@ if let Some(session_id) = request.session_id() {
}
```

WebSocket messages can be delivered to any client from anywhere in the application, including [controllers](../) and [background jobs](../../background-jobs/).
WebSocket messages can be delivered to any client from anywhere in the application, including [controllers](index.md) and [background jobs](../background-jobs/index.md).

## Starting a WebSocket server

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/encryption.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Encryption

Rwf uses [AES-128](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) for encrypting user [sessions](../controllers/sessions) and private [cookies](../controllers/cookies). The same functionality is available through the [`rwf::crypto`](https://docs.rs/rwf/latest/rwf/crypto/index.html) module to encrypt and decrypt arbitrary data.
Rwf uses [AES-128](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) for encrypting user [sessions](controllers/sessions.md) and private [cookies](controllers/cookies.md). The same functionality is available through the [`rwf::crypto`](https://docs.rs/rwf/latest/rwf/crypto/index.html) module to encrypt and decrypt arbitrary data.

## Encrypt data

Expand Down
10 changes: 5 additions & 5 deletions docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ impl Controller for Index {
`rwf::prelude::*` includes the vast majority of types, structs, traits and functions you'll be using when building controllers with Rwf.
Adding this declaration to your source files will make handling imports easier, but it's not required.

Rwf controllers are defined as Rust structs that implement the [`Controller`](../controllers/) trait. The trait is asynchronous, hence the `#[async_trait]` macro[^2],
Rwf controllers are defined as Rust structs that implement the [`Controller`](controllers/index.md) trait. The trait is asynchronous, hence the `#[async_trait]` macro[^2],
and has only one method you need to implement: `async fn handle`. This method
accepts a [`Request`](../controllers/request), and must return a [`Response`](../controllers/response).
accepts a [`Request`](controllers/request.md), and must return a [`Response`](controllers/response.md).

In this example, we are returning HTTP `200 - OK` with the body `<h1>My first Rwf app</h1>`. This is not strictly valid HTML,
but it'll work in all browsers for our demo purposes.
Expand Down Expand Up @@ -100,6 +100,6 @@ The full code for this is available on GitHub in [examples/quick-start](https://

## Learn more

- [Controllers](controllers/)
- [Models](models/)
- [Views](views/)
- [Controllers](controllers/index.md)
- [Models](models/index.md)
- [Views](views/index.md)
2 changes: 1 addition & 1 deletion docs/docs/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async fn main() {

## Log queries

By default, queries executed against the database are not logged. If you want to see what's being executed (and how long queries are taking to return results), toggle the `log_queries` setting in the [configuration](../configuration).
By default, queries executed against the database are not logged. If you want to see what's being executed (and how long queries are taking to return results), toggle the `log_queries` setting in the [configuration](configuration.md).

## Log requests

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/migrating-from-python.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Migrating from Python

Rwf is written in Rust, so if you have an existing application you want to migrate to Rust, you have options. Rwf comes with its own [WSGI](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) server, so you can run your existing Django or Flask apps without modifications, side by side with Rwf [controllers](../controllers/).
Rwf is written in Rust, so if you have an existing application you want to migrate to Rust, you have options. Rwf comes with its own [WSGI](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) server, so you can run your existing Django or Flask apps without modifications, side by side with Rwf [controllers](controllers/index.md).

## Using WSGI

Expand Down
1 change: 1 addition & 0 deletions docs/docs/models/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ nav:
- 'scopes.md'
- 'debug-queries.md'
- 'custom-queries.md'
- 'grouping.md'
- '...'
8 changes: 3 additions & 5 deletions docs/docs/models/connection-pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ let users = User::all()
Returning the connection to the pool is done automatically when the `conn` variable goes out of scope. In Rust semantics, the `conn` variable is "dropped". For example, to checkout a connection for only one query, you can do so inside its own scope:

```rust
async fn get_users() -> Result<Vec<User>, Error> {
let users = {
let mut conn = Pool::connection().await?;
let users = User::all()
.fetch_all(&mut conn)
.await?;
Ok(users)
// The connection is returned to the pool here.
}
.await?
};
```

## Transactions
Expand Down
Loading
Loading