Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/vps/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import shows from '@/routes/shows/show.index'
import spotify from '@/routes/spotify/spotify.index'
import upload from '@/routes/upload/upload.index'
import uploadMultipart from '@/routes/upload-multipart/upload-multipart.index'
import betterAuthRoutes from '@/routes/user/better-auth.routes'
import user from '@/routes/user/user.index'
import { db } from './db'
import { regenerateSitemap } from './routes/redirect/seo/sitemap'
Expand Down Expand Up @@ -66,8 +65,9 @@ const setupRoutesEffect = Effect.gen(function* () {
app.route('/api/music', music)
app.route('/api/music-reminders', musicReminders)

// Kept at root, not under /api: auth has its own basePath/email links, and these are externally-referenced public URLs.
app.route('/auth', betterAuthRoutes)
// Kept at root, not under /api: these are externally-referenced public URLs.
// /auth is handled by the Effect router directly (apps/vps/src/http/routes.ts,
// step 2c) -- not mounted here.
app.route('/s', shareRouter)
app.route('', rss)
app.route('', seoRouter)
Expand Down
22 changes: 22 additions & 0 deletions apps/vps/src/http/routes.blackbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,25 @@ describe('Effect toWebHandler fallback', () => {
expect(res.status).toBe(404)
})
})

describe('better-auth route (Step 2c)', () => {
it('GET /auth/get-session is handled by the auth route, not the Hono fallback', async () => {
const res = await webHandler.handler(new Request('http://localhost/auth/get-session'))

// better-auth's own response for an unauthenticated session check, not a 404 --
// proves /auth/* is matched ahead of the wildcard fallback.
expect(res.status).toBe(200)
expect(await res.json()).toBeNull()
})

it('unknown /auth/* paths are handled by better-auth (404 from better-auth, not the Hono fallback)', async () => {
const withoutAuth = await webHandler.handler(new Request('http://localhost/does-not-exist'))
const withAuth = await webHandler.handler(new Request('http://localhost/auth/does-not-exist'))

expect(withoutAuth.status).toBe(404)
expect(withAuth.status).toBe(404)
// Different bodies would indicate the two 404s come from different sources
// (Hono's notFound handler vs. better-auth's own routing).
expect(await withAuth.text()).not.toEqual(await withoutAuth.text())
})
})
18 changes: 17 additions & 1 deletion apps/vps/src/http/routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Effect, Layer } from 'effect'
import { HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse } from 'effect/unstable/http'
import type { AppType } from '@/app'
import { auth } from '@/lib/auth'
import { prepareAuthRequest } from '@/routes/user/better-auth.routes'

// Routes every request to the existing Hono app unchanged. Removed one HttpApi group at a time as routes are ported (docs/migration-effect-http-api.md).
export const honoFallback = (honoApp: AppType) =>
Expand All @@ -12,5 +14,19 @@ export const honoFallback = (honoApp: AppType) =>
})
)

// better-auth owns its own routing; we can't redefine it as HttpApiEndpoints. Kept at
// its own path (not under /api) since its basePath appears in emailed links.
const betterAuthRoute = HttpRouter.add('*', '/auth/*', (request) =>
Effect.gen(function* () {
const webRequest = yield* HttpServerRequest.toWeb(request)
const webResponse = yield* Effect.promise(() =>
Promise.resolve(auth.handler(prepareAuthRequest(webRequest)))
)
return HttpServerResponse.fromWeb(webResponse)
})
)

export const createWebHandler = (honoApp: AppType) =>
HttpRouter.toWebHandler(Layer.mergeAll(honoFallback(honoApp), HttpServer.layerServices))
HttpRouter.toWebHandler(
Layer.mergeAll(betterAuthRoute, honoFallback(honoApp), HttpServer.layerServices)
)
2 changes: 1 addition & 1 deletion apps/vps/src/routes/user/better-auth.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { auth } from '@/lib/auth'

const betterAuthApp = new Hono()

function prepareAuthRequest(request: Request) {
export function prepareAuthRequest(request: Request) {
const hasOrigin = request.headers.has('origin') || request.headers.has('referer')

if (request.method === 'POST' && !hasOrigin && request.headers.has('cookie')) {
Expand Down