{"id":21659789,"url":"https://github.com/SakaDream/actix-web-rest-api-with-jwt","last_synced_at":"2025-07-17T22:33:08.967Z","repository":{"id":36961231,"uuid":"184862092","full_name":"SakaDream/actix-web-rest-api-with-jwt","owner":"SakaDream","description":"A simple CRUD backend app using Actix-web, Diesel and JWT","archived":false,"fork":false,"pushed_at":"2024-11-15T03:54:09.000Z","size":3913,"stargazers_count":531,"open_issues_count":6,"forks_count":107,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-11-25T09:45:03.196Z","etag":null,"topics":["actix-web","diesel-rs","docker","jwt","restful-api","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SakaDream.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-04T06:51:39.000Z","updated_at":"2024-11-18T09:39:09.000Z","dependencies_parsed_at":"2024-11-25T09:43:52.251Z","dependency_job_id":null,"html_url":"https://github.com/SakaDream/actix-web-rest-api-with-jwt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SakaDream/actix-web-rest-api-with-jwt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SakaDream%2Factix-web-rest-api-with-jwt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SakaDream%2Factix-web-rest-api-with-jwt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SakaDream%2Factix-web-rest-api-with-jwt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SakaDream%2Factix-web-rest-api-with-jwt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SakaDream","download_url":"https://codeload.github.com/SakaDream/actix-web-rest-api-with-jwt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SakaDream%2Factix-web-rest-api-with-jwt/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265672343,"owners_count":23808844,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actix-web","diesel-rs","docker","jwt","restful-api","rust"],"created_at":"2024-11-25T09:31:33.401Z","updated_at":"2025-07-17T22:33:08.146Z","avatar_url":"https://github.com/SakaDream.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# Actix-web REST API with JWT\n\n![CI](https://github.com/SakaDream/actix-web-rest-api-with-jwt/workflows/CI/badge.svg)\n![Docker CICD](https://github.com/SakaDream/actix-web-rest-api-with-jwt/workflows/Docker%20CICD/badge.svg)\n\nA simple CRUD backend app using Actix-web, Diesel and JWT\n\n## Require\n\n- [Rust Stable](https://rustup.rs)\n- [Postgres](https://www.postgresql.org/)\n\nOr using [Docker](https://www.docker.com/)\n\nP/s: On Linux distro maybe got error like \"= note: /usr/bin/ld: cannot find -lsqlite3\"\n- Fedora/CentOS\n  - Step 1: Find lib by command yum list '*sqlite*'\n  - Step 2: Run command sudo dnf/yum install libsqlite3x.x86_64 libsqlite3x-devel.x86_64\n- Ubuntu/Ubuntu Server\n  - Step 1: Run command sudo apt-get install libsqlite3-dev libpq-dev\n\n## How to run\n\n### Manual\n\n- Install postgresql and sqlite backend libraries, more details [here](https://github.com/diesel-rs/diesel/blob/master/guide_drafts/backend_installation.md)\n  - For Windows: Copy all files inside `libs\\windows` folder to other location (e.g `C:\\libs`). Add `PQ_LIB_DIR` and `SQLITE3_LIB_DIR` environment variable with value `C:\\libs`. Then restart all terminal windows.\n  - For Linux: Install `libpq` and `libsqlite3` depends on your distribution.\n  - For MacOS: Install `libpq` using homebrew: `brew install libpq`\n- Rename `secret.key.sample` to `secret.key` or create your own key by running `head -c16 /dev/urandom \u003e secret.key` in\n  command line (Linux/UNIX only) and copy to `/src` folder\n- Create a database in postgres cli or [pgAdmin](https://www.pgadmin.org/) tool\n- Rename `dotenv.sample` to `.env` and update the database connection string in `DATABASE_URL` key.\n- Build with release profile: `cargo build --release`\n- Run release binary in command line/terminal.\n  - Windows: `target/release/actix-web-rest-api-with-jwt.exe`\n  - Linux/UNIX: `target/release/actix-web-rest-api-with-jwt`\n- Enjoy! 😄\n\n### Docker\n\n- Enter into project directory\n- Run `docker-compose -f docker-compose.local.yml up` for local environment\n  or `docker-compose -f docker-compose.prod.yml up` for production environment\n- Enjoy! 😄\n\n### Note for yew-address-book-client\n\n- I also made [yew-address-book-client](https://github.com/SakaDream/yew-address-book-client), an Address Book Frontend\n  using yew-rs.\n- yew-address-book-client is heavily under in development, currently the web client does not have login/signup page, so\n  if you want to integrate with backend-side, comment this line bellow in `main.rs` to disable authentication middleware\n  \u003chttps://github.com/SakaDream/actix-web-rest-api-with-jwt/blob/636d6e548f60d341c05707a0e5d3f4e1ee02e60a/src/main.rs#L70\u003e\n\n## APIs\n\n### Address: **`localhost:8000`**\n\n### `GET /api/ping`: Ping\n\n```bash\ncurl -X GET -i 'http://127.0.0.1:8000/api/ping'\n```\n\n- Response:\n  - 200 OK\n\n    ```text\n    pong!\n    ```\n\n### `POST /api/auth/signup`: Signup\n\n```bash\ncurl -X POST -i 'http://127.0.0.1:8000/api/auth/signup' \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\n    \"username\": \"user\",\n    \"email\": \"user@email.com\",\n    \"password\": \"4S3cr3tPa55w0rd\"\n  }'\n```\n\n- Request body:\n\n  ```text\n  {\n     \"username\": string,\n     \"email\": string,\n     \"password\": string       // a raw password\n  }\n  ```\n\n- Response\n  - 200 OK\n\n  ```json\n  {\n     \"message\": \"signup successfully\",\n     \"data\": \"\"\n  }\n  ```\n\n  - 400 Bad Request\n\n  ```json\n  {\n     \"message\": \"User '{username}' is already registered\",\n     \"data\": \"\"\n  }\n  ```\n\n### `POST /api/auth/login`: Login\n\n```bash\ncurl -X POST -H 'Content-Type: application/json' -i 'http://127.0.0.1:8000/api/auth/login'  \\\n  --data '{\"username_or_email\":\"user\",  \"password\":\"4S3cr3tPa55w0rd\"}'\n```\n\n- Request body:\n\n  ```text\n  {\n     \"username_or_email\": string,\n     \"password\": string       // a raw password\n  }\n  ```\n\n- Response\n  - 200 OK\n\n  ```text\n  {\n     \"message\": \"login successfully\",\n     \"data\": {\n       \"token\": string      // bearer token\n     }\n  }\n  ```\n\n  - 400 Bad Request\n\n  ```json\n  {\n     \"message\": \"wrong username or password, please try again\",\n     \"data\": \"\"\n  }\n  ```\n\n### `POST /api/auth/logout`: Logout\n\n```bash\ncurl -X POST -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzcyNTc4NzksImV4cCI6MTU3Nzg2MjY3OSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiYzUxNWE3NTg3NGYzNGVjNGFmNDJmNWE2M2QxMDVjMGYifQ.B9w6FxFdypb5GCRMKXZ9CZWFxQLFjvmPSusMCtcE-Ac' \\\n  -i 'http://127.0.0.1:8000/api/auth/logout'\n```\n\n### `GET /api/address-book`: Get all people information\n\n```bash\ncurl -X GET -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzU4NzM4MjksImV4cCI6MTU3NjQ3ODYyOSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiZjU5N2M3MTIxZTExNDBhMGE0ZjE0YmQ4N2NjM2Q4MWUifQ.6qppDfRgOw45eExJ7MUEwpcu3AUXXe9_ifj_mp7k22k' \\\n  -i 'http://127.0.0.1:8000/api/address-book'\n```\n\n- Header:\n  - Authorization: bearer \\\u003ctoken\\\u003e\n- Response\n  - 200 OK\n\n  ```text\n  {\n     \"message\": \"ok\",\n     \"data\": [\n        {\n          \"id\": int32,\n          \"name\": string,\n          \"gender\": boolean,      // true for male, false for female\n          \"age\": int32,\n          \"address\": string,\n          \"phone\": string,\n          \"email\": string\n        }\n     ]\n  }\n  ```\n\n### `GET /api/address-book/{id}`: Get person information by id\n\n```bash\ncurl -X GET -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzU4NzM4MjksImV4cCI6MTU3NjQ3ODYyOSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiZjU5N2M3MTIxZTExNDBhMGE0ZjE0YmQ4N2NjM2Q4MWUifQ.6qppDfRgOw45eExJ7MUEwpcu3AUXXe9_ifj_mp7k22k' \\\n  -i 'http://127.0.0.1:8000/api/address-book/2'\n```\n\n- Param path:\n  - id: int32\n- Header:\n  - Authorization: bearer \\\u003ctoken\\\u003e\n- Response\n  - 200 OK\n\n  ```text\n  {\n     \"message\": \"ok\",\n     \"data\": {\n       \"id\": int32,\n       \"name\": string,\n       \"gender\": boolean,      // true for male, false for female\n       \"age\": int32,\n       \"address\": string,\n       \"phone\": string,\n       \"email\": string\n     }\n  }\n  ```\n\n  - 404 Not Found\n\n  ```json\n  {\n     \"message\": \"person with id {id} not found\",\n     \"data\": \"\"\n  }\n  ```\n\n### `GET /api/address-book/filter`: Filter person information\n\n```bash\ncurl -X GET -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzU4NzM4MjksImV4cCI6MTU3NjQ3ODYyOSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiZjU5N2M3MTIxZTExNDBhMGE0ZjE0YmQ4N2NjM2Q4MWUifQ.6qppDfRgOw45eExJ7MUEwpcu3AUXXe9_ifj_mp7k22k' \\\n  -i 'http://127.0.0.1:8000/api/address-book/filter?name=foo\u0026sort_by=name\u0026sort_direction=asc\u0026page_num=0\u0026page_size=10'\n```\n\n- Query param:\n  - id: int32\n  - name: string\n  - gender: boolean\n  - age: int32\n  - address: String\n  - phone: string\n  - email: string\n  - sort_by: string\n  - sort_direction: string (ASC or DESC)\n  - page_num: int32\n  - page_size: int32\n- Header:\n  - Authorization: bearer \\\u003ctoken\\\u003e\n- Response\n  - 200 OK\n\n  ```text\n  {\n    \"message\": \"ok\",\n    \"data\": [\n      {\n        \"id\": int32,\n        \"name\": string,\n        \"gender\": boolean,      // true for male, false for female\n        \"age\": int32,\n        \"address\": string,\n        \"phone\": string,\n        \"email\": string\n      }\n    ],\n    \"page_num\": int32,\n    \"page_size\": int32,\n    \"total_elements\": int32\n  }\n  ```\n\n### `POST /api/address-book`: Add person information\n\n```bash\ncurl -X POST -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzU4NzM4MjksImV4cCI6MTU3NjQ3ODYyOSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiZjU5N2M3MTIxZTExNDBhMGE0ZjE0YmQ4N2NjM2Q4MWUifQ.6qppDfRgOw45eExJ7MUEwpcu3AUXXe9_ifj_mp7k22k' \\\n  -i 'http://127.0.0.1:8000/api/address-book' \\\n  --data '{\n    \"name\": \"c\",\n    \"gender\": true,\n    \"age\": 32,\n    \"address\": \"addr\",\n    \"phone\": \"133\",\n    \"email\": \"e@q.com\"\n  }\n'\n```\n\n- Header:\n  - Authorization: bearer \\\u003ctoken\\\u003e\n- Request body:\n\n  ```text\n  {\n    \"name\": string,\n    \"gender\": boolean,      // true for male, false for female\n    \"age\": int32,\n    \"address\": string,\n    \"phone\": string,\n    \"email\": string\n  }\n  ```\n\n- Response\n  - 201 Created\n\n  ```json\n  {\n    \"message\": \"ok\",\n    \"data\": \"\"\n  }\n  ```\n\n  - 500 Internal Server Error\n\n  ```json\n  {\n    \"message\": \"can not insert data\",\n    \"data\": \"\"\n  }\n  ```  \n\n### `PUT /api/address-book/{id}`: Update person information by id\n\n```bash\ncurl -X PUT -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzU4NzM4MjksImV4cCI6MTU3NjQ3ODYyOSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiZjU5N2M3MTIxZTExNDBhMGE0ZjE0YmQ4N2NjM2Q4MWUifQ.6qppDfRgOw45eExJ7MUEwpcu3AUXXe9_ifj_mp7k22k' \\\n  -i 'http://127.0.0.1:8000/api/address-book/2' \\\n  --data '{\n    \"name\": \"b\",\n    \"gender\": true,\n    \"age\": 32,\n    \"address\": \"addr\",\n    \"phone\": \"133\",\n    \"email\": \"b@q.com\"\n  }\n'\n```\n\n- Param path:\n  - id: int32\n- Header:\n  - Authorization: bearer \\\u003ctoken\\\u003e\n- Request body:\n\n  ```text\n  {\n    \"name\": string,\n    \"gender\": boolean,      // true for male, false for female\n    \"age\": int32,\n    \"address\": string,\n    \"phone\": string,\n    \"email\": string\n  }\n  ```\n\n- Response\n  - 200 OK\n\n  ```json\n  {\n    \"message\": \"ok\",\n    \"data\": \"\"\n  }\n  ```\n\n  - 500 Internal Server Error\n\n  ```json\n  {\n    \"message\": \"can not update data\",\n    \"data\": \"\"\n  }\n  ```\n\n### `DELETE /api/address-book/{id}`: Delete person information by id\n\n```bash\ncurl -X DELETE -H 'Content-Type: application/json' \\\n  -H 'Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzU4NzM4MjksImV4cCI6MTU3NjQ3ODYyOSwidXNlciI6ImMiLCJsb2dpbl9zZXNzaW9uIjoiZjU5N2M3MTIxZTExNDBhMGE0ZjE0YmQ4N2NjM2Q4MWUifQ.6qppDfRgOw45eExJ7MUEwpcu3AUXXe9_ifj_mp7k22k' \\\n  -i 'http://127.0.0.1:8000/api/address-book/2'\n```\n\n- Param path:\n  - id: int32\n- Header:\n  - Authorization: bearer \\\u003ctoken\\\u003e\n- Response\n  - 200 OK\n\n  ```json\n  {\n    \"message\": \"ok\",\n    \"data\": \"\"\n  }\n  ```\n\n  - 500 Internal Server Error\n\n  ```json\n  {\n    \"message\": \"can not delete data\",\n    \"data\": \"\"\n  }\n  ```\n\n### browser OPTIONS curl request example\n\n```bash\ncurl -X OPTIONS -i 'http://127.0.0.1:8000/api/login' \\\n  -H \"Origin: http://example.com\" -H \"Access-Control-Request-Method: POST\"\n```\n\n- Response\n\n  ```text\n  HTTP/1.1 200 OK\n  content-length: 0\n  access-control-max-age: 3600\n  access-control-allow-methods: POST,DELETE,GET,PUT\n  access-control-allow-origin: *\n  access-control-allow-headers: authorization,content-type,accept\n  date: Tue, 07 Jan 2020 15:17:48 GMT\n  ```\n\n### Errors\n\n- Invalid or missing token\n  - Status code: 401 Unauthorized\n  - Response:\n\n  ```json\n  {\n    \"message\": \"invalid token, please login again\",\n    \"data\": \"\"\n  }\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSakaDream%2Factix-web-rest-api-with-jwt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSakaDream%2Factix-web-rest-api-with-jwt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSakaDream%2Factix-web-rest-api-with-jwt/lists"}