Skip to content

Commit 39fc2fa

Browse files
committed
feat: add contact form server-side.
1 parent 271f63a commit 39fc2fa

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

server-side/contact.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { AutoRouter, cors, error } from 'npm:itty-router';
2+
3+
const { preflight, corsify } = cors();
4+
const router = AutoRouter({
5+
before: [preflight],
6+
finally: [corsify],
7+
});
8+
9+
const contactWebhook = Deno.env.get('CONTACT_WEBHOOK');
10+
if (!contactWebhook) throw 'Missing CONTACT_WEBHOOK env var';
11+
const turnstileSecret = Deno.env.get('TURNSTILE_SECRET');
12+
if (!turnstileSecret) throw 'Missing TURNSTILE_SECRET env var';
13+
14+
router.post('/contact', async ({ formData }) => {
15+
const data = await formData();
16+
const cloudflareToken = data.get('cf-turnstile-response');
17+
if (!cloudflareToken) return error(400, 'Cloudflare captcha token missing.');
18+
const name = data.get('name');
19+
if (!name) return error(400, 'Missing name field');
20+
const email = data.get('email');
21+
if (!email) return error(400, 'Missing email field');
22+
const message = data.get('message');
23+
if (!message) return error(400, 'Missing message field');
24+
25+
const turnstileData = new FormData();
26+
turnstileData.append('secret', turnstileSecret);
27+
turnstileData.append('response', cloudflareToken);
28+
// turnstileData.append("remoteip", ip);
29+
30+
const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
31+
const result = await fetch(url, {
32+
body: turnstileData,
33+
method: 'POST',
34+
});
35+
if (!result.ok) {
36+
console.error('Error validating turnstile challenge:', await result.text());
37+
return error(400, 'Invalid turnstile challenge response');
38+
}
39+
40+
const response = await fetch(contactWebhook, {
41+
method: 'POST',
42+
headers: {
43+
'Content-Type': 'application/json',
44+
},
45+
body: JSON.stringify({
46+
text: `New message from ${name}:${email} >> ${message}`,
47+
}),
48+
});
49+
if (response.ok) {
50+
return new Response(undefined, { status: 200 });
51+
} else {
52+
return new Response(undefined, { status: 500 });
53+
}
54+
});
55+
56+
Deno.serve(router.fetch);

server-side/deno.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"nodeModulesDir": "auto"
3+
}

server-side/deno.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)