|
- import fastify, {FastifyRequest, FastifyServerOptions} from 'fastify';
- import {fastifyErrorHandler} from './packages/fastify-compliant-http-errors';
- import fastifySendData from './packages/fastify-send-data';
- import fastifyServiceSession from './packages/fastify-service-session';
- import {Session, SessionService, SessionServiceImpl} from './modules/auth';
- import {Uuid} from '@theoryofnekomata/uuid-buffer';
- import fastifyHomeRoute from './packages/fastify-home-route';
- import {User} from './modules/user';
- import {IncomingMessage} from 'http';
- import {createDeflate, createGunzip} from 'zlib';
- import {PassThrough, Transform} from 'stream';
-
- interface RequestLike extends Pick<FastifyRequest, 'query' | 'headers' | 'body'> {}
-
- declare module 'fastify' {
- interface FastifyRequest {
- session?: Session & { user: User },
- }
- }
-
- enum AvailableDecoder {
- GZIP = 'gzip',
- DEFLATE = 'deflate',
- }
-
- type DecoderFunction = () => Transform;
-
- const DECODERS: Record<AvailableDecoder, DecoderFunction> = {
- [AvailableDecoder.GZIP]:() => createGunzip(),
- [AvailableDecoder.DEFLATE]: () => createDeflate(),
- }
-
- const DEFAULT_DECODER: DecoderFunction = () => new PassThrough();
-
- class PackRequestTransformStream extends Transform {
- private data: Record<string, unknown> = {
- last: null,
- commit: null,
- ref: null,
- }
-
- constructor() {
- super();
- const headerRegExp = /([0-9a-fA-F]+) ([0-9a-fA-F]+) (.+?)( |00|\u0000)|^(0000)$/gi;
- let bufferedData = Buffer.from('');
- this.on('data', (chunk) => {
- const isHeaderRead = this.data.last && this.data.commit;
- if (!isHeaderRead) {
- bufferedData = Buffer.concat([bufferedData, chunk]);
- const bufferAsString = bufferedData.toString('utf-8');
- const bufferHeaderMatch = bufferAsString.match(headerRegExp);
- if (bufferHeaderMatch) {
- const [
- _header,
- last,
- commit,
- ref,
- ] = Array.from(bufferHeaderMatch);
- this.data = {
- last,
- commit,
- ref,
- }
- }
- }
- this.push(chunk);
- })
- }
- }
-
- const receivePackRequestParser = (
- request: FastifyRequest,
- payload: IncomingMessage,
- done: Function,
- ) => {
- console.log(request.headers);
- const encoding = request.headers['content-encoding'];
- let theDecoder: DecoderFunction = DEFAULT_DECODER;
- if (encoding) {
- const { [encoding as AvailableDecoder]: decoder } = DECODERS;
- if (!decoder) {
- done(new Error(`Unknown encoding: ${encoding}`));
- return;
- }
- theDecoder = decoder;
- }
-
- const requestParserStream = new PackRequestTransformStream();
- const pipeline = payload
- .pipe(theDecoder())
- .pipe(requestParserStream)
-
- pipeline.on('end', () => {
- done(null, pipeline);
- });
- };
-
- export const createServer = (opts?: FastifyServerOptions) => {
- const server = fastify(opts);
-
- server.setErrorHandler(fastifyErrorHandler)
- server.register(fastifyHomeRoute);
- server.addContentTypeParser('application/x-git-receive-pack-request', receivePackRequestParser);
- server.addContentTypeParser('application/x-git-upload-pack-request', receivePackRequestParser); // TODO
- server.register(fastifyServiceSession, {
- sessionRequestKey: 'session',
- getSession: async (sessionId: string) => {
- const sessionService: SessionService = new SessionServiceImpl()
- return sessionService.get(Uuid.from(sessionId))
- },
- isSessionValid: async (sessionId: string) => {
- const sessionService: SessionService = new SessionServiceImpl()
- return sessionService.isValid(Uuid.from(sessionId))
- },
- extractSessionId: (request: RequestLike) => {
- const sessionIdKey = 'sessionId'
-
- const query = request.query as Record<string, unknown>
- const querySessionId = query[sessionIdKey]
- if (typeof querySessionId === 'string') {
- return querySessionId
- }
-
- const { authorization } = request.headers
- if (typeof authorization === 'string') {
- const [authType, headerSessionId] = authorization.split(' ')
- if (authType === 'Bearer') {
- return headerSessionId
- }
- }
-
- const body = request.body as Record<string, unknown> ?? {}
- const bodySessionId = body[sessionIdKey]
- if (typeof bodySessionId === 'string') {
- return bodySessionId
- }
-
- return undefined
- }
- })
- server.register(fastifySendData);
-
- return server;
- }
|