Skip to content

Commit 7535eec

Browse files
committed
WIP #578 #577 # 511
1 parent d5c1d8e commit 7535eec

File tree

11 files changed

+199
-178
lines changed

11 files changed

+199
-178
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ See [STATUS.md](server/STATUS.md) to learn more about which features will remain
1515
- Fix initial indexing bug #560
1616
- Fix errors on succesful export / import #565
1717
- Fix envs for store path, change `ATOMIC_STORE_DIR` to `ATOMIC_DATA_DIR` #567
18+
- Refactor static file asset hosting #578
19+
- Meta tags server side #577
20+
- Include JSON-AD in initial response, speed up first render #511
1821

1922
## [v0.34.0] - 2022-10-31
2023

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ features = ["rustls"]
6969
version = "4"
7070

7171
[dependencies.actix-web-static-files]
72+
git = "https://github.com/joepio/actix-web-static-files/"
7273
version = "4"
7374

7475
[dependencies.atomic_lib]
52.4 KB
Loading

server/app_assets/dist/index.js

Lines changed: 52 additions & 52 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/app_assets/dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/app_assets/index.html

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
<meta content="width=device-width,initial-scale=1" name="viewport">
77
<title>Atomic Data Browser</title>
88
<meta content="The easiest way to create, share and model Linked Atomic Data." name="description">
9-
<link href="/app_assets/icon.png" rel="icon" type="image/png">
10-
<link href="/app_assets/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180">
11-
<link href="/app_assets/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
12-
<link href="/app_assets/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
13-
<link href="/app_assets/site.webmanifest" rel="manifest">
14-
<link color="#1e43a3" href="/app_assets/safari-pinned-tab.svg" rel="mask-icon">
9+
<link href="/icon.png" rel="icon" type="image/png">
10+
<link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180">
11+
<link href="/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
12+
<link href="/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
13+
<link href="/site.webmanifest" rel="manifest">
14+
<link color="#1e43a3" href="/safari-pinned-tab.svg" rel="mask-icon">
1515
<meta content="#ffffff" name="msapplication-TileColor">
1616
<meta content="#ffffff" name="theme-color">
1717
<meta content="yes" name="apple-mobile-web-app-capable">
@@ -32,7 +32,10 @@
3232
body {
3333
background-color: var(--background-color);
3434
}
35+
3536
</style>
37+
<!-- Meta tags and code added by from Atomic-Server -->
38+
<!-- { inject_html_head } -->
3639
</head>
3740

3841
<body>
@@ -80,9 +83,8 @@
8083
</defs>
8184
</svg>
8285
</div>
83-
<script src="/app_assets/dist/index.js" type="module"></script>
86+
<script src="/dist/index.js" type="module"></script>
8487
<!-- Server custom script, can be set with -->
85-
<script>{ script }</script>
8688

8789
<!-- Service worker -->
8890
<script>

server/app_assets/site.webmanifest

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
"start_url": "/",
55
"icons": [
66
{
7-
"src": "/app_assets/android-chrome-192x192.png",
7+
"src": "/android-chrome-192x192.png",
88
"sizes": "192x192",
99
"type": "image/png"
1010
},
1111
{
12-
"src": "/app_assets/android-chrome-512x512.png",
12+
"src": "/android-chrome-512x512.png",
1313
"sizes": "512x512",
1414
"type": "image/png"
1515
}

server/src/handlers/single_page_app.rs

Lines changed: 128 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::fmt::Display;
2+
use std::fmt::Formatter;
3+
14
use crate::{appstate::AppState, errors::AtomicServerResult};
25
use actix_web::HttpResponse;
36

@@ -6,10 +9,21 @@ use actix_web::HttpResponse;
69
pub async fn single_page(
710
appstate: actix_web::web::Data<AppState>,
811
) -> AtomicServerResult<HttpResponse> {
9-
let template = include_str!("../../templates/atomic-data-browser.html");
10-
let body = template
11-
.replace("{ script }", &appstate.config.opts.script)
12-
.replace("{ asset_url }", &appstate.config.opts.asset_url);
12+
let template = include_str!("../../app_assets/index.html");
13+
// TODO Get the agent
14+
// let subject = urls::AGENT;
15+
let subject = "http://localhost:9883/Folder/ltg0aypur9d";
16+
let meta_tags: MetaTags = if let Ok(resource) =
17+
appstate
18+
.store
19+
.get_resource_extended(subject, true, Some(urls::PUBLIC_AGENT))
20+
{
21+
resource.into()
22+
} else {
23+
MetaTags::default()
24+
};
25+
26+
let body = template.replace("<!-- { inject_html_head } -->", &meta_tags.to_string());
1327

1428
let resp = HttpResponse::Ok()
1529
.content_type("text/html")
@@ -23,3 +37,113 @@ pub async fn single_page(
2337

2438
Ok(resp)
2539
}
40+
41+
use atomic_lib::urls;
42+
use atomic_lib::Resource;
43+
use atomic_lib::Storelike;
44+
45+
/* HTML tags for social media and link previews. Also includes JSON-AD body of the requested resource, if publicly available. */
46+
struct MetaTags {
47+
description: String,
48+
title: String,
49+
image: String,
50+
json: Option<String>,
51+
}
52+
53+
impl From<Resource> for MetaTags {
54+
fn from(r: Resource) -> Self {
55+
let description = if let Ok(d) = r.get(urls::DESCRIPTION) {
56+
d.to_string()
57+
} else {
58+
"Open this resource in your browser to view its contents.".to_string()
59+
};
60+
let title = if let Ok(d) = r.get(urls::NAME) {
61+
d.to_string()
62+
} else {
63+
"Atomic Server".to_string()
64+
};
65+
let image = if let Ok(d) = r.get(urls::DOWNLOAD_URL) {
66+
// TODO: check if thefile is actually an image
67+
d.to_string()
68+
} else {
69+
"/default_social_preview.jpg".to_string()
70+
};
71+
let json = if let Ok(serialized) = r.to_json_ad() {
72+
Some(serialized)
73+
} else {
74+
None
75+
};
76+
Self {
77+
description,
78+
title,
79+
image,
80+
json,
81+
}
82+
}
83+
}
84+
85+
impl Default for MetaTags {
86+
fn default() -> Self {
87+
Self {
88+
description: "Sign in to view this resource".to_string(),
89+
title: "Atomic Server".to_string(),
90+
image: "/default_social_preview.jpg".to_string(),
91+
json: None,
92+
}
93+
}
94+
}
95+
96+
impl Display for MetaTags {
97+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
98+
let description = escape_html(&self.description);
99+
let image = &self.image;
100+
let title = escape_html(&self.title);
101+
102+
write!(
103+
f,
104+
"<meta name=\"description\" content=\"{description}\">
105+
<meta property=\"og:title\" content=\"{title}\">
106+
<meta property=\"og:description\" content=\"{description}\">
107+
<meta property=\"og:image\" content=\"{image}\">
108+
<meta property=\"twitter:card\" content=\"summary_large_image\">
109+
<meta property=\"twitter:title\" content=\"{title}\">
110+
<meta property=\"twitter:description\" content=\"{description}\">
111+
<meta property=\"twitter:image\" content=\"{image}\">"
112+
)?;
113+
if let Some(json_unsafe) = &self.json {
114+
let json_base64 = base64::encode(json_unsafe);
115+
write!(
116+
f,
117+
"\n<meta property=\"json-ad-initial\" content=\"{}\">",
118+
json_base64
119+
)?;
120+
};
121+
Ok(())
122+
}
123+
}
124+
125+
fn escape_html(s: &str) -> String {
126+
s.replace('<', "&lt;")
127+
.replace('>', "&gt;")
128+
.replace('&', "&amp;")
129+
.replace('\'', "&#x27;")
130+
.replace('"', "&quot;")
131+
.replace('/', "&#x2F;")
132+
}
133+
134+
#[cfg(test)]
135+
mod test {
136+
use super::MetaTags;
137+
138+
#[test]
139+
// Malicious test: try escaping html and adding script tag
140+
fn evil_meta_tags() {
141+
let html = MetaTags {
142+
description: "\"<script>alert('evil')</script>\"".to_string(),
143+
..Default::default()
144+
}
145+
.to_string();
146+
println!("{}", html);
147+
assert!(!html.contains("<script>"));
148+
}
149+
}

server/src/routes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub fn config_routes(app: &mut actix_web::web::ServiceConfig, config: &Config) {
2121
app.service(web::resource("/ws").to(handlers::web_sockets::web_socket_handler))
2222
// .service(web::resource("/sw.js").to(handlers::service_worker::service_worker))
2323
.service(web::resource("/download/{path:[^{}]+}").to(handlers::download::handle_download))
24-
.service(ResourceFiles::new("/app_assets", generated))
24+
.service(ResourceFiles::new("/", generated).do_use_guard())
2525
// Catch all (non-download) HTML requests and send them to the single page app
2626
.service(
2727
web::resource(ANY)

0 commit comments

Comments
 (0)