Axios request adding URL variable to localhost URL - javascript

I have a GET request Axios:
const fetchData = () => {
axios( {
method: "GET",
url: inputData.cUrl,
headers: { "content-type": "text/html" }
} ).then( ( response ) => {
const parser = new DOMParser();
const doc = parser.parseFromString( response, "text/html" );
console.log( doc );
} ).catch( e => console.log( e ) );
};
However, if inputData.cUrl is "www.google.com", the request will fail with the error message of
"GET http://localhost:3000/www.google.com 400 (Header required)".
2 questions.
Why does it append the url to the end of my localhost url? I want the get request to only go to the url the user puts in, not appended to my localhost.
And what does (Header required) mean? Never seen this with axios before.
Thank you for your help!

You need to add the http protocol in front of the URL. Here you go.
const inputData = {};
inputData.cUrl = 'https://www.google.com';
const fetchData = () => {
axios({
method: 'GET',
url: inputData.cUrl,
headers: {
'content-type': 'text/html'
}
})
.then(response => {
const parser = new DOMParser();
const doc = parser.parseFromString(response, 'text/html');
console.log(doc);
})
.catch(e => console.log(e));
};
you can ignore this because the Request was going to your server instead of 'www.google.com'

Related

How to access property of stringified JSON?

I have this code that sends me back an url and an error. I'm trying to access the url so I can navigate to it with router.
With this code:
const redirectToStripe = async () => {
const response = await fetch(
"http://localhost:5000/create-checkout-session",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(cartItems.value),
}
)
.then((response) => response.json())
.then((response) =>
console.log("stringied response", JSON.stringify(response))
);
const { url } = await response.json();
console.log("url=", url); <--------------Doesn't execute, no console.log() readout
// window.location.href = url;
// router.go(url) <------- NEED TO FIX THIS AND UNCOMMENT;
};
I get this error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'json')
at redirectToStripe
and this console.log() readout:
stringied response {"url":"https://checkout.stripe.com/c/pay/cs_test_a1X3r92YtZfM9H"}
That is the url I'm trying to navigate to, but I don't know how to access it in this stringified form. How do I grab the value of "url" so I can put it in the function:
router.go(url)
The later "url" console.log() never executes because of the json error (pretty sure), but I'm guessing it's the same url as the stringified one above?
I also don't know why I'm getting that error or if it's even consequential and needs to be fixed because I'm already getting the url I need. Does the error have something to do with the "Content-Type" header? Did I pick the right one? Is it something else I'm doing wrong?
Also, this is what the backend endpoint looks like if it adds context or anything.
app.post("/create-checkout-session", async (req, res) => {
// Make an array of just our Stripe Price ID and quantities
const lineItems = req.body.map((item) => {
console.log("lineItems= ", item.item.priceId, item.item.quantity);
return {
price: item.item.priceId,
quantity: item.item.quantity,
};
});
const session = await stripe.checkout.sessions.create({
mode: "payment",
line_items: lineItems,
success_url: `http://localhost:8080/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `http://localhost:8080/`,
});
return res.send({ url: session.url });
});
EDITS
#pope_maverick
This code:
const redirectToStripe = () => {
const response = fetch("http://localhost:5000/create-checkout-session", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(cartItems.value),
}).then((response) => response.json());
const {url} = response.json();
// const { url } = await response.json();
console.log("url=", url);
gets me the error:
Uncaught TypeError: response.json is not a function
You forgot to return the response in your last .then callback. So your const response is actually void.
const response = await fetch(
"http://localhost:5000/create-checkout-session",
// [...]
)
.then((response) => response.json())
.then((response) => {
console.log("stringied response", JSON.stringify(response))
// ❗️ Return `response` here, or the Promise will return the returned value of `console.log` which is `void`!
return response
});
You face this issue because the API returns a string not an object so you are suppsed to use Response.text() over Response.json(), have a look the MDN Response.text()
Try below:
const redirectToStripe = async () => {
const response = await fetch(
"http://localhost:5000/create-checkout-session",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(cartItems.value),
}
)
.then(response => response.text())
.then((url) => {
const { url } = url;
console.log("url=", url);
router.go(url)
})
.catch(err => console.log(err))
};

Error when page loads, but before anything is executed

When I open my local host, I am getting the following error
Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': Failed to parse URL from //at getData ((index):60)
Which is pointing to these lines of code
const response = await fetch(url, {
&
getData(`/${url}`)
I'm not sure why I am getting this error when I load the page, as should I only get something like this when I search for something?
This is the larger block of code I am referring to:
document.getElementById('search').addEventListener('submit', function(e) { e.preventDefault(); getData(); })
const form = document.getElementById('Submit')
var formResult = new FormData(form);
const url = '/' + encodeURIComponent(formResult.get("search"));
async function getData(url = '', data = {}) {
const response = await fetch(url, {
method: 'GET',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
});
return response.json();
}
getData(`/${url}`)
.then(data => {
console.log(data);
})
Any insight would be appreciated.
Edit based on comments:
Front end:
const form = document.getElementById('Submit')
var formResult = new FormData(form);
const url = '/?url=' + encodeURIComponent(formResult.get("search"));
async function getData(url = '', data = {}) {
const response = await fetch(url) {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
.then(response =>{
console.log(response)
})
.catch(err=>{
console.error(err)
})
Portion of my express Server:
const url = req.body
let urlDecoded = decodeURIComponent(url.url)
console.log(url, urlDecoded)
app.use(express.static("Public"));
app.post('/:url', async function (req, res) {
console.log(req.query.url);
try {
await whoisanalyzer.init();
const site = await whoisanalyzer.open(decodeURIComponent(req.query.url));
const data = await site.analyze();
return res.status(200).json(data);
} catch (ex) {
console.log(ex);
return res.status(500).json({ message : "Oops." });
}});
I think the problem is in the getData() function because of the parameter of it getData(url=' ')
The getData() function replace url with the parameter not with the variable so the fetch url is gonna be
Fetch(" ", { ....})
You have to define the url or the parameter with anther name
You also call the function inside the same function in
getData(`/${url}`)
.then(data => {
console.log(data);
})
That is wrong because the function will never end
You can do it directly like that
document.getElementById('search').addEventListener('submit', async function(e) {
e.preventDefault();
const form = document.getElementById('Submit')
var formResult = new FormData(form);
const url = '/' + encodeURIComponent(formResult.get("search"));
const response = await fetch(url)
.then(response =>{
console.log(response)
})
.catch(err=>{
cosnole.error(err)
})
if you want to take a url and send it to the back end and your front end code is like this
<form action="POST">
<input type="text" name="url">
<input type="submit" value="press">
</form>
so your the code in your js file is gonna be like this below :-
const form = document.querySelector('form')
form.addEventListener('submit', async(e) => {
e.preventDefault()
let urlIN = form.url.value
let url = encodeURIComponent(urlIN)
console.log(url)
const data = await fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: url
})
}).then(data => {
console.log(data)
console.log('get')
})
.catch(err => {
console.error(err)
})
})
and i tested it and it's working , i could send the url of this page and decoded it and i printed it in my console like that
my back end code
const url = req.body
let urlDecoded = decodeURIComponent(url.url)
console.log(url, urlDecoded)
and the result is
{
url: 'https%3A%2F%2Fstackoverflow.com%2Fquestions%2F65757144%2Ferror-when-page-loads-but-before-anything-is-executed%2F65760895%3Fnoredirect%3D1%23comment116273379_65760895'
}
Error when page loads, but before anything is executed

Getting pdf file from api response

I am calling an api and getting pdf in return.
fetch(`api` + guid, {
method: "GET",
headers: {
"Accept": "application/octet-stream",
"Authorization": "Bearer " + token,
},
responseType: 'arraybuffer',
})
.then((res) => res.text())
.then((data) => {
fs.writeFileSync('file.pdf', data);
});
I get the pdf file but the issue is the pdf file is always empty. But when I accept response as json, it works fine.
I found similar problems like this but none of the solution worked for me yet.
It would be great if someone can point out the issue.
I found the issue.
As I am using fetch not Axios.
We cannot pass responseType as Fetch's option.
fetch(`api` + guid, {
method: "GET",
headers: {
"Accept": "application/octet-stream",
"Authorization": "Bearer " + token,
},
// responseType: 'arraybuffer' //#1 remove this,
})
Instead the response in itself can be passed as arraybuffer as below.
.then((res) => res.arraybuffer())
instead of
.then((res) => res.text())
Now instead of directly using the response to write our pdf file. We can change the data to base64 string and decode it back again to create our pdf file. I used base64ToPdf npm package to handle that.
.then(data => {
var base64Str = Buffer.from(data).toString('base64');
base64.base64Decode(base64Str, "file.pdf");
})
I hope this help others. :)
Change res.arraybuffer() to res.arrayBuffer()
Below is the working code with webdriverio-
var headers = {
Authorization: "Bearer " + accessToken,
Accept: 'application/pdf'
}
fetch(
apiurl,
{
headers: {
Accept: "application/octet-stream",
Authorization: "Bearer " + accessToken
},
},
)
.then((res) => {
if (!res.ok) {
return res.status.toString()
}
return res.arrayBuffer()
})
.then((data) => {
var base64Str = Buffer.from(data).toString('base64');
base64.base64Decode(base64Str, filename);
})
.catch(
(err) => {
return err.Message;
})
Here's example which works for me:
async createPdf(context, data) {
let url = new URL(baseURL + '/invoice/createPdf');
url.search = new URLSearchParams({
id: data
})
await fetch(url, {
method: 'GET',
headers: {
'Authorization': "Bearer " + localStorage.getItem("jwt"),
'Accept': 'application/octet-stream'
},
}).then((res) => res.arrayBuffer())
.then(data => {
var base64Str = Buffer.from(data).toString('base64');
var binaryString = window.atob(base64Str);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
var arrBuffer = bytes;
var newBlob = new Blob([arrBuffer], { type: "application/pdf" });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
document.body.appendChild(link);
link.href = data;
link.download = "Faktura.pdf";
link.click();
window.URL.revokeObjectURL(data);
link.remove();
})
}
In my case, the response is same as yours and I'm trying to convert it to a pdf file so that I can preview it on the UI.
For this, I need to fetch the URL already present in the response which is of type blob... to fetch the URL I did URL.createObjectURL(myblob)
const [url,seturl] = useState('');
response
.then((resp) => resp.blob())
.then((myBlob) => {
seturl(URL.createObjectURL(myBlob)); //<-- use this for fetching url from your response
console.log(myBlob);
})
.catch((err) => {
console.log(err.message());
});

getting requested files as an empty array in Laravel API from javascript

here is my javascript form handler
where i get data from the form to send it as request to API
import { Store } from './http/requests.js';
$(document).ready(function () {
$('#form_submit').submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
Store(formData);
});
});
js requests file handler
where i use customized post,get functions to send data with options that i provide on it
import { get, post } from '../helper.js';
let pageName = window.location.pathname;
pageName = pageName.slice(1, pageName.length - 5);
export const Store = (value) => {
switch (pageName) {
case 'add_car':
post('user/create_car', value, true, 'multipart/form-data')
.then((res) => {
console.log(res);
return res;
})
.catch((err) => console.log(err));
default:
break;
}
};
then the helper file where i use fetch get,post with option that i receive from "requests.js" file and provide it here
import { Local as loc } from './localStorage.js';
const API_URL = 'http://127.0.0.1:8000/api';
// token if exists in localStorage
const token = loc('get', 'token');
// POST Request
export const post = (
url,
formData,
auth = false,
type = 'application/json',
providedToken = token,
) => {
return fetch(`${API_URL}/${url}`, {
method: 'POST',
body: JSON.stringify(formData),
headers: {
'Content-Type': type,
Authorization: auth ? `Bearer ${providedToken}` : null,
},
})
.then((res) => res.json())
.then((res) => {
console.log(res);
return res;
})
.catch((err) => console.log(err));
};
and finally the Laravel API Cotroller where i tried to debug the issue
public function create_car(Request $request)
{
return (response()->json([
"files" => $_FILES,
"all Request data" => $request,
]));
}
the response i get when i send data from javascript to Laravel API
API gives me back this empty object as a response
it's seems like fetch has a problem ... anyway i just replaced fetch library with axios and everything runs perfectly
here is what i did on helper.js file
// POST Request
export const post = (
url,
formData,
auth = false,
type = 'application/json',
providedToken = token,
) => {
return axios({
method: 'POST',
url: `${API_URL}/${url}`,
data: formData,
headers: {
'Content-Type': type,
Authorization: auth ? `Bearer ${providedToken}` : null,
},
})
.then((res) => {
console.log(res);
return res.data;
})
.catch((err) => console.log(err.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
});

Categories