@gracile/engine 0.1.1 → 0.2.0-next.1
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/ambient.d.ts +9 -4
- package/dist/assertions.test.d.ts +2 -0
- package/dist/assertions.test.d.ts.map +1 -0
- package/dist/assertions.test.js +22 -0
- package/dist/dev/dev.d.ts +6 -7
- package/dist/dev/dev.d.ts.map +1 -1
- package/dist/dev/dev.js +25 -18
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +175 -0
- package/dist/render/route-template.d.ts.map +1 -1
- package/dist/render/route-template.js +21 -8
- package/dist/routes/collect.d.ts.map +1 -1
- package/dist/routes/collect.js +39 -30
- package/dist/routes/match.js +1 -1
- package/dist/routes/route.d.ts +4 -5
- package/dist/routes/route.d.ts.map +1 -1
- package/dist/routes/route.js +1 -2
- package/dist/server/env.d.ts +2 -1
- package/dist/server/env.d.ts.map +1 -1
- package/dist/server/env.js +5 -3
- package/dist/server/request.d.ts +1 -1
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +139 -97
- package/dist/server/utils.d.ts +21 -3
- package/dist/server/utils.d.ts.map +1 -1
- package/dist/server/utils.js +61 -10
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vite/plugins/build-routes.d.ts.map +1 -1
- package/dist/vite/plugins/build-routes.js +1 -0
- package/dist/vite/plugins/virtual-routes.d.ts.map +1 -1
- package/dist/vite/plugins/virtual-routes.js +6 -1
- package/package.json +22 -26
- package/dist/build/build.d.ts +0 -2
- package/dist/build/build.d.ts.map +0 -1
- package/dist/build/build.js +0 -7
- package/dist/dev/server.d.ts +0 -30
- package/dist/dev/server.d.ts.map +0 -1
- package/dist/dev/server.js +0 -82
- package/dist/preview.d.ts +0 -6
- package/dist/preview.d.ts.map +0 -1
- package/dist/preview.js +0 -12
- package/dist/server/server.d.ts +0 -4
- package/dist/server/server.d.ts.map +0 -1
- package/dist/server/server.js +0 -25
- package/dist/vite/build.d.ts +0 -2
- package/dist/vite/build.d.ts.map +0 -1
- package/dist/vite/build.js +0 -114
- package/dist/vite/config.d.ts +0 -28
- package/dist/vite/config.d.ts.map +0 -1
- package/dist/vite/config.js +0 -74
- package/dist/vite/server.d.ts +0 -6
- package/dist/vite/server.d.ts.map +0 -1
- package/dist/vite/server.js +0 -20
package/dist/server/request.js
CHANGED
|
@@ -2,73 +2,116 @@ import { Readable, Writable } from 'node:stream';
|
|
|
2
2
|
import { logger } from '@gracile/internal-utils/logger';
|
|
3
3
|
import { createServerAdapter } from '@whatwg-node/server';
|
|
4
4
|
import c from 'picocolors';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { isUnknownObject } from '../assertions.js';
|
|
6
|
+
import { errorPage } from '../errors/templates.js';
|
|
7
|
+
import { renderRouteTemplate } from '../render/route-template.js';
|
|
7
8
|
import { renderSsrTemplate } from '../render/utils.js';
|
|
8
9
|
import { getRoute } from '../routes/match.js';
|
|
9
10
|
// NOTE: Find a more canonical way to ponyfill the Node HTTP request to standard Request
|
|
10
11
|
// @ts-expect-error Abusing this feature!
|
|
11
12
|
const adapter = createServerAdapter((request) => request);
|
|
12
13
|
export function createGracileMiddleware({ vite, routes, routeImports, routeAssets, root, serverMode, }) {
|
|
13
|
-
const middleware = async (req, res, next) => {
|
|
14
|
-
// Typing workaround
|
|
14
|
+
const middleware = async (req, res, next, locals) => {
|
|
15
|
+
// HACK: Typing workaround
|
|
15
16
|
if (!req.url)
|
|
16
17
|
throw Error('Incorrect url');
|
|
17
18
|
if (!req.method)
|
|
18
19
|
throw Error('Incorrect method');
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return next();
|
|
28
|
-
const requestPonyfilled = (await Promise.resolve(adapter.handleNodeRequest(req)));
|
|
29
|
-
async function renderPageFn(handlerInfos, routeInfos) {
|
|
30
|
-
const { output } = await renderRouteTemplate({
|
|
31
|
-
request: requestPonyfilled,
|
|
32
|
-
vite,
|
|
33
|
-
mode: 'dev',
|
|
34
|
-
routeInfos,
|
|
35
|
-
handlerInfos,
|
|
36
|
-
routeAssets,
|
|
37
|
-
root,
|
|
38
|
-
serverMode,
|
|
39
|
-
});
|
|
40
|
-
return output || undefined;
|
|
20
|
+
const { url: urlPath, method } = req;
|
|
21
|
+
// if (urlPath === '/favicon.ico') return next();
|
|
22
|
+
async function createErrorPage(e) {
|
|
23
|
+
logger.error(e.message);
|
|
24
|
+
let errorPageHtml = await renderSsrTemplate(errorPage(e));
|
|
25
|
+
if (vite)
|
|
26
|
+
errorPageHtml = await vite.transformIndexHtml(urlPath, errorPageHtml);
|
|
27
|
+
return errorPageHtml;
|
|
41
28
|
}
|
|
42
29
|
try {
|
|
30
|
+
const requestPonyfilled = (await Promise.resolve(adapter.handleNodeRequest(
|
|
31
|
+
// HACK: Incorrect typings
|
|
32
|
+
req)));
|
|
33
|
+
// NOTE: Maybe it should be constructed from `req`
|
|
34
|
+
const fullUrl = requestPonyfilled.url;
|
|
43
35
|
// MARK: Get route infos
|
|
44
|
-
const
|
|
45
|
-
url:
|
|
36
|
+
const routeOptions = {
|
|
37
|
+
url: fullUrl,
|
|
46
38
|
vite,
|
|
47
39
|
routes,
|
|
48
40
|
routeImports,
|
|
41
|
+
};
|
|
42
|
+
const routeInfos = await getRoute(routeOptions).catch(async (error) => {
|
|
43
|
+
// MARK: User defined Gracile 404
|
|
44
|
+
logger.error(String(error));
|
|
45
|
+
const url = new URL('/404/', fullUrl).href;
|
|
46
|
+
const options = { ...routeOptions, url };
|
|
47
|
+
const notFound = await getRoute(options).catch(() => null);
|
|
48
|
+
return notFound;
|
|
49
|
+
});
|
|
50
|
+
if (routeInfos === null) {
|
|
51
|
+
// MARK: Default, fallback 404
|
|
52
|
+
const message = `404 not found!\n\n---\n\nCreate a /src/routes/404.{js,ts} to get a custom page.\n${method} - ${urlPath}`;
|
|
53
|
+
res.statusCode = 404;
|
|
54
|
+
res.statusMessage = '404 not found!';
|
|
55
|
+
const errorPage404 = await createErrorPage(new Error(message));
|
|
56
|
+
return res.end(errorPage404);
|
|
57
|
+
}
|
|
58
|
+
const routeTemplateOptions = {
|
|
59
|
+
request: requestPonyfilled,
|
|
60
|
+
vite,
|
|
61
|
+
mode: 'dev', // vite && vite.config.mode === 'dev' ? 'dev' : 'build',
|
|
62
|
+
routeAssets,
|
|
63
|
+
root,
|
|
64
|
+
serverMode,
|
|
65
|
+
routeInfos,
|
|
66
|
+
};
|
|
67
|
+
logger.info(`[${c.yellow(method)}] ${c.yellow(urlPath)}`, {
|
|
68
|
+
timestamp: true,
|
|
49
69
|
});
|
|
50
70
|
let output;
|
|
51
71
|
// TODO: should move this to `special-file` so we don't recalculate on each request
|
|
52
72
|
// + we would be able to do some route codegen.
|
|
53
73
|
const response = {};
|
|
54
74
|
// NOTE: Only for Express for now.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
// console.log({ locals });
|
|
76
|
+
let providedLocals = {};
|
|
77
|
+
// if ('locals' in res && isUnknownObject(res.locals)) locals = res.locals;
|
|
78
|
+
if (locals && isUnknownObject(locals))
|
|
79
|
+
providedLocals = locals;
|
|
58
80
|
// MARK: Server handler
|
|
59
|
-
const handler =
|
|
60
|
-
if ('handler' in
|
|
81
|
+
const handler = routeInfos.routeModule.handler;
|
|
82
|
+
if ('handler' in routeInfos.routeModule &&
|
|
61
83
|
typeof handler !== 'undefined') {
|
|
62
|
-
const
|
|
84
|
+
const routeContext = Object.freeze({
|
|
63
85
|
request: requestPonyfilled,
|
|
64
|
-
url: new URL(
|
|
86
|
+
url: new URL(fullUrl),
|
|
65
87
|
response,
|
|
66
|
-
params:
|
|
67
|
-
locals,
|
|
68
|
-
};
|
|
88
|
+
params: routeInfos.params,
|
|
89
|
+
locals: providedLocals,
|
|
90
|
+
});
|
|
91
|
+
// MARK: Run user middleware
|
|
92
|
+
// NOTE: Experimental
|
|
93
|
+
// eslint-disable-next-line no-inner-declarations
|
|
94
|
+
// async function useHandler() {}
|
|
95
|
+
// if (vite) {
|
|
96
|
+
// const middleware = await vite
|
|
97
|
+
// .ssrLoadModule('/src/middleware.ts')
|
|
98
|
+
// .catch(() => null)
|
|
99
|
+
// .then((m) => m.default);
|
|
100
|
+
// if (middleware)
|
|
101
|
+
// await middleware(
|
|
102
|
+
// routeContext,
|
|
103
|
+
// async () => {
|
|
104
|
+
// await useHandler();
|
|
105
|
+
// },
|
|
106
|
+
// );
|
|
107
|
+
// else await useHandler();
|
|
108
|
+
// } else {
|
|
109
|
+
// await useHandler();
|
|
110
|
+
// }
|
|
111
|
+
//
|
|
69
112
|
// MARK: Top level handler
|
|
70
113
|
if (typeof handler === 'function') {
|
|
71
|
-
const handlerOutput = (await Promise.resolve(handler(
|
|
114
|
+
const handlerOutput = (await Promise.resolve(handler(routeContext)));
|
|
72
115
|
if (handlerOutput instanceof Response)
|
|
73
116
|
output = handlerOutput;
|
|
74
117
|
else
|
|
@@ -79,26 +122,38 @@ export function createGracileMiddleware({ vite, routes, routeImports, routeAsset
|
|
|
79
122
|
const handlerWithMethod = handler[requestPonyfilled.method];
|
|
80
123
|
if (typeof handlerWithMethod !== 'function')
|
|
81
124
|
throw TypeError('Handler must be a function.');
|
|
82
|
-
const handlerOutput = await Promise.resolve(handlerWithMethod(
|
|
125
|
+
const handlerOutput = await Promise.resolve(handlerWithMethod(routeContext));
|
|
83
126
|
if (handlerOutput instanceof Response)
|
|
84
127
|
output = handlerOutput;
|
|
85
128
|
else {
|
|
86
|
-
output = await
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
129
|
+
output = await renderRouteTemplate({
|
|
130
|
+
...routeTemplateOptions,
|
|
131
|
+
handlerInfos: { data: handlerOutput, method },
|
|
132
|
+
}).then((r) => r.output);
|
|
90
133
|
}
|
|
91
134
|
// MARK: No GET, render page
|
|
92
135
|
}
|
|
93
136
|
else if (handler &&
|
|
94
137
|
'GET' in handler === false &&
|
|
95
138
|
requestPonyfilled.method === 'GET') {
|
|
96
|
-
output = await
|
|
139
|
+
output = await renderRouteTemplate({
|
|
140
|
+
...routeTemplateOptions,
|
|
141
|
+
handlerInfos: { data: null, method: 'GET' },
|
|
142
|
+
routeInfos,
|
|
143
|
+
}).then((r) => r.output);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const message = `This route doesn't handle the \`${method}\` method!`;
|
|
147
|
+
res.statusCode = 404;
|
|
148
|
+
res.statusMessage = message;
|
|
149
|
+
return res.end(await createErrorPage(new Error(message)));
|
|
97
150
|
}
|
|
98
|
-
// MARK: No handler, render page
|
|
99
151
|
}
|
|
100
152
|
else {
|
|
101
|
-
output = await
|
|
153
|
+
output = await renderRouteTemplate({
|
|
154
|
+
...routeTemplateOptions,
|
|
155
|
+
handlerInfos: { data: null, method: 'GET' },
|
|
156
|
+
}).then((r) => r.output);
|
|
102
157
|
}
|
|
103
158
|
// MARK: Return response
|
|
104
159
|
// NOTE: try directly with the requestPonyfill. This might not be necessary
|
|
@@ -120,69 +175,56 @@ export function createGracileMiddleware({ vite, routes, routeImports, routeAsset
|
|
|
120
175
|
// TODO: use this with page only?
|
|
121
176
|
// if (output.bodyUsed === false)
|
|
122
177
|
// throw new Error('Missing body.');
|
|
123
|
-
if (output.body)
|
|
124
|
-
output.body
|
|
178
|
+
if (output.body) {
|
|
179
|
+
const piped = await output.body
|
|
125
180
|
.pipeTo(Writable.toWeb(res))
|
|
126
181
|
.catch((e) => logger.error(String(e)));
|
|
182
|
+
return piped;
|
|
183
|
+
}
|
|
127
184
|
// else throw new Error('Missing body.');
|
|
128
|
-
|
|
129
|
-
|
|
185
|
+
// NOTE: Other shapes
|
|
186
|
+
return res.end(output);
|
|
130
187
|
// MARK: Stream page render
|
|
131
188
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.pipe(res);
|
|
161
|
-
}
|
|
189
|
+
new Headers(response.headers)?.forEach((content, header) => res.setHeader(header, content));
|
|
190
|
+
if (response.status)
|
|
191
|
+
res.statusCode = response.status;
|
|
192
|
+
if (response.statusText)
|
|
193
|
+
res.statusMessage = response.statusText;
|
|
194
|
+
res.setHeader('Content-Type', 'text/html');
|
|
195
|
+
// MARK: Page stream error
|
|
196
|
+
return output
|
|
197
|
+
?.on('error', (error) => {
|
|
198
|
+
const errorMessage = `There was an error while rendering a template chunk on server-side.\n` +
|
|
199
|
+
`It was omitted from the resulting HTML.`;
|
|
200
|
+
logger.error(errorMessage);
|
|
201
|
+
logger.error(error.message);
|
|
202
|
+
res.statusCode = 500;
|
|
203
|
+
res.statusMessage = errorMessage;
|
|
204
|
+
/* NOTE: Safety closing tags, maybe add more */
|
|
205
|
+
// Maybe just returning nothing is better to not break the page?
|
|
206
|
+
// Should send a overlay message anyway via WebSocket
|
|
207
|
+
// vite.ws.send()
|
|
208
|
+
if (vite)
|
|
209
|
+
setTimeout(() => {
|
|
210
|
+
vite.hot.send('gracile:ssr-error', {
|
|
211
|
+
message: errorMessage,
|
|
212
|
+
});
|
|
213
|
+
}, 500);
|
|
214
|
+
return res.end('' /* errorInline(error) */);
|
|
215
|
+
})
|
|
216
|
+
.pipe(res);
|
|
162
217
|
// MARK: Errors
|
|
163
218
|
}
|
|
164
219
|
catch (e) {
|
|
165
220
|
const error = e;
|
|
166
221
|
if (vite)
|
|
167
222
|
vite.ssrFixStacktrace(error);
|
|
168
|
-
|
|
169
|
-
logger.error(error.message);
|
|
170
|
-
if (error.cause === 404) {
|
|
171
|
-
// TODO: Handle 404 with dedicated page
|
|
172
|
-
if (!vite)
|
|
173
|
-
return next();
|
|
174
|
-
res.statusCode = 404;
|
|
175
|
-
return res.end('404');
|
|
176
|
-
// TODO: use a nice framework service page
|
|
177
|
-
// .redirect(new URL('/__404/', requestPonyfilled.url).href)
|
|
178
|
-
}
|
|
179
|
-
let errorTemplate = await renderSsrTemplate(errorPage(error));
|
|
180
|
-
if (vite)
|
|
181
|
-
errorTemplate = await vite.transformIndexHtml(req.url, errorTemplate);
|
|
223
|
+
const ultimateErrorPage = await createErrorPage(error);
|
|
182
224
|
res.statusCode = 500;
|
|
183
|
-
|
|
225
|
+
res.statusMessage = 'Gracile middleware error';
|
|
226
|
+
return res.end(ultimateErrorPage);
|
|
184
227
|
}
|
|
185
|
-
return next();
|
|
186
228
|
};
|
|
187
229
|
return middleware;
|
|
188
230
|
}
|
package/dist/server/utils.d.ts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
import type { Server } from 'http';
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { IncomingMessage, Server, ServerResponse } from 'node:http';
|
|
2
|
+
export declare function printAddressInfos(options: {
|
|
3
|
+
instance?: Server;
|
|
4
|
+
address: string;
|
|
5
|
+
}): void;
|
|
6
|
+
export declare function notFoundHandler(req: IncomingMessage, res: ServerResponse): void;
|
|
7
|
+
export type LocalMiddlewareContext = {
|
|
8
|
+
request: Request;
|
|
9
|
+
response: ResponseInit;
|
|
10
|
+
};
|
|
11
|
+
export type BasicAuthUser = {
|
|
12
|
+
userName: string | null;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* @param context
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
export declare const authenticateBasic: (context: LocalMiddlewareContext, validate: (user: {
|
|
19
|
+
name: string;
|
|
20
|
+
pass: string;
|
|
21
|
+
}) => boolean) => BasicAuthUser;
|
|
4
22
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AASzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB,QA2BA;AASD,wBAAgB,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,QAaxE;AAED,MAAM,MAAM,sBAAsB,GAAG;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,YACpB,sBAAsB,YACrB,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,KACzD,aAwBF,CAAC"}
|
package/dist/server/utils.js
CHANGED
|
@@ -1,21 +1,72 @@
|
|
|
1
1
|
// NOTE: Util. to pretty print for user provided server.
|
|
2
|
+
// import type { AddressInfo } from 'node:net';
|
|
2
3
|
import { logger } from '@gracile/internal-utils/logger';
|
|
3
4
|
import { DEV } from 'esm-env';
|
|
4
5
|
import c from 'picocolors';
|
|
5
6
|
import { IP_EXPOSED } from './env.js';
|
|
6
|
-
export function
|
|
7
|
-
|
|
7
|
+
export function printAddressInfos(options) {
|
|
8
|
+
let address = null;
|
|
9
|
+
if (options.instance) {
|
|
10
|
+
const infos = options.instance.address();
|
|
11
|
+
if (typeof infos === 'object' && infos && infos.port && infos.address) {
|
|
12
|
+
address = `http://${infos.address}:${infos.port}/`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
else if (options.address) {
|
|
16
|
+
address = options.address;
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
throw new Error('Incorrect options');
|
|
8
20
|
logger.info(c.green(`${DEV ? 'development' : 'production'} server started`), {
|
|
9
21
|
timestamp: true,
|
|
10
22
|
});
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`${
|
|
15
|
-
|
|
16
|
-
: ''}
|
|
23
|
+
logger.info(`
|
|
24
|
+
${c.dim('┃')} Local ${c.cyan(address)}` +
|
|
25
|
+
`${address?.includes(IP_EXPOSED)
|
|
26
|
+
? `${c.dim('┃')} Network ${c.cyan(address)}`
|
|
27
|
+
: ''}
|
|
17
28
|
`);
|
|
18
|
-
|
|
29
|
+
}
|
|
30
|
+
function sendHtml(res, payload) {
|
|
31
|
+
res.setHeader('content/type', 'text/html');
|
|
32
|
+
res.end(payload);
|
|
33
|
+
}
|
|
34
|
+
function fallback404(res) {
|
|
35
|
+
return sendHtml(res, '404 — Not found!');
|
|
36
|
+
}
|
|
37
|
+
export function notFoundHandler(req, res) {
|
|
38
|
+
const host = req.headers.host;
|
|
39
|
+
if (!host) {
|
|
40
|
+
fallback404(res);
|
|
41
|
+
return;
|
|
19
42
|
}
|
|
20
|
-
|
|
43
|
+
const url = new URL('/404/', `http://${host}`);
|
|
44
|
+
fetch(url)
|
|
45
|
+
.then((t) => t.text())
|
|
46
|
+
.then((r) => sendHtml(res, r))
|
|
47
|
+
.catch(() => fallback404(res));
|
|
21
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* @param context
|
|
51
|
+
* @returns
|
|
52
|
+
*/
|
|
53
|
+
export const authenticateBasic = (context, validate) => {
|
|
54
|
+
const b64 = context.request.headers.get('authorization')?.split(' ')?.[1];
|
|
55
|
+
if (b64) {
|
|
56
|
+
const [name, pass] = Buffer.from(b64, 'base64').toString().split(':');
|
|
57
|
+
if (name && pass) {
|
|
58
|
+
validate({ name, pass });
|
|
59
|
+
return { userName: name };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Authentication failed
|
|
64
|
+
*/
|
|
65
|
+
context.response.headers = new Headers({
|
|
66
|
+
...context.response.headers,
|
|
67
|
+
'WWW-Authenticate': 'Basic',
|
|
68
|
+
});
|
|
69
|
+
context.response.status = 401;
|
|
70
|
+
context.response.statusText = 'You are not authenticated!';
|
|
71
|
+
return { userName: null };
|
|
72
|
+
};
|