Formulir kontak di situs statis

Formulir kontak di situs statis6 menit baca

Memperbaiki error 405 pada formulir kontak yang di-host di Vercel

Halaman statis di Vercel menjawab POST formulir dengan 405 Method Not Allowed; ini penyebabnya, dan cara mengirim formulir ke backend.

Preet SutharPendiri, Ikiform

Vercel menyajikan build statis Anda sebagai file, dan POST ke file mendapat 405 dengan body kosong karena tidak ada function yang menangani path itu. Arahkan action formulir ke endpoint Ikiform Anda, atau tulis Vercel Function yang menerima kiriman. Dengan Ikiform, atur ID formulir per environment Vercel agar preview mengirim ke formulir uji dan production mengirim ke formulir sungguhan.

Mengapa Vercel menjawab 405

Vercel mengarahkan setiap request ke file statis atau ke function. Situs statis, build Vite, atau aplikasi Next.js dengan output: "export" hanya punya file. GET untuk /contact mengembalikan file; POST ke path yang sama tidak punya tujuan, jadi Vercel menolaknya sebelum kode Anda sempat berjalan:

Terminal
curl -i -X POST -d "message=hello" https://your-project.vercel.app/contact
Respons
HTTP/2 405
server: Vercel
content-disposition: inline
x-vercel-cache: HIT
content-length: 0

Respons tidak punya body, jadi browser menampilkan halaman kosong atau layar error-nya sendiri. Tiga setup berujung di sini:

Kode AndaMengapa 405 di Vercel
<form method="post"> tanpa actionFormulir mengirim ke halaman tempat ia berada, yang berupa file statis
action="/api/contact" di proyek Vite atau HTML biasaTidak ada file di folder api/ di root proyek, jadi tidak ada function untuk path itu
Server Action atau Route Handler Next.js dalam static exportoutput: "export" tidak mendukung Server Actions, atau Route Handlers yang membaca request. next dev melaporkan error-nya, dan build tidak punya server untuk menjalankannya
Bagaimana Vercel memutuskan apa yang dilakukan dengan POST formuliraction ke situs Vercel Andaaction ke IkiformPOST/contactdari formulirroutingVercelfile ataufunction?adafunction?functionAndajika Andamenulisnya405, bodykosongfile statisPOST keikiform.comformulir yangsamaIkiformsimpan, kirimemailhalamanterimakasihfile statis diVercelyatidak303Bagaimana Vercel memutuskan apa yang dilakukan dengan POST formuliraction ke situs Vercel Andaaction ke IkiformPOST /contactdari formulirrouting Vercelfile atau function?adafunction?function Andajika Andamenulisnya405,bodykosongfile statisPOST keikiform.comformulir yang samaIkiformsimpan, kirim emailhalaman terimakasihfile statis diVercelya303tidak
  1. Formulir mengirim ke path di deployment Vercel Anda.
  2. Vercel mencari function yang menangani path itu.
  3. Jika Anda menulisnya, function itu berjalan. Di build statis tidak ada, jadi Vercel menjawab 405 dengan body kosong.
  4. Dengan action mengarah ke Ikiform, kiriman tidak pernah sampai ke Vercel.
  5. Ikiform menyimpan pesan, mengirimi Anda email, dan me-redirect browser kembali ke halaman statis di situs Vercel Anda.
Vercel tidak rusak di sini. Deployment statis tidak punya kode untuk POST, dan function adalah satu-satunya cara menambahkannya di sisi Vercel.

Jadi Anda menambahkan function atau mengirim kiriman ke tempat lain. Vercel Function di api/contact.ts bisa dipakai, tetapi Anda lalu butuh API email, penyaringan spam, dan rate limit, dan Anda yang memeliharanya. Mengirim ke Ikiform menjaga deployment tetap statis. Perbaikan di HTML cukup satu atribut:

Sebelum
<form method="post">
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>
Sesudah
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">

Jika Anda lebih suka menulis function sendiri

Function adalah pilihan yang wajar jika pesan harus dikirim ke tempat yang hanya bisa dijangkau kode Anda. Hitung apa saja yang dibutuhkan sebelum mulai:

  • Akun penyedia email, domain pengirim yang terverifikasi, dan API key di environment variable Vercel.
  • Validasi di server, karena atribut required di browser hanya kemudahan, bukan pemeriksaan.
  • Penyaringan spam dan rate limit, atau formulir kontak yang mengirimi Anda email dari setiap bot di internet.
  • Tempat menyimpan pesan saat penyedia email sedang down, dan cara mengirim ulang.

Form backend menangani daftar itu untuk Anda. Jika Anda tetap ingin kode sendiri ikut terlibat, biarkan formulir mengirim ke Ikiform dan terima webhook bertanda tangan di sebuah function; server Anda sendiri menunjukkan handler-nya.

Satu ID formulir per environment Vercel

Setiap pull request di Vercel mendapat deployment preview. Jika preview mengirim ke formulir production, setiap pesan uji masuk ke inbox Anda di samping pesan asli. Buat formulir Ikiform kedua untuk preview, dan biarkan environment variable Vercel yang memilih. Di Settings โ€บ Environment Variables, tambahkan nama yang sama dua kali:

Environment variable Vercel
VITE_IKIFORM_FORM_ID   Production   frm_xxxxxxxxxxxxxxxx
VITE_IKIFORM_FORM_ID   Preview      frm_yyyyyyyyyyyyyyyy

Vite mengganti placeholder %NAME% di index.html dengan variabel VITE_ saat build, jadi formulir HTML biasa bisa memakainya tanpa JavaScript. VITE_VERCEL_ENV diatur oleh Vercel untuk proyek Vite, dan mencatat dari deployment mana sebuah pesan berasal:

index.html
<form id="contact" action="https://ikiform.com/f/%VITE_IKIFORM_FORM_ID%" method="post">
  <label for="name">Name</label>
  <input id="name" name="name" autocomplete="name" required />

  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="6" minlength="10" required></textarea>

  <input type="hidden" name="build" value="%VITE_VERCEL_ENV%" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button type="submit">Send message</button>
</form>
  • Vercel membaca environment variable saat build untuk situs statis. Setelah mengubahnya, deploy ulang, atau nilai lama tetap ada di HTML.
  • Vite membiarkan placeholder apa adanya jika variabelnya tidak ada, jadi ID yang hilang ikut terkirim sebagai %VITE_IKIFORM_FORM_ID% dan setiap kiriman gagal dengan 400 Bad Request sebelum mencapai formulir. Pengaman di bawah menangkap hal itu.
  • ID formulir tetap publik bagaimanapun juga. Hanya variabel VITE_ yang sampai ke browser, itulah sebabnya rahasia tidak boleh disimpan di sana.
src/contact.js
const form = document.querySelector("#contact");

if (form && form.action.includes("%VITE_")) {
  console.error("VITE_IKIFORM_FORM_ID is not set for this Vercel environment");
  form.querySelector("button").disabled = true;
}

Memakai Next.js dengan output: "export"? Baca process.env.NEXT_PUBLIC_IKIFORM_FORM_ID di client component; panduan utama punya formulir untuk static export. Jika aplikasi Next.js Anda memang berjalan di server Vercel, Server Action bisa mengirim dengan secret key: lihat panduan Next.js.

Header dan URL bersih

Jika situs Anda mengatur Content-Security-Policy, atur di vercel.json dan sertakan Ikiform. cleanUrls menyajikan thanks.html di /thanks, yang menjadi tujuan redirect yang lebih rapi:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "cleanUrls": true,
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Content-Security-Policy",
          "value": "default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
        }
      ]
    }
  ]
}

Preview dan domain yang diizinkan

URL preview seperti your-project-git-branch-team.vercel.app bukan subdomain dari your-project.vercel.app, jadi tidak cocok di Allowed domains. Kiriman dari sana masuk ke spam dengan origin_mismatch. Itu alasan lain untuk memakai formulir preview terpisah: biarkan domain yang diizinkannya kosong, atau tambahkan host preview yang sedang Anda uji.

Dengan Vercel Authentication aktif dan cakupan Standard Protection, yang mencakup setiap deployment kecuali domain production, URL preview berada di balik login Vercel. Hanya tim Anda yang bisa mengaksesnya, jadi formulir preview tanpa domain yang diizinkan tidak terbuka untuk publik. Cek Settings โ€บ Deployment Protection sebelum mengandalkannya. Kiriman dari preview bukan uji localhost, jadi dihitung terhadap paket Anda seperti kiriman live lainnya.

Pastikan berfungsi

  1. Jalankan curl di atas terhadap URL production Anda sebelum perbaikan, dan pastikan hasilnya 405. Setelah perbaikan, action formulir di HTML yang di-deploy diawali https://ikiform.com/f/.
  2. Buka deployment preview, kirim, dan pastikan pesannya masuk ke formulir preview, bukan formulir production.
  3. Kirim di domain production Anda dan cek field build berisi production.
  4. Cek inbox setiap penerima notifikasi. Masing-masing mendapat email berisi field, dan Reply terkirim ke pengirim formulir jika formulir punya field email.
  5. Tidak ada yang masuk? Ubah filter status di dashboard ke Spam. Spam mendapat jawaban sukses yang sama dengan kiriman asli.

Hal yang sering menjebak

MasalahYang harus dilakukan
Masih 405 setelah mengubah formulirDeployment yang Anda uji dibangun sebelum perubahan, atau handler JavaScript mengirim ke path Anda sendiri dengan fetch. Cari /api/contact di file hasil build.
400 Bad Request di setiap kiriman, atau 404 not_found dari IkiformID formulir tidak sampai ke build, atau ID-nya salah untuk environment itu. Cek variabelnya ada untuk environment tersebut lalu deploy ulang.
Preview berfungsi, kiriman production masuk ke spamDomain production Anda tidak ada di Allowed domains formulir production. Tambahkan domain kustom serta your-project.vercel.app.
Browser mendarat di halaman terima kasih Ikiform, bukan halaman Anda_redirect diabaikan kecuali domainnya ada di Allowed domains dan berupa URL https:. Tambahkan domainnya, atau atur Redirect after submit di pengaturan formulir sebagai gantinya.

Pertanyaan

Mentok di salah satu langkah, atau ingin panduan untuk situasi Anda? Email hello@ikiform.com.