Why does my fetch POST request on button submit results in pending promise and page continuously loading - api

I am working on creating a user in Shopify by using the Admin and Storefront API build in my Next.js project. The user inputs an email and clicks "Sign up" which sends a post fetch request to my Next.js middleware. The post request fails and never sends back a response and the browser tab continuously circles like it is loading. Here is the API call belo. Why is it that the network tab of the inspector states "Pending"? I Thought .then() resolves a promise. Thank you for any help in advance.
export default function login(req: NextApiRequest, res: NextApiResponse) {
var myHeaders = new Headers()
myHeaders.append('Access-Control-Allow-Origin', '*')
myHeaders.append('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
myHeaders.append('Access-Control-Allow-Headers', 'Content-Type')
myHeaders.append('Content-Type', 'application/json')
myHeaders.append('Authorization', `${secretToken}`)
var raw = JSON.stringify({
customer: {
email: email,
accepts_marketing: true,
verified_email: true,
},
})
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
}
fetch('https://xxxxxxxxx.myshopify.com/admin/api/2022-10/customers.json', requestOptions)
.then((response) => response.text())
.then((result) => {
console.log("result - ",result)
res.status(200);
}).finally(() => {
console.log("Done")
})
.catch((error) => console.log('error', error))
"CAUTION: request is not finished yet"

Related

First preflight fails for post request from jsfiddle

I was testing get and post requests in jsfiddle to better understand cors and csrf.
const data = { name: 'example', password: 'password'};
fetch('http://localhost:3001', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hi')
})
app.post('/', (req, res) => {
console.log('received')
res.send('Received')
})
app.listen(3001, () => {
console.log('Listening on port', 3001)
})
Is it normal that the first preflight request fails when doing a post request?
Also, shouldn't the successful preflight request happen before the post request? (On the server side, the code handling the post request isn't executed (nothing logged in console), which means that the browser cancelled the post request. How would the browser know not to follow through with the post request without waiting for the preflight request to complete first?)
Update:
Tried it using a simple html page instead of jsfiddle and the preflight request doesn't fail, but it still happens after the fetch request
Edit:
Only one options request is received on the server
// debugging middleware, should be first router handler of any kind
let requestCntr = 0
app.use((req, res, next) => {
let thisRequest = requestCntr++
console.log(
`${thisRequest}: ${req.method}, ${req.originalUrl}, `,
req.headers
)
// watch for end of theresponse
res.on('close', () => {
console.log(
`${thisRequest}: close response, res.statusCode = ${res.statusCode}, outbound headers: `,
res.getHeaders()
)
})
next()
})
Edit 2: from console
For a get request, no network error is shown in the Network tab, but the same error appears in the console except with a status code
It seems that Chrome simply displays the preflight request with a network error in the Network tab if it's related to csrf. Since opaque GET requests are fine, this doesn't happen for GET requests. So in the case of a post request, even if "preflight" shows up twice, it's the same preflight request.

Why Axios is not providing response header when app is opening second time?

Here is my API request
const getData= async () => {
const cookie='workid_token=eyJra4rgrtF7SnlSETjIGrFYQy-P2SFmlE6A.Tw_rx0Ut_Kj9zLWRQ9X23w';
const qs = require('qs')
let body = qs.stringify({
gid: '1196'
})
await axios.post(
'https://www.google.com', body,
{
headers: {
'Cookie': cookie,
'Content-Type': 'application/x-www-form-urlencoded',
},
},
).then(response => {
console.log('data', response);
if (response.data.status === '1') {
const PHPSESSID = response.headers['set-cookie'];
var separatedvalue = PHPSESSID[0];
var sessid = separatedvalue.split('; path=/')[0];
}
}).catch(error => {
console.log(error);
});
};
I am implementing Axios API post request in my React Native application. When I run the application first time I am getting set-cookie value in response headers. If I kill the application and I open it second time I am not getting value in set-cookie. Also not receiving response from the API.
Note: I want to receive value from set-cookie all the times.

React Native fetching request from API freezes UI

I'm able to fetch messages from the API and render them in the component successfully. However, as the number of messages increases, fetching from the API causes the app to freeze and clicking any event (such as selecting a different tab or button) will be only triggered when the request is done.
I've read about using next-frame to solve this issue but I'm finding difficulties in how to add it to my code. I'd like to know how to implement next-frame inside it.
This is the section of code that fetches messages from the backend:
componentWillMount()
{
/**load user's messages */
loadmessages() {
fetch(server + 'view_user_messages.php', {
method: 'POST',
headers: {
'Accept': 'text/plain',
'Content-Type': 'text/plain',
},
body: JSON.stringify({
user_idDB: modulevariables.globaluserid
})
}).then((response) => response.text())
.then((responseJson) => {
var jsonconvertedrows = JSON.parse(responseJson)
this.setState({ messagestable: jsonconvertedrows })
}).catch((error) => {
console.log(error);
})
}
}

Redirect_uri mismatch in fetch and gapi

working on connecting users to google, and we're trying to get their access and refresh tokens from the google api, and we're getting an issue exchanging the OAuth2 Code for tokens. Both sets of code have the same error.
I initialize the gapi client and fill in the information needed like so:
gapi.load('client:auth2', _ => {
gapi.client.init({
'apiKey': 'omitted for security',
clientId: 'omitted for security',
'scope': 'https://www.googleapis.com/auth/drive',
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest']
}).then(_ => {
gapi.auth2.getAuthInstance().grantOfflineAccess().then(resp => {
if(resp.code){
gapi.client.request({
path: 'https://www.googleapis.com/oauth2/v4/token',
method: 'post',
params: {code: resp.code},
body: {
code: resp.code,
client_id: opts.clientId,
client_secret: 'omitted for security',
grant_type: 'authorization_code',
redirect_uri: 'omitted for security',
access_type: 'offline'
},
}).then((onfulfill, onreject, context) => {
console.log('fulfilled', onfulfill);
console.log('rejected: ', onreject);
console.log('context', context);
}).catch(err => console.error(err.body));
}
});
});
});
What I'm trying to do in the .then() is to call the token endpoint to exchange the code in the response for a refresh and access token to store in my back end and the user's local storage.
I get this error response from both versions of the code. (better, more reliable code is provided here.)
{ "error": "redirect_uri_mismatch", "error_description": "Bad
Request" }
I also have a backend setup stashed as a last resort that accepts the code from gapi.auth2.getAuthInstance().grantOfflineAccess() calls the token endpoint, and returns the access_token and refresh_token to the client.
This code is similar, but not quite. instead of using the google api library, I used fetch, and it works fine. (Fetch and XHR on the front end have the same issues as the gapi.client.request function....)
const gConfig = require('./basic.json');
const scopes = ['https://www.googleapis.com/auth/drive'];
const { client_id, client_secret, redirect_uris } = gConfig.web;
const authClient = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
app.post('/', (req, res) => {
const { code } = req.body;
console.log('Received Code From Request: ', code);
let data = { code , client_id, client_secret,redirect_uri: redirect_uris[0], grant_type: 'refresh_token'};
let encodedParams = Object.keys(data).map(k => encodeURIComponent(k) + '=' + encodeURIComponent(data[k])).join('&');
fetch(
`https://www.googleapis.com/oauth2/v4/token?code=${code}`,
{ method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encodedParams }
).then((res) => {
console.log('called the api with fetch');
console.dir(res.json());
});
authClient.getToken(code, (err, token) => {
if (err) {
console.error(err);
res.status(500).json(err);
}
// console.dir(token);
console.log('TOKEN: =>', token);
res.json(token);
});
});
Is there anyone that's done this on the front end successfully?
You can't get a refresh token in a browser. Your example code would only work on a server. To do oauth at the client you should request "token" instead of "code".

Express CORS response

I am using express to return an api response retrieved via a request call.
router.post('/', function(req, res){
var options = {
...
}
rp(options)
.then(function (parsedBody) {
console.log(parsedBody);
res.json(parsedBody)
})
The console log displays the expected payload, also when I use Postman I also see the expected payload.
When though my client app gets the response it is:
Response {type: "cors", url: "http://localhost:3001/api/", redirected: false, status: 200, ok: true, …}
Ive tried adding CORS middleware:
app.use(function(request, response, next) {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers",
"Origin, X-Rquested-With, Content-Type, Accept");
next();
});
My client is a very simple react app using fetch:
fetch('http://localhost:3001/api/', {
method: 'POST',
dataType: 'JSON',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: data,
}).then((response) => {
console.log(response);
}).catch((response) => {
console.log('Error');
});
My react app is localhost:3000 and the express api localhost:3001, the expected payload is a very simple object...
{
athlete: {
firstname: "Matt"
...
}
}
How can I just forward on the api request response to the clients fetch success method?
The problem is not CORS related, the response within the react app needed parsing as json:
.then((response) => {
console.log(response.json());
})