Rust: Serverless URL Shortener Pakai Rust dan Cloudflare Worker - ID
Pengenalan
Pengenalan
Pada artikel kali ini, kita akan coba membuat suatu URL shortener seperti bit.ly menggunakan bahasa pemrograman Rust, Platform Serverless Cloudflare Worker, dan Key-Value Database KV.
Disclaimer: Saya tidak disponsori atau terkait dengan CloudFlare.
Sebelum memulai proyek ini, diharapkan Anda memiliki kemampuan dalam bahasa Rust.
Prasayarat
- Rust
- Wrangler
- Cloudflare Account
- KV Namespaces
Cloudflare Workers
Cloudflare Worker adalah sebuah platform yang digunakan untuk menjalankan kode JavaScript, Rust, Python, dan bahasa lainnya di edge network Cloudflare, memungkinkan Anda untuk melakukan pemrosesan dan manipulasi data secara langsung di server terdekat dengan pengguna Anda. Cloudflare Worker akan kita gunakan sebagai “tempat” menjalakan proyek URL Shortener kita.
Cloudflare KV
Cloudflare Workers KV adalah layanan penyimpanan data key-value yang terintegrasi dengan platform Cloudflare Workers. Pada dasarnya adalah tempat menyimpan data yang bisa diakses dan diambil dengan cepat oleh aplikasi web Anda yang berjalan di Cloudflare Workers.
System Design
Pada proyek sederhana ini, kita akan mempunyai 2 endpoint:
- Generate short link, dan simpan di Cloudflare KV
- Redirect ke URL asli menggunakan short link.
Login ke Cloudflare menggunakan Wrangler
Agar command-command seperti wrangler deploy dapat berjalan, maka diperlukan login ke cloudflare menggunakan perintah berikut:
npx wrangler login
Generate Proyek
Setelah login ke akun cloudflare, selanjutnya adalah generate proyek baru menggunakan perintah berikut:
npx wrangler generate lazy-shorter-link https://github.com/cloudflare/workers-sdk/templates/experimental/worker-rust
cd lazy-shorter-link # Change directory to your project
Waktunya Coding!
Kita akan membuat 2 endpoint yaitu:
GET “/:url”: Endpoint dengan pola ini akan digunakan untuk mengambil informasi terkait URL yang telah disingkat sebelumnya.
POST “/short-link”: Endpoint ini akan digunakan untuk membuat URL yang sudah diperpendek.
Namun, sebelum kita implementasi kode, kita perlu membuat namespace KV yang akan gunakan untuk menyimpan data. Jalankan perintah berikut:
npx wrangler kv:namespace create "KV_URL"
Jika berhasil, maka akan menampilkan berikut:
Setelah mendapatkan binding dan id KV, kita akan menambahkan pada file konfigurasi sehingga dapat diakses pada environment dev dan prod.
Ubah konfigurasi wrangler.toml sesuai dengan output perintah diatas
Tambahkan library pendukung pada Cargo.toml sebagai berikut
lib.rs
Secara kesuluruhan, kode kita akan seperti ini:
use rand::distributions::Alphanumeric;
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use worker::{kv::KvStore, *};
#[derive(Deserialize, Serialize)]
struct GenericResponse {
status: u16,
message: String,
}
#[derive(Deserialize, Serialize)]
struct ShortUrl {
url: String,
}
#[event(fetch)]
async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> {
Router::new()
.get_async("/:url", |req, env| async move {
let key = req.path().clone();
if let Some(p) = key.split("/").last() {
let kv = env.kv("KV_URL")?;
let actual_url = kv.get(p).text().await?;
if let Some(a) = actual_url {
let furl = a.to_string();
return Response::redirect(Url::parse(&furl).unwrap());
} else {
return Response::error("Not found", 404);
}
} else {
return Response::error("Not found", 404);
}
})
.post_async("/short-link", |mut req, ctx| async move {
let body = req.json::<ShortUrl>().await?;
let kv = ctx.env.kv("KV_URL")?;
if !is_valid_url(&body.url) {
return Response::from_json(&GenericResponse {
status: 400,
message: "Invalid URL".to_string(),
});
}
let _key = generate_short_link(&body.url, kv).await?;
Response::from_json(&GenericResponse {
status: 200,
message: format!("https://{}{}{}", req.url()?.host_str().unwrap(), "/", _key),
})
})
.run(req, env)
.await
}
// validate url and return a boolean
fn is_valid_url(url: &str) -> bool {
Url::parse(url).is_ok()
}
// generate short link and return a Result
pub async fn generate_short_link(url: &str, kv: KvStore) -> Result<String> {
let key = thread_rng()
.sample_iter(&Alphanumeric)
.take(5)
.map(char::from)
.collect::<String>();
kv.put(&key, &url)?.execute().await?;
return Result::Ok(key);
}
GET /:url :
implementasi dari GET /:url berikut:
get_async("/:url", |req, env| async move {
let key = req.path().clone();
if let Some(p) = key.split("/").last() {
let kv = env.kv("KV_URL")?;
let actual_url = kv.get(p).text().await?;
if let Some(a) = actual_url {
let furl = a.to_string();
return Response::redirect(Url::parse(&furl).unwrap());
} else {
return Response::error("Not found", 404);
}
} else {
return Response::error("Not found", 404);
}
})
POST /short-link
implementasi dari POST /short-link berikut:
post_async("/short-link", |mut req, ctx| async move {
let body = req.json::<ShortUrl>().await?;
let kv = ctx.env.kv("KV_URL")?;
if !is_valid_url(&body.url) {
return Response::from_json(&GenericResponse {
status: 400,
message: "Invalid URL".to_string(),
});
}
let _key = generate_short_link(&body.url, kv).await?;
Response::from_json(&GenericResponse {
status: 200,
message: format!("https://{}{}{}", req.url()?.host_str().unwrap(), "/", _key),
})
})
Testing Pada Environment Dev
Jalankan perintah berikut untuk menjalankan code secara local
npx wrangler dev
Maka akan muncul output sebagai berikut:
Akses link diatas untuk melakukan testing
Deploy ke Cloudflare Worker
Jalankan perintah berikut untuk melakukan deployment code yang sudah dikembangkan ke cloudflare worker
npx wrangler deploy
Berikut adalah output dari deployment
Akses secara Publik
Coba akses kedua endpoint tersebut melalui cloudflare worker kalian
Contoh:
/short-link
/:url
Kesimpulan
Dengan demikian, kita telah berhasil membuat sebuah URL shortener menggunakan Rust, Cloudflare Worker, dan Cloudflare KV. Selamat mencoba!
Follow my linkedin on: www.linkedin.com/in/marchel-fahrezi-212a87185