# Formulaires HTML

> Envoyez n'importe quel formulaire HTML à Ikiform sans JavaScript : redirections, champs réservés, tableaux et honeypot.

Un simple formulaire HTML suffit à toute l'intégration. Pas de script, pas d'iframe, rien à intégrer : réglez l'`action` sur l'endpoint de votre formulaire et gardez votre markup et votre CSS. Cela fonctionne aussi dans les créateurs de sites qui permettent de coller du HTML personnalisé ; voir [Créateurs de sites](https://ikiform.com/fr/docs/guides/site-builders.md).

## Un formulaire de base

`contact.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label>
    Name
    <input name="name" autocomplete="name" required />
  </label>
  <label>
    Email
    <input name="email" type="email" autocomplete="email" required />
  </label>
  <label>
    Message
    <textarea name="message" rows="5"></textarea>
  </label>
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>
```

- `method` doit valoir `post`. Le navigateur envoie `application/x-www-form-urlencoded`, ou `multipart/form-data` si vous définissez `enctype`. Les deux fonctionnent.
- Chaque contrôle doté d'un `name` devient un champ. Le navigateur n'envoie pas les contrôles sans nom ni les contrôles désactivés.
- Les valeurs sont stockées en texte UTF-8, normalisées en NFC, avec les fins de ligne CRLF converties en LF et les caractères de contrôle supprimés.
- La validation du navigateur, comme `required` et `type="email"`, aide les gens, mais ce n'est pas un contrôle de sécurité. Définissez des [champs](https://ikiform.com/fr/docs/fields.md) pour qu'Ikiform applique des règles côté serveur.

## Après l'envoi

Un envoi réussi depuis un navigateur reçoit une redirection `303`. Ikiform choisit la cible dans cet ordre :

1. Le réglage **Redirect after submit** du formulaire dans le tableau de bord. N'importe quelle URL `http:` ou `https:` fonctionne ici, car seuls les membres de l'espace de travail peuvent la définir.
2. Un champ `_redirect` (ou `_next`) dans l'envoi, s'il respecte les règles ci-dessous.
3. Sinon, la page de remerciement hébergée par Ikiform à `/f/<formId>/thanks`. Si le formulaire a des domaines autorisés et que l'envoi vient d'une page `https:` sur l'un d'eux, la page renvoie un lien vers celle-ci.

### Règles pour _redirect

Une valeur `_redirect` vient du navigateur du visiteur, donc Ikiform ne la suit que si c'est une URL `https:` sans nom d'utilisateur, mot de passe ni port personnalisé, sur l'un des domaines autorisés du formulaire ou l'un de leurs sous-domaines. Les formulaires sans domaines autorisés ignorent complètement `_redirect`. Avec `example.com` comme domaine autorisé :

| _redirect | Suivie | Pourquoi |
| --- | --- | --- |
| `https://example.com/thanks` | Oui | Domaine autorisé |
| `https://app.example.com/done` | Oui | Sous-domaine d'un domaine autorisé |
| `http://example.com/thanks` | Non | Pas en `https:` |
| `https://example.com:8443/thanks` | Non | Port personnalisé |
| `https://user@example.com/` | Non | Contient un nom d'utilisateur |
| `https://example.com.evil.dev/` | Non | Ni le domaine ni l'un de ses sous-domaines |

Un `_redirect` qui n'est pas suivi mène à la page de remerciement hébergée ; il ne provoque jamais d'erreur. Les requêtes JSON ignorent les redirections et reçoivent `201` avec l'id de la soumission.

### Quand un envoi est refusé

Si un envoi est refusé, par exemple parce qu'un champ obligatoire manque, le navigateur affiche une page d'erreur hébergée avec le statut HTTP de l'erreur. Elle liste les problèmes par libellé de champ et renvoie vers le formulaire. Voir [Erreurs](https://ikiform.com/fr/docs/errors.md) pour tous les codes.

## Noms de champs et tableaux

Les noms répétés et les noms terminés par `[]` deviennent des tableaux. Utilisez `[]` pour les groupes de cases à cocher et `<select multiple>`, pour qu'un choix unique soit quand même stocké comme tableau.

`fields.html`:

```html
<fieldset>
  <legend>Topics</legend>
  <label><input type="checkbox" name="topics[]" value="billing" /> Billing</label>
  <label><input type="checkbox" name="topics[]" value="api" /> API</label>
</fieldset>

<select name="plan">
  <option value="starter">Starter</option>
  <option value="team">Team</option>
</select>

<label><input type="checkbox" name="newsletter" /> Send me product news</label>
```

Cocher les deux sujets et la case newsletter stocke :

`Champs stockés`:

```json
{
  "topics": ["billing", "api"],
  "plan": "team",
  "newsletter": "on"
}
```

- Les noms entre crochets comme `address[city]` sont gardés tels quels ; ils ne deviennent pas des objets imbriqués. Envoyez du JSON si vous voulez des valeurs imbriquées.
- Une case non cochée n'est pas envoyée du tout. Avec un [champ](https://ikiform.com/fr/docs/fields.md#types) `checkbox` défini, une case absente est stockée comme `false` et une case cochée comme `true`.
- Une soumission peut avoir jusqu'à 100 champs, des noms jusqu'à 128 caractères et des valeurs jusqu'à 16 Ko. Voir [Limites](https://ikiform.com/fr/docs/limits.md).

> L'envoi de fichiers n'existe pas encore. Un input de fichier vide est ignoré ; un envoi qui contient un vrai fichier est refusé avec `422 files_not_supported`.

## Champs réservés

Les noms qui commencent par `_` sont des instructions pour Ikiform. Ils ne sont jamais stockés comme réponses.

| Champ | Effet |
| --- | --- |
| `_gotcha` | Honeypot. Laissez-le vide et masqué ; une valeur remplie ajoute 5 au score de spam, ce qui suffit à stocker l'envoi comme spam. Le nom peut être changé par formulaire. |
| `_redirect`, `_next` | Où envoyer le navigateur après un envoi réussi. Voir [Règles pour _redirect](#redirect-rules). |
| `_subject` | Objet des e-mails de notification. Les espaces multiples sont réduits et il est tronqué à 200 caractères. |
| `_replyto` | Adresse de réponse des e-mails de notification. Ignorée sauf s'il s'agit d'une seule adresse e-mail valide. |
| `_idempotency` | Clé d'idempotence, équivalente à l'en-tête `Idempotency-Key`. Voir [Idempotence](https://ikiform.com/fr/docs/frameworks.md#idempotency). |
| `_ikiform_ts` | Heure d'affichage signée, définie par le SDK et le composant shadcn/ui. Un envoi effectué moins de 2 secondes après l'affichage est classé comme spam. |
| `cf-turnstile-response` | Le token Turnstile, ajouté par le widget Turnstile ou le SDK. |
| `_ikiform_via` | Défini par la page de vérification humaine d'Ikiform. Ne l'envoyez pas vous-même. |

Tout autre champ commençant par `_` est également retiré : vous pouvez utiliser des noms comme `_source` pour vos propres marqueurs masqués sans qu'ils soient stockés.

`demo.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="email" type="email" required />
  <input type="hidden" name="_subject" value="New demo request" />
  <input type="hidden" name="_redirect" value="https://example.com/thanks" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Request a demo</button>
</form>
```

## Le honeypot

Le nom par défaut du honeypot est `_gotcha`. Vous pouvez le changer par formulaire sous **Honeypot field** dans les paramètres du formulaire ; le nom choisi est traité comme réservé et jamais stocké. Un simple attribut `hidden` suffit pour la plupart des bots. Si du spam passe quand même, cachez plutôt l'input hors de l'écran, car certains bots ignorent les inputs marqués `hidden` :

`honeypot.html`:

```html
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden">
  <label>
    Leave this empty
    <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </label>
</div>
```

Gardez `tabindex="-1"` et `autocomplete="off"` pour que les utilisateurs au clavier et les gestionnaires de mots de passe ne le remplissent jamais.

## Ajouter une vérification humaine

Les formulaires dont le contrôle anti-spam est réglé sur **Ikiform** ne demandent aucun changement dans votre HTML. Quand un navigateur envoie sans token, Ikiform répond par une courte page « Checking you're human » sur ikiform.com. Elle exécute Cloudflare Turnstile, puis renvoie les champs d'origine avec le token. Votre visiteur arrive sur la même page de remerciement qu'avant. Voir [Protection anti-spam](https://ikiform.com/fr/docs/spam.md#human-check) pour le parcours complet.

### Avec vos propres clés Turnstile

Si le formulaire utilise **Your own Turnstile keys**, affichez le widget vous-même. Il ajoute le champ `cf-turnstile-response` à l'envoi. Les envois sans token valide sont refusés avec `403 captcha_failed`.

`turnstile.html`:

```html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="email" type="email" required />
  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
  <button>Send</button>
</form>
```
