bxo 0.0.5-dev.47 ā 0.0.5-dev.48
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.ts +45 -7
- package/index.ts +41 -0
- package/package.json +1 -1
- package/plugins/cors.ts +10 -16
- package/test-cors.ts +0 -0
package/example.ts
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
|
-
import BXO from
|
|
2
|
-
import { cors } from
|
|
1
|
+
import BXO from './index';
|
|
2
|
+
import { cors } from './plugins/cors';
|
|
3
3
|
|
|
4
4
|
const app = new BXO();
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Use CORS plugin
|
|
7
|
+
app.use(cors({
|
|
8
|
+
origin: ['http://localhost:3000', 'http://localhost:3001'],
|
|
9
|
+
credentials: true,
|
|
10
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
|
11
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'X-Custom-Header']
|
|
12
|
+
}));
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
// Test route that returns a Response object
|
|
15
|
+
app.get('/test-response', () => {
|
|
16
|
+
return new Response(JSON.stringify({ message: 'Hello from Response object' }), {
|
|
17
|
+
status: 200,
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'X-Custom-Response-Header': 'test-value'
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Test route that returns plain data
|
|
26
|
+
app.get('/test-data', () => {
|
|
27
|
+
return { message: 'Hello from plain data' };
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Test route that sets custom headers via ctx.set
|
|
31
|
+
app.get('/test-headers', (ctx) => {
|
|
32
|
+
ctx.set.headers = {
|
|
33
|
+
'X-Custom-Header': 'set-via-context',
|
|
34
|
+
'Cache-Control': 'no-cache'
|
|
35
|
+
};
|
|
36
|
+
return { message: 'Headers set via context' };
|
|
10
37
|
});
|
|
11
38
|
|
|
12
39
|
app.get("/api/actions/nodula.auth.login", (ctx) => {
|
|
@@ -15,6 +42,17 @@ app.get("/api/actions/nodula.auth.login", (ctx) => {
|
|
|
15
42
|
|
|
16
43
|
app.post("/api/actions/nodula.auth.login", (ctx) => {
|
|
17
44
|
return { message: 'Hello, world!' };
|
|
18
|
-
})
|
|
45
|
+
})
|
|
46
|
+
// Note: OPTIONS requests are handled automatically by the CORS plugin
|
|
19
47
|
|
|
20
|
-
|
|
48
|
+
// Start the server
|
|
49
|
+
app.start(3000, 'localhost').then(() => {
|
|
50
|
+
console.log('š Server started at http://localhost:3000');
|
|
51
|
+
console.log('š Test endpoints:');
|
|
52
|
+
console.log(' GET /test-response - Returns Response object');
|
|
53
|
+
console.log(' GET /test-data - Returns plain data');
|
|
54
|
+
console.log(' GET /test-headers - Sets headers via ctx.set');
|
|
55
|
+
console.log(' OPTIONS /* - Handled automatically by CORS plugin');
|
|
56
|
+
console.log('\nš Check CORS headers in browser dev tools or curl:');
|
|
57
|
+
console.log(' curl -H "Origin: http://localhost:3001" -H "Access-Control-Request-Method: GET" -X OPTIONS http://localhost:3000/test-response');
|
|
58
|
+
});
|
package/index.ts
CHANGED
|
@@ -1055,6 +1055,47 @@ export default class BXO {
|
|
|
1055
1055
|
|
|
1056
1056
|
// Convert response to Response object
|
|
1057
1057
|
if (response instanceof Response) {
|
|
1058
|
+
// If there are headers set via ctx.set.headers, merge them with the Response headers
|
|
1059
|
+
if (ctx.set.headers && Object.keys(ctx.set.headers).length > 0) {
|
|
1060
|
+
const newHeaders = new Headers(response.headers);
|
|
1061
|
+
|
|
1062
|
+
// Add headers from ctx.set.headers
|
|
1063
|
+
Object.entries(ctx.set.headers).forEach(([key, value]) => {
|
|
1064
|
+
newHeaders.set(key, value);
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
// Handle cookies if any are set
|
|
1068
|
+
if (ctx.set.cookies && ctx.set.cookies.length > 0) {
|
|
1069
|
+
const cookieHeaders = ctx.set.cookies.map(cookie => {
|
|
1070
|
+
let cookieString = `${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`;
|
|
1071
|
+
if (cookie.domain) cookieString += `; Domain=${cookie.domain}`;
|
|
1072
|
+
if (cookie.path) cookieString += `; Path=${cookie.path}`;
|
|
1073
|
+
if (cookie.expires) cookieString += `; Expires=${cookie.expires.toUTCString()}`;
|
|
1074
|
+
if (cookie.maxAge) cookieString += `; Max-Age=${cookie.maxAge}`;
|
|
1075
|
+
if (cookie.secure) cookieString += `; Secure`;
|
|
1076
|
+
if (cookie.httpOnly) cookieString += `; HttpOnly`;
|
|
1077
|
+
if (cookie.sameSite) cookieString += `; SameSite=${cookie.sameSite}`;
|
|
1078
|
+
return cookieString;
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
// Add Set-Cookie headers
|
|
1082
|
+
cookieHeaders.forEach((cookieHeader, index) => {
|
|
1083
|
+
if (index === 0) {
|
|
1084
|
+
newHeaders.set('Set-Cookie', cookieHeader);
|
|
1085
|
+
} else {
|
|
1086
|
+
newHeaders.set(`Set-Cookie-${index}`, cookieHeader);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
// Create new Response with merged headers
|
|
1092
|
+
return new Response(response.body, {
|
|
1093
|
+
status: ctx.set.status || response.status,
|
|
1094
|
+
statusText: response.statusText,
|
|
1095
|
+
headers: newHeaders
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1058
1099
|
return response;
|
|
1059
1100
|
}
|
|
1060
1101
|
|
package/package.json
CHANGED
package/plugins/cors.ts
CHANGED
|
@@ -85,29 +85,23 @@ export function cors(options: CORSOptions = {}): Plugin {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
|
-
onResponse: async (ctx
|
|
88
|
+
onResponse: async (ctx) => {
|
|
89
89
|
// Handle CORS headers for actual requests
|
|
90
90
|
const requestOrigin = getRequestOrigin(ctx.request);
|
|
91
91
|
const allowedOrigin = validateOrigin(requestOrigin, origin);
|
|
92
92
|
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
newResponse.headers.set('Access-Control-Allow-Origin', allowedOrigin || '*');
|
|
102
|
-
newResponse.headers.set('Access-Control-Allow-Methods', methods.join(', '));
|
|
103
|
-
newResponse.headers.set('Access-Control-Allow-Headers', allowedHeaders.join(', '));
|
|
104
|
-
newResponse.headers.set('Access-Control-Max-Age', maxAge.toString());
|
|
93
|
+
// Set CORS headers for all responses
|
|
94
|
+
ctx.set.headers = {
|
|
95
|
+
...ctx.set.headers,
|
|
96
|
+
'Access-Control-Allow-Origin': allowedOrigin || '*',
|
|
97
|
+
'Access-Control-Allow-Methods': methods.join(', '),
|
|
98
|
+
'Access-Control-Allow-Headers': allowedHeaders.join(', '),
|
|
99
|
+
'Access-Control-Max-Age': maxAge.toString()
|
|
100
|
+
};
|
|
105
101
|
|
|
106
102
|
if (credentials) {
|
|
107
|
-
|
|
103
|
+
ctx.set.headers['Access-Control-Allow-Credentials'] = 'true';
|
|
108
104
|
}
|
|
109
|
-
|
|
110
|
-
return newResponse;
|
|
111
105
|
}
|
|
112
106
|
};
|
|
113
107
|
}
|
package/test-cors.ts
ADDED
|
File without changes
|