-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ef16682
commit eebacc4
Showing
5 changed files
with
62 additions
and
44 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export const NOT_FOUND = () => new Response('Not found', { status: 404 }); | ||
export const SERVER_ERROR = () => new Response('Server error', { status: 500 }); | ||
export const BAD_REQUEST = (message: string = 'Bad request') => new Response(message, { status: 400 }); | ||
export const BAD_REQUEST = (message: string = 'Bad request') => new Response(message, { status: 400 }); |
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,38 @@ | ||
import { shortenUrl } from '../../shorten-url'; | ||
import { urls } from '../../db/schema'; | ||
import { eq } from 'drizzle-orm'; | ||
import { NOT_FOUND, SERVER_ERROR } from '../responses'; | ||
import { DrizzleD1Database } from 'drizzle-orm/d1'; | ||
|
||
export default async (method: string, pathname: string, url: string, db: DrizzleD1Database) => { | ||
// TODO refactor routing - switch case | ||
if (method === 'GET' && pathname === '/api/redirect') { | ||
const [record] = await db.select().from(urls).where(eq(urls.short, url)); | ||
|
||
if (!record) { | ||
return NOT_FOUND(); | ||
} | ||
|
||
return Response.redirect(record.long, 301); | ||
} else if (method === 'POST' && pathname === '/api/shorten') { | ||
try { | ||
const longUrl = new URL(url).toString(); | ||
const shortUrl = await shortenUrl(longUrl); | ||
|
||
await db | ||
.insert(urls) | ||
.values({ | ||
long: longUrl, | ||
short: shortUrl, | ||
}) | ||
.onConflictDoNothing() | ||
.run(); | ||
|
||
return Response.json({ shortUrl }); | ||
} catch (e) { | ||
return SERVER_ERROR(); | ||
} | ||
} | ||
|
||
return NOT_FOUND(); | ||
}; |
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,16 @@ | ||
import { z } from 'zod'; | ||
import { BAD_REQUEST } from './responses'; | ||
|
||
const URL_SCHEMA = z.string().url(); | ||
|
||
export default async (urL: string): Promise<Response | string> => { | ||
// TODO - bit weird | ||
const validatedUrl = await URL_SCHEMA.safeParseAsync(urL); | ||
|
||
const isValidUrl = validatedUrl.success; | ||
if (!isValidUrl) { | ||
return BAD_REQUEST('Invalid URL'); | ||
} | ||
|
||
return validatedUrl.data; | ||
}; |
Empty file.
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,59 +1,23 @@ | ||
import { drizzle } from 'drizzle-orm/d1'; | ||
import { z } from 'zod'; | ||
import { shortenUrl } from './shorten-url'; | ||
import { urls } from './db/schema'; | ||
import { eq } from 'drizzle-orm'; | ||
import { BAD_REQUEST, NOT_FOUND, SERVER_ERROR } from './responses'; | ||
import routes from './http/routes'; | ||
import validation from './http/validation'; | ||
|
||
export interface Env { | ||
DB: D1Database; | ||
} | ||
|
||
const URL_SCHEMA = z.string().url(); | ||
|
||
export default { | ||
async fetch(request: Request, env: Env) { | ||
const { pathname, searchParams } = new URL(request.url); | ||
const db = drizzle(env.DB); | ||
const method = request.method; | ||
|
||
const validatedUrl = await URL_SCHEMA.safeParseAsync(searchParams.get('url')); | ||
|
||
const isValidUrl = validatedUrl.success; | ||
if (!isValidUrl) { | ||
return BAD_REQUEST('Invalid URL'); | ||
} | ||
|
||
// TODO refactor routing | ||
if (method === 'GET' && pathname === '/api/redirect') { | ||
const [record] = await db.select().from(urls).where(eq(urls.short, validatedUrl.data)) | ||
|
||
if (!record) { | ||
return NOT_FOUND(); | ||
} | ||
|
||
return Response.redirect(record.long, 301); | ||
} | ||
else if (method === 'POST' && pathname === '/api/shorten') { | ||
try { | ||
const longUrl = new URL(validatedUrl.data).toString(); | ||
const shortUrl = await shortenUrl(longUrl); | ||
|
||
await db | ||
.insert(urls) | ||
.values({ | ||
long: longUrl, | ||
short: shortUrl, | ||
}) | ||
.onConflictDoNothing() | ||
.run(); | ||
|
||
return Response.json({ shortUrl }); | ||
} catch (e) { | ||
return SERVER_ERROR(); | ||
} | ||
const validatedUrl = await validation(searchParams.get('url')!); // TODO remove ! | ||
if (validatedUrl instanceof Response) { | ||
// TODO - refactor, awkward | ||
return validatedUrl; | ||
} | ||
|
||
return NOT_FOUND(); | ||
return await routes(method, pathname, validatedUrl, db); | ||
}, | ||
}; |