wip
This commit is contained in:
@@ -12,5 +12,6 @@ pub fn rocket_builder() -> Rocket<Build> {
|
||||
.attach(Chromium::ignite())
|
||||
.mount("/", routes![
|
||||
routes::pdf::render_pdf_cv,
|
||||
routes::pdf::render_html_cv
|
||||
])
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
use nanobyte_opentelemetry::{default_filter_layer, LogLevel};
|
||||
use std::{panic, fs::File, io::Write};
|
||||
|
||||
use log::error;
|
||||
use nanobyte_opentelemetry::{default_filter_layer, LogLevel, install_panic_handler};
|
||||
use ovlach_pdf::rocket_builder;
|
||||
use tracing::Level;
|
||||
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() {
|
||||
install_panic_handler();
|
||||
let _opentelemetry = nanobyte_opentelemetry::init_telemetry(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
Some(default_filter_layer(LogLevel::Normal))
|
||||
Some(default_filter_layer(LogLevel::DebugWithoutRs))
|
||||
);
|
||||
let _ = rocket_builder().launch().await;
|
||||
}
|
||||
@@ -1,17 +1,20 @@
|
||||
use core::panic;
|
||||
use std::{fs, io::Write};
|
||||
|
||||
use headless_chrome::Browser;
|
||||
use headless_chrome::types::PrintToPdfOptions;
|
||||
use nanobyte_opentelemetry::rocket::TracingSpan;
|
||||
use rocket::{get, fs::NamedFile};
|
||||
use tracing::{info_span, info};
|
||||
use crate::chromium::rocket::BrowserHolder;
|
||||
use rocket::{get, response::stream::ByteStream, fairing::Fairing, fs::NamedFile, futures::TryFutureExt};
|
||||
use tempfile::NamedTempFile;
|
||||
use tera::Context;
|
||||
use tracing::{info_span, error, debug};
|
||||
use crate::{chromium::rocket::BrowserHolder, tools::{tera::NanoTera, pdf::PdfStream}};
|
||||
use urlencoding::encode;
|
||||
|
||||
fn generate_pdf(browser: Browser) {
|
||||
// TODO: request-id
|
||||
fn generate_pdf(browser: Browser, file: &NamedTempFile) -> Vec<u8> {
|
||||
let tab = browser.new_tab().unwrap();
|
||||
let path = format!("file://{}", file.path().to_str().unwrap());
|
||||
info_span!("open_pdf").in_scope(|| {
|
||||
tab.navigate_to("file:///home/6a6996c0-1609-48b6-8ca6-affbef1b4d1d/Devel/Nanobyte/ovlach/ovlach_pdf/template.html").unwrap().wait_until_navigated().unwrap();
|
||||
debug!("Render pdf from {}", &path);
|
||||
tab.navigate_to(&path).unwrap().wait_until_navigated().unwrap();
|
||||
});
|
||||
|
||||
let options = PrintToPdfOptions{
|
||||
@@ -31,25 +34,33 @@ fn generate_pdf(browser: Browser) {
|
||||
tab.print_to_pdf(Some(options)).unwrap()
|
||||
});
|
||||
|
||||
info_span!("write_temporary_file").in_scope(|| {
|
||||
let mut file = fs::OpenOptions::new()
|
||||
// .create(true) // To create a new file
|
||||
.write(true)
|
||||
// either use the ? operator or unwrap since it returns a Result
|
||||
.open("/tmp/foo.pdf").unwrap();
|
||||
file.write_all(&bytes).unwrap();
|
||||
});
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#[get("/cv/<username>/pdf")]
|
||||
pub async fn render_pdf_cv(username: &str, browser: BrowserHolder, tracing: TracingSpan) -> Option<NamedFile> {
|
||||
#[tracing::instrument]
|
||||
fn render_template(template_name: &str, file: &NamedTempFile, tera: NanoTera) {
|
||||
// TODO: handle errors
|
||||
tera.0.render_to("two_column.html.tera", &Context::new(), file);
|
||||
}
|
||||
|
||||
#[get("/cv/<username>/output.pdf")]
|
||||
pub async fn render_pdf_cv(username: &str, browser: BrowserHolder, tera: NanoTera, tracing: TracingSpan) -> PdfStream {
|
||||
let entered_span = tracing.0.enter();
|
||||
let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap();
|
||||
render_template("two_column", &file, tera);
|
||||
let span = info_span!("render_pdf", username = username);
|
||||
info!("generate PDF");
|
||||
span.in_scope(||{
|
||||
generate_pdf(browser.browser);
|
||||
let pdf = span.in_scope(||{
|
||||
generate_pdf(browser.browser, &file)
|
||||
});
|
||||
info!("done generating");
|
||||
drop(entered_span);
|
||||
Some(NamedFile::open("/tmp/foo.pdf").await.expect("failed to open foo.pdf"))
|
||||
PdfStream::new(pdf)
|
||||
}
|
||||
|
||||
/// Route only for debuging
|
||||
#[get("/cv/<username>/output.html")]
|
||||
pub async fn render_html_cv(username: &str, tera: NanoTera, tracing: TracingSpan) -> NamedFile {
|
||||
let entered_span = tracing.0.enter();
|
||||
let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap();
|
||||
render_template("two_column", &file, tera);
|
||||
NamedFile::open(file.path()).await.unwrap()
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod tera;
|
||||
pub mod pdf;
|
||||
25
src/tools/pdf.rs
Normal file
25
src/tools/pdf.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use rocket::{response::{Responder, self}, Request, Response, http::{Header, ContentType}};
|
||||
use std::io::Cursor;
|
||||
|
||||
|
||||
|
||||
pub struct PdfStream {
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl PdfStream {
|
||||
pub fn new(data: Vec<u8>) -> PdfStream {
|
||||
PdfStream { data }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[rocket::async_trait]
|
||||
impl<'r> Responder<'r, 'static> for PdfStream {
|
||||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
|
||||
Response::build()
|
||||
.header(ContentType::PDF)
|
||||
.sized_body(self.data.len(), Cursor::new(self.data))
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
16
src/tools/tera.rs
Normal file
16
src/tools/tera.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use rocket::{request::{FromRequest, Outcome}, Request};
|
||||
use tera::Tera;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NanoTera(pub Tera);
|
||||
|
||||
|
||||
// Allows a route to access the span
|
||||
#[rocket::async_trait]
|
||||
impl<'r> FromRequest<'r> for NanoTera {
|
||||
type Error = ();
|
||||
|
||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, ()> {
|
||||
rocket::outcome::Outcome::Success(NanoTera(Tera::new("templates/*").unwrap()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user