Skip to content

Commit d157cf4

Browse files
committed
Add HTML fallback routing to resolve_worker_from_request
Allow requests with .html extension to match prerendered routes without the extension. For example, /about.html will now match route /about. This eliminates the need to duplicate HTML routes in both static and prerendered arrays, keeping only the extensionless version in prerendered.
1 parent 950f468 commit d157cf4

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
--
2+
-- OpenWorkers Database Schema - Add HTML fallback routing
3+
--
4+
-- Allow requests with .html extension to match prerendered routes
5+
-- without the extension. For example, /about.html matches route /about.
6+
--
7+
8+
BEGIN;
9+
10+
-- ============================================================================
11+
-- Update resolve_worker_from_request to handle .html fallback
12+
-- ============================================================================
13+
14+
CREATE OR REPLACE FUNCTION resolve_worker_from_request(
15+
p_domain varchar DEFAULT NULL,
16+
p_worker_id uuid DEFAULT NULL,
17+
p_worker_name varchar DEFAULT NULL,
18+
p_path varchar DEFAULT '/'
19+
)
20+
RETURNS request_resolution AS $$
21+
DECLARE
22+
v_result request_resolution;
23+
v_worker_id_temp uuid;
24+
v_project_id_temp uuid;
25+
v_route_record RECORD;
26+
BEGIN
27+
-- Priority 1: Direct worker_id (used for service bindings, worker-to-worker calls)
28+
IF p_worker_id IS NOT NULL THEN
29+
v_result.worker_id := p_worker_id;
30+
v_result.project_id := NULL;
31+
v_result.backend_type := 'worker'::enum_backend_type;
32+
v_result.assets_storage_id := NULL;
33+
v_result.priority := NULL;
34+
RETURN v_result;
35+
END IF;
36+
37+
-- Priority 2: Resolve project_id/worker_id from worker_name (subdomain) or domain (custom domain)
38+
IF p_worker_name IS NOT NULL THEN
39+
-- Subdomain case: name.workers.rocks → lookup in endpoints
40+
-- Projects have priority over standalone workers for routing
41+
SELECT project_id, worker_id
42+
INTO v_project_id_temp, v_worker_id_temp
43+
FROM endpoints
44+
WHERE name = p_worker_name
45+
ORDER BY type DESC -- 'project' > 'worker' alphabetically
46+
LIMIT 1;
47+
48+
IF NOT FOUND THEN
49+
RETURN NULL; -- Endpoint not found
50+
END IF;
51+
ELSIF p_domain IS NOT NULL THEN
52+
-- Custom domain case: example.com → lookup in domains
53+
SELECT project_id, worker_id
54+
INTO v_project_id_temp, v_worker_id_temp
55+
FROM domains
56+
WHERE name = p_domain;
57+
58+
IF NOT FOUND THEN
59+
RETURN NULL; -- Domain not found
60+
END IF;
61+
ELSE
62+
-- No identifier provided
63+
RETURN NULL;
64+
END IF;
65+
66+
-- If we have a project, match route pattern
67+
IF v_project_id_temp IS NOT NULL THEN
68+
SELECT backend_type, worker_id, priority
69+
INTO v_route_record
70+
FROM project_routes
71+
WHERE project_id = v_project_id_temp
72+
AND (
73+
pattern = p_path
74+
OR (pattern LIKE '%/*' AND p_path LIKE REPLACE(pattern, '/*', '') || '%')
75+
-- Allow /about.html to match route /about (prerendered fallback)
76+
OR (p_path LIKE '%.html' AND pattern = REPLACE(p_path, '.html', ''))
77+
)
78+
ORDER BY priority DESC
79+
LIMIT 1;
80+
81+
IF NOT FOUND THEN
82+
RETURN NULL; -- No route matches
83+
END IF;
84+
85+
v_result.project_id := v_project_id_temp;
86+
v_result.worker_id := v_route_record.worker_id;
87+
v_result.backend_type := v_route_record.backend_type;
88+
v_result.priority := v_route_record.priority;
89+
90+
-- If storage backend, get ASSETS storage_config_id from main worker's environment
91+
IF v_route_record.backend_type = 'storage' THEN
92+
SELECT value::uuid
93+
INTO v_result.assets_storage_id
94+
FROM environment_values ev
95+
JOIN workers w ON w.environment_id = ev.environment_id
96+
WHERE w.id = v_project_id_temp -- main worker has same id as project
97+
AND ev.key = 'ASSETS'
98+
AND ev.type = 'assets';
99+
100+
IF v_result.assets_storage_id IS NULL THEN
101+
RETURN NULL; -- ASSETS binding not found
102+
END IF;
103+
ELSE
104+
v_result.assets_storage_id := NULL;
105+
END IF;
106+
107+
RETURN v_result;
108+
END IF;
109+
110+
-- If we have a standalone worker (not in a project)
111+
IF v_worker_id_temp IS NOT NULL THEN
112+
v_result.worker_id := v_worker_id_temp;
113+
v_result.project_id := NULL;
114+
v_result.backend_type := 'worker'::enum_backend_type;
115+
v_result.assets_storage_id := NULL;
116+
v_result.priority := NULL;
117+
RETURN v_result;
118+
END IF;
119+
120+
-- Nothing matched
121+
RETURN NULL;
122+
END;
123+
$$ LANGUAGE plpgsql;
124+
125+
COMMENT ON FUNCTION resolve_worker_from_request(varchar, uuid, varchar, varchar) IS 'Resolves endpoint and route with .html fallback support for prerendered routes';
126+
127+
COMMIT;

0 commit comments

Comments
 (0)