|
| 1 | +# RustAPI Sorun Giderme Notları |
| 2 | + |
| 3 | +Bu doküman, RustAPI ile çalışırken karşılaşılan yaygın sorunları ve çözümlerini içerir. |
| 4 | + |
| 5 | +## ✅ Temel Kurallar |
| 6 | + |
| 7 | +### 1. **`Schema` Derive Macro'su Kullanımı** |
| 8 | + |
| 9 | +**Sorun:** |
| 10 | +```rust |
| 11 | +#[derive(Debug, Deserialize)] |
| 12 | +pub struct ListParams { |
| 13 | + pub page: Option<u32>, |
| 14 | +} |
| 15 | +``` |
| 16 | +``` |
| 17 | +error[E0277]: the trait bound `...: Handler<_>` is not satisfied |
| 18 | +``` |
| 19 | + |
| 20 | +**Çözüm:** |
| 21 | +Query parametreleri için kullanılan struct'lara **mutlaka** `Schema` derive macro'su eklenmelidir: |
| 22 | + |
| 23 | +```rust |
| 24 | +#[derive(Debug, Deserialize, Schema)] // ✅ Schema eklendi |
| 25 | +pub struct ListParams { |
| 26 | + pub page: Option<u32>, |
| 27 | +} |
| 28 | +``` |
| 29 | + |
| 30 | +**Neden?** |
| 31 | +- RustAPI, OpenAPI dökümantasyonu oluşturmak için tüm extractorların schema bilgisine ihtiyaç duyar |
| 32 | +- `Query<T>` extractor'ı, `T: RustApiSchema` trait bound'ı gerektirir |
| 33 | +- `Schema` derive macro'su bu trait'i otomatik implement eder |
| 34 | + |
| 35 | +--- |
| 36 | + |
| 37 | +### 2. **utoipa Değil, rustapi-openapi Kullan** |
| 38 | + |
| 39 | +**Yanlış:** |
| 40 | +```toml |
| 41 | +[dependencies] |
| 42 | +utoipa = "4.2" # ❌ Kullanma |
| 43 | +``` |
| 44 | + |
| 45 | +**Doğru:** |
| 46 | +```toml |
| 47 | +[dependencies] |
| 48 | +rustapi-rs = { version = "0.1.233", features = ["full"] } |
| 49 | +rustapi-openapi = "0.1.233" # ✅ Bunu kullan |
| 50 | +``` |
| 51 | + |
| 52 | +**Not:** |
| 53 | +- RustAPI kendi OpenAPI implementasyonunu kullanır (`rustapi-openapi`) |
| 54 | +- `utoipa` eklersen bağımlılık çakışmaları olabilir |
| 55 | +- `Schema` derive macro'su `rustapi_rs::prelude::*` içinde zaten var |
| 56 | + |
| 57 | +--- |
| 58 | + |
| 59 | +### 3. **Query Extractor ile Attribute Macros** |
| 60 | + |
| 61 | +**Yanlış:** |
| 62 | +```rust |
| 63 | +#[derive(Debug, Deserialize, IntoParams)] // ❌ IntoParams utoipa'dan |
| 64 | +pub struct ListParams { |
| 65 | + #[param(minimum = 1)] // ❌ param attribute yok |
| 66 | + pub page: Option<u32>, |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +**Doğru:** |
| 71 | +```rust |
| 72 | +#[derive(Debug, Deserialize, Schema)] // ✅ Schema kullan |
| 73 | +pub struct ListParams { |
| 74 | + /// Page number (1-indexed) // ✅ Doc comments OpenAPI'ye yansır |
| 75 | + pub page: Option<u32>, |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +**Notlar:** |
| 80 | +- `#[param(...)]` attribute'u RustAPI'de yok |
| 81 | +- Validation kuralları için `validator` crate kullan: |
| 82 | + ```rust |
| 83 | + #[derive(Debug, Deserialize, Validate, Schema)] |
| 84 | + pub struct CreateTask { |
| 85 | + #[validate(length(min = 1, max = 200))] |
| 86 | + pub title: String, |
| 87 | + } |
| 88 | + ``` |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +### 4. **Handler Macro Kullanımı** |
| 93 | + |
| 94 | +**Doğru Kullanım:** |
| 95 | +```rust |
| 96 | +#[rustapi_rs::get("/tasks")] |
| 97 | +#[rustapi_rs::tag("Tasks")] |
| 98 | +#[rustapi_rs::summary("List Tasks")] |
| 99 | +async fn list_tasks( |
| 100 | + State(store): State<TaskStore>, |
| 101 | + Query(params): Query<ListParams>, // ✅ Schema derive'lı struct |
| 102 | +) -> Json<PaginatedTasks> { |
| 103 | + // ... |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +**RustApi::auto() ile Kullanım:** |
| 108 | +```rust |
| 109 | +#[tokio::main] |
| 110 | +async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { |
| 111 | + // Handler macro'ları kullanıldığında auto() yeterli |
| 112 | + RustApi::auto() |
| 113 | + .state(store) |
| 114 | + .run("127.0.0.1:8080") |
| 115 | + .await |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +### 5. **serde_json::Value ile Schema Sorunu** |
| 122 | + |
| 123 | +**Sorun:** |
| 124 | +```rust |
| 125 | +async fn handler() -> Json<serde_json::Value> { // ❌ Schema yok |
| 126 | + Json(json!({ "key": "value" })) |
| 127 | +} |
| 128 | +``` |
| 129 | +``` |
| 130 | +error: the trait `RustApiSchema` is not implemented for `serde_json::Value` |
| 131 | +``` |
| 132 | + |
| 133 | +**Çözüm 1 - Wrapper Struct (Önerilen):** |
| 134 | +```rust |
| 135 | +#[derive(Serialize, Schema)] |
| 136 | +struct MyResponse { |
| 137 | + key: String, |
| 138 | +} |
| 139 | + |
| 140 | +async fn handler() -> Json<MyResponse> { // ✅ Type-safe |
| 141 | + Json(MyResponse { |
| 142 | + key: "value".to_string(), |
| 143 | + }) |
| 144 | +} |
| 145 | +``` |
| 146 | + |
| 147 | +**Çözüm 2 - String olarak dönme:** |
| 148 | +```rust |
| 149 | +#[derive(Serialize, Schema)] |
| 150 | +struct JsonResponse { |
| 151 | + data: String, // JSON as string |
| 152 | +} |
| 153 | + |
| 154 | +async fn handler() -> Json<JsonResponse> { |
| 155 | + let value = json!({ "key": "value" }); |
| 156 | + Json(JsonResponse { |
| 157 | + data: serde_json::to_string(&value).unwrap(), |
| 158 | + }) |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +**Neden?** |
| 163 | +- `serde_json::Value` RustAPI'nin Schema trait'ini implement etmez |
| 164 | +- OpenAPI dökümantasyonu için concrete type'lar gerekir |
| 165 | +- Type-safe struct'lar hata yakalamayı kolaylaştırır |
| 166 | + |
| 167 | +--- |
| 168 | + |
| 169 | +### 6. **impl IntoResponse Dönüş Tipi** |
| 170 | + |
| 171 | +**Sorun:** |
| 172 | +```rust |
| 173 | +#[rustapi_rs::get("/")] |
| 174 | +async fn handler() -> impl IntoResponse { // ❌ Handler trait error |
| 175 | + Html("<h1>Hello</h1>") |
| 176 | +} |
| 177 | +``` |
| 178 | + |
| 179 | +**Çözüm:** |
| 180 | +Concrete type kullan: |
| 181 | +```rust |
| 182 | +#[rustapi_rs::get("/")] |
| 183 | +async fn handler() -> Html<String> { // ✅ Concrete type |
| 184 | + Html("<h1>Hello</h1>".to_string()) |
| 185 | +} |
| 186 | +``` |
| 187 | + |
| 188 | +**Alternatif Response Types:** |
| 189 | +- `Html<String>` - HTML içerik |
| 190 | +- `Json<T>` - JSON response (T: Schema olmalı) |
| 191 | +- `String` - Plain text |
| 192 | +- `StatusCode` - Sadece status code |
| 193 | +- `(StatusCode, Json<T>)` - Status + JSON |
| 194 | + |
| 195 | +--- |
| 196 | + |
| 197 | +## 📋 Checklist: Yeni Bir Handler Eklerken |
| 198 | + |
| 199 | +- [ ] Query params struct'ına `Schema` derive ekle |
| 200 | +- [ ] Response struct'larına `Schema` derive ekle |
| 201 | +- [ ] Request body struct'larına `Schema` derive ekle |
| 202 | +- [ ] Validation gerekiyorsa `Validate` derive ve attribute'lar ekle |
| 203 | +- [ ] `#[rustapi_rs::get/post/...]` macro'larını kullan |
| 204 | +- [ ] `RustApi::auto()` ile automatic route discovery kullan |
| 205 | +- [ ] `cargo check` ile compile et |
| 206 | +- [ ] Swagger UI'dan test et (`http://127.0.0.1:8080/docs`) |
| 207 | + |
| 208 | +--- |
| 209 | + |
| 210 | +## 🔍 Debug İpuçları |
| 211 | + |
| 212 | +### Hata: "Handler trait not implemented" |
| 213 | + |
| 214 | +1. **Tüm extractor'ların Schema implement ettiğinden emin ol:** |
| 215 | + ```rust |
| 216 | + Query(params): Query<ListParams> // ListParams: Schema olmalı |
| 217 | + ``` |
| 218 | + |
| 219 | +2. **FromRequest trait'i doğru implement edilmiş mi kontrol et:** |
| 220 | + - `State<T>`, `Query<T>`, `Path<T>` → `FromRequestParts` implement eder |
| 221 | + - `Json<T>`, `Body` → `FromRequest` implement eder |
| 222 | + - `FromRequestParts` otomatik olarak `FromRequest` implement eder (blanket impl) |
| 223 | + |
| 224 | +3. **Parametre sırası önemli:** |
| 225 | + ```rust |
| 226 | + async fn handler( |
| 227 | + State(...): State<...>, // ✅ State first |
| 228 | + Query(...): Query<...>, // ✅ Query params |
| 229 | + Json(...): Json<...>, // ✅ Body son olmalı |
| 230 | + ) -> ... |
| 231 | + ``` |
| 232 | + |
| 233 | +### Hata: "State not found" |
| 234 | + |
| 235 | +```rust |
| 236 | +// State'i ekle: |
| 237 | +RustApi::auto() |
| 238 | + .state(my_state) // ← Bunu unutma! |
| 239 | + .run("0.0.0.0:8080") |
| 240 | + .await |
| 241 | +``` |
| 242 | + |
| 243 | +--- |
| 244 | + |
| 245 | +## 📚 Faydalı Kaynaklar |
| 246 | + |
| 247 | +- [RustAPI Cookbook](https://tuntii.github.io/RustAPI/cookbook/) |
| 248 | +- [Examples Repository](https://github.com/Tuntii/rustapi-rs-examples) |
| 249 | +- [RustAPI Documentation](https://docs.rs/rustapi-rs/) |
| 250 | + |
| 251 | +--- |
| 252 | + |
| 253 | +## 🎯 Özet |
| 254 | + |
| 255 | +**En önemli 3 kural:** |
| 256 | +1. **Query/Path/Response struct'larına `Schema` derive ekle** |
| 257 | +2. **`utoipa` kullanma, `rustapi-openapi` zaten var** |
| 258 | +3. **`RustApi::auto()` kullanırken handler macro'larını kullan** |
| 259 | + |
| 260 | +Bu kurallara uyarsan RustAPI ile sorunsuz çalışırsın! 🚀 |
0 commit comments