Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

README.md 4.3 KiB

2 semanas atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. # axum-api-template
  2. An opinionated Axum web API template modelled after the ASP.NET project layout.
  3. ## Philosophy
  4. | ASP.NET concept | This template |
  5. |---|---|
  6. | `Program.cs` bootstrap | `src/main.rs` |
  7. | `appsettings.json` + env overrides | `config/*.toml` + `APP__*` env vars |
  8. | `IServiceCollection` / DI | `AppState` (shared via Axum `State` extractor) |
  9. | Controller classes | `src/handlers/` — one file per resource |
  10. | Request / Response DTOs | `src/models/` — `*Request` / `*Response` suffix convention |
  11. | `ProblemDetails` | `src/errors/ApiError` — single `IntoResponse` impl |
  12. | `app.Use*` middleware pipeline | `src/routes/mod.rs` `build_router()` |
  13. | Route groups (`MapGroup`) | `src/routes/v1.rs` nested routers |
  14. ## Project layout
  15. ```
  16. axum-api-template/
  17. ├── config/
  18. │ ├── default.toml # base config (committed)
  19. │ ├── development.toml # dev overrides (committed)
  20. │ └── production.toml # prod overrides (committed; no secrets)
  21. ├── src/
  22. │ ├── main.rs # entry point — startup sequence
  23. │ ├── lib.rs # re-exports all modules for integration tests
  24. │ ├── config/ # AppConfig (layered TOML + env vars)
  25. │ ├── errors/ # ApiError → consistent JSON error envelope
  26. │ ├── handlers/
  27. │ │ ├── health.rs # GET /health/live, /health/ready
  28. │ │ └── items.rs # full CRUD scaffold for an example resource
  29. │ ├── middleware/
  30. │ │ ├── auth.rs # AuthenticatedUser extractor (JWT stub)
  31. │ │ └── request_id.rs # X-Request-ID documentation anchor
  32. │ ├── models/
  33. │ │ ├── item.rs # Item domain struct + CreateItemRequest + ItemResponse
  34. │ │ └── pagination.rs # PaginationQuery + PagedResponse<T>
  35. │ ├── routes/
  36. │ │ ├── mod.rs # build_router() — middleware stack assembly
  37. │ │ └── v1.rs # /api/v1/* route table
  38. │ └── state/ # AppState (Arc<InnerState>)
  39. ├── tests/
  40. │ ├── common/mod.rs # shared test helpers (TestServer factory)
  41. │ └── health_test.rs # integration tests for /health/*
  42. ├── .env.example
  43. ├── .gitignore
  44. └── Cargo.toml
  45. ```
  46. ## Quickstart
  47. ```bash
  48. cp .env.example .env
  49. # Edit .env — at minimum set APP__DATABASE__URL
  50. cargo run
  51. # → Listening on 0.0.0.0:8080
  52. ```
  53. ## Configuration
  54. Configuration is resolved in order of increasing precedence:
  55. 1. `config/default.toml`
  56. 2. `config/{APP_ENV}.toml` (set `APP_ENV=production` in your environment)
  57. 3. Environment variables prefixed `APP__` with double-underscore separators
  58. ```bash
  59. # Examples
  60. APP__SERVER__PORT=9000
  61. APP__DATABASE__URL=postgres://user:pass@db/myapp
  62. APP__AUTH__JWT_SECRET=super-secret
  63. ```
  64. ## Naming conventions
  65. | Thing | Convention | Example |
  66. |---|---|---|
  67. | Handler functions | `verb_resource` | `list_items`, `create_item` |
  68. | Request DTOs | `{Resource}CreateRequest` | `CreateItemRequest` |
  69. | Response DTOs | `{Resource}Response` | `ItemResponse` |
  70. | Route modules | version-namespaced | `routes/v1.rs` |
  71. | Config env vars | `APP__{SECTION}__{KEY}` | `APP__SERVER__PORT` |
  72. | Error variants | PascalCase domain names | `ApiError::NotFound` |
  73. ## Endpoints
  74. | Method | Path | Description |
  75. |---|---|---|
  76. | `GET` | `/health/live` | Liveness check |
  77. | `GET` | `/health/ready` | Readiness check (dependency health) |
  78. | `GET` | `/api/v1/items` | List items (paginated) |
  79. | `POST` | `/api/v1/items` | Create item |
  80. | `GET` | `/api/v1/items/:id` | Get item by ID |
  81. | `PUT` | `/api/v1/items/:id` | Update item |
  82. | `DELETE` | `/api/v1/items/:id` | Delete item |
  83. ## Error shape
  84. All errors return a consistent JSON envelope:
  85. ```json
  86. {
  87. "error": {
  88. "status": 404,
  89. "code": "NOT_FOUND",
  90. "message": "Item 00000000-0000-0000-0000-000000000001 not found",
  91. "trace_id": "01924b72-1234-7abc-def0-000000000000"
  92. }
  93. }
  94. ```
  95. ## Next steps
  96. - [ ] Replace the in-memory stubs in `handlers/items.rs` with real `sqlx` queries
  97. - [ ] Implement JWT validation in `middleware/auth.rs`
  98. - [ ] Add `APP__DATABASE__URL` to `.env` and uncomment the DB pool in `state/mod.rs`
  99. - [ ] Tighten the CORS policy in `routes/mod.rs` for production
  100. - [ ] Add a service layer between handlers and DB for business logic