mirror of
https://github.com/actix/examples
synced 2024-11-23 14:31:07 +01:00
chore: fmt
This commit is contained in:
parent
b7b1005d2a
commit
f30795f014
2
.github/workflows/clippy-fmt.yml
vendored
2
.github/workflows/clippy-fmt.yml
vendored
@ -51,6 +51,6 @@ jobs:
|
|||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
uses: giraffate/clippy-action@v1
|
uses: giraffate/clippy-action@v1
|
||||||
with:
|
with:
|
||||||
reporter: 'github-pr-check'
|
reporter: "github-pr-check"
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
clippy_flags: --workspace --all-features --tests
|
clippy_flags: --workspace --all-features --tests
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
singleQuote: true
|
arrowParens: "avoid"
|
||||||
arrowParens: avoid
|
|
||||||
semi: false
|
semi: false
|
||||||
overrides:
|
overrides:
|
||||||
- files: '*.md'
|
- files: "*.md"
|
||||||
options:
|
options:
|
||||||
printWidth: 9999
|
printWidth: 9999
|
||||||
proseWrap: never
|
proseWrap: "never"
|
||||||
|
@ -22,11 +22,7 @@
|
|||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 0
|
"Right": 0
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [false, false, false]
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"hash": "3a5b2a81088aa91ade3106165f926c337a88f4e29ae3bb170c4b687208aba20d"
|
"hash": "3a5b2a81088aa91ade3106165f926c337a88f4e29ae3bb170c4b687208aba20d"
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
> Curated examples using the Actix ecosystem.
|
> Curated examples using the Actix ecosystem.
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
|
||||||
[![build status](https://github.com/actix/examples/workflows/CI%20%28Linux%29/badge.svg?branch=master&event=push)](https://github.com/actix/examples/actions)
|
[![build status](https://github.com/actix/examples/workflows/CI%20%28Linux%29/badge.svg?branch=master&event=push)](https://github.com/actix/examples/actions)
|
||||||
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
|
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
## Community Showcase
|
## Community Showcase
|
||||||
|
|
||||||
- [Merino](https://github.com/mozilla-services/merino): Web service for Firefox Suggest.
|
- [Merino](https://github.com/mozilla-services/merino): Web service for Firefox Suggest.
|
||||||
@ -52,9 +56,9 @@
|
|||||||
- [Fullstack-Rust](https://github.com/vascokk/fullstack-rust): A Full Stack Rust application (Connect5 game) with Actix Web, Yew, Bulma CSS and Diesel.
|
- [Fullstack-Rust](https://github.com/vascokk/fullstack-rust): A Full Stack Rust application (Connect5 game) with Actix Web, Yew, Bulma CSS and Diesel.
|
||||||
- [Mozilla Services Skeleton App](https://github.com/mozilla-services/skeleton)
|
- [Mozilla Services Skeleton App](https://github.com/mozilla-services/skeleton)
|
||||||
- [rayspace.dev](https://github.com/ryspc/rayspace.dev): Minimalist dev portfolio and blog implemented as a Rust-powered SPA, featuring GitHub OAuth, session management, static file serving, API endpoints, and SQLx integration.
|
- [rayspace.dev](https://github.com/ryspc/rayspace.dev): Minimalist dev portfolio and blog implemented as a Rust-powered SPA, featuring GitHub OAuth, session management, static file serving, API endpoints, and SQLx integration.
|
||||||
- [Blog with markdown rendering](https://github.com/gemini-15/blog-engine): Blog example built with Actix Web, diesel (with Postgres) and r2d2 rendering articles in markdown with metadata and a front-end with React.
|
- [Blog with markdown rendering](https://github.com/gemini-15/blog-engine): Blog example built with Actix Web, diesel (with Postgres) and r2d2 rendering articles in markdown with metadata and a front-end with React.
|
||||||
- [Rust, Angular, PostgreSQL and JWT Security](https://github.com/stav121/actix-angular-project-template): Boilerplate project that implements an Angular + Actix Web application with login and registration pages, that is pre-dockerized.
|
- [Rust, Angular, PostgreSQL and JWT Security](https://github.com/stav121/actix-angular-project-template): Boilerplate project that implements an Angular + Actix Web application with login and registration pages, that is pre-dockerized.
|
||||||
- [planters_cycle](https://github.com/grimm-integrations/planters_cycle): Another boilerplate fullstack application with identity system, prisma and NextJs.
|
- [planters_cycle](https://github.com/grimm-integrations/planters_cycle): Another boilerplate fullstack application with identity system, prisma and NextJs.
|
||||||
|
|
||||||
## Paid Resources
|
## Paid Resources
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ cargo run (or ``cargo watch -x run``)
|
|||||||
```
|
```
|
||||||
|
|
||||||
In this example, you can get the:
|
In this example, you can get the:
|
||||||
|
|
||||||
- successful result at [http://localhost:8080/success](http://localhost:8080/success) (accessible)
|
- successful result at [http://localhost:8080/success](http://localhost:8080/success) (accessible)
|
||||||
- failed result at [http://localhost:8080/fail](http://localhost:8080/fail) (inaccessible, `ERR_EMPTY_RESPONSE`).
|
- failed result at [http://localhost:8080/fail](http://localhost:8080/fail) (inaccessible, `ERR_EMPTY_RESPONSE`).
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
function post(url = ``, data = {}) {
|
function post(url = ``, data = {}) {
|
||||||
// Default options are marked with *
|
// Default options are marked with *
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
method: "POST", // *GET, POST, PUT, DELETE, etc.
|
||||||
mode: 'cors', // no-cors, cors, *same-origin
|
mode: "cors", // no-cors, cors, *same-origin
|
||||||
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json; charset=utf-8',
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
},
|
},
|
||||||
redirect: 'follow', // manual, *follow, error
|
redirect: "follow", // manual, *follow, error
|
||||||
referrer: 'no-referrer', // no-referrer, *client
|
referrer: "no-referrer", // no-referrer, *client
|
||||||
body: JSON.stringify(data), // body data type must match "Content-Type" header
|
body: JSON.stringify(data), // body data type must match "Content-Type" header
|
||||||
}).then(response => response.json()); // parses response to JSON
|
}).then(response => response.json()) // parses response to JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
// window.addEventListener('load', function() {
|
// window.addEventListener('load', function() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
jQuery(document).ready(function () {
|
jQuery(document).ready(function () {
|
||||||
let rotation = 0;
|
let rotation = 0
|
||||||
jQuery("img").click(function () {
|
jQuery("img").click(function () {
|
||||||
rotation += 360;
|
rotation += 360
|
||||||
jQuery("img").css({'transform': 'rotate(' + rotation + 'deg)'});
|
jQuery("img").css({ transform: "rotate(" + rotation + "deg)" })
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
@ -11,7 +11,7 @@ cargo run
|
|||||||
### web client
|
### web client
|
||||||
|
|
||||||
- [http://localhost:8080/user/info](http://localhost:8080/user/info)
|
- [http://localhost:8080/user/info](http://localhost:8080/user/info)
|
||||||
```json5
|
```json
|
||||||
// payload structure
|
// payload structure
|
||||||
{
|
{
|
||||||
"username": "username",
|
"username": "username",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// import './assets/main.css'
|
// import './assets/main.css'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from "vue"
|
||||||
import App from './App.vue'
|
import App from "./App.vue"
|
||||||
|
|
||||||
createApp(App).mount('#app')
|
createApp(App).mount("#app")
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from "node:url"
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from "vite"
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from "@vitejs/plugin-vue"
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [vue()],
|
||||||
vue(),
|
|
||||||
],
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
### NOTE:
|
### NOTE:
|
||||||
|
|
||||||
You may need to ensure that you are running the commands with the correct SQL user.
|
You may need to ensure that you are running the commands with the correct SQL user. On many Linux distributions you may prefix the shell commands with `sudo -u postgres`
|
||||||
On many Linux distributions you may prefix the shell commands with `sudo -u postgres`
|
|
||||||
|
|
||||||
1. Create database user
|
1. Create database user
|
||||||
|
|
||||||
@ -25,6 +24,7 @@ On many Linux distributions you may prefix the shell commands with `sudo -u post
|
|||||||
This step is **optional** and you can also use an existing database user for that. Just make sure to replace `test_user` by the database user of your choice in the following steps and change the `.env` file containing the configuration accordingly.
|
This step is **optional** and you can also use an existing database user for that. Just make sure to replace `test_user` by the database user of your choice in the following steps and change the `.env` file containing the configuration accordingly.
|
||||||
|
|
||||||
An alternative using SQL:
|
An alternative using SQL:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE USER test_user WITH PASSWORD 'testing';
|
CREATE USER test_user WITH PASSWORD 'testing';
|
||||||
```
|
```
|
||||||
@ -36,6 +36,7 @@ On many Linux distributions you may prefix the shell commands with `sudo -u post
|
|||||||
```
|
```
|
||||||
|
|
||||||
An alternative using SQL:
|
An alternative using SQL:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE DATABASE testing_db OWNER test_user;
|
CREATE DATABASE testing_db OWNER test_user;
|
||||||
```
|
```
|
||||||
@ -54,7 +55,7 @@ On many Linux distributions you may prefix the shell commands with `sudo -u post
|
|||||||
GRANT ALL PRIVILEGES ON SCHEMA testing TO test_user;
|
GRANT ALL PRIVILEGES ON SCHEMA testing TO test_user;
|
||||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA testing TO test_user;
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA testing TO test_user;
|
||||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA testing TO test_user;
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA testing TO test_user;
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Create `.env` file:
|
5. Create `.env` file:
|
||||||
|
|
||||||
|
@ -47,9 +47,7 @@ _Mutation example:_
|
|||||||
|
|
||||||
```graphql
|
```graphql
|
||||||
mutation {
|
mutation {
|
||||||
createHuman(
|
createHuman(newHuman: { name: "Fresh Kid Ice", appearsIn: EMPIRE, homePlanet: "earth" }) {
|
||||||
newHuman: { name: "Fresh Kid Ice", appearsIn: EMPIRE, homePlanet: "earth" }
|
|
||||||
) {
|
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
appearsIn
|
appearsIn
|
||||||
|
13
justfile
Normal file
13
justfile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
_list:
|
||||||
|
@just --list
|
||||||
|
|
||||||
|
# Format project.
|
||||||
|
[group("lint")]
|
||||||
|
fmt:
|
||||||
|
cargo +nightly fmt
|
||||||
|
fd --type=file --hidden --extension=yml --extension=md --extension=js --exec-batch npx -y prettier --write
|
||||||
|
|
||||||
|
# Run Clippy over workspace.
|
||||||
|
[group("lint")]
|
||||||
|
clippy:
|
||||||
|
cargo clippy --workspace --all-targets --all-features
|
@ -1,73 +1,73 @@
|
|||||||
const http = require('http')
|
const http = require("http")
|
||||||
|
|
||||||
const n = 120
|
const n = 120
|
||||||
let connected = 0
|
let connected = 0
|
||||||
let messages = 0
|
let messages = 0
|
||||||
let start = Date.now()
|
let start = Date.now()
|
||||||
let phase = 'connecting'
|
let phase = "connecting"
|
||||||
let connection_time
|
let connection_time
|
||||||
let broadcast_time
|
let broadcast_time
|
||||||
|
|
||||||
let message = process.argv[2] || 'msg'
|
let message = process.argv[2] || "msg"
|
||||||
let expected_data = 'data: ' + message
|
let expected_data = "data: " + message
|
||||||
|
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
http
|
http
|
||||||
.get(
|
.get(
|
||||||
{
|
{
|
||||||
host: '127.0.0.1',
|
host: "127.0.0.1",
|
||||||
port: 8080,
|
port: 8080,
|
||||||
path: '/events',
|
path: "/events",
|
||||||
},
|
},
|
||||||
(response) => {
|
response => {
|
||||||
response.on('data', (data) => {
|
response.on("data", data => {
|
||||||
if (data.includes(expected_data)) {
|
if (data.includes(expected_data)) {
|
||||||
messages += 1
|
messages += 1
|
||||||
} else if (data.includes('data: connected\n')) {
|
} else if (data.includes("data: connected\n")) {
|
||||||
connected += 1
|
connected += 1
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.on('error', (_) => {})
|
.on("error", _ => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
if (phase === 'connecting' && connected === n) {
|
if (phase === "connecting" && connected === n) {
|
||||||
// done connecting
|
// done connecting
|
||||||
phase = 'messaging'
|
phase = "messaging"
|
||||||
connection_time = Date.now() - start
|
connection_time = Date.now() - start
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase === 'messaging') {
|
if (phase === "messaging") {
|
||||||
phase = 'waiting'
|
phase = "waiting"
|
||||||
start = Date.now()
|
start = Date.now()
|
||||||
|
|
||||||
http
|
http
|
||||||
.request(
|
.request(
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
host: '127.0.0.1',
|
host: "127.0.0.1",
|
||||||
port: 8080,
|
port: 8080,
|
||||||
path: '/broadcast/' + message,
|
path: "/broadcast/" + message,
|
||||||
|
},
|
||||||
|
response => {
|
||||||
|
response.on("data", _ => {})
|
||||||
},
|
},
|
||||||
(response) => {
|
|
||||||
response.on('data', (_) => {})
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase === 'waiting' && messages >= n) {
|
if (phase === "waiting" && messages >= n) {
|
||||||
// all messages received
|
// all messages received
|
||||||
broadcast_time = Date.now() - start
|
broadcast_time = Date.now() - start
|
||||||
phase = 'paused'
|
phase = "paused"
|
||||||
messages = 0
|
messages = 0
|
||||||
phase = 'messaging'
|
phase = "messaging"
|
||||||
}
|
}
|
||||||
|
|
||||||
process.stdout.write('\r\x1b[K')
|
process.stdout.write("\r\x1b[K")
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`Connected: ${connected}, connection time: ${connection_time} ms, total broadcast time: ${broadcast_time} ms`
|
`Connected: ${connected}, connection time: ${connection_time} ms, total broadcast time: ${broadcast_time} ms`,
|
||||||
)
|
)
|
||||||
}, 20)
|
}, 20)
|
||||||
|
@ -1,41 +1,42 @@
|
|||||||
const http = require('http')
|
const http = require("http")
|
||||||
|
|
||||||
let drop_goal = 5_000
|
let drop_goal = 5_000
|
||||||
let dropped = 0
|
let dropped = 0
|
||||||
|
|
||||||
let query = {
|
let query = {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
host: '127.0.0.1',
|
host: "127.0.0.1",
|
||||||
port: 8080,
|
port: 8080,
|
||||||
path: '/events',
|
path: "/events",
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
if (dropped < drop_goal) {
|
if (dropped < drop_goal) {
|
||||||
let request = http
|
let request = http
|
||||||
.request(query, (response) => {
|
.request(query, response => {
|
||||||
response.on('data', (data) => {
|
response.on("data", data => {
|
||||||
if (data.includes('data: connected\n')) {
|
if (data.includes("data: connected\n")) {
|
||||||
// drop connection after welcome message
|
// drop connection after welcome message
|
||||||
dropped += 1
|
dropped += 1
|
||||||
request.abort()
|
request.abort()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('error', () => {})
|
.on("error", () => {})
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
http.request({ ...query, path: '/' }, () => print_status(true))
|
http
|
||||||
|
.request({ ...query, path: "/" }, () => print_status(true))
|
||||||
.setTimeout(100, () => print_status(false))
|
.setTimeout(100, () => print_status(false))
|
||||||
.on('error', () => {})
|
.on("error", () => {})
|
||||||
}, 20)
|
}, 20)
|
||||||
|
|
||||||
function print_status(accepting_connections) {
|
function print_status(accepting_connections) {
|
||||||
process.stdout.write('\r\x1b[K')
|
process.stdout.write("\r\x1b[K")
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`Connections dropped: ${dropped}, accepting connections: ${accepting_connections}`
|
`Connections dropped: ${dropped}, accepting connections: ${accepting_connections}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,13 @@ cargo run --bin websocket-chat-server
|
|||||||
|
|
||||||
## WebSocket Browser Client
|
## WebSocket Browser Client
|
||||||
|
|
||||||
Open url: [http://localhost:8080/](http://localhost:8080/)
|
- Open in browser: <http://localhost:8080/>.
|
||||||
Use two tabs to set up a proper conversation.
|
- Use two tabs to set up a proper conversation.
|
||||||
|
|
||||||
## Python Client using aiohttp
|
## Python Client using aiohttp
|
||||||
|
|
||||||
Client connects to server. Reads input from stdin and sends to server.
|
- Client connects to server. Reads input from stdin and sends to server.
|
||||||
Create a venv environment `python3 -m venv venv`
|
- Create a venv environment `python3 -m venv venv`.
|
||||||
Launch venv environment `source ./venv/bin/activate`
|
- Launch venv environment `source ./venv/bin/activate`.
|
||||||
Fetch the needed python libraries `pip3 install -r requirements.txt`
|
- Fetch the needed python libraries `pip3 install -r requirements.txt`.
|
||||||
Then start client as `./client.py`
|
- Then start client as `./client.py`.
|
||||||
|
Loading…
Reference in New Issue
Block a user