From 93ab91e732d2ffbd758ace9127f645c5ce402380 Mon Sep 17 00:00:00 2001 From: Joep Meindertsma Date: Mon, 27 Feb 2023 16:58:21 +0100 Subject: [PATCH] Use get_subject --- server/src/handlers/get_resource.rs | 33 ++------------ server/src/handlers/post_resource.rs | 33 ++------------ server/src/handlers/search.rs | 2 +- server/src/handlers/single_page_app.rs | 7 ++- server/src/handlers/upload.rs | 2 +- server/src/helpers.rs | 63 ++++++++++++++++++-------- 6 files changed, 59 insertions(+), 81 deletions(-) diff --git a/server/src/handlers/get_resource.rs b/server/src/handlers/get_resource.rs index 41a23bd38..784547d7a 100644 --- a/server/src/handlers/get_resource.rs +++ b/server/src/handlers/get_resource.rs @@ -1,9 +1,8 @@ use crate::{ appstate::AppState, - content_types::get_accept, content_types::ContentType, errors::AtomicServerResult, - helpers::{get_client_agent, try_extension}, + helpers::{get_client_agent, get_subject}, }; use actix_web::{web, HttpResponse}; use atomic_lib::Storelike; @@ -16,39 +15,13 @@ pub async fn handle_get_resource( path: Option>, appstate: web::Data, req: actix_web::HttpRequest, + conn: actix_web::dev::ConnectionInfo, ) -> AtomicServerResult { let mut timer = Timer::new(); let headers = req.headers(); - let mut content_type = get_accept(headers); - let server_url = &appstate.config.server_url; // Get the subject from the path, or return the home URL - let subject = if let Some(subj_end) = path { - let mut subj_end_string = subj_end.as_str(); - // If the request is for the root, return the home URL - if subj_end_string.is_empty() { - server_url.to_string() - } else { - if content_type == ContentType::Html { - if let Some((ext, path)) = try_extension(subj_end_string) { - content_type = ext; - subj_end_string = path; - } - } - // Check extensions and set datatype. Harder than it looks to get right... - // This might not be the best way of creating the subject. But I can't access the full URL from any actix stuff! - let querystring = if req.query_string().is_empty() { - "".to_string() - } else { - format!("?{}", req.query_string()) - }; - let subject = format!("{}/{}{}", server_url, subj_end_string, querystring); - subject - } - } else { - // There is no end string, so It's the root of the URL, the base URL! - String::from(server_url) - }; + let (subject, content_type) = get_subject(&req, &conn, &appstate)?; let store = &appstate.store; timer.add("parse_headers"); diff --git a/server/src/handlers/post_resource.rs b/server/src/handlers/post_resource.rs index 3b46c9eab..3368954a1 100644 --- a/server/src/handlers/post_resource.rs +++ b/server/src/handlers/post_resource.rs @@ -1,9 +1,8 @@ use crate::{ appstate::AppState, - content_types::get_accept, content_types::ContentType, errors::AtomicServerResult, - helpers::{get_client_agent, try_extension}, + helpers::{get_client_agent, get_subject}, }; use actix_web::{web, HttpResponse}; use atomic_lib::Storelike; @@ -16,39 +15,13 @@ pub async fn handle_post_resource( appstate: web::Data, req: actix_web::HttpRequest, body: web::Bytes, + conn: actix_web::dev::ConnectionInfo, ) -> AtomicServerResult { let mut timer = Timer::new(); let headers = req.headers(); - let mut content_type = get_accept(headers); - let server_url = &appstate.config.server_url; // Get the subject from the path, or return the home URL - let subject = if let Some(subj_end) = path { - let mut subj_end_string = subj_end.as_str(); - // If the request is for the root, return the home URL - if subj_end_string.is_empty() { - server_url.to_string() - } else { - if content_type == ContentType::Html { - if let Some((ext, path)) = try_extension(subj_end_string) { - content_type = ext; - subj_end_string = path; - } - } - // Check extensions and set datatype. Harder than it looks to get right... - // This might not be the best way of creating the subject. But I can't access the full URL from any actix stuff! - let querystring = if req.query_string().is_empty() { - "".to_string() - } else { - format!("?{}", req.query_string()) - }; - let subject = format!("{}/{}{}", server_url, subj_end_string, querystring); - subject - } - } else { - // There is no end string, so It's the root of the URL, the base URL! - String::from(server_url) - }; + let (subject, content_type) = get_subject(&req, &conn, &appstate)?; let store = &appstate.store; timer.add("parse_headers"); diff --git a/server/src/handlers/search.rs b/server/src/handlers/search.rs index 8813ea1b5..98ca30246 100644 --- a/server/src/handlers/search.rs +++ b/server/src/handlers/search.rs @@ -78,7 +78,7 @@ pub async fn search_query( let subjects = docs_to_subjects(top_docs, &fields, &searcher)?; // Create a valid atomic data resource. - let subject: String = get_subject(&req, &conn, &appstate)?; + let (subject, _) = get_subject(&req, &conn, &appstate)?; let mut results_resource = atomic_lib::plugins::search::search_endpoint().to_resource(store)?; results_resource.set_subject(subject.clone()); diff --git a/server/src/handlers/single_page_app.rs b/server/src/handlers/single_page_app.rs index 614636d3a..62d5df533 100644 --- a/server/src/handlers/single_page_app.rs +++ b/server/src/handlers/single_page_app.rs @@ -1,6 +1,7 @@ use std::fmt::Display; use std::fmt::Formatter; +use crate::helpers::get_subject; use crate::{appstate::AppState, errors::AtomicServerResult}; use actix_web::HttpResponse; @@ -9,9 +10,13 @@ use actix_web::HttpResponse; pub async fn single_page( appstate: actix_web::web::Data, path: actix_web::web::Path, + req: actix_web::HttpRequest, + conn: actix_web::dev::ConnectionInfo, ) -> AtomicServerResult { let template = include_str!("../../app_assets/index.html"); - let subject = format!("{}/{}", appstate.store.get_server_url(), path); + // We could check the extension and serialize the Resource in the response. However, I'm not sure this is a great idea. + let (subject, _content_type) = get_subject(&req, &conn, &appstate)?; + let meta_tags: MetaTags = if let Ok(resource) = appstate .store diff --git a/server/src/handlers/upload.rs b/server/src/handlers/upload.rs index 01b55e76d..4794412b3 100644 --- a/server/src/handlers/upload.rs +++ b/server/src/handlers/upload.rs @@ -36,7 +36,7 @@ pub async fn upload_handler( ) -> AtomicServerResult { let store = &appstate.store; let parent = store.get_resource(&query.parent)?; - let subject = get_subject(&req, &conn, &appstate)?; + let (subject, _) = get_subject(&req, &conn, &appstate)?; if let Some(agent) = get_client_agent(req.headers(), &appstate, subject)? { check_write(store, &parent, &agent)?; } else { diff --git a/server/src/helpers.rs b/server/src/helpers.rs index e78540c1e..449efb963 100644 --- a/server/src/helpers.rs +++ b/server/src/helpers.rs @@ -9,7 +9,7 @@ use atomic_lib::Storelike; use percent_encoding::percent_decode_str; use std::str::FromStr; -use crate::content_types::ContentType; +use crate::content_types::{get_accept, ContentType}; use crate::errors::{AppErrorType, AtomicServerError}; use crate::{appstate::AppState, errors::AtomicServerResult}; @@ -224,7 +224,9 @@ pub fn get_subject( req: &actix_web::HttpRequest, conn: &actix_web::dev::ConnectionInfo, appstate: &AppState, -) -> AtomicServerResult { +) -> AtomicServerResult<(String, ContentType)> { + let content_type = get_accept(req.headers()); + let domain = &appstate.config.opts.domain; let host = conn.host(); let subdomain = if let Some(index) = host.find(domain) { @@ -243,23 +245,48 @@ pub fn get_subject( } let server_without_last_slash = subject_url.to_string().trim_end_matches('/').to_string(); let subject = format!("{}{}", server_without_last_slash, &req.uri().to_string()); - Ok(subject) + // if let Some((ct, path)) = try_extension(req.path()) { + // content_type = ct; + // return Ok((path.to_string(), content_type)); + // } + Ok((subject, content_type)) } -/// Finds the extension -pub fn try_extension(path: &str) -> Option<(ContentType, &str)> { - let items: Vec<&str> = path.split('.').collect(); - if items.len() == 2 { - let path = items[0]; - let content_type = match items[1] { - "json" => ContentType::Json, - "jsonld" => ContentType::JsonLd, - "jsonad" => ContentType::JsonAd, - "html" => ContentType::Html, - "ttl" => ContentType::Turtle, - _ => return None, - }; - return Some((content_type, path)); +/// Finds the extension of a supported serialization format. +/// Not used right now, see: https://github.com/atomicdata-dev/atomic-data-rust/issues/601 +#[allow(dead_code)] +fn try_extension(path: &str) -> Option<(ContentType, &str)> { + // Check if path ends with one of the folliwing extensions + let extensions = [ + ".json", + ".jsonld", + ".jsonad", + ".html", + ".ttl", + ".nt", + ".nq", + ".ntriples", + ".nt", + ]; + let mut found = None; + for ext in extensions.iter() { + if path.ends_with(ext) { + println!("Found extension: {}", ext); + let path = &path[0..path.len() - ext.len()]; + let content_type = match *ext { + ".json" => Some(ContentType::Json), + ".jsonld" => Some(ContentType::JsonLd), + ".jsonad" => Some(ContentType::JsonAd), + ".html" => Some(ContentType::Html), + ".ttl" => Some(ContentType::Turtle), + ".nt" => Some(ContentType::NTriples), + ".ntriples" => Some(ContentType::NTriples), + _ => None, + }; + if let Some(ct) = content_type { + found = Some((ct, path)); + } + } } - None + found }