Skip to content

Commit e3619da

Browse files
committed
URL refactor
1 parent 273502b commit e3619da

File tree

8 files changed

+73
-48
lines changed

8 files changed

+73
-48
lines changed

lib/src/agents.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ impl Agent {
7373
Ok(Agent {
7474
private_key: None,
7575
public_key: public_key.into(),
76-
subject: format!("{}/agents/{}", store.get_server_url(), public_key),
76+
subject: store
77+
.get_server_url()
78+
.clone()
79+
.set_path(&format!("agents/{}", public_key))
80+
.to_string(),
7781
name: None,
7882
created_at: crate::utils::now(),
7983
})

lib/src/atomic_url.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ impl AtomicUrl {
111111
Ok(self)
112112
}
113113

114+
/// Removes existing path, sets the new one. Escapes special characters
114115
pub fn set_path(&mut self, path: &str) -> &Self {
115116
self.url.set_path(path);
116117
self

lib/src/plugins/bookmark.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn bookmark_endpoint() -> Endpoint {
3030
fn handle_bookmark_request(
3131
url: url::Url,
3232
store: &impl Storelike,
33-
_: Option<&str>,
33+
_agent: Option<&str>,
3434
) -> AtomicResult<Resource> {
3535
let params = url.query_pairs();
3636
let mut path = None;

lib/src/resources.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl Resource {
189189

190190
/// Create a new resource with a generated Subject
191191
pub fn new_generate_subject(store: &impl Storelike) -> Resource {
192-
let generated = format!("{}/{}", store.get_server_url(), random_string(10));
192+
let generated = format!("{}{}", store.get_server_url(), random_string(10));
193193

194194
Resource::new(generated)
195195
}

server/src/handlers/download.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ pub async fn handle_download(
1212
req: actix_web::HttpRequest,
1313
) -> AtomicServerResult<HttpResponse> {
1414
let headers = req.headers();
15-
let server_url = &appstate.config.server_url;
1615
let store = &appstate.store;
1716

1817
// We replace `/download` with `/` to get the subject of the Resource.
1918
let subject = if let Some(pth) = path {
20-
let subject = format!("{}/{}", server_url, pth);
21-
subject
19+
appstate
20+
.store
21+
.get_server_url()
22+
.clone()
23+
.set_path(pth.as_str())
24+
.to_string()
2225
} else {
2326
// There is no end string, so It's the root of the URL, the base URL!
2427
return Err("Put `/download` in front of an File URL to download it.".into());

server/src/handlers/resource.rs

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use crate::{
2-
appstate::AppState, content_types::get_accept, content_types::ContentType,
3-
errors::AtomicServerResult, helpers::get_client_agent, timer::Timer,
2+
appstate::AppState,
3+
content_types::get_accept,
4+
content_types::ContentType,
5+
errors::AtomicServerResult,
6+
helpers::{get_client_agent, get_subject},
7+
timer::Timer,
48
};
59
use actix_web::{web, HttpResponse};
610
use atomic_lib::Storelike;
@@ -14,42 +18,19 @@ pub async fn handle_get_resource(
1418
req: actix_web::HttpRequest,
1519
conn: actix_web::dev::ConnectionInfo,
1620
) -> AtomicServerResult<HttpResponse> {
21+
let store = &appstate.store;
1722
let mut timer = Timer::new();
18-
19-
let domain = &appstate.config.opts.domain;
20-
let host = conn.host();
21-
let find = host.find(domain);
22-
let subdomain = if let Some(index) = find {
23-
if index == 0 {
24-
None
25-
} else {
26-
Some(host[0..index - 1].to_string())
27-
}
28-
} else {
29-
panic!("Wrong domain! A requested URL did not contain the host for this domain. This should not be able to happen.");
30-
};
3123
let headers = req.headers();
3224
let content_type = get_accept(headers);
33-
34-
// You'd think there would be a simpler way of getting the requested URL...
35-
// See https://github.com/actix/actix-web/issues/2895
36-
let mut subject = appstate.store.get_server_url().clone();
37-
38-
// Doe this include the query params?
39-
subject.set_path(&req.uri().to_string());
40-
41-
if let Some(sd) = subdomain {
42-
subject.set_subdomain(Some(&sd))?;
43-
}
44-
45-
let store = &appstate.store;
4625
timer.add("parse_headers");
4726

27+
let subject = get_subject(&req, &conn, &appstate)?;
28+
timer.add("parse_subject");
29+
4830
let for_agent = get_client_agent(headers, &appstate, subject.to_string())?;
4931
timer.add("get_agent");
5032

5133
let mut builder = HttpResponse::Ok();
52-
5334
tracing::debug!("get_resource: {} as {}", subject, content_type.to_mime());
5435
builder.append_header(("Content-Type", content_type.to_mime()));
5536
// This prevents the browser from displaying the JSON response upon re-opening a closed tab
@@ -60,8 +41,9 @@ pub async fn handle_get_resource(
6041
));
6142
// When users uses back button, don't show the JSON response
6243
builder.append_header(("Vary", "Accept"));
44+
timer.add("set_headers");
6345

64-
let resource = store.get_resource_extended(subject.as_str(), false, for_agent.as_deref())?;
46+
let resource = store.get_resource_extended(&subject, false, for_agent.as_deref())?;
6547
timer.add("get_resource");
6648

6749
let response_body = match content_type {

server/src/handlers/upload.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ use atomic_lib::{
99
use futures::{StreamExt, TryStreamExt};
1010
use serde::Deserialize;
1111

12-
use crate::{appstate::AppState, errors::AtomicServerResult, helpers::get_client_agent};
12+
use crate::{
13+
appstate::AppState,
14+
errors::AtomicServerResult,
15+
helpers::{get_client_agent, get_subject},
16+
};
1317

1418
#[derive(Deserialize, Debug)]
1519
pub struct UploadQuery {
@@ -28,17 +32,11 @@ pub async fn upload_handler(
2832
appstate: web::Data<AppState>,
2933
query: web::Query<UploadQuery>,
3034
req: actix_web::HttpRequest,
35+
conn: actix_web::dev::ConnectionInfo,
3136
) -> AtomicServerResult<HttpResponse> {
3237
let store = &appstate.store;
3338
let parent = store.get_resource(&query.parent)?;
34-
let subject = format!(
35-
"{}{}",
36-
store.get_server_url(),
37-
req.head()
38-
.uri
39-
.path_and_query()
40-
.ok_or("Path must be given")?
41-
);
39+
let subject = get_subject(&req, &conn, &appstate)?;
4240
if let Some(agent) = get_client_agent(req.headers(), &appstate, subject)? {
4341
check_write(store, &parent, &agent)?;
4442
} else {
@@ -83,8 +81,16 @@ pub async fn upload_handler(
8381
.map_err(|_e| "Too large")?;
8482

8583
let subject_path = format!("files/{}", urlencoding::encode(&file_id));
86-
let new_subject = format!("{}/{}", store.get_server_url(), subject_path);
87-
let download_url = format!("{}/download/{}", store.get_server_url(), subject_path);
84+
let new_subject = store
85+
.get_server_url()
86+
.clone()
87+
.set_path(&subject_path)
88+
.to_string();
89+
let download_url = store
90+
.get_server_url()
91+
.clone()
92+
.set_path(&format!("download/{}", subject_path))
93+
.to_string();
8894

8995
let mut resource = atomic_lib::Resource::new_instance(urls::FILE, store)?;
9096
resource.set_subject(new_subject);

server/src/helpers.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Functions useful in the server
22
33
use actix_web::http::header::HeaderMap;
4-
use atomic_lib::authentication::AuthValues;
4+
use atomic_lib::{authentication::AuthValues, Storelike};
55

66
use crate::{appstate::AppState, errors::AtomicServerResult};
77

@@ -77,3 +77,32 @@ pub fn get_client_agent(
7777
.map_err(|e| format!("Authentication failed: {}", e))?;
7878
Ok(Some(for_agent))
7979
}
80+
81+
/// Extracts the full URL from the request, connection and the store.
82+
// You'd think there would be a simpler way of getting the requested URL...
83+
// See https://github.com/actix/actix-web/issues/2895
84+
pub fn get_subject(
85+
req: &actix_web::HttpRequest,
86+
conn: &actix_web::dev::ConnectionInfo,
87+
appstate: &AppState,
88+
) -> AtomicServerResult<String> {
89+
let domain = &appstate.config.opts.domain;
90+
let host = conn.host();
91+
let subdomain = if let Some(index) = host.find(domain) {
92+
if index == 0 {
93+
None
94+
} else {
95+
Some(host[0..index - 1].to_string())
96+
}
97+
} else {
98+
panic!("Wrong domain! A requested URL did not contain the host for this domain. This should not be able to happen.");
99+
};
100+
101+
let mut subject_url = appstate.store.get_server_url().clone();
102+
if let Some(sd) = subdomain {
103+
subject_url.set_subdomain(Some(&sd))?;
104+
}
105+
let server_without_last_slash = subject_url.to_string().trim_end_matches('/').to_string();
106+
let subject = format!("{}{}", server_without_last_slash, &req.uri().to_string());
107+
Ok(subject)
108+
}

0 commit comments

Comments
 (0)