-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement hono and cleanup peer server DO
- Loading branch information
Showing
8 changed files
with
155 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export enum AppHeaders { | ||
ContentType = 'content-type', | ||
IpAddress = 'cf-connecting-ip', | ||
} | ||
|
||
export enum ContentType { | ||
Plaintext = 'text/plain', | ||
FormData = 'application/x-www-form-urlencoded', | ||
Json = 'application/json', | ||
} | ||
|
||
export enum PeerJsRoutes { | ||
Index = '/', | ||
PeerJs = '/peerjs', | ||
GenerateId = '/peerjs/id', | ||
} | ||
|
||
export enum DeadropRoutes { | ||
Drop = '/drop', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,35 @@ | ||
const WELCOME_TEXT = | ||
'{"name":"PeerJS Server","description":"A server side element to broker connections between PeerJS clients.","website":"https://peerjs.com/"}'; | ||
const HEARTBEAT = '{"type":"HEARTBEAT"}'; | ||
const OPEN = '{"type":"OPEN"}'; | ||
const ID_TAKEN = | ||
'{"type":"ID-TAKEN","payload":{"msg":"ID is taken"}}'; | ||
import { PeerServerDO } from './lib/durable_objects'; | ||
import { cors, tracing } from './lib/middleware'; | ||
import { hono } from './lib/http/core'; | ||
import { PeerJsRoutes } from './constants'; | ||
|
||
export class PeerServerDO implements DurableObject { | ||
constructor(private state: DurableObjectState, private env: Env) { | ||
this.state.setWebSocketAutoResponse( | ||
new WebSocketRequestResponsePair(HEARTBEAT, HEARTBEAT), | ||
); | ||
} | ||
const WELCOME_TEXT = JSON.stringify({ | ||
name: 'PeerJS Server', | ||
description: | ||
'A server side element to broker connections between PeerJS clients.', | ||
website: 'https://peerjs.com/', | ||
}); | ||
|
||
async fetch(request: Request) { | ||
const url = new URL(request.url); | ||
const app = hono(); | ||
|
||
const id = url.searchParams.get('id'); | ||
const token = url.searchParams.get('token'); | ||
app.use(cors()); | ||
app.use(tracing()); | ||
|
||
if (!id || !token) return new Response(null, { status: 400 }); | ||
app.get(PeerJsRoutes.Index, (c) => c.text(WELCOME_TEXT)); | ||
|
||
const [wsclient, wsserver] = Object.values(new WebSocketPair()); | ||
app.get(PeerJsRoutes.PeerJs, (c) => { | ||
const url = new URL(c.req.url); | ||
|
||
const existingWss = this.state.getWebSockets(id); | ||
const objId = c.env.PEER_SERVER.idFromName(url.host); | ||
const stub = c.env.PEER_SERVER.get(objId); | ||
|
||
if ( | ||
existingWss.length > 0 && | ||
existingWss[0].deserializeAttachment().token !== token | ||
) { | ||
wsserver.accept(); | ||
wsserver.send(ID_TAKEN); | ||
wsserver.close(1008, 'ID is taken'); | ||
return new Response(null, { webSocket: wsclient, status: 101 }); | ||
} else { | ||
existingWss.forEach((ws) => ws.close(1000)); | ||
} | ||
return stub.fetch(c.req.raw); | ||
}); | ||
|
||
this.state.acceptWebSocket(wsserver, [id]); | ||
wsserver.serializeAttachment({ id, token }); | ||
wsserver.send(OPEN); | ||
|
||
return new Response(null, { webSocket: wsclient, status: 101 }); | ||
} | ||
|
||
webSocketMessage( | ||
ws: WebSocket, | ||
message: string, | ||
): void | Promise<void> { | ||
const msg = JSON.parse(message); | ||
const dstWs = this.state.getWebSockets(msg.dst)[0]; | ||
|
||
msg.src = ws.deserializeAttachment().id; | ||
|
||
dstWs.send(JSON.stringify(msg)); | ||
} | ||
} | ||
app.get(PeerJsRoutes.GenerateId, (c) => c.text(crypto.randomUUID())); | ||
|
||
export default { | ||
async fetch(request: Request, env: Env) { | ||
const url = new URL(request.url); | ||
|
||
switch (url.pathname) { | ||
case '/': | ||
return new Response(WELCOME_TEXT); | ||
case '/peerjs': | ||
let objId = env.PEER_SERVER.idFromName(url.host); | ||
let stub = env.PEER_SERVER.get(objId); | ||
return stub.fetch(request); | ||
case '/peerjs/id': | ||
return new Response(crypto.randomUUID(), { | ||
status: 200, | ||
headers: { | ||
'Content-Type': 'text/plain', | ||
'Access-Control-Allow-Origin': '*', | ||
}, | ||
}); | ||
default: | ||
return new Response(null, { status: 404 }); | ||
} | ||
}, | ||
fetch: app.fetch, | ||
}; | ||
|
||
export { PeerServerDO }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const HEARTBEAT = JSON.stringify({ type: 'HEARTBEAT' }); | ||
const OPEN = JSON.stringify({ type: 'OPEN' }); | ||
const ID_TAKEN = JSON.stringify({ | ||
type: 'ID-TAKEN', | ||
payload: { msg: 'ID is taken' }, | ||
}); | ||
|
||
export class PeerServerDO implements DurableObject { | ||
constructor(private state: DurableObjectState, private env: Env) { | ||
this.state.setWebSocketAutoResponse( | ||
new WebSocketRequestResponsePair(HEARTBEAT, HEARTBEAT), | ||
); | ||
} | ||
|
||
async fetch(request: Request) { | ||
const url = new URL(request.url); | ||
|
||
const id = url.searchParams.get('id'); | ||
const token = url.searchParams.get('token'); | ||
|
||
if (!id || !token) return new Response(null, { status: 400 }); | ||
|
||
const [wsclient, wsserver] = Object.values(new WebSocketPair()); | ||
|
||
const existingWss = this.state.getWebSockets(id); | ||
|
||
if ( | ||
existingWss.length > 0 && | ||
existingWss[0].deserializeAttachment().token !== token | ||
) { | ||
wsserver.accept(); | ||
wsserver.send(ID_TAKEN); | ||
wsserver.close(1008, 'ID is taken'); | ||
return new Response(null, { webSocket: wsclient, status: 101 }); | ||
} else { | ||
existingWss.forEach((ws) => ws.close(1000)); | ||
} | ||
|
||
this.state.acceptWebSocket(wsserver, [id]); | ||
wsserver.serializeAttachment({ id, token }); | ||
wsserver.send(OPEN); | ||
|
||
return new Response(null, { webSocket: wsclient, status: 101 }); | ||
} | ||
|
||
webSocketMessage( | ||
ws: WebSocket, | ||
message: string, | ||
): void | Promise<void> { | ||
const msg = JSON.parse(message); | ||
const dstWs = this.state.getWebSockets(msg.dst)[0]; | ||
|
||
msg.src = ws.deserializeAttachment().id; | ||
|
||
dstWs.send(JSON.stringify(msg)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Hono, MiddlewareHandler } from 'hono'; | ||
|
||
export type HonoCtx = { | ||
Bindings: Env; | ||
Variables: { | ||
requestId: string; | ||
ipAddress?: string; | ||
error?: boolean; | ||
}; | ||
}; | ||
|
||
export type Middleware = MiddlewareHandler<HonoCtx>; | ||
|
||
export const hono = () => new Hono<HonoCtx>(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { cors as baseCors } from 'hono/cors'; | ||
import { AppHeaders } from '../constants'; | ||
import { Middleware } from './http/core'; | ||
|
||
export const tracing = (): Middleware => async (c, next) => { | ||
c.set('requestId', crypto.randomUUID()); | ||
|
||
const ipAddress = c.req.header(AppHeaders.IpAddress)! as string; | ||
c.set('ipAddress', ipAddress); | ||
|
||
await next(); | ||
}; | ||
|
||
export const cors = (): Middleware => | ||
baseCors({ | ||
origin: [ | ||
'https://deadrop.io', | ||
'https://*nieky-allens-projects.vercel.app', | ||
'https://*nieky.vercel.app', | ||
], | ||
allowHeaders: ['Content-Type', 'Authorization', 'Set-Cookie'], | ||
allowMethods: ['GET', 'HEAD', 'OPTIONS'], | ||
credentials: true, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6337,6 +6337,11 @@ hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: | |
dependencies: | ||
react-is "^16.7.0" | ||
|
||
hono@^4.5.9: | ||
version "4.5.9" | ||
resolved "https://registry.yarnpkg.com/hono/-/hono-4.5.9.tgz#2627c55c4c97ae826973dddac857ba4476fde6c6" | ||
integrity sha512-zz8ktqMDRrZETjxBrv8C5PQRFbrTRCLNVAjD1SNQyOzv4VjmX68Uxw83xQ6oxdAB60HiWnGEatiKA8V3SZLDkQ== | ||
|
||
[email protected]: | ||
version "1.2.0" | ||
resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-1.2.0.tgz#8f689b835982ffbf245eda99730e92b8462c111e" | ||
|