How to receive Fetch() POST in php? - javascript

So i got this POST json method here, but can't understand how to get my json data
It's packed in BLOB which is packed in FormData
How to receive such POST in php? (and convert this FormData(Blob) back to json?)
JS
const data = new FormData();
const jsonBlob = new Blob([JSON.stringify(myJSON)], {type: "application/json"});
data.append("data", jsonBlob);
fetch(website,{
method: "POST",
body: data,
}).then(resp=>{
if(!resp.ok){
const err = new Error("Error response");
err.resp = resp;
throw err;
}
console.log("OK");
}).catch(err =>{
console.error(err);
})
I'm big noobo, so i can't even receive it
Seems like it works differently with fetch()
PHP
if(isset($_POST['data'])){
}

The simpliest way to send a JSON to server is to simply send it as the POST request body. There is no need to wrap it like a file. For example,
var myJSON = {
hello: 'world',
foo: 'bar',
};
fetch(website, {
method: "POST",
body: JSON.stringify(myJSON),
})
On server side, your message will be readable through the "php://input" stream. You can read it like an ordinary file:
$request_raw = file_get_contents('php://input');
$json_object = json_decode($request_raw);
You can save the below code as a PHP file and test it yourself. On load, it would send itself another POST reqeust, parse it as key-value pairs, return it to your browser and show it:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$request_raw = file_get_contents('php://input');
$request = json_decode($request_raw);
foreach ($request as $key => $value) {
echo "{$key}: {$value}\n";
}
exit;
}
?>
<div id="result"></div>
<script>
var myJSON = {
hello: 'world',
foo: 'bar',
};
const data = new FormData();
fetch(document.location.href, {
method: "POST",
body: JSON.stringify(myJSON),
}).then(resp => {
if(!resp.ok){
const err = new Error("Error response");
err.resp = resp;
throw err;
}
console.log("OK");
return resp.text();
}).catch(err =>{
console.error(err);
}).then(body => {
document.getElementById('result').innerText = body;
});
</script>

Related

Sending data with fetch. How to include variable in body [duplicate]

I know that with the new Fetch API (used here with ES2017's async/await) you can make a GET request like this:
async getData() {
try {
let response = await fetch('https://example.com/api');
let responseJson = await response.json();
console.log(responseJson);
} catch(error) {
console.error(error);
}
}
But how do you make a POST request?
Long story short, Fetch also allows you to pass an object for a more personalized request:
fetch("http://example.com/api/endpoint/", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
//make sure to serialize your JSON body
body: JSON.stringify({
name: myName,
password: myPassword
})
})
.then( (response) => {
//do something awesome that makes the world a better place
});
Check out the fetch documentation for even more goodies and gotchas:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Please note that since you're doing an async try/catch pattern, you'll just omit the then() function in my example ;)
if you want to make a simple post request without sending data as JSON.
fetch("/url-to-post",
{
method: "POST",
// whatever data you want to post with a key-value pair
body: "name=manas&age=20",
headers:
{
"Content-Type": "application/x-www-form-urlencoded"
}
}).then((response) =>
{
// do something awesome that makes the world a better place
});
The best way to POST form data to a PHP-script is the Fetch API. Here is an example:
function postData() {
const form = document.getElementById('form')
let data = new FormData()
data.append('name', form.name.value)
fetch('../php/contact.php', {
method: 'POST',
body: data,
}).then(response => {
if (!response.ok) {
throw new Error('Network response was not ok.')
}
}).catch(console.error)
}
<form id="form" action="javascript:postData()">
<input id="name" name="name" placeholder="Name" type="text" required>
<input type="submit" value="Submit">
</form>
Here is a very basic example of a PHP-script that takes the data and sends an email:
<?php
header('Content-type: text/html; charset=utf-8');
if (isset($_POST['name'])) {
$name = $_POST['name'];
}
$to = "test#example.com";
$subject = "New name submitted";
$body = "You received the following name: $name";
mail($to, $subject, $body);
2021 answer: just in case you land here looking for how to make GET and POST Fetch api requests using async/await or promises as compared to axios.
I'm using jsonplaceholder fake API to demonstrate:
Fetch api GET request using async/await:
const asyncGetCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncGetCall()
Fetch api POST request using async/await:
const asyncPostCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
});
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncPostCall()
GET request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
POST request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
})
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
GET request using Axios:
const axiosGetCall = async () => {
try {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosGetCall()
POST request using Axios:
const axiosPostCall = async () => {
try {
const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts', {
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosPostCall()
Here is a solution for a POST request using node-fetch, with async/await.
async function post(data) {
try {
// Create request to api service
const req = await fetch('http://127.0.0.1/api', {
method: 'POST',
headers: { 'Content-Type':'application/json' },
// format the data
body: JSON.stringify({
id: data.id,
foo: data.foo,
bar: data.bar
}),
});
const res = await req.json();
// Log success message
console.log(res);
} catch(err) {
console.error(`ERROR: ${err}`);
}
}
// Call your function
post() // with your parameter of Course
Here is a complete example: After spending hours tinkering with incomplete code snippets I finally managed to post some json from javascript, pick it up using php on a server, added a data field and finally updated the original web page. Here is the HTML, the PHP and the JS. My thanks to everyone who posted the original code fragments collected here. Similar code is on-line here: https://www.nbest.co.uk/Fetch/index.php
<!DOCTYPE HTML>
<!-- Save this to index.php and view this page in your browser -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Javascript Fetch Example</title>
</head>
<body>
<h1>Javascript Fetch Example</h1>
<p>Save this to index.php and view this page in your browser.</p>
<button type="button" onclick="myButtonClick()">Press Me</button>
<p id="before">This is the JSON before the fetch.</p>
<p id="after">This is the JSON after the fetch.</p>
<script src="fetch.js"></script>
</body>
</html>
<!-- --------------------------------------------------------- -->
// Save this as fetch.js --------------------------------------------------------------------------
function success(json) {
document.getElementById('after').innerHTML = "AFTER: " + JSON.stringify(json);
console.log("AFTER: " + JSON.stringify(json));
} // ----------------------------------------------------------------------------------------------
function failure(error) {
document.getElementById('after').innerHTML = "ERROR: " + error;
console.log("ERROR: " + error);
} // ----------------------------------------------------------------------------------------------
function myButtonClick() {
var url = 'json.php';
var before = {foo: 'Hello World!'};
document.getElementById('before').innerHTML = "BEFORE: " + JSON.stringify(before);
console.log("BEFORE: " + JSON.stringify(before));
fetch(url, {
method: 'POST',
body: JSON.stringify(before),
headers:{
'Content-Type': 'application/json'
}
}).then(res => res.json())
.then(response => success(response))
.catch(error => failure(error));
} // ----------------------------------------------------------------------------------------------
<?php
// Save this to json.php ---------------------------------------
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
if ($contentType === "application/json") {
$content = trim(file_get_contents("php://input"));
$decoded = json_decode($content, true);
$decoded['bar'] = "Hello World AGAIN!"; // Add some data to be returned.
$reply = json_encode($decoded);
}
header("Content-Type: application/json; charset=UTF-8");
echo $reply;
// -------------------------------------------------------------
?>
In this article, I described about the Second Parameter of fetch().
For submit JSON data
const user = { name: 'Sabesan', surname: 'Sathananthan' };
const response = await fetch('/article/fetch/post/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(user)
});
For submit form
const form = document.querySelector('form');
const response = await fetch('/users', {
method: 'POST',
body: new FormData(form)
})
For file upload
const input = document.querySelector('input[type="file"]');
const data = new FormData();
data.append('file', input.files[0]);
data.append('user', 'foo');
fetch('/avatars', {
method: 'POST',
body: data
});

When axios posting an array of images I am getting a 500 error

Okay so i have some code where an user can upload Images. He can upload a multiple images. The thing is that when the user uploads the pictures and there is a request sent to the server I get a 500 error code.
The code:
ChangeImages(images) {
this.images = images;
console.log("imagesEmit", this.images);
console.log(this.step);
console.log("images", images);
console.log("thishome", this.home);
const formData = new FormData();
let id = this.homeId;
formData.append(
"data",
JSON.stringify({ file: this.images[0], position: 1 })
);
console.log(formData);
axios
.post(`/api/upload-home-picture/${id}`, formData, {
headers: { "Content-Type": "multipart/form-data" },
})
.then((response) => {
this.home.images[0].push(response.data);
});
},
So here as you see I am sending the request in a listener. I am gonna show the results in console.logs:
this.images:
```"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABsoA…wD3k6myVTczaWMZ5Ebv8P2lNvc037YOAAAAAASUVORK5CYII="`````
this.home:
funding_round_end: (...)
funding_round_start: (...)
funding_round_time: (...)
hpi_zip_avg_appreciation: (...)
id: (...)
images: (...)
info: (...)
interest: (...)
invest_now: (...)
Also the payload:
{"images":"data:image/png;base64,
And the backend code:
#bp.route('/upload-home-picture', methods=['POST'])
#login_required
def upload_home_picture():
# TODO test permission
data = json.loads(request.form['data'])
home_id = data['home']
home = UserHome.query.get(home_id)
url = _upload_file()
db.session.add(UserHomeImage(url=url, home=home, pos=0))
db.session.commit()
result = dict(url=url, pos=0)
return jsonify(result)
´´´
It is better to send an image without JSON.stringify.
onUpload() {
let formData = new FormData();
formData.append('file', this.images[0]);
axios.post(
`/api/upload-home-picture/${id}`
,formData
,{headers: {"Content-Type": "multipart/form-data"}}
)
.then((response) => {
this.home.images[0].push(response.data);
});
.catch(e => {
//...
})
}
And it will be easier to get it as a file in Python.

Formidable returns null and two empty objects even though I am passing the correct FormData File image

I have the following code that happens on submit of a form
data contains the File, and it console's just fine. When I pass it to formidable in next JS it returns empty objects for Field and Files, and can't seem to figure out why.
const formData = new FormData();
formData.append("image", data.picture[0], data.picture[0].name);
console.log(data.picture[0]);
console.log(formData);
console.log(formData.get("image"));
const res = await fetch("../api/image", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
import formidable from "formidable";
// first we need to disable the default body parser
export const config = {
api: {
bodyParser: false,
},
};
export default async function image(req, res) {
const form = new formidable.IncomingForm();
form.uploadDir = "./";
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
console.log(err);
console.log(fields);
console.log(files);
});
//console.log(form);
// cloudinary.uploader.upload(`${body}`, function (error, result) {
// console.log(result, error);
// });
try {
// const result = req.body;
res.status(200).send({ message: "hello world" });
} catch (error) {
console.error(error);
res.status(error.requestResult.statusCode).send(error.message);
}
}
Ended up using axios, no idea why it works over fetch, and I tried the content type change in fetch as well
var formData = new FormData();
formData.append("image", data.picture[0], data.picture[0].name);
axios.post('../api/image', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})

2 API Calls in One JavaScript

presently I am attempting to make 2 different api calls one after the other within 1 java/nodejs script. It seems after my first function runs successfully, the second one errors with the following:
FetchError: request to failed, reason: socket hang up;
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET'
Below is a code snippet of what I have tried thus far:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
//const express = require("express");
var apiName = "<LOCAL SYSTEM FILE TO UPLOAD>";
var lookupName = "<LOCAL SYSTEM FILE TO UPLOAD>";
var accessToken = "Bearer <ACCESS TOKEN>";
var url = '<URL API #1>';
var url2 = '<URL API #2>;
var headers = {
'Accept': 'application/json',
'Authorization': accessToken,
};
const form = new formData();
const buffer2 = fs.readFileSync(lookupName);
const buffer = fs.readFileSync(apiName);
const uploadAPI = function uploadAPI() {
form.append("Content-Type", "application/octect-stream");
form.append('file', buffer);
fetch(url, {method: 'POST', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
const uploadLookup = function uploadLookup() {
form.append("Content-Type", "application/octect-stream");
form.append('file', buffer2);
fetch(url2, {method: 'PUT', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
if (!apiName !== true) {
uploadAPI()
} else {}
if (!lookupName !== true) {
console.log("Uploading Lookup File");
uploadLookup()
} else {}
I tried using a "setTimeout" function which does not seem to work as I would have liked it to. My best guess is each API call would need to be it's own separate socket connection? Any help with getting me in the right direction is appreciated.
Promise.all([
fetch(url),
fetch(url2)
]).then(function (res) {
// Get a JSON object from each of the responses
return res.json();
}).then(function (data) {
// do something with both sets of data here
console.log(data);
}).catch(function (error) {
// if there's an error, log it
});

Retrieve data from external static JSON file and use in AWS Lambda

I am looking to pull some data from an external static JSON file based on an event sent to AWS Lambda.
So when someone sends their "customer_id" we pull the matching "email" and "option" from the external JSON file
https://3objects.netlify.com/3objects.json
Here is the code I have so far?
const AWS = require('aws-sdk');
const ses = new AWS.SES();
const request = require('request');
exports.handler = (event) => {
console.log(event.customer_id);
request({
url: 'https://3objects.netlify.com/3objects.json',
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
})
}, function (error, response) {
if (!error && response.statusCode == 200) {
var jsonResponse = JSON.parse(body); // turn response into JSON
// do stuff with the response and pass it back to Lambda...
});
// After JSON data retrieval of 'email' and 'option' from https://3objects.netlify.com/3objects.json we send them an email with this info
clientEmail = email;
contact_option = option;
var eParams = {Destination: {ToAddresses: [clientEmail]}, Message: {Body: { Text: { Data: 'Your contact option is ${contact_option}' },},Subject: { Data: "Your Contact Preference" }}, Source: "sales#example.com"};
var email = ses.sendEmail(eParams, function (err, data) { if (err) console.log(err); else { console.log("===EMAIL SENT==="); } });
};
How can I query and use that external JSON url data?
I prefer to using node-fetch. It is a package that let you use the fetch function from ES6.
I created an example of using node-fetch. The function getCustomers gets the customers from the url.
Then I created a function that returns a Promise. Inside this Promise, the retrieved data is send by mail using AWS.SES().
const AWS = require('aws-sdk'),
ses = new AWS.SES(),
fetch = require('node-fetch');
exports.handler = async (event) => {
console.log(event.customer_id);
const customers = await getCustomers();
customers.map(async customer => {
await sendEmailToCustomer(customer);
});
}
async function getCustomers() {
try {
const resp = await fetch('https://3objects.netlify.com/3objects.json');
const json = await resp.json();
console.log(json);
return json;
}
catch(e) {
throw e;
}
}
const sendEmailToCustomer = (customer) => new Promise((resolve, reject) => {
ses.sendEmail({
Destination:
{ ToAddresses: [customer.email] },
Message:
{
Body: { Text: { Data: `Your contact option is ${customer.customer_id}` }},
Subject: { Data: "Your Contact Preference" }
},
Source: "sales#example.com"}, (error, result => {
if (error) return reject(error);
resolve(result);
console.log(result);
})
}
In general, you should post the exact error you're facing instead of general question. it would help contributors to figure out the problem you're facing.
In your code snippet above, the part
// After JSON data retrieval of 'email' and 'option' from https://3objects.netlify.com/3objects.json we send them an email with this info
clientEmail = email;
contact_option = option;
var eParams = {Destination: {ToAddresses: [clientEmail]}, Message: {Body: { Text: { Data: 'Your contact option is ${contact_option}' },},Subject: { Data: "Your Contact Preference" }}, Source: "sales#example.com"};
var email = ses.sendEmail(eParams, function (err, data) { if (err) console.log(err); else { console.log("===EMAIL SENT==="); } });
is executed before the request returns. You need to move that code inside your callback to execute it when the request finishes.
I also would suggest you to convert your code to async/await for better readability and avoid this type of error.
See this article to learn how to do that : https://www.stormacq.com/2019/06/22/async-js.html

Categories