diff --git a/src/frontend/servers/y-provider/__tests__/convert.test.ts b/src/frontend/servers/y-provider/__tests__/convert.test.ts index 02d09108..0173634e 100644 --- a/src/frontend/servers/y-provider/__tests__/convert.test.ts +++ b/src/frontend/servers/y-provider/__tests__/convert.test.ts @@ -26,8 +26,9 @@ describe('Server Tests', () => { const response = await request(app) .post('/api/convert') - .set('Origin', origin) - .set('Authorization', 'wrong-api-key'); + .set('origin', origin) + .set('authorization', 'wrong-api-key') + .set('content-type', 'application/json'); expect(response.status).toBe(401); expect(response.body).toStrictEqual({ @@ -40,8 +41,9 @@ describe('Server Tests', () => { const response = await request(app) .post('/api/convert') - .set('Origin', origin) - .set('Authorization', 'Bearer test-secret-api-key'); + .set('origin', origin) + .set('authorization', 'Bearer test-secret-api-key') + .set('content-type', 'application/json'); // Warning: Changing the authorization header to Bearer token format will break backend compatibility with this microservice. expect(response.status).toBe(401); @@ -55,8 +57,9 @@ describe('Server Tests', () => { const response = await request(app) .post('/api/convert') - .set('Origin', origin) - .set('Authorization', apiKey); + .set('origin', origin) + .set('authorization', apiKey) + .set('content-type', 'application/json'); expect(response.status).toBe(400); expect(response.body).toStrictEqual({ @@ -69,11 +72,10 @@ describe('Server Tests', () => { const response = await request(app) .post('/api/convert') - .set('Origin', origin) - .set('Authorization', apiKey) - .send({ - content: '', - }); + .set('origin', origin) + .set('authorization', apiKey) + .set('content-type', 'application/json') + .send(''); expect(response.status).toBe(400); expect(response.body).toStrictEqual({ @@ -93,20 +95,17 @@ describe('Server Tests', () => { const response = await request(app) .post('/api/convert') - .set('Origin', origin) - .set('Authorization', apiKey) - .send({ - content: document, - }); + .set('origin', origin) + .set('authorization', apiKey) + .set('content-type', 'application/json') + .send(document); expect(response.status).toBe(200); - expect(response.body).toStrictEqual({ - content: expect.any(String), - }); + expect(response.body).toBeInstanceOf(Buffer); const editor = ServerBlockNoteEditor.create(); const doc = new Y.Doc(); - Y.applyUpdate(doc, Buffer.from(response.body.content, 'base64')); + Y.applyUpdate(doc, response.body); const blocks = editor.yDocToBlocks(doc, 'document-store'); expect(blocks).toStrictEqual([ diff --git a/src/frontend/servers/y-provider/__tests__/server.test.ts b/src/frontend/servers/y-provider/__tests__/server.test.ts index d98f9958..762a76df 100644 --- a/src/frontend/servers/y-provider/__tests__/server.test.ts +++ b/src/frontend/servers/y-provider/__tests__/server.test.ts @@ -40,30 +40,30 @@ describe('Server Tests', () => { }); }); - it('allows JSON payloads up to 500kb for the CONVERT route', async () => { + it('allows payloads up to 500kb for the CONVERT route', async () => { const app = initApp(); const largePayload = 'a'.repeat(400 * 1024); // 400kb payload const response = await request(app) .post(routes.CONVERT) - .set('Origin', origin) - .set('Authorization', apiKey) - .set('Content-Type', 'application/json') - .send({ data: largePayload }); + .set('origin', origin) + .set('authorization', apiKey) + .set('content-type', 'text/markdown') + .send(largePayload); expect(response.status).not.toBe(413); }); - it('rejects JSON payloads larger than 500kb for the CONVERT route', async () => { + it('rejects payloads larger than 500kb for the CONVERT route', async () => { const app = initApp(); const oversizedPayload = 'a'.repeat(501 * 1024); // 501kb payload const response = await request(app) .post(routes.CONVERT) - .set('Origin', origin) - .set('Authorization', apiKey) - .set('Content-Type', 'application/json') - .send({ data: oversizedPayload }); + .set('origin', origin) + .set('authorization', apiKey) + .set('content-type', 'text/markdown') + .send(oversizedPayload); expect(response.status).toBe(413); }); diff --git a/src/frontend/servers/y-provider/src/handlers/convertHandler.ts b/src/frontend/servers/y-provider/src/handlers/convertHandler.ts index 3694377c..15bab784 100644 --- a/src/frontend/servers/y-provider/src/handlers/convertHandler.ts +++ b/src/frontend/servers/y-provider/src/handlers/convertHandler.ts @@ -2,15 +2,7 @@ import { ServerBlockNoteEditor } from '@blocknote/server-util'; import { Request, Response } from 'express'; import * as Y from 'yjs'; -import { logger, toBase64 } from '@/utils'; - -interface ConversionRequest { - content: string; -} - -interface ConversionResponse { - content: string; -} +import { logger } from '@/utils'; interface ErrorResponse { error: string; @@ -19,35 +11,30 @@ interface ErrorResponse { const editor = ServerBlockNoteEditor.create(); export const convertHandler = async ( - req: Request< - object, - ConversionResponse | ErrorResponse, - ConversionRequest, - object - >, - res: Response, + req: Request, + res: Response, ) => { - const content = req.body?.content; - - if (!content) { + if (!req.body || req.body.length === 0) { res.status(400).json({ error: 'Invalid request: missing content' }); return; } try { // Perform the conversion from markdown to Blocknote.js blocks - const blocks = await editor.tryParseMarkdownToBlocks(content); + const blocks = await editor.tryParseMarkdownToBlocks(req.body.toString()); if (!blocks || blocks.length === 0) { res.status(500).json({ error: 'No valid blocks were generated' }); return; } - // Create a Yjs Document from blocks, and encode it as a base64 string + // Create a Yjs Document from blocks const yDocument = editor.blocksToYDoc(blocks, 'document-store'); - const documentContent = toBase64(Y.encodeStateAsUpdate(yDocument)); - res.status(200).json({ content: documentContent }); + res + .status(200) + .setHeader('content-type', 'application/octet-stream') + .send(Y.encodeStateAsUpdate(yDocument)); } catch (e) { logger('conversion failed:', e); res.status(500).json({ error: 'An error occurred' }); diff --git a/src/frontend/servers/y-provider/src/servers/appServer.ts b/src/frontend/servers/y-provider/src/servers/appServer.ts index aca007fa..2dbfba99 100644 --- a/src/frontend/servers/y-provider/src/servers/appServer.ts +++ b/src/frontend/servers/y-provider/src/servers/appServer.ts @@ -47,7 +47,10 @@ export const initApp = () => { app.post( routes.CONVERT, httpSecurity, - express.json({ limit: '500kb' }), + express.raw({ + limit: '500kb', + type: '*/*', + }), convertHandler, );