Why is axios not sending the correct post data? - javascript

Why is PHP saying "undefined index request"? The json format looks completely correct to me.
let json = JSON.stringify(
{ request: "getUser" },
{ username: "test" }
);
const response = await axios.post('http://localhost/projects/serverFiles/index.php', json);
My PHP
<?php
ini_set("log_errors", 1);
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
echo print_r($_POST["request"]);
?>

Related

Posting nested JSON to WordPress Admin Ajax - can't access object data

I'm trying to mock a payload my WordPress webhook will be receiving once an integration is setup. The payload will contain nested JSON. I've not been able to access data in the JSON object in my PHP function.
This is the structure of the payload I can expect:
data: {
attributes: {
user_name: "John Doe",
user_email: "johndoe#xyz.com"
}
}
Here's my JavaScript that's attempting to POST the same data:
fetch(wp_ajax.ajax_url, {
method: 'POST',
body: new URLSearchParams({
action: 'course_signup',
data: {
attributes: {
user_name: "John Doe",
user_email: "johndoe#xyz.com"
}
}
})
})
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.log(err));
Here's my PHP:
<?php
add_action('wp_ajax_course_signup', 'course_signup');
add_action('wp_ajax_nopriv_course_signup', 'course_signup');
function course_signup()
{
$data = json_decode($_POST['data']);
$user_name = $data['attributes']['user_name'];
$user_email = $data['attributes']['user_email'];
$data = $_POST['data'];
echo json_encode(array(
"action" => $_POST["action"],
"user_name" => $user_name,
"user_email" => $user_email
));
die();
}
Here's the response of my console.log(response)):
{
action: "course_signup",
user_email: null,
user_name: null
}
In the Network tab for the POST request I see the payload as:
action: course_signup
data: [object Object]
Thanks CBroe,
Using Postman helped simplify this.
I updated my PHP to the following which allowed me to access the data I wanted:
$payload = json_decode(file_get_contents('php://input'), true);
$user_name = $payload['data']['attributes']['user_name'];
$user_email = $payload['data']['attributes']['user_email'];

Adding http response code in php breaks axios

After adding http response code in the login file axios is returning these errors even if the login email and password are correct and the catch block isn't executed I get these errors. If I remove the http_response_code(400) it will work and return the user or the message with 200 ok but I don't want that.
How do i fix it? thanks in advance.
Access to XMLHttpRequest at 'http://localhost/classroom-api/api/user/login.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.
POST http://localhost/classroom-api/api/user/login.php net::ERR_FAILED
login.php
<?php
// Headers
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods, Authorization, X-Requested-With');
require_once '../../vendor/autoload.php';
use Firebase\JWT\JWT;
require_once '../../config/Database.php';
require_once '../../models/User.php';
// Connect db
$database = new Database();
$db = $database->connect();
$user = new User($db);
try {
// Get posted data
$data = json_decode(file_get_contents("php://input"));
if(empty($data->email) || empty($data->password)) {
throw new Exception("Please enter all fields");
}
$user->email = $data->email;
$user->password = $data->password;
if ($user->login()) {
// Create token
$key = 'ajdZiWodDaAs1123';
$iat = time();
$payload = [
'iss' => 'localhost',
'aud' => 'localhost',
'iat' => $iat,
'nbf' => $iat,
'exp' => $iat + 259200000, // 3 days
'data' => [
"id" => $user->id
]
];
$token = JWT::encode($payload, $key, 'HS256');
echo json_encode(
array(
"id" => $user->id,
"full_name" => $user->fname ." ".$user->lname,
"email" => $user->email,
"token" => $token
)
);
} else {
throw new Exception("Invalid credentials");
}
} catch (Exception $e) {
http_response_code(400);
echo json_encode(
array('message' => $e->getMessage())
);
}
?>
axios
import axios from 'axios';
const base_url = 'http://localhost/classroom-api';
const route = '/api/user';
export const login = async (userData) => {
const res = await axios.post(base_url + route + '/login.php', userData);
console.log(res);
};
although it does work in postman
Browsers will first send an OPTIONS request to check for CORS headers.
Add this right after the headers:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS')
exit('ok');

How to send a response in PHP to a request made through the javascript fetch API?

I have an application in PHP, which receives data from the client that is in another domain. Data arrives from the fetch API via the POST method, but PHP doesn't send a response to the fetch API.
foo.com/endpoint.php:
<?php
include_once('database/connection.php');
header('Content-Type: application/json');
$ip = $_POST["ip"];
$city = $_POST["city"];
$state = $_POST["state"];
$country = $_POST["country"];
$category = $_POST["category"];
// Checking if the req ip already have registered other req
$ip_query = "SELECT * FROM registers WHERE `ip` = '$ip'";
$ip_result = mysqli_query($conn, $ip_query);
$ip_check = mysqli_fetch_assoc($ip_result);
if (!$ip_check) {
// registering data after validation
$new_query = "INSERT INTO `registers` (`ip`, `city`, `state`, `country`, `category`, `created`) VALUES ('$ip', '$city', '$state', '$country', '$category', '2022-07-21 00:00:01')";
$new_create = mysqli_query($conn, $new_query);
$result = array(
'ok' => true,
'status' => 200
);
// sending response
http_response_code(200);
echo json_encode($result);
} else {
// sending response if already registered
http_response_code(503);
}
Client side fetch code:
fetch(this.url, {
method: 'POST',
mode: 'no-cors',
body: this.getFormValues(),
headers: {
"Accept": "application/json",
'Content-Type': 'application/json'
}
})
.then(resp => resp.json())
.then(data => {
console.log(data)
if (data.ok) {
this.Metrics.setSent()
} else {
throw Error(r.statusText)
}
})
.then(() => {
this.Metrics.setSent()
this.Metrics.dismiss()
})
.catch(erro => {
console.log("Erro: ",erro)
this.Metrics.dismiss()
});
It's all right about storing data, my problem is just sending the response :(
PHP does not parse the POST body into JSON automatically. To fix this, you have to add json_decode() to your code like this:
$ip = json_decode($_POST, true)["ip"];
I hadn't noticed that when making a request using the "no-cors" mode i'd get an opaque response.
I just added the code below to the beginning of my PHP file, changed the fetch mode to "cors" and everything worked as it was supposed to work:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');
header("Access-Control-Allow-Credentials: true");
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization") ;
header("HTTP/1.1 200 OK");
die();
}
I made the adaptations suggested by #brrrrrrr and updated the queries to prevent SQL injections.
Thx everyone.

Decompress GZIP string response from a PHP server in NodeJS

I have an existing PHP code that is doing a curl request to a 3rd-party PHP server.
The 3rd-party server returns a GZIP string.
In PHP, I can use gzdecode to decode the gzip string.
How can I do it in NodeJS/Javascript? I tried using decompress-response with no avail.
Also tried using got instead of request, enabled auto-decompress, also doesn't work.
Edit: Also tried zlib and pako, also doesn't work.
Sample Code [ PHP ]
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $params,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 3000000,
CURLOPT_ENCODING => '',
CURLOPT_CUSTOMREQUEST => "GET",
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo false;
} else {
$response = gzdecode($response);
echo $response;
}
This is the solution that works for me.
I used got instead of axios because I can't get it to work there.
I set my request options:
const requestOptions = {
encoding: null, // this is important
headers: {
"Accept-Encoding": "gzip",
}
...
};
Don't forget that encoding: null line, because without that, the response will be automatically converted to a string. ( We need a buffer to make this work )
Then I created a function like this to handle my request:
const zlib = require("zlib");
async function performRequest(url, options) {
try {
const response = await got(url, options);
if (response.headers["content-encoding"] === "gzip") {
const body = response.body;
try {
const dezziped = zlib.gunzipSync(response.body);
response.body = JSON.parse(dezziped.toString());
} catch (error) {
response.body = body;
}
}
return response.body;
} catch (error) {
return error;
}
}
Note: This is a synchronous operation, you can use gunzip instead if you want to do the async way.

Why am I getting a JSON error related to content type in my ajax request?

I'm getting the following error when trying to make an ajax request (with Angularjs) to my PHP API.
SyntaxError: Unexpected token n in JSON at position 24
I'd appreciate any help. Thanks
Here is my Angular JS code:
var data = {"username":"sarahexample", "password":"5f4dcc3b5aa765d61d8327deb882cf99"};
$http({
method: 'POST',
url: 'http://localhost/API/auth',
data : JSON.stringify(data)
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
And here is the PHP auth function which executes when that endpoint is requested.
protected function auth($parameters) {
if ($this->method == 'POST') {
//echo the POST data back to the client side to test it's working
//This works when I take out the php Content-Type header
echo json_encode($_POST);
} else {
//echo "Only accepts POST requests";
}
}
In my PHP API I have the following header (which when taken out everything works fine however I'd like it to work with the header).
header("Content-Type: application/json");
I tried leaving in the above header and also adding in contentType: 'application/json' in the ajax request as follows (however this did not solve the JSON error):
$http({
method: 'POST',
url: 'http://localhost/API/auth',
contentType: 'application/json',
data : JSON.stringify(data)
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
In the Network tab in the console:
Request URL:http://localhost/API/auth
Request Method:POST
Status Code:200 OK
Remote Address:[::1]:80
Referrer Policy:no-referrer-when-downgrade
Response Headers
view source
Access-Control-Allow-Methods:*
Access-Control-Allow-Origin:*
Connection:Keep-Alive
Content-Length:6
Content-Type:application/json
Date:Thu, 28 Sep 2017 17:17:31 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.27 (Win64) PHP/5.6.31
X-Powered-By:PHP/5.6.31
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:73
Content-Type:application/json
Host:localhost
Origin:http://localhost
Pragma:no-cache
Referer:http://localhost/phonegap_tut/
Request Payload
view source
{username: "sarahexample", password: "5f4dcc3b5aa765d61d8327deb882cf99"}
password
:
"5f4dcc3b5aa765d61d8327deb882cf99"
username
:
"sarahexample"
I discovered why the error was occuring. There was a combination of a few things.
Firstly there was a silly mistake on my part where I was echoing the data twice by accident:
I have a class called MyAPI.php which contains the auth method. I was echoing the data from here when I should have been returning it as it gets echoed again in another script called api.php. This was adding a null onto the end of the JSON data that the server returned.
So here's my new auth function:
protected function auth($parameters) {
if ($this->method == 'POST') {
//need to get the POST data this way because we have the Content-Type header set to application/json, so $_POST will no longer be populated
$rawPostData = file_get_contents('php://input');
//return the data because we will echo it from the api.php script
return $rawPostData;
}else{
$errorMessage = array("error" => "Only accepts POST requests");
return json_encode($errorMessage);
}
}
And here is the script called api.php which echos the result.
<?php
require_once 'MyAPI.class.php';
try {
$API = new MyAPI($_REQUEST, $_SERVER['HTTP_ORIGIN']);
echo $API->processAPI();
} catch (Exception $e) {
echo json_encode(Array('error' => $e->getMessage()));
}
?>
Now another thing. I needed to add responseType:'json' to the ajax request as follows:
var data = {"username":"sarahexample","password":"5f4dcc3b5aa765d61d8327deb882cf99"};
$http({
method: 'POST',
url: 'http://localhost/API/auth',
data : JSON.stringify(data),
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
responseType:'json'
}).then(function successCallback(response) {
console.log('success');
if(response.data.hasOwnProperty('error')){
console.log(response.data.error);
}else{
console.log(response.data.username);
}
}, function errorCallback(response) {
console.log("error");
console.log(response);
});
Right way to do this is check your JSON output before echo.
// Check if your JSON conversion succeed
$json = json_encode($_POST);
if ($json === false) {
// JSONify the error message:
$json = json_encode(array("jsonError", json_last_error_msg()));
if ($json === false) {
// This should not happen, but we go all the way now:
$json = '{"jsonError": "unknown"}';
}
// Set HTTP response status code to: 500 - Internal Server Error
http_response_code(500);
}
echo $json;

Categories