Rust ile Web Servis Uygulaması
Bundan önceki iki makalemizde bir rust uygulama yapısının nasıl olacağından bahsetmiştik. Şimdi ise bu yapıları daha katmanlı bir hale getireceğiz. Daha sonrada bunu bir web servis uygulaması haline getireceğiz. Rust hızlı bir şekilde gelişme sürecine devam ediyor. Burada dikkat etmeniz gereken 2018 sürümüyle öncesi arasında farklar olduğudur.
Tekrardan Cargo.toml dosyamızı açıyoruz. Buraya bir kaç tane daha ekleme yapacağız. Öncelike actix-web ve actix-rt ekliyoruz.Bu kütüphaneler Rust için güçlü, pragmatik ve son derece hızlı bir web çerçevesi oluşturmaktadır. Daha sonra serde kütüphanesini JSON serialization için ekleyeceğiz.
1 2 3 4 5 6 7 8 9 10 |
[dependencies] mysql = "*" chrono = "0.4" actix-web = "2.0" actix-rt = "*" serde = "*" |
Veritabanı Katmanı
Veritabanı katmanını oluşturmak için src klasörü altında database_layer.rs dosyasını oluşturmakla işe başlıyoruz. Daha önceki makalelerimizde kullandığımız CALISAN tablosuyla yolumuza devam ediyoruz.
Yukarıda da bahsettiğimiz gibi serialization işlemleri için serde ekliyoruz. Calisan yapısınında seriazlize işlemini yapabilmesi için aşağıdaki gibi tanımlıyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
use chrono::prelude::*; use mysql::prelude::*; use mysql::*; use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize)] pub struct Calisan { pub sicil: u64, pub kimlik_no: String, pub maas: f64, pub ad_soyad: String, pub bolum:String, pub tarih: NaiveDate, } pub fn today() -> NaiveDate { let l = Local::today(); NaiveDate::from_ymd(l.year(), l.month(), l.day()) } |
Geneltanımlarımızı yaptıktan sonra veritabanına işlem yapacak olan fonksiyonlarımızı eklemeye başlıyoruz. Ekleme ve getirme işlemlerini kodumuza ekliyoruz. Fonksiyonalarda referans olarak calisan ve conn (bağlantı) değerlerini almaktadır. & işareti referans veriyi işaret etmektedir. Dönüş değeri olarak conn.last_insert_id() son eklenen veriyi dönmekteyiz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
pub fn add_calisan( conn: &mut PooledConn, calisan: &Calisan) -> std::result::Result<u64, mysql::error::Error> { conn.exec_drop( "insert into CALISAN (sicil, kimlik_no, maas,ad_soyad, bolum,tarih) values (:sicil, :kimlik_no, :maas,:ad_soyad, :bolum,:tarih)", params! { "sicil" => &calisan.sicil, "kimlik_no" => &calisan.kimlik_no, "maas" => &calisan.maas, "ad_soyad" => &calisan.ad_soyad, "bolum" => &calisan.bolum, "tarih" => today(), }, ) .and_then(|_| Ok(conn.last_insert_id())) } |
Sicil ile çalışan bilgisini alma fonksiyonunu ekliyoruz. Dönüş bilgisi olarak Calisan yapısını dönecektir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
pub fn find_calisan_by_sicil( conn: &mut PooledConn, sicil: u64, ) -> std::result::Result<option, mysql::error::Error> { let row = conn.exec_first( "select sicil, kimlik_no, maas,ad_soyad, bolum,tarih from CALISAN where sicil=:sicil", params! { "sicil" => sicil }, )?; Ok(row.map(|(sicil, kimlik_no, maas,ad_soyad, bolum,tarih)| Calisan { sicil: sicil, kimlik_no: kimlik_no, maas: maas, ad_soyad: ad_soyad, bolum: bolum, tarih: tarih })) } |
Web Servis Katmanı
Src klasörü altına web_service.rs dosyasını oluşturuyoruz.actix_web ile web uygulamaları oluşturabildiğimizi söylemiştim. Bu konuda dikkat edilmesi gereken konu diğer kütüphaneler ile uyumluluğudur. Bazen versiyonlar arasında uyumsuzluklar olabiliyor.
1 2 3 4 5 6 7 8 |
use super::database_layer::*; use actix_web::*; use mysql::*; use serde::Deserialize; |
Çalışan bulma servisimiz ile /product/1 çağrım örneğinde ki gibi bir çağrım yapıyoruz. Çağrım sonunda şayet veri bulursan JSON formatında çalışan bilgisini döneceğiz. Bir hata durumunda ise InternalServerError() ile dönüş yapıyor olacağız. Dikkat ederseniz web::Data şeklinde bir tanımlamamız var bununlada uygulamada kullacağız paylaşımlı tipleri uygulamamıza yolluyoruz. Biz bu örnekte connection bilgisini bu şekilde katmanımıza gönderiyor olacağız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#[get("/calisan/{id}")] async fn get_calisan(path: web::Path, data: web::Data) -> HttpResponse { let sicil = *path; match data .get_conn() .and_then(|mut conn| find_calisan_by_sicil(&mut conn, sicil)) { Ok(res) => match res { Some(calisan) => HttpResponse::Ok().json(calisan), None => HttpResponse::NotFound().finish(), }, Err(_) => HttpResponse::InternalServerError().finish(), } } |
Çalışan ekleme fonksiyonunda POST işlemini kullanarak Calisan verisini gönderiyor olacağız. web::Json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#[post("/calisan")] async fn register_calisan(calisan_json: web::Json, data: web::Data) -> HttpResponse { let calisan = calisan_json.into_inner(); match data .get_conn() .and_then(|mut conn| insert_calisan(&mut conn, &calisan)) { Ok(sicil) => { //Return a calisan with id set. HttpResponse::Ok().json(Calisan { sicil: sicil, ..calisan }) }, Err(_) => HttpResponse::InternalServerError().finish(), } } |
Ana Uygulama
Main fonksiyonumuzu üzerinde düzenleme yapıyor olacağız. Diğer uygulamamızdaki mysql bağlantısını da kullanıyoruz. Daha sonra bir HttpServer oluşturacağız. Bu Sunucuya web servis methodlarımızı register ederek işlemlerimize devam ediyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
mod web_service; mod database_layer; use mysql::*; use actix_web::*; #[actix_rt::main] async fn main() { println!("Sistem açıldı...."); let url = "mysql://dbUser:parola@localhost:3306/Demo"; let pool = match Pool::new(url) { Ok(pool) => pool, Err(e) => { println!("Bağlantı oluşturulamadı. {:?}", e); return; } }; let shared_data = web::Data::new(pool); let server = match HttpServer::new(move || { App::new() .app_data(shared_data.clone()) .service(web_service::get_calisan) .service(web_service::register_calisan) }).bind("127.0.0.1:8080") { Ok(s) => s, Err(e) => { println!("Port açılamadı. {:?}", e); return; } }; match server.run().await { Ok(_) => println!("Sunucu normal şekilde kapatıldı."), Err(e) => println!("Sunucu hatalı şekilde kapandı: {:?}", e), }; } |
Sunucumuz ayağa kalktıktan sonra herhangi bir internet tarayıcı üstünden 127.0.0.1:8080/calisan/1 çağrımı ile servisimizi deneyebiliriz. Buradaki 1 yerine sizin sisteminizde kayıtlı olan sicil numarası ne ise kullanabilirsiniz.
Sürçi lisan ettiysek affola
Kaynaklar :
https://docs.rs/
https://actix.rs/actix-web/actix_web/