bxo 0.0.5-dev.77 → 0.0.5-dev.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/url-encoding-example.ts +81 -0
- package/package.json +1 -1
- package/src/index.ts +20 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import BXO from "../src";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const app = new BXO({ serve: { port: 3000 } });
|
|
5
|
+
|
|
6
|
+
// Route with space in the path
|
|
7
|
+
app.get("/api/resources/Workspace Item", (ctx) => {
|
|
8
|
+
return ctx.json({
|
|
9
|
+
message: "Found Workspace Item resource!",
|
|
10
|
+
path: ctx.request.url,
|
|
11
|
+
pathname: new URL(ctx.request.url).pathname
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Route with URL-encoded space
|
|
16
|
+
app.get("/api/resources/Workspace%20Item", (ctx) => {
|
|
17
|
+
return ctx.json({
|
|
18
|
+
message: "Found URL-encoded Workspace Item resource!",
|
|
19
|
+
path: ctx.request.url,
|
|
20
|
+
pathname: new URL(ctx.request.url).pathname
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Route with path parameter (recommended approach)
|
|
25
|
+
app.get("/api/resources/:resourceType", (ctx) => {
|
|
26
|
+
return ctx.json({
|
|
27
|
+
message: `Found resource type: ${ctx.params.resourceType}`,
|
|
28
|
+
path: ctx.request.url,
|
|
29
|
+
pathname: new URL(ctx.request.url).pathname,
|
|
30
|
+
params: ctx.params
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Test route to show the difference
|
|
35
|
+
app.get("/test", (ctx) => {
|
|
36
|
+
return ctx.text(`
|
|
37
|
+
<!DOCTYPE html>
|
|
38
|
+
<html>
|
|
39
|
+
<head>
|
|
40
|
+
<title>URL Encoding Test</title>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
<h1>URL Encoding Test</h1>
|
|
44
|
+
<p>Test the following URLs:</p>
|
|
45
|
+
<ul>
|
|
46
|
+
<li><a href="/api/resources/Workspace Item">/api/resources/Workspace Item</a> (with space)</li>
|
|
47
|
+
<li><a href="/api/resources/Workspace%20Item">/api/resources/Workspace%20Item</a> (URL encoded)</li>
|
|
48
|
+
<li><a href="/api/resources/My%20Resource">/api/resources/My%20Resource</a> (URL encoded with params)</li>
|
|
49
|
+
</ul>
|
|
50
|
+
|
|
51
|
+
<h2>Test with JavaScript fetch:</h2>
|
|
52
|
+
<button onclick="testFetch('/api/resources/Workspace Item')">Test with space</button>
|
|
53
|
+
<button onclick="testFetch('/api/resources/Workspace%20Item')">Test URL encoded</button>
|
|
54
|
+
<button onclick="testFetch('/api/resources/My%20Resource')">Test with params</button>
|
|
55
|
+
|
|
56
|
+
<div id="result"></div>
|
|
57
|
+
|
|
58
|
+
<script>
|
|
59
|
+
async function testFetch(url) {
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(url);
|
|
62
|
+
const data = await response.json();
|
|
63
|
+
document.getElementById('result').innerHTML =
|
|
64
|
+
'<h3>Result:</h3><pre>' + JSON.stringify(data, null, 2) + '</pre>';
|
|
65
|
+
} catch (error) {
|
|
66
|
+
document.getElementById('result').innerHTML =
|
|
67
|
+
'<h3>Error:</h3><pre>' + error.message + '</pre>';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
`, 200, {
|
|
72
|
+
"Content-Type": "text/html"
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
app.start();
|
|
77
|
+
console.log(`Server is running on http://localhost:${app.server?.port}`);
|
|
78
|
+
console.log(`Test URL encoding at http://localhost:${app.server?.port}/test`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
main().catch(console.error);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -799,6 +799,16 @@ export default class BXO {
|
|
|
799
799
|
if (h) return await h(req);
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
+
// 1.5) Try URL-decoded pathname for exact matches
|
|
803
|
+
const decodedPathname = decodeURIComponent(url.pathname);
|
|
804
|
+
if (decodedPathname !== url.pathname) {
|
|
805
|
+
const exactDecoded = nativeRoutes[decodedPathname];
|
|
806
|
+
if (exactDecoded) {
|
|
807
|
+
const h = exactDecoded[method] || exactDecoded["DEFAULT"];
|
|
808
|
+
if (h) return await h(req);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
802
812
|
// 2) Fallback to our matcher list
|
|
803
813
|
for (const r of this.routes) {
|
|
804
814
|
if (r.matcher === null) continue; // exact paths handled above
|
|
@@ -807,6 +817,16 @@ export default class BXO {
|
|
|
807
817
|
if (m) return this.dispatch(r, req);
|
|
808
818
|
}
|
|
809
819
|
|
|
820
|
+
// 2.5) Try URL-decoded pathname for pattern matches
|
|
821
|
+
if (decodedPathname !== url.pathname) {
|
|
822
|
+
for (const r of this.routes) {
|
|
823
|
+
if (r.matcher === null) continue; // exact paths handled above
|
|
824
|
+
if (r.method !== method && r.method !== "DEFAULT") continue;
|
|
825
|
+
const m = decodedPathname.match(r.matcher);
|
|
826
|
+
if (m) return this.dispatch(r, req);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
810
830
|
// Create 404 response
|
|
811
831
|
let notFoundResponse = new Response("Not Found", { status: 404 });
|
|
812
832
|
|