Skip to content

Commit

Permalink
refactor(workers): optimize worker responses
Browse files Browse the repository at this point in the history
  • Loading branch information
pascaliske committed Apr 12, 2023
1 parent 51a8dd3 commit 832dc76
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ yarn-error.log
# IDEs and editors
/.idea
.envrc
.dev.vars
.project
.classpath
.c9/
Expand Down
34 changes: 34 additions & 0 deletions workers/responses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* eslint-disable max-classes-per-file */

export class CreatedResponse extends Response {
/**
* Created Response - HTTP 201
*/
public constructor(public readonly message: string) {
super(JSON.stringify({ message }), { status: 201 })

this.headers.set('Content-Type', 'application/json')
}
}

export class BadRequestResponse<R = string> extends Response {
/**
* Bad Request Response - HTTP 400
*/
public constructor(public readonly message: string, public readonly reason?: R) {
super(JSON.stringify({ message, reason }), { status: 400 })

this.headers.set('Content-Type', 'application/json')
}
}

export class InternalServerErrorResponse<R = Error> extends Response {
/**
* Internal Server Error Response - HTTP 500
*/
public constructor(public readonly message: string, public readonly reason?: R) {
super(JSON.stringify({ message, reason }), { status: 500 })

this.headers.set('Content-Type', 'application/json')
}
}
84 changes: 55 additions & 29 deletions workers/routes/contact.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Handler, Context } from 'hono'
import type { ContactFormGroup } from 'pages/contact/contact.component'
import { CreatedResponse, BadRequestResponse, InternalServerErrorResponse } from '../responses'
import { Environment } from '..'

type ContactFormRequest = Record<keyof ContactFormGroup, string>
Expand All @@ -24,43 +25,68 @@ export const contact: () => Handler = () => {
const data: Record<keyof ContactFormGroup, string> = await context.req.json()

// check honeypot field
if (data?.prefix?.length > 0) {
return context.json({}, 400)
if (data.prefix.length > 0) {
return new BadRequestResponse('Invalid request data!', ['prefix'])
}

// check email field
if (data?.email?.length === 0) {
return context.json({}, 400)
if (data.email.length === 0) {
return new BadRequestResponse('Invalid request data!', ['email'])
}

// process request
const request: Request = new Request('https://api.mailchannels.net/tx/v1/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
from: { email: 'no-reply@pascaliske.dev', name: 'Pascal Iske' },
// eslint-disable-next-line camelcase
reply_to: { email: data.email, name: data.name },
personalizations: [
{
to: [{ email: 'info@pascaliske.dev', name: 'Pascal Iske' }],
},
],
subject: `Contact Request from ${data.email}`,
content: [
{
type: 'text/plain',
value: template(data),
},
],
}),
// check message field
if (data?.message?.length === 0) {
return new BadRequestResponse('Invalid request data!', ['message'])
}

// prepare forward request
const url: URL = new URL('https://api.mailchannels.net/tx/v1/send')

const headers: Headers = new Headers()
headers.set('Accept', 'application/json')
headers.set('Content-Type', 'application/json')

const body: string = JSON.stringify({
from: { email: 'no-reply@pascaliske.dev', name: 'Pascal Iske' },
// eslint-disable-next-line camelcase
reply_to: { email: data.email, name: data.name },
personalizations: [
{
to: [{ email: 'info@pascaliske.dev', name: 'Pascal Iske' }],
},
],
subject: `Contact Request from ${data.email}`,
content: [
{
type: 'text/plain',
value: template(data),
},
],
})

// process response
const response: Response = await fetch(request)
const body: string = await response.json()
// activate dry-run on staging
if (context.env.ENVIRONMENT === 'staging') {
url.searchParams.set('dry-run', 'true')
}

// forward request
const request: Request = new Request(url, { method: 'POST', headers, body })
const { status, statusText }: Response = await fetch(request)

// response
return context.json(body)
switch (status) {
// success
case 200:
case 202:
return new CreatedResponse('Successfully sent contact request!')

// bad request
case 400:
return new BadRequestResponse('Invalid request data!')

// error
default:
return new InternalServerErrorResponse('Internal server error!', statusText)
}
}
}

0 comments on commit 832dc76

Please sign in to comment.