Scratch space for learning atproto app development

tidy

Changed files
+9 -42
src
-35
src/lib/http.ts
···
}
}
-
export function formHandler<
-
Req extends IncomingMessage = IncomingMessage,
-
Res extends ServerResponse<Req & { body: unknown }> = ServerResponse<
-
Req & { body: unknown }
-
>,
-
>(fn: AsyncHandler<Req & { body: unknown }, Res>): Handler<Req, Res> {
-
return handler(async (req, res, next) => {
-
if (req.method !== 'POST') {
-
return void res.writeHead(405).end()
-
}
-
if (req.headers['content-type'] !== 'application/x-www-form-urlencoded') {
-
return void res.writeHead(415).end('Unsupported Media Type')
-
}
-
-
// Read the request payload
-
const chunks: Uint8Array[] = []
-
for await (const chunk of req) chunks.push(chunk)
-
const payload = Buffer.concat(chunks).toString('utf-8')
-
-
// Parse the Form URL-encoded payload
-
const body = payload ? Object.fromEntries(new URLSearchParams(payload)) : {}
-
-
// Define the body property on the request object
-
Object.defineProperty(req, 'body', {
-
value: body,
-
writable: false,
-
enumerable: true,
-
configurable: true,
-
})
-
-
// Call the provided async handler with the modified request
-
return fn(req as Req & { body: unknown }, res, next)
-
})
-
}
-
export async function startServer(
requestListener: RequestListener,
{
+9 -7
src/routes.ts
···
import * as Profile from '#/lexicon/types/app/bsky/actor/profile'
import * as Status from '#/lexicon/types/xyz/statusphere/status'
import { env } from '#/env'
-
import { formHandler, handler } from '#/lib/http'
+
import { handler } from '#/lib/http'
import { page } from '#/lib/view'
import { home } from '#/pages/home'
import { login } from '#/pages/login'
···
// OAuth metadata
app.get(
'/oauth-client-metadata.json',
-
handler(async (req: Request, res: Response) => {
+
handler((req: Request, res: Response) => {
res.json(ctx.oauthClient.clientMetadata)
}),
)
···
// Public keys
app.get(
'/.well-known/jwks.json',
-
handler(async (req: Request, res: Response) => {
+
handler((req: Request, res: Response) => {
res.json(ctx.oauthClient.jwks)
}),
)
···
// Login page
app.get(
'/login',
-
handler(async (req: Request, res: Response) => {
+
handler((req: Request, res: Response) => {
res.type('html').send(page(login({})))
}),
)
···
// Login handler
app.post(
'/login',
-
formHandler(async (req: Request, res: Response) => {
+
express.urlencoded({ extended: true }),
+
handler(async (req: Request, res: Response) => {
// Validate
const handle = req.body?.handle
if (typeof handle !== 'string' || !isValidHandle(handle)) {
···
// Logout handler
app.post(
'/logout',
-
formHandler(async (req: Request, res: Response) => {
+
handler(async (req: Request, res: Response) => {
const session = await getIronSession<Session>(req, res, {
cookieName: 'sid',
password: env.COOKIE_SECRET,
···
// "Set status" handler
app.post(
'/status',
-
formHandler(async (req: Request, res: Response) => {
+
express.urlencoded({ extended: true }),
+
handler(async (req: Request, res: Response) => {
// If the user is signed in, get an agent which communicates with their server
const agent = await getSessionAgent(req, res, ctx)
if (!agent) {