Skip to content

Commit 5f86f5f

Browse files
authored
Merge pull request #3 from BrainbirdLab/Remove-HONO
chore: Migrate server from Hono to XebecServer and update route handlers
2 parents 8b80054 + c2b35e7 commit 5f86f5f

2 files changed

Lines changed: 65 additions & 68 deletions

File tree

server/libs/apiServer.ts

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,76 @@
11
import { io } from "./websockets.ts";
22

3-
import { Hono } from "https://deno.land/x/hono@v3.12.4/mod.ts";
4-
53
import fileHandler from "./fileHandler.ts";
64

75
import "https://deno.land/x/dotenv@v3.2.2/mod.ts";
86

7+
import { XebecServer } from "https://deno.land/x/xebec@v0.0.4/mod.ts";
8+
99
const { clienturl, devMode } = Deno.env.toObject();
1010

11-
const app = new Hono();
11+
const app = new XebecServer();
1212

1313
console.log('Hono server instance created');
1414

1515
//set custom headers for all responses
16-
app.use("*", async (ctx, next) => {
16+
app.use(async (_, next) => {
1717
const start = Date.now();
18-
await next();
18+
const res = await next();
1919
const ms = Date.now() - start;
20-
ctx.header('X-Server', 'Deno');
21-
ctx.header('X-Powered-By', 'Hono');
20+
res.headers.set('X-Server', 'Deno');
21+
res.headers.set('X-Powered-By', 'Hono');
2222
if (devMode) {
2323
console.log('Dev mode enabled');
24-
ctx.header('Access-Control-Allow-Origin', '*');
24+
res.headers.set('Access-Control-Allow-Origin', '*');
2525
} else {
26-
ctx.header('Access-Control-Allow-Origin', clienturl);
26+
res.headers.set('Access-Control-Allow-Origin', clienturl);
2727
}
28-
ctx.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
29-
ctx.header('X-Response-Time', `${ms}ms`);
28+
res.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
29+
res.headers.set('X-Response-Time', `${ms}ms`);
30+
31+
return res;
3032
});
3133

32-
app.options('*', (ctx) => {
33-
ctx.status(200);
34-
return ctx.text('OK');
34+
app.OPTIONS('*', (_) => {
35+
return new Response(null, { status: 200 });
3536
});
3637

3738
app.route('/api/files', fileHandler);
3839

39-
app.get('/', (ctx) => {
40+
app.GET('/', (_) => {
4041
//random emoji from unicode range
4142
const emoji = String.fromCodePoint(0x1F600 + Math.floor(Math.random() * 20));
42-
return ctx.text(`Hello from Poketab - ${emoji}`);
43+
return new Response(`Server is up and running ${emoji}`);
4344
});
4445

4546
//maintainace break message from admin
46-
app.get('/mbm/:adminPasskey/:message/:time', (ctx) => {
47+
app.GET('/mbm/:adminPasskey/:message/:time', (req) => {
4748
//read env variable
48-
const { adminPasskey } = ctx.req.param();
49-
const { message } = ctx.req.param();
50-
const { time } = ctx.req.param();
5149

50+
const { adminPasskey, message, time } = req.params;
5251

5352
if (!adminPasskey || !message) {
54-
ctx.status(400);
55-
return ctx.json({ message: 'Invalid request' });
53+
return new Response('Invalid request', { status: 400 });
5654
}
5755

5856
//check if passkey is correct
5957
const key = Deno.env.get('adminPasskey');
6058

6159
if (adminPasskey !== key) {
62-
ctx.status(401);
63-
return ctx.json({ message: 'Unauthorized' });
60+
return new Response('Unauthorized', { status: 401 });
6461
}
6562

6663
//send message to all connected clients
6764
io.emit('maintainanceBreak', message, parseInt(time));
6865

69-
ctx.status(200);
70-
return ctx.json({ message: 'Message sent' });
66+
return new Response('Message sent', { status: 200 });
7167

7268
});
7369

7470

7571
export const handler = io.handler(async (req: Request) => {
7672
//upgrade to websocket
77-
return await app.fetch(req) || new Response(null, { status: 404 });
73+
return await app.handler(req) || new Response(null, { status: 404 });
7874
});
7975

8076
console.log('Socket-io binded to Hono server');

server/libs/fileHandler.ts

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,72 +3,64 @@ import { type RedisValue } from "https://deno.land/x/redis@v0.32.1/mod.ts";
33
import { redis, _R_fileUploadAuth } from "../db/database.ts";
44

55
import { io } from "./websockets.ts";
6-
import { Hono } from "https://deno.land/x/hono@v3.12.4/mod.ts";
6+
import { XebecServer } from "https://deno.land/x/xebec@v0.0.4/mod.ts";
77

8-
const app = new Hono();
8+
const app = new XebecServer();
99

1010
const MAX_SIZE = 50 * 1024 * 1024;
1111

1212
//file upload
13-
app.post('/upload/:key/:uid/:messageId', async (ctx) => {
13+
app.POST('/upload/:key/:uid/:messageId', async (req) => {
1414

1515
try {
1616
console.log('Upload request received');
1717

18-
const { key, uid, messageId } = ctx.req.param();
18+
const { key, uid, messageId } = req.params;
1919

2020
const res = await _R_fileUploadAuth(key, uid);
2121

2222
const [exists, activeUsers] = res as [number, number];
2323

2424
if (!exists){
25-
ctx.status(401);
26-
return ctx.json({ message: 'Unauthorized' });
25+
return new Response('Unauthorized', { status: 401 });
2726
}
2827

2928

3029
if (Number(activeUsers) < 2){
31-
ctx.status(400);
32-
return ctx.json({ message: 'Not enough users' });
30+
return new Response('Not enough users', { status: 400 });
3331
}
3432

3533
//check file size before parsing form
36-
const contentLength = ctx.req.header('content-length');
34+
const contentLength = req.headers.get('content-length');
3735

3836
if (!contentLength) {
39-
ctx.status(400);
40-
return ctx.json({ message: 'No content length' });
37+
return new Response('No content length', { status: 400 });
4138
}
4239

4340
if (+contentLength > MAX_SIZE) {
44-
ctx.status(400);
45-
return ctx.json({ message: `File size should be within ${MAX_SIZE} bytes.` });
41+
return new Response(`File size should be within ${MAX_SIZE} bytes.`, { status: 400 });
4642
}
4743

48-
const form = await ctx.req.formData();
44+
const form = await req.formData();
4945

5046

5147
if (!form) {
52-
ctx.status(400);
53-
return ctx.json({ message: 'No data found' });
48+
return new Response('No data found', { status: 400 });
5449
}
5550

5651
//file size
5752
const files = form.getAll('file') as File[];
5853

5954
if (!files.length) {
60-
ctx.status(400);
61-
return ctx.json({ message: 'No file found. Check field avatar.' });
55+
return new Response('No file found. Check field avatar.', { status: 400 });
6256
}
6357

6458
if (files.length > 1) {
65-
ctx.status(400);
66-
return ctx.json({ message: 'Multiple files found. Only one file allowed.' });
59+
return new Response('Multiple files found. Only one file allowed.', { status: 400 });
6760
}
6861

6962
if (files[0].size > MAX_SIZE) {
70-
ctx.status(400);
71-
return ctx.json({ message: `File size should be within ${MAX_SIZE} bytes.` });
63+
return new Response(`File size should be within ${MAX_SIZE} bytes.`, { status: 400 });
7264
}
7365

7466
const maxUser = await redis.hget(`chat:${key}`, 'maxUsers') as unknown as number;
@@ -106,28 +98,26 @@ app.post('/upload/:key/:uid/:messageId', async (ctx) => {
10698
});
10799
});
108100

109-
return ctx.json({ message: 'File uploaded' });
101+
return new Response('File uploaded', { status: 200 });
110102
} catch (_) {
111103
console.log("Error while receiving");
112104
console.log(_);
113-
ctx.status(400);
114-
return ctx.json({ message: 'Error while receiving' });
105+
return new Response('Error while receiving', { status: 400 });
115106
}
116107
});
117108

118109
//file download
119-
app.get('/download/:key/:userId/:messageId', async (ctx) => {
110+
app.GET('/download/:key/:userId/:messageId', async (req) => {
120111

121-
const { key, userId, messageId } = ctx.req.param();
112+
const { key, userId, messageId } = req.params;
122113

123114
try {
124115

125116
const res = await redis.exists(`chat:${key}`, `uid:${userId}`, `chat:${key}:file:${messageId}`);
126117

127118
if (res !== 3){
128119
console.log('Unauthorized');
129-
ctx.status(401);
130-
return ctx.json({ message: 'Unauthorized' });
120+
return new Response('Unauthorized', { status: 401 });
131121
}
132122

133123
//check if this user has not downloaded this file before
@@ -146,34 +136,45 @@ app.get('/download/:key/:userId/:messageId', async (ctx) => {
146136
const dir = await Deno.stat(path).catch(() => null);
147137

148138
if (!dir) {
149-
return ctx.json({message: 'File not found'});
139+
return new Response('File not found', { status: 404 });
150140
}
151141

152142
const file = await Deno.open(path);
153143
const size = (await file.stat()).size;
154144

155145
//serve file
156-
return ctx.newResponse(file.readable, 200, {
157-
'Content-Disposition': `attachment;`,
158-
'Content-Length': size.toString(),
159-
'Content-Type': 'application/octet-stream'
146+
// return ctx.newResponse(file.readable, 200, {
147+
// 'Content-Disposition': `attachment;`,
148+
// 'Content-Length': size.toString(),
149+
// 'Content-Type': 'application/octet-stream'
150+
// });
151+
152+
return new Response(file.readable, {
153+
status: 200,
154+
headers: new Headers({
155+
'Content-Disposition': `attachment;`,
156+
'Content-Length': size.toString(),
157+
'Content-Type': 'application/octet-stream'
158+
})
160159
});
161160

162161
} catch (_) {
163-
ctx.status(404);
164-
return ctx.json({ message: 'Error downloading file'});
162+
return new Response('Error downloading file', { status: 404 });
165163
} finally {
166164

167165
const downloadInfo = await redis.hmget(`chat:${key}:file:${messageId}`, 'downloadCount', 'maxDownload');
168166

169167
const [downloadCount, maxDownload] = downloadInfo as unknown as [number, number];
170168

171169
if (Number(downloadCount + 1) >= Number(maxDownload)){
172-
173-
await redis.del(`chat:${key}:file:${messageId}`);
174-
await Deno.remove(`./uploads/${key}/${messageId}`);
175-
176-
console.log(`File deleted: ${messageId}`);
170+
171+
try {
172+
await redis.del(`chat:${key}:file:${messageId}`);
173+
await Deno.remove(`./uploads/${key}/${messageId}`);
174+
console.log(`File deleted: ${messageId}`);
175+
} catch (_) {
176+
console.log('Error deleting file');
177+
}
177178
}
178179
}
179180
});

0 commit comments

Comments
 (0)