J'essaie de créer un panneau d'administration (opérations CRUD) pour un site Web. Je crée d'abord le point de terminaison de l'API, puis je l'héberge sur mon sous-domaine. Je reçois maintenant des données de ce point de terminaison. Afficher tous les contacts (GET), les contacts individuels (GET) et ajouter de nouveaux contacts (POST) fonctionne très bien, mais je suis bloqué pendant des jours sur la mise à jour des contacts (PUT).
Les formulaires pré-remplis fonctionnent bien. Lorsque je soumets les données, j'obtiens l'erreur suivante :
Access to XMLHttpRequest at 'https://api.itisgoodtohave.me/contacts/update.php' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status. PUT https://api.itisgoodtohave.me/contacts/update.php net::ERR_FAILED Uncaught (in promise) AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
update.php
:
<?php header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Headers: *"); header("Access-Control-Allow-Methods: *"); include 'DbConnection.php'; $objDb = new DbConnection; $conn = $objDb->connect(); $method = $_SERVER['REQUEST_METHOD']; if ($method = "POST") { $contact = json_decode(file_get_contents('php://input')); $sql = "UPDATE contacts SET name=:name, email=:email, phone=:phone WHERE id=:id"; $stmt = $conn->prepare($sql); $stmt->bindParam(':id', $contact->id); $stmt->bindParam(':name', $contact->name); $stmt->bindParam(':email', $contact->email); $stmt->bindParam(':phone', $contact->phone); if ($stmt->execute()) { $response = ['status' => 1, 'message' => "Contact updated sucessfully."]; } else { $response = ['status' => 0, 'message' => "Could not update contact."]; } echo json_encode($response); } else { echo "some error occured"; }
EditContact.js
import React from 'react'; import axios from 'axios'; import { useState, useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; export default function EditContact() { const [inputs, setInputs] = useState([]) const navigate = useNavigate(); const { id } = useParams(); useEffect(() => { showContact(); }, []) function showContact() { axios.get(`https://api.mywebsite.com/contacts/single_read.php/?id=${id}`) .then(function(response) { setInputs(response.data); }) } const handleChange = (event) => { const name = event.target.name; const value = event.target.value; setInputs(values=> ({...values, [name]: value})); console.log(inputs) } const handleSubmit = (event) => { event.preventDefault(); axios.put('https://api.mywebsite.com/contacts/update.php', inputs) .then(function(response){ console.log(response) navigate('/admin/contacts') }) } return ( <div> <h3>Edit Contact</h3> <form onSubmit={handleSubmit}> <label>Name</label> <input defaultValue={inputs.name} type="text" name="name" onChange={handleChange} /> <br /> <label>Email</label> <input defaultValue={inputs.email} type="text" name="email" onChange={handleChange} /> <br /> <label>Phone</label> <input defaultValue={inputs.phone} type="text" name="phone" onChange={handleChange} /> <br /> <button type="submit">Save</button> </form> </div> ) }
J'ai essayé tous les points de terminaison dans Postman. Tous (GET, POST, PUT, DELETE) fonctionnent. Ces entrées ont été mises à jour dans ma base de données.
Après des heures de recherche sur CORS sur Google, de réécriture de mon code, etc., je n'arrive tout simplement pas à comprendre. Je suis assez nouveau dans le codage, mais il me semble illogique que POST fonctionne mais pas PUT (ou il me manque une logique de base ici).
Je serais heureux si quelqu'un pouvait suggérer de nouvelles idées. J'ai hâte d'apprendre :)
Postman est un client HTTP, pas un navigateur. CORS fonctionne dans les navigateurs, les clients HTTP ignoreront donc ces en-têtes. Il est donc parfaitement logique que vous n'ayez aucun problème à appeler l'API à l'aide de Postman.
La partie importante du message d'erreur est
对预检请求的响应未通过访问控制检查:它没有 HTTP 正常状态
. Preflight request est une requête HTTP avec la méthode OPTIONS. Vous pouvez traiter cela comme une demande de reconnaissance pour vérifier si d'autres demandes sont autorisées (Voir la documentation MDN). Cette erreur indique que la réponse à cette requête OPTIONS n'était pas un HTTP 200. La solution ici est de garantir que la requête OPTIONS entraînera un HTTP 200 avec tous les en-têtes CORS définis.