Make HTTP request to web API using regular JavaScript - javascript

I am trying to access a php script on a server that returns a JSON object. I am trying to do this with pure JS (not jQuery or React).
I have the following JS:
//Define Parameters:
var param1 = document.getElementById("param1");
var param2 = document.getElementById("param2");
//Send data to the server:
function sendData() {
var XHR = new XMLHttpRequest();
//On Success:
XHR.addEventListener("load", function(event) {
alert(event.target.responseText);
});
//On Fail:
XHR.addEventListener("error", function(event) {
alert('Oops! Something went wrong.');
});
//Setup the request:
XHR.open("POST", "https://www.example.com/folder/file.php");
XHR.setRequestHeader('Content-Type', 'application/json');
//Perform the request:
XHR.send(JSON.stringify({
param1: param1,
param2: param2
}));
}
These parameters are inputted from a HTML page by the user. It seams that the request is not sending to POST parameters and the request type is OPTIONS not POST.
EDIT 1:
As suggested in the comments, I have tried a fetch request and the request is working. It does not appear to be passing my POST parameters through. My code is as follows.
//Define Parameters:
var param1 = document.getElementById("param1");
var param2 = document.getElementById("param2");
var formData = new FormData(document.getElementById('form'));
formData.append('param1', param1);
formData.append('param2', param2);
//Send data to the server:
function sendData() {
var url = 'https://www.example.com/folder/file.php';
fetch(url, {
method: 'POST',
body: formData,
headers:{
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
}
}).then(res => res.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));
}

Remove the headers section in your fetch request so that the defaults are used instead.

Have you checked to see that the right type of data is being sent in the fetch request? The wrong type being received in a field can mess with the results you see. What errors are you receiving?
This link may also describe something you're running into on the fetch:
https://stanko.github.io/uploading-files-using-fetch-multipart-form-data/
(This really should be a comment, but I don't have the reputation for that, sorry).

Related

POST error with missing body when use XMLHttpRequest but works with Fetch?

I have the following post function
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
function post(url, params, callback, method='POST') {
var http = new XMLHttpRequest();
http.open(method, url, true);
http.setRequestHeader('Content-type', 'application/json');
http.onload = function() {
console.log(http.status) <---- 500
console.log(http.responseText) <----'ERROR: An 'ipAddr' must be provided in the request body.',
callback(http);
};
console.log(JSON.stringify(params)) <--- print {"ipAddr":"175.00.00.00","params":"params_string"}
http.send(JSON.stringify(params));
}
keep getting 500 with responseText saying ipAddr is missing
but I am passing in ipAddr in the request body...what am I missing?
by the way the endpoint I am trying to reach works. Confrimed with curl
curl -i --header tion/json" -d '{"ipAddr": "175.00.00.00", "params": "params_string"}' --request POST https://my.endpoint/run
this returns me a 200 result.
update...
switch to using fetch, then it worked? not sure why, its the same content translate over
var fetch = require("node-fetch");
function post(url, params, callback, method='POST') {
// request options
const options = {
method: 'POST',
body: JSON.stringify(params),
headers: {
'Content-Type': 'application/json',
}
}
// send post request
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
}

How to move the API calls to server side from a working browser side website?

I am using javascript to make a POST request, and it works fine when I open my index.html file in the browser and click on the 'POST' button that I have linked to the following code. However, I would like to move this to server side and due to the numerous posts online I am confused as to how to do that? Any help is appreciated.
This is my working js code which returns the values in JSON format
const sendRequest = (method, url, data) => {
const promise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader(
"accessToken",
"AB 1234"
);
xhr.setRequestHeader("requestId", "req");
xhr.setRequestHeader("deviceId", "dev");
xhr.responseType = "json";
if (data) {
xhr.setRequestHeader("Content-Type", "application/json");
}
xhr.onload = () => {
if (xhr.status >= 400) {
reject(xhr.response);
} else {
resolve(xhr.response);
}
};
xhr.onerror = () => {
reject("Something went wrong!");
};
xhr.send(JSON.stringify(data));
});
return promise;
};
It's not clear how your server connects to your front-end, is it through an API? Is it react? So I'm giving you the most basic answer I could think of, but try to bring more details.
I'm assuming you already have a nodejs server ready to make this request.
The XMLHttpRequest belongs to browser's API and you can'y use it in Node.js, but there are two ways to do it:
1. Use the Node.js HTTP api
2. Use a lib
I think is very important to know how the HTTP api works, but I'm giving you the short answer using a lib called Axios.
const axios = require('axios')
const sendRequest = (method, url, data) => {
axios({
method,
url,
data
})
}
As stated node does not have XHR, but you should be able to re-implement the request without a great deal of effort by using a request
node-fetch resource: https://github.com/node-fetch/node-fetch
Example Request:
const fetch = require('node-fetch');
const body = {a: 1};
fetch('https://httpbin.org/post', {
method: 'post',
body: JSON.stringify(body),
headers: {'Content-Type': 'application/json'}
})
.then(res => res.json())
.then(json => console.log(json));

How to add request headers as array to window.open post url in javascript?

I have code something similar.
url : /files/docuemnttype/zipfile
window.open('POST', url, '_blank',{"reporttype" : [1,2,3,4,5]});
I am trying to send the reporttype array as request header in post call with window.open.
Can some one help me how this work.
Thanks!!
You cannot use window.open to do POST request to the backend service, what you could do would be use fetch function
fetch(url, {
method: "POST",
body: JSON.stringify({"reporttype" : [1,2,3,4,5]}),
headers: {"Content-Type": "application/json"}
.then(response => response.json())
.then(data => console.log(data));
You could also try using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
console.log(xhr.response);
}
}
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/json");
xhr.send(JSON.stringify({"reporttype" : [1,2,3,4,5]}));
the question here address this problem. You can't do it with 'window.open' fuction on JavaScript.
You need to pass this information with XMLHttpResponse object using the setRequestHeader function, or manipulate the request through the backend server, if you have access to it.

why fetch cache mode and headers options are not working to get a fresh response?

I try to get a fresh list of data by invoking a url using fetch. This url return a json. Following the instructions described in these links fetch(), how do you make a non-cached request? and https://hacks.mozilla.org/2016/03/referrer-and-cache-control-apis-for-fetch/, I build the following init object.
const headers = new Headers();
headers.append('pragma', 'no-cache');
headers.append('cache-control', 'no-cache');
const init = {
method: 'GET',
headers: headers,
cache: 'reload',
};
But after adding it as a second argument to fetch method the return data does not include the most recently added data, so I think it is due to cache.
The complete example is as follows
function getYears() {
const id = getId();
const request = new Request(`index.php?ep=name&id=${id}`);
const headers = new Headers();
headers.append('pragma', 'no-cache');
headers.append('cache-control', 'no-cache');
const init = {
method: 'GET',
headers: headers,
cache: 'reload',
};
fetch(request, init)
.then(response => response.json())
.then(json => {
window.yearCollection = years;
})
.catch(error => {
console.log(error.message);
});
}
The logical flow is the following, when loading the page the method getYears () is invoked, then when sending data in a form, the page is reloaded. Here the list of years is not updated, I must refresh the page manually, to get the list with the updated data

Axios - DELETE Request With Request Body and Headers?

I'm using Axios while programming in ReactJS and I pretend to send a DELETE request to my server.
To do so I need the headers:
headers: {
'Authorization': ...
}
and the body is composed of
var payload = {
"username": ..
}
I've been searching in the inter webs and only found that the DELETE method requires a "param" and accepts no "data".
I've been trying to send it like so:
axios.delete(URL, payload, header);
or even
axios.delete(URL, {params: payload}, header);
But nothing seems to work...
Can someone tell me if it's possible (I presume it is) to send a DELETE request with both headers and body and how to do so?
So after a number of tries, I found it working.
Please follow the order sequence it's very important else it won't work
axios.delete(URL, {
headers: {
Authorization: authorizationToken
},
data: {
source: source
}
});
axios.delete does supports both request body and headers.
It accepts two parameters: url and optional config. You can use config.data to set the request body and headers as follows:
axios.delete(url, { data: { foo: "bar" }, headers: { "Authorization": "***" } });
See here - https://github.com/axios/axios/issues/897
Here is a brief summary of the formats required to send various http verbs with axios:
GET: Two ways
First method
axios.get('/user?ID=12345')
.then(function (response) {
// Do something
})
Second method
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
// Do something
})
The two above are equivalent. Observe the params keyword in the second method.
POST and PATCH
axios.post('any-url', payload).then(
// payload is the body of the request
// Do something
)
axios.patch('any-url', payload).then(
// payload is the body of the request
// Do something
)
DELETE
axios.delete('url', { data: payload }).then(
// Observe the data keyword this time. Very important
// payload is the request body
// Do something
)
Key take aways
get requests optionally need a params key to properly set query parameters
delete requests with a body need it to be set under a data key
axios.delete is passed a url and an optional configuration.
axios.delete(url[, config])
The fields available to the configuration can include the headers.
This makes it so that the API call can be written as:
const headers = {
'Authorization': 'Bearer paperboy'
}
const data = {
foo: 'bar'
}
axios.delete('https://foo.svc/resource', {headers, data})
For those who tried everything above and still don't see the payload with the request - make sure you have:
"axios": "^0.21.1" (not 0.20.0)
Then, the above solutions work
axios.delete("URL", {
headers: {
Authorization: `Bearer ${token}`,
},
data: {
var1: "var1",
var2: "var2"
},
})
You can access the payload with
req.body.var1, req.body.var2
Here's the issue:
https://github.com/axios/axios/issues/3335
For Delete, you will need to do as per the following
axios.delete("/<your endpoint>", { data:<"payload object">})
It worked for me.
I had the same issue I solved it like that:
axios.delete(url, {data:{username:"user", password:"pass"}, headers:{Authorization: "token"}})
Actually, axios.delete supports a request body.
It accepts two parameters: a URL and an optional config. That is...
axios.delete(url: string, config?: AxiosRequestConfig | undefined)
You can do the following to set the response body for the delete request:
let config = {
headers: {
Authorization: authToken
},
data: { //! Take note of the `data` keyword. This is the request body.
key: value,
... //! more `key: value` pairs as desired.
}
}
axios.delete(url, config)
I hope this helps someone!
If we have:
myData = { field1: val1, field2: val2 }
We could transform the data (JSON) into a string then send it, as a parameter, toward the backend:
axios.delete("http://localhost:[YOUR PORT]/api/delete/" + JSON.stringify(myData),
{ headers: { 'authorization': localStorage.getItem('token') } }
)
In the server side, we get our object back:
app.delete("/api/delete/:dataFromFrontEnd", requireAuth, (req, res) => {
// we could get our object back:
const myData = JSON.parse(req.params.dataFromFrontEnd)
})
Note: the answer from "x4wiz" on Feb 14 at 15:49 is more accurate to the question than mine! My solution is without the "body" (it could be helpful in some situation...)
Update: my solution is NOT working when the object has the weight of 540 Bytes (15*UUIDv4) and more (please, check the documentation for the exact value). The solution of "x4wiz" (and many others above) is way better. So, why not delete my answer? Because, it works, but mostly, it brings me most of my Stackoverflow's reputation ;-)
i found a way that's works:
axios
.delete(URL, {
params: { id: 'IDDataBase'},
headers: {
token: 'TOKEN',
},
})
.then(function (response) {
})
.catch(function (error) {
console.log(error);
});
I hope this work for you too.
To send an HTTP DELETE with some headers via axios I've done this:
const deleteUrl = "http//foo.bar.baz";
const httpReqHeaders = {
'Authorization': token,
'Content-Type': 'application/json'
};
// check the structure here: https://github.com/axios/axios#request-config
const axiosConfigObject = {headers: httpReqHeaders};
axios.delete(deleteUrl, axiosConfigObject);
The axios syntax for different HTTP verbs (GET, POST, PUT, DELETE) is tricky because sometimes the 2nd parameter is supposed to be the HTTP body, some other times (when it might not be needed) you just pass the headers as the 2nd parameter.
However let's say you need to send an HTTP POST request without an HTTP body, then you need to pass undefined as the 2nd parameter.
Bare in mind that according to the definition of the configuration object (https://github.com/axios/axios#request-config) you can still pass an HTTP body in the HTTP call via the data field when calling axios.delete, however for the HTTP DELETE verb it will be ignored.
This confusion between the 2nd parameter being sometimes the HTTP body and some other time the whole config object for axios is due to how the HTTP rules have been implemented. Sometimes an HTTP body is not needed for an HTTP call to be considered valid.
For Axios DELETE Request, you need to include request payload and headers like this under one JSON object:
axios.delete(URL, {
headers: {
'Authorization': ...
},
data: {
"username": ...
}
})
Why can't I do it easily as I do similar to POST requests?
Looking at the Axios documentation, we see that the methods for .get, .post... have a different signature:
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
Notice how only post, patch and put have the data parameter. This is because these methods are the ones that usually include a body.
Looking at RFC7231, we see that a DELETE request is not expected to have a body; if you include a body, what it will mean is not defined in the spec, and servers are not expected to understand it.
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
(From the 5th paragraph here).
In this case, if you are also in control of the server, you could decide to accept this body in the request and give it whatever semantics you want. May be you are working with somebody else's server, and they expect this body.
Because DELETE requests with bodies are not defined in the specs, and because they're not common, Axios didn't include them in those method aliases. But, because they're possible, you can do it, just takes a bit more effort.
I'd argue that it would be more conventional to include the information on the url, so you'd do:
axios.delete(
`https://example.com/user/${encodeURIComponent(username}`,
{ headers: ... }
)
or, if you want to be able to delete the user using different criteria (sometimes by username, or by email, or by id...)
axios.delete(
`https://example.com/user?username=${encodeURIComponent(username)}`,
{ headers: ... }
)
Not realated to axios but might help people tackle the problem they are looking for. PHP doesn't parse post data when preforming a delete call. Axios delete can send body content with a request.
example:
//post example
let url = 'http://local.test/test/test.php';
let formData = new FormData();
formData.append('asdf', 'asdf');
formData.append('test', 'test');
axios({
url: url,
method: 'post',
data: formData,
}).then(function (response) {
console.log(response);
})
result: $_POST Array
(
[asdf] => asdf
[test] => test
)
// delete example
axios({
url: url,
method: 'delete',
data: formData,
}).then(function (response) {
console.log(response);
})
result: $_POST Array
(
)
to get post data on delete call in php use:
file_get_contents('php://input');
axios.post('/myentity/839', {
_method: 'DELETE'
})
.then( response => {
//handle success
})
.catch( error => {
//handle failure
});
Thanks to:
https://www.mikehealy.com.au/deleting-with-axios-and-laravel/
I encountered the same problem...
I solved it by creating a custom axios instance. and using that to make a authenticated delete request..
const token = localStorage.getItem('token');
const request = axios.create({
headers: {
Authorization: token
}
});
await request.delete('<your route>, { data: { <your data> }});
I tried all of the above which did not work for me. I ended up just going with PUT (inspiration found here) and just changed my server side logic to perform a delete on this url call. (django rest framework function override).
e.g.
.put(`http://127.0.0.1:8006/api/updatetoken/20`, bayst)
.then((response) => response.data)
.catch((error) => { throw error.response.data; });
Use {data: {key: value}} JSON object, the example code snippet is given below:
// Frontend Code
axios.delete(`URL`, {
data: {id: "abcd", info: "abcd"},
})
.then(res => {
console.log(res);
});
// Backend Code (express.js)
app.delete("URL", (req, res) => {
const id = req.body.id;
const info = req.body.info;
db.query("DELETE FROM abc_table WHERE id=? AND info=?;", [id, info],
(err, result) => {
if (err) console.log(err);
else res.send(result);
}
);
});
Axios DELETE request does supports similar what POST request does, but comes in different formats.
DELETE request payload sample code:
axios.delete(url, { data: { hello: "world" }, headers: { "Authorization": "Bearer_token_here" } });
POST request payload sample code:
axios.post(url, { hello: "world" }, { headers: { "Authorization": "Bearer_token_here" } });
Noticed that { hello: "world" } is configured in different ways, but both performs same functions.
this code is generated from post man and it's perfectly work for delete api request with body.
var data = JSON.stringify({"profile":"false","cover":"true"});
var config = {
method: 'delete',
url: 'https://api.fox.com/dev/user/image',
headers: {
'Authorization': 'Bearer token',
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});

Categories