generated from lucien/actix-react-template
better api and yyyy/mm/dd format for dates in the db #8
2 changed files with 60 additions and 9 deletions
|
@ -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
|
||||||
)",
|
)",
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -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,6 +120,7 @@ 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", 2486))?
|
.bind(("0.0.0.0", 2486))?
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue