Axios post stalled in Chrome (CORS) - javascript

I am converting a code that connected AWS Lambda to nanoexpress. My VueJS frontend was not passing data correctly so I started to do changes and now I cannot reach the backend at all and I have no idea why.
The backend is trivial:
const nanoexpress = require('nanoexpress');
const app = nanoexpress();
app.post('/v1/authorizeUser', async (req) => {
console.log(req);
const { email, password } = req.body;
console.log(email);
return { status: 'Ok', body: req.body };
});
app.listen(3000).then(r => console.log('started'));
This is the original store.js code. I am able to send the request from Vue app in Chrome but it is not parsed correctly. Probably because of missing or incorrect content type
const axiosResponse = await axios.post(`${API_ENDPOINT}/authorizeUser`, JSON.stringify({
email: payload.email,
password: payload.password,
}));
and the server log:
body: [Object: null prototype] {
'{"email":"literak#seznam.cz","password":"centrum"}': ''
}
undefined
When I added Axios options, the chrome shows an error for this request but there is nothing on server.
const options = {
headers: {
'Content-Type': 'application/json',
},
};
const axiosResponse = await axios.post(`${API_ENDPOINT}/authorizeUser`, JSON.stringify({
email: payload.email,
password: payload.password,
}), options);
Chrome request looks strange, there is no response section, request headers are very different and I can see in the Timing tab, that the request stalled.
If I remove stringify function, it behaves the same:
const axiosResponse = await axios.post(`${API_ENDPOINT}/authorizeUser`, {
email: payload.email,
password: payload.password,
}, options);
And same trouble without stringify and custom options:
const axiosResponse = await axios.post(`${API_ENDPOINT}/authorizeUser`, {
email: payload.email,
password: payload.password,
}, options);
Only the first variant with stringify and without options reaches the server. I use Postman the request is processed by the server.
logs:
body: { email: 'literak#seznam.cz', password: 'centrum' }
}
literak#seznam.cz
Axios is the latest 0.19.2 version. Chrome is up to date as well. I have no idea why the other combinations do not reach the server. It looks like Chrome received a correct request. What can be wrong? It drives me crazy.
Update: console
Error: Network Error
at createError (createError.js?2d83:16)
at XMLHttpRequest.handleError (xhr.js?b50d:83)

CORS in nanoexpress is apparently known bug:
const corsPerRoute = cors();
app.options('/my-route', corsPerRoute, () => {});
app.get('/my-route', corsPerRoute, (req, res) => {
res.send('this route protected by your cors per-route config');
});

Related

Cross-Origin Request Blocked using NodeJS/Coinbase API

I'm trying to get Coinbase to work using NodeJS
I get the following error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3000/create-payment. (Reason: CORS request did not succeed). Status code: (null).
I've tried downloading one of those Corse plugins that should allow it but I just can't get it to work.
Javascript code:
<script> const button = document.getElementById('order');
button.addEventListener('click', event => { const form = document.getElementById('payment-form');
event.preventDefault(); // Prevent the form from submitting to the server
form.submit();
const price = "<?php echo $price; ?>";
const amount = document.getElementById('quantitymills').value;
const total_price = document.getElementById('inputd').value;
const fname = document.getElementById('fname').value;
const email = document.getElementById('email').value;
fetch('http://localhost:3000/create-payment', {
method: 'POST',
body: JSON.stringify({ price }),
body: JSON.stringify({ amount }),
body: JSON.stringify({ total_price }),
body: JSON.stringify({ name }),
body: JSON.stringify({ email }),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(payment => {
// Do something with the payment details
console.log(payment);
})
.catch(error => console.error(error)); });
Nodejs code:
const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');
const mysql = require('mysql2');
const app = express();
// Parse application/x-www-form-urlencoded requests app.use(bodyParser.urlencoded({ extended: false }));
// Connect to the database
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'coinbase' });
// Create a payment
app.post('http://localhost:3000/create-payment', async (req, res) => { try {
// Make an API request to create the payment
const response = await axios.post(
'https://api.commerce.coinbase.com/charges',
{
name: 'Product one',
description: 'Product one',
local_price: {
amount: req.body.total_price,
currency: 'USD' },
metadata: {},
pricing_type: 'fixed_price',
redirect_url: 'http://localhost/index.php'
},
{
headers:
{ 'X-CC-Api-Key': 'myapikey' } }
);
// Store the payment URL in the database
const payment = {
url: response.data.hosted_url,
amount: req.body.total_price,
currency: 'USD',
status: 'pending'
};
db.query('INSERT INTO payments SET ?', payment, (error, result) => {
if (error) throw error;
res.send(payment);
});
} catch (error) { console.error(error); } });
app.listen(3000, () => { console.log('Server listening on port 3000'); });
It might be something else wrong in my code, I am still new to coding and could have messed up in another area not quite sure.
Any help would be greatly appreciated!
Downloading cors plugin
tried 127.0.0.1 instead of localhost
tried switching ports
Try it like this:
npm install --save cors
Then inside your code put
const cors = require('cors');
at the begining and this before the row with app.listen(3000....)
app.use(cors({
origin: '*'
}));
This will allow request from all domains to your backend.
To authorize only your domain (your browser requests) substitute the "star" after origin with the domain (even localhost:port) where your frontend is running.
Hint: you should create environments variable for the domain names. So if you deploy it to a production site you can dynamically substitute them.

Pact verification failed! with console error Missing requests: GET /users/login

am very new to Pact-js and contract testing I'll try my best to explain my issue.
for now, I am only trying to generate the consumer contract
here is my pact provider:
export const provider = new Pact({
consumer: 'Users',
provider: 'UsersService',
port: 1234,
log: path.resolve(process.cwd(), 'logs', 'pact.log'),
pactfileWriteMode: 'overwrite',
logLevel: "DEBUG",
dir: path.resolve(process.cwd(), 'pacts'),
});
and here is my test:
jest.mock("axios");
const EXPECTED_BODY = {...}
describe("Pact tests axios", () => {
describe("/GET login", () => {
beforeAll(() => provider.setup());
afterEach(()=> provider.verify())
afterAll(() => provider.finalize());
it("should login user and response with user object", async () => {
await provider.addInteraction({
state: 'user logged', uponReceiving: 'request logged user', withRequest: {
method: 'GET',
path: '/users/login',
body: {username: "test", password: "11223344"},
}, willRespondWith: {
status: 200, headers: {
'Content-Type': 'application/json',
}, body: eachLike(EXPECTED_BODY),
},
});
axios.get.mockResolvedValueOnce(EXPECTED_BODY);
const loggedUser = await loginUser("test", "11223344")
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.get).toHaveBeenLastCalledWith("http://localhost:8080/users/login", {"headers": {"Content-Type": "application/json"}, "params": {"password": "11223344", "username": "test"}})
expect(loggedUser).toEqual(EXPECTED_BODY)
})
});
})
I should say that my original request takes two parameters username and password and returns an object containing all that user's information of course the user exists if not it returns null
here is the API call function if needed:
export default async function loginUser(username, password) {
try{
return await axios.get(("http://localhost:8080/users/login"), {
headers: {
"Content-Type": "application/json"
},
params: {
username: username,
password: password
}
})
}catch (e){
return null
}
}
Pact expects you to actually make the call to the endpoint you're mocking in Pact.
Missing requests: GET /users/login
This error says "you said you'd make a GET call to /users/login but I didn't receive it".
jest.mock("axios");
This looks like you're mocking the HTTP client Axios. Now you have a mock for the thing that needs to send requests to the Pact Mock.
In a Pact test, think of it as a unit tests for your API client code. The actual request needs to be sent to the Pact Mock and Pact will check the correct request was made, and return back the mocked response.
So the solution is simple:
Remove all of the axios mocking
Provide a way to modify the API target for loginUser
Configure your API client to send the request to localhost:1234 instead of the real thing before running the tests
(NOTE: you can have pact find a free port dynamically by not setting the port option, and take the host from the response from the setup() call)

GetResponse 400 Bad Request

I'm trying to send a POST method to https://api.getresponse.com/v3/contacts from my Vue using axios. I'm unsure why I kept getting a 400 Bad Request. I've tried checking the Network tab on Mozilla dev tools but there doesn't seem to have any Response message it just returned me.
XHR OPTIONS https://api.getresponse.com/v3/contacts [HTTP/1.1 400 Bad Request 763ms]
I have double confirm from GetResponse documentation to add the Content-Type header to application/json and to set my API key as X-Auth-Token: api-key <API_KEY>.
NOTE: I am also getting CORS header ‘Access-Control-Allow-Origin’ missing but I believe it does not have anything to do with the Error 400.
Here are some code snippets from my Vue file.
axios-config.js
const instance = axios.create({
baseURL: process.env.VUE_APP_GET_RESPONSE_BASE_URL,
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': `api-key ${process.env.VUE_APP_GET_RESPONSE_API_KEY}`,
}
});
Vue
import axios from "#/services/axios-config.js";
user: {
name: "",
campaign: {
campaignId: `${process.env.VUE_APP_GET_RESPONSE_CAMPAIGN_ID}`
},
email: "",
customFieldValue: {
customFieldId: "interest",
value: []
}
}
async callSubscribeAPI() {
try{
const response = await axios.post("/contacts",this.user);
console.log(response);
}catch(error){
console.log("error");
console.log(error);
}
}
This works for me:
(async() => {
const url = 'https://api.getresponse.com/v3/accounts';
const payload = await axios({
method: 'get',
url,
headers: {
"X-Auth-Token": "api-key 12345*****",
"content-type": "application/json"
}
});
console.log("payload", payload.data);
})()

Server status 400 blocks json from sending response to client

I'm currently developing client side for my app.
When i try to login user in case where email and password is correct everything works fine but sending error data isn't occuring because status(400) blocks it.
Here is part of my server side code for user login that isn't sending object with isAuth, message, err:
User.findOne({ email: req.body.email }, (err, user) => {
if (!user) return res.status(400).json({
isAuth: false,
message: "Auth failed, bad email",
err
})
But when I make it like that i get the error with all parameters:
User.findOne({ email: req.body.email }, (err, user) => {
if (!user) return res.json({
isAuth: false,
message: "Auth failed, bad email",
err
})
Another strange thing is that when I send bad request with Postman I'm getting all the response data.
And here is client side function that is making request, the console.log(request) part is blocked because of status 400:
const submitForm = async (e) => {
e.preventDefault()
const request = await axios.post('/api/login', { email: email, password: password }).then(res => res.data)
console.log(request)
dispatch({
type: "USER_LOGIN",
payload: request
})
}
And here is some of Chrome stuff from console:
xhr.js:166 POST http://localhost:3000/api/login 400 (Bad Request)
createError.js:17 Uncaught (in promise) Error: Request failed with status code 400
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:60)
There was an axios error/bug.
I have rewrited my code using fetch API. It seems that axios has some kind of bug when it comes to handling 4xx and 5xx status.
Now client part looks like this:
const submitForm = async (e) => {
e.preventDefault()
const request = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email, password }),
headers: {
'Content-Type': 'application/json',
}
}).then(res => res.json())
console.log(request)
dispatch({
type: "USER_LOGIN",
payload: request
})
}
At the server side everything is just as it should be, return res.status(400).send(data)

Still getting a 503 error when making API calls in my React app

I am trying to get my React-Redux app to communicate to my deployed Heroku API via Axios.
When I try to make a POST request to my Heroku server via Axios I get this error message in my console in the Chrome developer tools:
As you can see in the screencap, I am getting "No 'Access-Control-Allow-Origin' header is present on the requested resource." as well as error status code of 503.
And something I find rather odd is that my /register request is being fired twice. Is that normal?
Here is the configuration in my app.js file in my backend code to enable cross domain requests:
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Origin,X-Auth,X-Requested-With,Content-Type,Accept,content-type,application/json,x-auth,Access-Control-Request-Method,Access-Control-Request-Headers");
next();
});
And here is the Axios code that makes the API call to the server in my front-end:
import axios from 'axios'
export function register(fields) {
console.log('below are the fields');
console.log(fields);
return function action(dispatch) {
let objArrSkills = Object.keys(fields.form_skills);
let skillsArr = objArrSkills.map(function (value) {
if (fields.form_skills[value] === true && fields.form_skills[value] !== undefined) {
return value;
}
});
let objArrArts = Object.keys(fields.form_arts);
let artsArr = objArrArts.map(function (value) {
if (fields.form_arts[value] === true && fields.form_arts[value] !== undefined) {
return value;
}
});
console.log('artsArr is...' + artsArr);
console.log('skillsArs is...' + skillsArr);
const request = axios({
method: 'post',
url: "https://jammr-backend.herokuapp.com/register",
data: {
firstName: fields.form_first_name,
lastName: fields.form_last_name,
email: fields.form_email,
password: fields.form_password,
skills: skillsArr,
iWantToMake: artsArr,
street: fields.form_address,
city: fields.form_city,
provinceState: fields.form_province,
gender: fields.form_gender,
imLookingFor: ['Acting', 'Drawing', 'Music', 'Writing', 'Programming', 'Videography']
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': "Access-Control-Allow-Headers,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Origin,X-Auth,X-Requested-With,Content-Type,Accept,content-type,application/json,x-auth,Access-Control-Request-Method,Access-Control-Request-Headers",
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS'
}
});
return request.then(response => {
console.log('axios call ran! Below is response....');
console.log(response);
dispatch({
type: 'REGISTER',
payload: {
myId: response.data,
fields: fields,
skills: skillsArr,
iWantToMake: artsArr
}
})
},
err => {
if (err) throw err;
})
}
};
Is there anything wrong with my code? Here is my front-end and back-end code on Github.
And in case it's relevant, my backend is deployed on Heroku. Also, I did try using the cors npm package, but it didn't work.
I would be willing to bet you are getting the 503 from the heroku stack because of some issue with your backend. (A timeout perhaps?) Obviously, the Heroku stack is not going to add the cross origin headers which is why you are seeing the cross origin errors in the JS console. Can you perhaps post your server logs?

Categories

Resources