Javascript Fetch not getting a response - javascript

I'm invoking an authentication service via javascript fetch to get an access token. The service is a simple RESTful call. I can see the call is successful using fiddler (with a 200 response and json data). However the fetch response never seems to get invoked. Below is a snippet:
const AUTHBODY = `grant_type=password&username=${username}&password=${password}&scope=roles offline_access profile`
const AUTHHEADER = new Headers({'Content-Type': 'application/x-www-form-urlencoded'})
const CONFIG = {
method: 'POST',
headers: AUTHHEADER,
body: AUTHBODY
}
fetch('http://localhost:23461/connect/token', CONFIG).then(function(response) {
console.log('response = ' + response)
return response.json()
}).then(function(json) {
console.log('json data = ' + json)
return json
}).catch(function(error) {
console.log('error = ' + error)
})
When executing the fetch above none of the console.logs gets executed... seems to just hang. But fiddler tells otherwise. Any ideas?

You probably met with the CORS origin policy problem. To tackle this you need some rights to access the server side of your API. In particular, you need to add a line in the header of php or another server endpoint:
<?php
header('Access-Control-Allow-Origin: *');
//or
header('Access-Control-Allow-Origin: http://example.com');
// Reading JSON POST using PHP
$json = file_get_contents('php://input');
$jsonObj = json_decode($json);
// Use $jsonObj
print_r($jsonObj->message);
...
// End php
?>
Also, make sure NOT to have in the header of your server endpoint:
header("Access-Control-Allow-Credentials" : true);
Model of working fetch code with POST request is:
const data = {
message: 'We send a message to the backend with fetch()'
};
const endpoint = 'http://example.com/php/phpGetPost.php';
fetch(endpoint, {
method: 'POST',
body: JSON.stringify(data)
})
.then((resp) => resp.json())
.then(function(response) {
console.info('fetch()', response);
return response;
});

Related

Javascript Fetch api, JSON.parse() has syntax error despite JSON being correct

I am trying to make a low dependency JavaScript to show temperature of raspberry pi. The server sends a JSON as a response to get request and the Client shows a web page.
The server is working as intended,I have checked in browser and using postman
const { spawn } = require("child_process");
const http = require('http');
http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
const temp = spawn('cat', ['/sys/class/thermal/thermal_zone0/temp']);
temp.stdout.on('data', function (data) {
data = data / 1000;
console.log('Temperature: ' + data + '°C');
res.end(JSON.stringify({"temp":data}));
});
temp.stderr.on('data', function (data) {
res.end(JSON.stringify({"temp":"Unavailable"}));
});
}
else {
res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({"temp":"Unavailable"}));
}
}).listen((process.argv[2] || 64567), () => {
console.log('Server listening on http://localhost:' + (process.argv[2] || 64567));
});
This is the client side code
<body>
<script defer>
await fetch('http://localhost:64567',{mode: 'no-cors'}).then(res => JSON.parse(res)).then(temp => document.getElementById("value").innerHTML = temp.temp);
// SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data
/*
await fetch('http://localhost:64567',{mode: 'no-cors'}).then(res => res.json()).then(temp => document.getElementById("value").innerHTML = temp.temp)
// SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
await fetch('https://api.npoint.io/d5a7160bab77dd869b82').then(res => res.json()).then(temp => document.getElementById("value").innerHTML = temp.temp)
// This one works
*/
</script>
<h3>Temperature:<span id="value"> </span> °C</h3>
</body>
but when I try to use fetch api in the client side, JSON.parse gives two different types of errors for different approaches, but when I use a publicly hosted JSON bin it works.
Expectation: Fetch JSON being fetched and parsed correctly.
Tried:
Two different approaches to parse JSON
Use a different host for JSON
res is a Response, not the text. Use res.json() to parse the body text as JSON.
fetch('http://localhost:64567').then(res => res.json())
So I figured it out, thanks to #Unmitigated , all I needed to do was set the CORS on the server side and remove mode:no-cors in the client side.
Adding headers like these, in the server was the fix.
const headers = {
'Access-Control-Allow-Origin': '*', /* #dev First, read about security */
'Access-Control-Allow-Methods': 'OPTIONS, GET',
'Access-Control-Max-Age': 2592000, // 30 days
'Content-Type': 'application/json; charset=utf-8'
/** add other headers as per requirement */
};

uploading post json request and reading it on the server

How do I send a json POST request using Javascript and read it on a flask server?
Last approach (reference):
const uploadjson = storeDictionary
const url = "/uploadset/"+setName
fetch(url, {method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: uploadjson})
.then((response) => response.json())
.then((data) => {
console.log('Success:', uploadjson);
})
.catch((error) => {
console.error('Error:', error);
console.log("Data:", uploadjson)
});
It results in the following error message:
Here's a part of the python code (flask) I wrote with help from the documentation:
#app.route("/uploadset/<name>", methods=['GET','POST'])
def uploads(name):
if flask.request.method == "POST":
print("Upload!")
if 'id' in flask.session:
if flask.session['id'] in client:
sessid = flask.session['id']
if name != "":
print("flask.request.files", flask.request.files)
file = flask.request.files['file']
try:
if processUploadedSet():
error = False
success = True
This results into a "server didn't understand your request".
I found out that the flask server is the problem:
Here's the server log:
If I return an empty string on the server the request works 'fine'.
How do I read json data using flask which was sent using the javascript?
You can read a json response in flask using flask.request.get_json
Simply replace file = flask.request.files['file']
with file = flask.request.get_json(cache=False)
Sending a json POST request is not the same as sending a file!

How to use Stripe's secret key and publishable key?

I would like to connect with the Stripe API using a https call using the https library.
var https = require('https');
I have gotten the secret key and publishable key and put it inside a object:
var stripe = {
secret_key: 'secret_key_given_in_the_dashboard',
publishable_key: 'publishable_key_given_in_the_dashboard'
}
I am now in the part of creating the requestDetail object:
var requestDetails = {
'protocol' : 'https:',
'hostname' : 'api.stripe.com',
'method' : 'POST', //WHICH OF POST GET PUT DELETE SHOULD I USE?
'path' : '???????????????????????',// WHICH ENDPOINT SHOULD I USE?
'auth' : '???????????????????????',// SHOULD I USE THE SECRET AND PUBLISHABLE KEY HERE?
'headers' : {
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length' : Buffer.byteLength(stringPayload)
}
};
I plan to make use of the requestDetails object in the call using https:
var req = https.request(requestDetails, function(res){
// Grab the status of the sent request
var status = res.statusCode;
//Callback successfully if the request went through
if(status == 200 || status == 201) {
callback(false);
} else {
callback('Status code returned was ' + status);
}
});
Where and how should I use the secret key and publishable key in order to make a call to the stripe API?
Which endpoint?
Which method (POST, GET, PUT,or DELETE)?
I would like to eventually create a order and pay through the STRIPE api.
But for now just any authenticated call through the stripe api will do as I need a sample format that works....
I'm not too sure where to add the secret key and publishable key....
You should install official stripe package (source: https://github.com/stripe/stripe-node), require the package and authenticate it using your secret key ( example from the github docs):
const stripe = require('stripe')('your_stripe_secret_key');
stripe.customers.create({
email: 'customer#example.com',
})
.then(customer => console.log(customer.id))
.catch(error => console.error(error));
The package is an abstraction to make the API requests for you.
More docs: https://stripe.com/docs/api?lang=node
However, if you want to use the https directly for Stripe API requests, which is not recommended, you can check the docs and examples for using the cURL, since it shows the endpoints for each example.
https://stripe.com/docs/api/authentication?lang=curl
try using fetch, 'Authorization': 'Bearer ' + sk.
My working example of retrieving a customer based on the customer_id:
const url = `https://api.stripe.com/v1/customers/${stripe_customer_id}`;
return await fetch(url, {
method: "get",
headers: {
"Content-Type": "application/json",
'Authorization': 'Bearer ' + sk,
}
})
.then(function(response) {
return response.json();
})
.then(function(response) {
// console.log(response);
return response;
});
};

Spring: request body missing error when sent from client but works with postman?

I have a Spring Rest backend setup as well as a react client. Both are setup on different local ports. I am trying to send a simple request from my React client using a fetch call to my spring rest api.
When sending the POST request using Postman, the API responds as expected.
When sending the request from the React client I receive the following 400 error:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing: public
org.springframework.http.ResponseEntity<?>
I have done the following:
Disabled CSRF on my spring application.
Set global CORS config to accept all requests.
Ensured on multiple occasions that the request body is correct and identical to that sent via Postman.
Here is my Fetch request from react client:
fetch(API_BASE_URL + '/api/auth/signin', {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json;charset=UTF-8',
'Access-Control-Request-Method': 'POST'
}),
body: {
username: this.state.uname,
password: this.state.password,
}
}).then(
function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function (data) {
let json = JSON.parse(data);
let token = json.tokenType + " " + json.accessToken;
localStorage.setItem(ACCESS_TOKEN, token);
alert('successfully saved token:' + token);
});
}
)
.catch(function (err) {
console.log('Fetch Error :-S', err);
});
For those interested:
The data passed in payload was of an incorrect format. While this may not appear logical, creating a variable as so:
let payload = {
username: this.state.username,
password: this.state.password,
};
And passing that as the body to fetch seems to work.
Hopefully this may help others facing the same problem..

Lumen Spotify API invalid client

I'm working on an app that allows authentication using Spotify
When trying to get the user's access token, i get a 400 bad request 'invalid_client'.
Here is my JS code which fires whenever the user is redirected to the app.
The url is localhost:3000/spotify?code=xxxxxxxxxxx&state=xxxxxxxxx
const myHeaders = new Headers();
myHeaders.append('Accept', 'application/json');
myHeaders.append('Access-Control-Allow-Origin', '*');
myHeaders.append('Content-Type', 'application/json');
//gets the param in the url
const paramCode = getParameterByName('code', window.location.href);
const defaultOptions = {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({
code: paramCode,
}),
mode: 'cors',
};
// POST request to the backend at http://localhost:8000/api/spotify/oauth
fetch(LocalAPI.getLocalTokenUrl(), defaultOptions)
.then((response) => {
return response.json();
})
.then((results) => {
console.log('token : ', results.access_token);
// "Client error: `POST https://accounts.spotify.com/api/token`
// resulted in a `400 Bad Request` response:
// {"error":"invalid_client","error_description":"Invalid client"}"
});
And here is my backend PHP code which fires whenever it receives a POST request at /api/spotify/oauth
It requests the user's access token but fails. A 400 bad request error is catched and sent to the JS code.
$code = $request->input('code');
$id = $this->getClientId();
$secret = $this->getClientSecret();
//encodes clientid and secret in base64
$token = \base64_encode("$id:$secret");
$headers = [
'Authorization' => 'Basic '.$token,
'Content-Type' => 'application/x-www-form-urlencoded'
];
try {
$guzzle = new Client();
$results = $guzzle->post($this->getTokenUrl(), [
'headers' => $headers,
'form_params' => [
'code' => $code,
'redirect_uri' => 'http://localhost:3000/spotify',
'grant_type' => 'authorization_code'
]
]);
}
catch (\GuzzleHttp\Exception\ServerException $e) {
echo json_encode($e->getResponse());
}
catch(\GuzzleHttp\Exception\ClientException $e) {
echo json_encode($e->getMessage());
}
catch(\GuzzleHttp\Exception\RequestException $e) {
echo json_encode($e->getResponse());
}
echo \GuzzleHttp\json_encode($results);
According to Spotify API documentation :
https://developer.spotify.com/web-api/user-guide/#response-status-codes
My request could be malformed ...
I tried messing with the Content-Type and set it to application/json. In this case, no errors are catched but i get a "JSON.parse: unexpected character at line 1 column 1 of the JSON data" in my JS code.
Any suggestion would be appreciated.
Best regards.

Categories

Resources