Axios - API returning HTML instead of JSON - node.js

I'm developing an application using the MERN stack. As I deployed my demo version on render.com, I faced some issues. Sometimes the Axios request is returning HTML, instead of a JSON file.
ItemController.js
const getItem = async (req, res) => {
const { type } = req.params;
if (!type) {
throw new BadRequestError("Please provide all values");
}
const items = await Item.find({ type: type });
res.status(StatusCodes.OK).json({ items });
};
Request
const authFetch = axios.create({
baseURL: "/api/v1",
});
//Request
const findItems = async () => {
dispatch({ type: LOADING_ITEMS_BEGIN });
let url = "/items";
if (state.currentCategory) {
url = url + "/" + state.currentCategory;
}
try {
const { data } = await authFetch.get(url);
console.log(data);
dispatch({ type: LOADING_ITEMS_SUCCESS, payload: { data } });
} catch (error) {
console.log(error);
dispatch({
type: LOGIN_USER_ERROR,
});
}
};
I've checked the request URL, it's always fine. But it seems like the requests do not even reach the server when it sends back HTML, and I get 200 as a status code.
I tried to trace the request, but couldn't find any clue
Edit: It seems fine using Postman, so something is definitely wrong with the request.

Related

How I do redirect using Express. EJS with external javascript?

I have a login form which is collect user email and password. Then I use JavaScript fetch to post data to express. then I use express validator check the inputs are correct. Then I send response res.status(200).redirect("/auth"); like this, but JavaScript is prevent the login page to redirect because in my external JavaScript I use e.preventDefault() function. But I want to redirect to next page. When I remove e.preventDefault() it stops the validation so I cant remove that. What should I do?
I'm using Node, Express Js, JSON file for storing Data, EJS Template with external JavaScript file. Aslo serving static JavaScript file too which is located in public/js/script.js file. Also using express-validator in middleware folder to validate the fields
Here is the express code:
export const loginsHandle = async (req, res) => {
const {
email,
password,
} = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({
errors: errors.array(),
});
} else {
try {
var accountPP = new PP({
email: email,
password: password,
});
let addingData = JSON.parse(fs.readFileSync(accountDataFile, "utf-8"));
addingData.push(accountPP);
await fs.writeFileSync(accountDataFile, JSON.stringify(addingData));
res.status(200).redirect("/auth");
} catch (error) {
console.log(error);
res.status(200).send(error);
}
}
};
Here is external JavaScript :
const form = document.querySelector("form");
const emailInput = document.getElementById("email");
const passwordInput = document.getElementById("password");
const btn = document.getElementById("submit");
const forGot = document.getElementById("forgot");
const singBtn = document.getElementById("sign");
const footer = document.getElementById("menuFoot");
forGot.addEventListener("click", (e) => {
e.preventDefault();
});
singBtn.addEventListener("click", (e) => {
e.preventDefault();
});
footer.addEventListener("click", (e) => {
e.preventDefault();
});
form.onsubmit = sendLogin;
function sendLogin(e) {
e.preventDefault();
let formData = new FormData(form);
let Params = {
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
body: JSON.stringify({
email: formData.get("email"),
password: formData.get("password"),
}),
method: "POST",
};
fetch("http://localhost:5001/login", Params)
.then((res) => {
return res.json();
})
.then((data) => {
if (data.errors) {
data.errors.forEach((err) => {
if (data.errors[0].param == "email") {
emailInput.style.borderColor = "red";
} else if (data.errors[0].param == "password") {
passwordInput.style.borderColor = "red";
} else {
emailInput.style.borderColor = "";
passwordInput.style.borderColor = "";
}
});
}
return data;
})
.catch((error) => console.log(error, "error"));
}
When you send a REST request using fetch() in the browser, the browser doesn't process the response. It's up to your code to look at the status code and body of the response and take any action that you need to. The browser will not change the URL based on the response.
My recommendation is to use 200 to indicate that the login was successful, and then in the browser code, navigate to /auth. In your server code, you should send a 500 status instead when there's an error.
To simulate a redirect, your best bet is to use location.replace (see How do I redirect to another webpage? for a discussion on why):
window.location.replace('/auth.html')

Axios is returning undefined

My API is returning proper data when I am requesting from Postman. Even API is getting properly called from React, I checked using console.log inside the controller, but I am always getting undefined response. I am not sure what the mistake is.
const submit = async (e: SyntheticEvent) => {
e.preventDefault();
const response = await axios
.get('certificates', {
params: { sponser },
})
.then((res) => {
console.log(response); //undefined
alert(res.status); //200
alert(res); //[object Object]
});
};
Could you please help me on the same.
You need to return res in the then to have access on response:
const response = await axios
.get('certificates', {
params: { sponser },
})
.then((res) => {
console.log(response); //undefined
alert(res.status); //200
alert(res); //[object Object]
// response is not defined here!
return res;
});
console.log(response);
Shorter way:
const response = await axios
.get('certificates', {
params: { sponser }
});
console.log(response);
It seems that OP is relatively new to js - I can recommend this intro to async js: https://javascript.info/async-await

React/Express - Axios get request help needed

Trying to make an API get request from front-end (React) to back-end (Express/MongoDB) using Axios. If I use Postman to make the request it works fine (you can enter a user ID in the request body and get back an array of objects containing that user ID, which is what I want), but doing it from a front-end built in React doesn't work, I just get an empty array returned. As far as I can tell my API call from the front-end is exactly the same as the one I'm making in Postman! Can anyone shed any light on this?
This is the code making the get request from the front end:
const getActivities = async (currentUser) => {
const config = {
crossdomain: true,
headers: {
"Content-Type": "application/json"
},
body: {
"user": `${currentUser[0].id}`,
}
}
try {
const res = await axios.get('http://localhost:5000/api/activities', config)
console.log(res)
dispatch({
type: GET_ACTIVITIES,
payload: res.data
})
} catch (error) {
console.log(error)
}
}
And this is the route on the back-end handling this particular request:
router.get('/', async (req, res) => {
try {
const activities = await Activities.find({ user: req.body.user }).sort({ date: -1 })
if (!activities) {
res.json({msg: "Nothing found. Go forth and exercise!" })
}
res.json(activities).send()
} catch (err) {
res.send(err.message)
}
})
Thanks in advance!
You cannot send a request body with GET method see API AXIOS only for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'.
for example if you want to keep a GET method use params
// React
const config = {
crossdomain: true,
headers: {
"Content-Type": "application/json"
},
params: {
user: `${currentUser[0].id}`,
}
}
try {
const res = await axios.get('http://localhost:5000/api/activities',config)
console.log(res.data)
}catch(err){
...
}
// Express
router.get('/', async (req, res) => {
console.log(req.query.user)
}

TestCafe Triggering Test By POST Request In Express

I had a question that doesn't seem to be answered anywhere.
I am running tests from within my Express.js api. I set up a page that has a button and a field to enter a keyword intended to be used during a testcafe test. My endpoint I set up is /testcafe. But after sending a post request to /testcafe, there is a long delay while test runs and so my question is what is the best next step besides hanging?
Also, can my post request body, which contains the keyword, be directly used in a test like this? Keep in mind it's this pattern:
frontend -> POST request -> Express server -> /testcafe endpoint - test
My problem is after it reaches test, I currently have it attempting to call fetch from within the request logger. Is this right?
import { ClientFunction, Selector } from 'testcafe';
import { RequestLogger, RequestHook } from 'testcafe';
import zlib from 'zlib';
import fetch from 'isomorphic-unfetch';
const url = 'https://www.mysitetesturl.com/page';
class MyRequestHook extends RequestHook {
constructor (requestFilterRules, responseEventConfigureOpts) {
super(requestFilterRules, responseEventConfigureOpts);
}
onRequest (e) {
console.log('in onRequest!')
console.log('========================')
console.log('Request Body')
let buf = e._requestContext.reqBody
console.log(buf.toLocaleString())
}
onResponse (e) {
let buf = Buffer(e.body)
let unzippedBody = Buffer(zlib.gunzipSync(buf))
let payload = unzippedBody.toLocaleString()
fetch('http://myapiipaddress/api/testcafe',
method: 'PUT',
body: JSON.stringify(payload)
)
.then((err, doc) => {
if(err) {
console.log(err)
} else {
console.log(doc)
}
})
}
}
const myRequestHook = new MyRequestHook({
url: url,
method:'get'},
{
includeHeaders: true,
includeBody: true
}
);
fetch('http://myapiipaddress/api/testcafe',
method: 'GET'
)
.then((err, doc) => {
if(err) {
console.log(err)
} else {
fixture`myfixture`
.page(doc.url)
.requestHooks(myRequestHook);
test(`mytest`, async t => {
const inputField = Selector('input');
await t
await t
.wait(5000)
.typeText(inputField, doc.text)
.wait(5000)
}
);
}
})
According to your scheme, you need to organize your code in a different way:
const createTestCafe = require('testcafe');
....
// Choose the necessary body parser for express application
// https://github.com/expressjs/body-parser
app.use(bodyParser.urlencoded({ extended: true }));
...
app.post('/', function (req, res) {
createTestCafe('localhost', 1337, 1338, void 0, true)
.then(testcafe => {
const runner = testcafe.createRunner();
return runner
.src('/tests')
.browsers('chrome')
.run();
})
.then(failedCount => {
testcafe.close();
res.end();
});
})

POST request with Axios not sending data to my server

Here is my React code for the form submission:
const handleSubmit = (e) => {
e.preventDefault();
console.log('item:', item);
Axios.post('http://<MY_SERVER>/item/add', {name:item})
.then(response => console.log(response))
.catch(err => console.log(err));
};
and this is the code in my Node API:
// Add a new Item
app.post('/item/add', (req, res) => {
const newItem = new Item({
name: req.body.name
});
newItem.save()
.then(item => {
res.json({msg: 'success'});
})
.catch(err => console.log(err));
});
When I run the handleSubmit nothing happens. I only get the console.logs... Also, here is the error from my server
'ValidationError: item validation failed: name: Path' `name` is required
So it is clear that the data sent over to the api is never received. I've tried changing it up in many ways I have came across online but no luck.
I have attached both ways to post data i.e. Form URL Encoded and JSON. For sending Form Url Encoded data we need an additional Library querystring.
You can install it using npm install query-string
Here is the code for both the requests. You don't need query-string if you are using content type application/json.
Here you go
var axios = require('axios');
const qs = require('querystring');
function sendFormUrlEncodedData() {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
const payload = {
name: 'morpheus',
job: 'leader'
};
//Send data with form url using querystring node package for it.
axios
.post('https://reqres.in/api/users', qs.stringify(payload), {
headers: headers
})
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err);
});
}
function sendJSONData() {
const headers = {
'Content-Type': 'application/json'
};
const payload = {
name: 'morpheus',
job: 'leader'
};
//Send data with JSON, so stringifying it.
axios
.post('https://reqres.in/api/users', JSON.stringify(payload), {
headers: headers
})
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err);
});
}
sendFormUrlEncodedData();
sendJSONData();
First of all check whether your backend code is working or not by using postman. I think you are getting validation error because of the error of your backend code. And also check whether that you are implemented the name attribute correctly with its data type.
After that update, the react code as below.
import axios from 'axios';
constructor() {
this.item = {
name: ''
}
}
handleSubmit(event) {
console.log('item:', this.item.name);
event.preventDefault();
axios.post('http://<MY_SERVER>/item/add', this.item)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
}

Resources