bxo 0.0.5-dev.43 → 0.0.5-dev.45
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/index.ts +80 -2
- package/package.json +1 -1
- package/plugins/cors.ts +7 -0
package/index.ts
CHANGED
|
@@ -136,7 +136,7 @@ interface BXOOptions {
|
|
|
136
136
|
// Plugin interface for middleware-style plugins
|
|
137
137
|
interface Plugin {
|
|
138
138
|
name?: string;
|
|
139
|
-
onRequest?: (ctx: Context) => Promise<void> | void;
|
|
139
|
+
onRequest?: (ctx: Context) => Promise<Response | void> | Response | void;
|
|
140
140
|
onResponse?: (ctx: Context, response: any) => Promise<any> | any;
|
|
141
141
|
onError?: (ctx: Context, error: Error) => Promise<any> | any;
|
|
142
142
|
}
|
|
@@ -153,7 +153,7 @@ export default class BXO {
|
|
|
153
153
|
onAfterRestart?: (instance: BXO) => Promise<void> | void;
|
|
154
154
|
onBeforeStop?: (instance: BXO) => Promise<void> | void;
|
|
155
155
|
onAfterStop?: (instance: BXO) => Promise<void> | void;
|
|
156
|
-
onRequest?: (ctx: Context, instance: BXO) => Promise<void> | void;
|
|
156
|
+
onRequest?: (ctx: Context, instance: BXO) => Promise<Response | void> | Response | void;
|
|
157
157
|
onResponse?: (ctx: Context, response: any, instance: BXO) => Promise<any> | any;
|
|
158
158
|
onError?: (ctx: Context, error: Error, instance: BXO) => Promise<any> | any;
|
|
159
159
|
} = {};
|
|
@@ -721,6 +721,84 @@ export default class BXO {
|
|
|
721
721
|
return new Response('WebSocket upgrade failed', { status: 400 });
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
+
// Handle OPTIONS requests for CORS preflight before route matching
|
|
725
|
+
if (method === 'OPTIONS') {
|
|
726
|
+
// Create a minimal context for OPTIONS requests
|
|
727
|
+
const ctx: Context = {
|
|
728
|
+
params: {},
|
|
729
|
+
query: {},
|
|
730
|
+
body: {},
|
|
731
|
+
headers: this.parseHeaders(request.headers),
|
|
732
|
+
cookies: {},
|
|
733
|
+
path: pathname,
|
|
734
|
+
request,
|
|
735
|
+
set: {},
|
|
736
|
+
status: ((code: number, data?: any) => {
|
|
737
|
+
ctx.set.status = code;
|
|
738
|
+
return data;
|
|
739
|
+
}) as any,
|
|
740
|
+
redirect: ((location: string, status: number = 302) => {
|
|
741
|
+
ctx.set.redirect = { location, status };
|
|
742
|
+
const responseHeaders: Record<string, string> = {
|
|
743
|
+
Location: location,
|
|
744
|
+
...(ctx.set.headers || {})
|
|
745
|
+
};
|
|
746
|
+
return new Response(null, {
|
|
747
|
+
status,
|
|
748
|
+
headers: responseHeaders
|
|
749
|
+
});
|
|
750
|
+
}) as any,
|
|
751
|
+
clearRedirect: (() => {
|
|
752
|
+
delete ctx.set.redirect;
|
|
753
|
+
if (ctx.set.headers) {
|
|
754
|
+
for (const key of Object.keys(ctx.set.headers)) {
|
|
755
|
+
if (key.toLowerCase() === 'location') {
|
|
756
|
+
delete ctx.set.headers[key];
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (typeof ctx.set.status === 'number' && ctx.set.status >= 300 && ctx.set.status < 400) {
|
|
761
|
+
delete ctx.set.status;
|
|
762
|
+
}
|
|
763
|
+
}) as any
|
|
764
|
+
};
|
|
765
|
+
|
|
766
|
+
// Run middleware onRequest hooks for OPTIONS requests
|
|
767
|
+
for (const plugin of this.middleware) {
|
|
768
|
+
if (plugin.onRequest) {
|
|
769
|
+
const result = await plugin.onRequest(ctx);
|
|
770
|
+
// If middleware returns a response, return it immediately
|
|
771
|
+
if (result instanceof Response) {
|
|
772
|
+
return result;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Run global onRequest hook
|
|
778
|
+
if (this.hooks.onRequest) {
|
|
779
|
+
const result = await this.hooks.onRequest(ctx, this);
|
|
780
|
+
if (result instanceof Response) {
|
|
781
|
+
return result;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// Run BXO instance onRequest hooks
|
|
786
|
+
for (const bxoInstance of this.plugins) {
|
|
787
|
+
if (bxoInstance.hooks.onRequest) {
|
|
788
|
+
const result = await bxoInstance.hooks.onRequest(ctx, this);
|
|
789
|
+
if (result instanceof Response) {
|
|
790
|
+
return result;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// If no middleware handled the OPTIONS request, return a default response
|
|
796
|
+
return new Response(null, {
|
|
797
|
+
status: 204,
|
|
798
|
+
headers: ctx.set.headers || {}
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
|
|
724
802
|
const matchResult = this.matchRoute(method, pathname);
|
|
725
803
|
if (!matchResult) {
|
|
726
804
|
return new Response('Not Found', { status: 404 });
|
package/package.json
CHANGED
package/plugins/cors.ts
CHANGED
|
@@ -60,6 +60,7 @@ export function cors(options: CORSOptions = {}): Plugin {
|
|
|
60
60
|
return {
|
|
61
61
|
name: 'cors',
|
|
62
62
|
onRequest: async (ctx) => {
|
|
63
|
+
console.log('onRequest', ctx.request.method);
|
|
63
64
|
// Handle preflight OPTIONS requests
|
|
64
65
|
if (ctx.request.method === 'OPTIONS') {
|
|
65
66
|
const requestOrigin = getRequestOrigin(ctx.request);
|
|
@@ -77,6 +78,12 @@ export function cors(options: CORSOptions = {}): Plugin {
|
|
|
77
78
|
if (credentials) {
|
|
78
79
|
ctx.set.headers['Access-Control-Allow-Credentials'] = 'true';
|
|
79
80
|
}
|
|
81
|
+
|
|
82
|
+
// Return a proper Response for OPTIONS requests
|
|
83
|
+
return new Response(null, {
|
|
84
|
+
status: 204,
|
|
85
|
+
headers: ctx.set.headers
|
|
86
|
+
});
|
|
80
87
|
}
|
|
81
88
|
},
|
|
82
89
|
onResponse: async (ctx, response) => {
|