Formulário de contato em site estático6 min de leitura
Adicione um formulário de contato a um site estático no Amazon S3
Endpoints de site do S3 só aceitam GET e HEAD via HTTP simples, então envie o formulário de contato para um backend de formulários e acerte os redirecionamentos com o CloudFront.
Um endpoint de site do S3 responde a um POST de formulário com 405 MethodNotAllowed, então aponte o action do formulário para o seu endpoint do Ikiform. Como o endpoint é http: simples, um _redirect de volta para ele nunca é seguido; defina Redirect after submit nas configurações do formulário, ou coloque o CloudFront na frente para ter https:. Com o CloudFront na frente do endpoint REST do bucket, redirecione para um nome de arquivo completo, como thanks.html, porque o default root object só vale para a raiz.
O que muda no S3
Um bucket configurado para hospedagem de site estático ganha o próprio endpoint de site, como http://www.example.com.s3-website-us-east-1.amazonaws.com. A AWS documenta que ele só suporta requisições GET e HEAD em objetos. Um envio de formulário recebe uma página de erro em HTML:
<html>
<head><title>405 Method Not Allowed</title></head>
<body>
<h1>405 Method Not Allowed</h1>
<ul>
<li>Code: MethodNotAllowed</li>
<li>Message: The specified method is not allowed against this resource.</li>
<li>Method: POST</li>
<li>ResourceType: OBJECT</li>Mais três características do S3 influenciam o formulário de contato:
| Característica do S3 | O que significa para o formulário |
|---|---|
| Endpoints de site não suportam HTTPS | O Ikiform só segue um _redirect para uma URL https:, então um redirecionamento de volta para o endpoint puro é ignorado |
| Os headers de resposta vêm do CloudFront, não do bucket | Uma Content-Security-Policy é definida numa response headers policy do CloudFront |
| O default root object do CloudFront só vale para a raiz | Com uma origem REST, https://example.com/thanks/ não carrega thanks/index.html; redirecione para thanks.html |
Para um site https:, a AWS recomenda o Amplify Hosting, que roda no CloudFront, ou o CloudFront na frente do bucket. O formulário funciona dos dois jeitos. O que muda é onde o visitante vai parar depois de enviar.
- No endpoint de site puro, a página é servida via http e envia ao Ikiform.
- O Ikiform armazena a mensagem, mas ignora um _redirect para um endereço http e mostra a página de agradecimento hospedada.
- Definir Redirect after submit no painel é o jeito de contornar isso, porque essa configuração aceita URLs http.
- Atrás do CloudFront com o seu próprio domínio, a página é https.
- O Ikiform segue o _redirect para o seu thanks.html, desde que o domínio esteja em Allowed domains.
Qual origem do CloudFront
O CloudFront pode ler do bucket de duas formas, e a escolha decide como deve ser a sua URL de agradecimento:
| Origem | Bucket | Páginas index de pastas | URL de agradecimento |
|---|---|---|---|
| O endpoint de site do S3, como origem personalizada | Precisa ter leitura pública | Funcionam: /thanks/ carrega thanks/index.html | /thanks/ ou /thanks.html |
| O endpoint REST, com origin access control | Continua privado, lido só pelo CloudFront | Só na raiz, pelo default root object | /thanks.html, um nome de arquivo completo |
Um nome de arquivo completo funciona com as duas, e é por isso que os exemplos usam um. Se você prefere não administrar o CloudFront, o Amplify Hosting pode fazer o deploy a partir do bucket com https: e uma CDN gerenciada; o formulário também não precisa de mudança lá.
O formulário
Sites no S3 costumam ser sites de empresas, então este formulário pede um e-mail de trabalho e o nome da empresa. Envie-o como contact.html ao lado de thanks.html:
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<label for="name">Name</label>
<input id="name" name="name" autocomplete="name" required />
<label for="email">Work email</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<label for="company">Company</label>
<input id="company" name="company" autocomplete="organization" />
<label for="message">How can we help?</label>
<textarea id="message" name="message" rows="6" minlength="10" required></textarea>
<input type="hidden" name="_redirect" value="https://www.example.com/thanks.html" />
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button type="submit">Send</button>
</form>- O
_redirectaponta para o domínio do CloudFront, com um nome de arquivo. Ele só é seguido quandowww.example.comouexample.comestá em Allowed domains. - No endpoint
http:puro, remova o input_redirecte defina Redirect after submit com a página de agradecimento. Essa configuração aceita URLshttp:, porque só a sua equipe pode mudá-la. - Mantenha
emailcomo nome do campo. Os e-mails de notificação o usam como endereço de reply-to.
Num site de empresa, geralmente mais de uma pessoa lê a caixa de entrada de contato. Adicione até 10 destinatários de notificação confirmados ao formulário; cada um recebe a mensagem, e quem clicar em Reply responde direto ao remetente. Se as mensagens também devem chegar a um canal compartilhado ou a uma fila de tickets, adicione um webhook assinado e direcione-o pelo Zapier ou pelo seu próprio código. O campo company chega como texto simples, então já está pronto para filtrar em qualquer um dos dois lugares.
Antes de subir, teste a página a partir de um servidor local com localhost em Allowed domains. Envios de localhost contam como testes, então você pode acertar o formulário antes de o bucket servi-lo.
Sincronize a pasta com o bucket e invalide as páginas no CloudFront para o novo formulário ser servido na hora:
aws s3 sync ./site s3://www.example.com --delete
aws cloudfront create-invalidation --distribution-id E1EXAMPLE --paths "/contact.html" "/thanks.html"Domínios permitidos em hosts da AWS
| Onde a página é servida | Adicione |
|---|---|
| Endpoint de site puro | O host completo do endpoint do bucket, como www.example.com.s3-website-us-east-1.amazonaws.com |
| Domínio padrão do CloudFront | O host exato d111111abcdef8.cloudfront.net, enquanto você testa |
| Seu próprio domínio | example.com, que também cobre www.example.com |
Nunca adicione amazonaws.com, um sufixo regional s3-website ou cloudfront.net sozinhos. Todo bucket ou distribuição do mundo passaria a corresponder. A AWS registra os domínios de endpoint de site do S3 na Public Suffix List pelo mesmo motivo: cada bucket é um site separado.
Headers pelo CloudFront
Os metadados de objetos do S3 não conseguem definir uma Content-Security-Policy, então defina-a numa response headers policy do CloudFront e anexe-a ao default cache behavior da distribuição. O valor do header é limitado a 1.783 caracteres:
{
"Name": "site-csp",
"SecurityHeadersConfig": {
"ContentSecurityPolicy": {
"Override": true,
"ContentSecurityPolicy": "default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
}
}
}aws cloudfront create-response-headers-policy --response-headers-policy-config file://csp-policy.jsonOverride: true substitui qualquer CSP que a origem envie. Com uma origem S3 pura não existe nenhuma, mas isso mantém a policy no controle se você trocar de origem depois.Confira se funciona
- Adicione os domínios da tabela acima, mais
localhostenquanto testa. - Envie a partir do seu domínio do CloudFront. Você deve cair em
thanks.htmlno seu próprio domínio. - Se você também mantém o endpoint de site puro público, envie a partir dele e confirme que chega à página definida em Redirect after submit.
- Abra Submissions no painel. O novo envio está lá com todos os campos que você enviou.
- Confira a caixa de entrada de cada destinatário das notificações. Cada um recebe um e-mail com os campos, e Reply vai para quem enviou quando o formulário tem um campo
email. - Não chegou nada? Mude o filtro de status do painel para Spam. Spam recebe a mesma resposta de sucesso de um envio real.
Pegadinhas
| Problema | O que fazer |
|---|---|
405 Method Not Allowed com Code: MethodNotAllowed | O formulário enviou para o bucket. O CloudFront ainda pode estar servindo o contact.html antigo; invalide-o. |
AccessDenied ou 403 depois do redirecionamento | O redirecionamento aponta para uma pasta como /thanks/ numa distribuição do CloudFront com origem REST. Aponte para thanks.html. |
| O navegador cai na página de agradecimento do Ikiform em vez da sua | O _redirect é ignorado, a menos que o domínio dele esteja em Allowed domains e ele seja uma URL https:. Adicione o domínio, ou defina Redirect after submit nas configurações do formulário. |
403 origin_not_allowed, ou todo envio cai no spam | O domínio da página não está em Allowed domains do formulário. Adicione-o, mais localhost para testes locais. Subdomínios de um domínio listado são permitidos. |
Perguntas
Não. Endpoints de site do S3 só suportam requisições GET e HEAD, então um POST recebe 405 MethodNotAllowed. Aponte o formulário para um backend de formulários, ou construa uma API com Lambda.
Não. O formulário também envia ao Ikiform a partir de uma página http. O CloudFront dá https, o que permite ao Ikiform seguir um _redirect de volta para a sua própria página de agradecimento.
Funciona e mantém tudo na AWS, mas você mesmo constrói a validação, o filtro de spam, o armazenamento e as novas tentativas, e o SES exige um remetente verificado. Um backend de formulários dá menos manutenção para um formulário de contato.
Pode manter, até a cópia em cache expirar. Invalide o contact.html depois de cada mudança, ou suba o HTML com um Cache-Control max-age curto para que os novos formulários entrem no ar rápido.
Não, não há plano gratuito. Testar é grátis: você pode enviar 50 envios de teste por mês a partir de localhost antes de pagar. Para entrar no ar, o Pro começa em US$ 6/mês para 500 envios, ou você pode pagar uma vez 10.000 envios por US$ 49 ou 50.000 envios por US$ 149, com créditos que nunca expiram.
Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.