Skip to content

Commit 8ce276b

Browse files
committed
Add AssetType enum and prerendered path transformation
Add AssetType enum (Immutable/Static/Prerendered) to map route priorities in a type-safe way. Transform paths for prerendered routes by adding .html extension when no extension is present (/ becomes /index.html, /about becomes /about.html).
1 parent 702101f commit 8ce276b

5 files changed

Lines changed: 85 additions & 28 deletions

File tree

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"rust-analyzer.cargo.features": ["v8", "database"],
2+
"rust-analyzer.cargo.features": ["v8", "database", "telemetry"],
33
"cSpell.words": [
44
"actix",
55
"appender",

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "openworkers-runner"
3-
version = "0.12.10"
3+
version = "0.12.11"
44
edition = "2024"
55
license = "MIT"
66
default-run = "openworkers-runner"

bin/main.rs

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -239,38 +239,40 @@ async fn handle_worker_request(
239239
// Handle resolution result
240240
let worker = match resolution {
241241
Some(res) => {
242+
use openworkers_runner::BackendType;
243+
use openworkers_runner::store::get_worker_with_bindings;
244+
242245
// Project routing: check backend type
243246
if res.project_id.is_some() {
244247
// Record backend type for telemetry
245248
span.record("backend_type", tracing::field::display(&res.backend_type));
246249

247250
match res.backend_type {
248-
openworkers_runner::BackendType::Worker => {
251+
BackendType::Worker => {
249252
if let Some(worker_id) = res.worker_id {
250-
let worker = openworkers_runner::store::get_worker_with_bindings(
251-
conn,
252-
WorkerIdentifier::Id(worker_id),
253-
)
254-
.await;
253+
let worker =
254+
get_worker_with_bindings(conn, WorkerIdentifier::Id(worker_id))
255+
.await;
255256

256257
match worker {
257258
Some(w) => w,
258259
None => {
259260
return Ok(error_response_with_span(
260261
&span,
261-
404,
262-
"Worker not found",
262+
500,
263+
"Route has worker backend but worker not found",
263264
));
264265
}
265266
}
266267
} else {
267-
return Ok(error_response(
268+
return Ok(error_response_with_span(
269+
&span,
268270
500,
269271
"Route has worker backend but no worker_id",
270272
));
271273
}
272274
}
273-
openworkers_runner::BackendType::Storage => {
275+
BackendType::Storage => {
274276
use openworkers_core::{
275277
HttpMethod, HttpRequest, OperationsHandler, RequestBody,
276278
};
@@ -279,17 +281,28 @@ async fn handle_worker_request(
279281
let storage_config_id = match &res.assets_storage_id {
280282
Some(id) => id,
281283
None => {
282-
return Ok(error_response(500, "ASSETS storage config not found"));
284+
return Ok(error_response_with_span(
285+
&span,
286+
500,
287+
"ASSETS storage config not found",
288+
));
283289
}
284290
};
285291

286292
// Load storage config
287293
let storage_config =
288294
openworkers_runner::store::get_storage_config(conn, storage_config_id)
289295
.await;
296+
290297
let storage_config = match storage_config {
291298
Some(config) => config,
292-
None => return Ok(error_response(500, "Storage config not found")),
299+
None => {
300+
return Ok(error_response_with_span(
301+
&span,
302+
500,
303+
"Storage config not found",
304+
));
305+
}
293306
};
294307

295308
// Create RunnerOperations with ASSETS binding to get limiters and stats
@@ -300,9 +313,24 @@ async fn handle_worker_request(
300313
},
301314
]);
302315

316+
// Transform path for prerendered routes (add .html extension)
317+
let request_path = if matches!(
318+
res.asset_type,
319+
Some(openworkers_runner::store::AssetType::Prerendered)
320+
) && !path.contains('.')
321+
{
322+
if path == "/" || path.is_empty() {
323+
"/index.html".to_string()
324+
} else {
325+
format!("{}.html", path)
326+
}
327+
} else {
328+
path.to_string()
329+
};
330+
303331
// Create HttpRequest for binding fetch
304332
let http_request = HttpRequest {
305-
url: path.to_string(),
333+
url: request_path,
306334
method: HttpMethod::Get,
307335
headers: std::collections::HashMap::new(),
308336
body: RequestBody::None,
@@ -331,8 +359,12 @@ async fn handle_worker_request(
331359
);
332360

333361
error!("Failed to fetch from storage: {}", e);
334-
span.record("response_status_code", 404u16);
335-
return Ok(error_response(404, "File not found"));
362+
span.record("response_status_code", 500u16);
363+
return Ok(error_response_with_span(
364+
&span,
365+
500,
366+
"Failed to fetch from storage",
367+
));
336368
}
337369
}
338370
}
@@ -341,16 +373,18 @@ async fn handle_worker_request(
341373
// Standalone worker
342374
else if let Some(worker_id) = res.worker_id {
343375
// Record backend type for standalone workers
344-
span.record("backend_type", "worker");
345-
let worker = openworkers_runner::store::get_worker_with_bindings(
346-
conn,
347-
WorkerIdentifier::Id(worker_id),
348-
)
349-
.await;
376+
span.record("backend_type", tracing::field::display(BackendType::Worker));
377+
let worker = get_worker_with_bindings(conn, WorkerIdentifier::Id(worker_id)).await;
350378

351379
match worker {
352380
Some(w) => w,
353-
None => return Ok(error_response_with_span(&span, 404, "Worker not found")),
381+
None => {
382+
return Ok(error_response_with_span(
383+
&span,
384+
500,
385+
"Route has worker_id but worker not found",
386+
));
387+
}
354388
}
355389
} else {
356390
return Ok(error_response_with_span(
@@ -363,8 +397,8 @@ async fn handle_worker_request(
363397
None => {
364398
return Ok(error_response_with_span(
365399
&span,
366-
404,
367-
"Endpoint or route not found",
400+
502,
401+
"No worker or project found for request",
368402
));
369403
}
370404
};

src/store.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,26 @@ impl std::fmt::Display for BackendType {
702702
}
703703
}
704704

705+
/// Asset type for storage routes (mapped from priority)
706+
#[derive(Debug, Clone, Copy, PartialEq)]
707+
pub enum AssetType {
708+
Immutable, // priority 3 - hashed files, cache forever
709+
Static, // priority 2 - public files (robots.txt, favicon, etc.)
710+
Prerendered, // priority 1 - HTML pages (need .html extension)
711+
}
712+
713+
impl AssetType {
714+
/// Map from database priority to asset type
715+
pub fn from_priority(priority: i32) -> Option<Self> {
716+
match priority {
717+
3 => Some(AssetType::Immutable),
718+
2 => Some(AssetType::Static),
719+
1 => Some(AssetType::Prerendered),
720+
_ => None,
721+
}
722+
}
723+
}
724+
705725
/// Project route
706726
#[derive(Debug, Clone)]
707727
pub struct Route {
@@ -720,6 +740,7 @@ pub struct RequestResolution {
720740
pub project_id: Option<String>,
721741
pub backend_type: BackendType,
722742
pub assets_storage_id: Option<String>,
743+
pub asset_type: Option<AssetType>,
723744
}
724745

725746
/// Resolve worker from request in a single DB call
@@ -740,10 +761,11 @@ pub async fn resolve_worker_from_request(
740761
project_id: Option<String>,
741762
backend_type: BackendType,
742763
assets_storage_id: Option<String>,
764+
priority: Option<i32>,
743765
}
744766

745767
let result = sqlx::query_as::<_, ResolutionRow>(
746-
"SELECT worker_id::text, project_id::text, backend_type, assets_storage_id::text
768+
"SELECT worker_id::text, project_id::text, backend_type, assets_storage_id::text, priority
747769
FROM resolve_worker_from_request($1, $2::uuid, $3, $4)",
748770
)
749771
.bind(domain)
@@ -759,6 +781,7 @@ pub async fn resolve_worker_from_request(
759781
project_id: row.project_id,
760782
backend_type: row.backend_type,
761783
assets_storage_id: row.assets_storage_id,
784+
asset_type: row.priority.and_then(AssetType::from_priority),
762785
}),
763786
Err(err) => {
764787
tracing::debug!("Failed to resolve request: {:?}", err);

0 commit comments

Comments
 (0)