better api and yyyy/mm/dd format for dates in the db

This commit is contained in:
linlkin 2024-12-06 03:52:12 +01:00
parent ac20ecc932
commit ec2322f04c
2 changed files with 61 additions and 10 deletions

View file

@ -12,7 +12,9 @@ pub fn init() -> sqlite::Result<()> {
"CREATE TABLE IF NOT EXISTS articles ( "CREATE TABLE IF NOT EXISTS articles (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
title TEXT NOT NULL, title TEXT NOT NULL,
subTitle TEXT, auteur TEXT,
edited_at DATE_FORMAT('now', '%YYYY-%mm-%dd'),
published_at DATE_FORMAT('now', '%YYYY-%mm-%dd'),
content TEXT NOT NULL content TEXT NOT NULL
)", )",
)?; )?;

View file

@ -1,7 +1,7 @@
mod create_db; mod create_db;
use create_db::init; use create_db::init;
use actix_web::{App, HttpServer, get, Responder, HttpResponse, http::header::ContentType}; use actix_web::{App, web, HttpServer, get, Responder, HttpResponse, http::header::ContentType};
use actix_files::Files; use actix_files::Files;
use serde_json::json; use serde_json::json;
use sqlite::{Connection, State}; use sqlite::{Connection, State};
@ -11,9 +11,9 @@ use serde::{Serialize, Deserialize};
struct Article { struct Article {
id: i64, id: i64,
title: String, title: String,
auteur: Option<String>, auteur: String,
edited_at: Option<String>, edited_at: String,
published_at: Option<String>, published_at: String,
content: String, content: String,
} }
@ -31,13 +31,13 @@ async fn get_articles() -> impl Responder {
while let State::Row = stmt.next().unwrap() { while let State::Row = stmt.next().unwrap() {
let id = stmt.read::<i64, _>(0).unwrap(); let id = stmt.read::<i64, _>(0).unwrap();
let title = stmt.read::<String, _>(1).unwrap(); let title = stmt.read::<String, _>(1).unwrap();
let content = stmt.read::<String, _>(3).unwrap(); let content = stmt.read::<String, _>(5).unwrap();
articles.push(Article { articles.push(Article {
id, id,
title, title,
auteur: None, auteur: "".to_string(),
edited_at: None, edited_at: "".to_string(),
published_at: None, published_at: "".to_string(),
content content
}); });
} }
@ -45,6 +45,54 @@ async fn get_articles() -> impl Responder {
HttpResponse::Ok().json(articles) HttpResponse::Ok().json(articles)
} }
#[get("/api/articles/{id}")]
async fn get_article(path: web::Path<i64>) -> impl Responder {
let id = path.into_inner();
// Open the database connection
let conn = match Connection::open("./data/data.db") {
Ok(conn) => conn,
Err(err) => {
eprintln!("Failed to connect to database: {}", err);
return HttpResponse::InternalServerError().body("Failed to connect to database");
}
};
// Fetch the article from the database
match fetch_article_by_id(&conn, id) {
Ok(Some(article)) => HttpResponse::Ok().json(article),
Ok(None) => HttpResponse::NotFound().body(format!("Article with ID {} not found", id)),
Err(err) => {
eprintln!("Database query error: {}", err);
HttpResponse::InternalServerError().body("Database query failed")
}
}
}
/// Fetches an article by its ID from the database.
fn fetch_article_by_id(conn: &Connection, id: i64) -> Result<Option<Article>, sqlite::Error> {
let mut stmt = conn.prepare(
"SELECT id, title, auteur, edited_at, published_at, content
FROM articles WHERE id = ?1"
)?;
stmt.bind((1, id))?;
let mut article = None;
while let State::Row = stmt.next()? {
article = Some(Article {
id: stmt.read::<i64, _>(0)?,
title: stmt.read::<String, _>(1)?,
auteur: stmt.read::<String, _>(2)?,
edited_at: stmt.read::<String, _>(3)?,
published_at: stmt.read::<String, _>(4)?,
content: stmt.read::<String, _>(5)?,
});
}
Ok(article)
}
#[get("/api")] #[get("/api")]
async fn api() -> impl Responder { async fn api() -> impl Responder {
let value = json!({ let value = json!({
@ -72,9 +120,10 @@ async fn main() -> Result<(), std::io::Error> {
.service(hello) .service(hello)
.service(get_articles) .service(get_articles)
.service(api) .service(api)
.service(get_article)
.service(Files::new("/", "public").index_file("index.html")) .service(Files::new("/", "public").index_file("index.html"))
}) })
.bind(("0.0.0.0", 8080))? .bind(("0.0.0.0", 2486))?
.run() .run()
.await .await
} }