Reputation: 33
I am trying to make an admin panel for a website (CRUD operations). I started by making API endpoints, which I then hosted on my subdomain. I am now fetching the data from that endpoint. Displaying all contacts (GET), single contacts (GET) and adding a new contact (POST) works fine, but I'm stuck for days now on updating a contact (PUT).
The pre-filled form works fine. When I submit data, I get the following errors:
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>
)
}
I've tried every endpoint in postman. All of them (GET, POST, PUT, DELETE) were working. And the entries were updated in my database.
After hours of googling on CORS, rewriting my code again etc, I just cant make sense. I am pretty new to coding, but for me it seems illogical that POST is working, but PUT isnt (or I am missing some basic logic here).
I would be happy if anyone could come up with a new idea. I am eager to learn :)
Upvotes: 1
Views: 659
Reputation: 895
I've tried every endpoint in postman. All of them (GET, POST, PUT, DELETE) were working. And the entries were updated in my database.
Postman is a HTTP client and not a browser. CORS is there for browsers so HTTP clients will just ignore these headers. So, it perfectly makes sense you have no issues when calling your API with Postman.
The important part of the error message is Response to preflight request doesn't pass access control check: It does not have HTTP ok status
. A preflight request is a HTTP request with the OPTIONS method. You can see this as a reconnaissance request to check if making further request is allowed (See the MDN docs). This error indicates that the response of this OPTIONS request is not HTTP 200. The solution here would be to make sure an OPTIONS request will result in a HTTP 200 with all CORS headers set.
Upvotes: 1