ClientSide code and server side code proplem - javascript

i had a proplem with making two js files one to be put in 'website' directory and the other outside it and when i add a post request it adds a new item to the array from the server side js file and itried it alot and it didnt work so ..
thats My ServerSide Code
/* Empty JS object to act as endpoint for all routes */
projectData = {};
/* Express to run server and routes */
const express = require('express');
/* Start up an instance of app */
const app = express();
/* Dependencies */
const bodyParser = require('body-parser')
/* Middleware*/
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const cors = require('cors');
app.use(cors());
/* Initialize the main project folder*/
app.use(express.static('website'));
const port = 3000;
/* Spin up the server*/
const server = app.listen(port, listening);
function listening(){
// console.log(server);
console.log(`running on localhost: ${port}`);
};
// GET route
app.post('/add', function (req, res) {
let data = req.body;
console.log(data);
});
// POST an animal
const data = []
app.post('/animal', addAnimal)
function addAnimal (req,res){
data.push(req.body);
console.log(data);
}
and That Is My ClientSide Code
/* Function to POST data */
const postData = async ( url = '', data = {})=>{
console.log(data)
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
try {
const newData = await response.json();
console.log(newData);
return newData
}catch(error) {
console.log("error", error);
// appropriately handle the error
}
}
// TODO-Call Function
postData('/addAnimal', {animal:'Tiger'});
postData('/addAnimal', {animal:'Lion'});
when i run the code inside the vs code editor it displays "{ animal: 'lion' }
{ animal: 'Tiger' }"
But it never console log the data

you forget to send the respone
must the route callback have a res endpoint
function addAnimal (req,res){
data.push(req.body);
console.log(data);
// add res end point
res.json({msg : 'added'})
}
//here too
app.post('/add', function (req, res) {
let data = req.body;
console.log(data);
res.end('hello world')
});

Your route is /add or /animal not /addAnimal
postData('/add', {animal:'Tiger'});
in your ServerSide this function should display a log
app.post('/add', function (req, res) {
let data = req.body;
console.log(data);
});
You can't console.log the data in your try / catch because you don't return any response in your server side. But first try log data in your server side controller for confirm the good serverSide execution, and return your response.

Related

make a request to an external api

i am learning node js and i have a problem. basically I'm trying to create an api route that will make a call to an external api
but when I do a test with postman, I get the error "Cannot GET /api/books". has anyone have an idea?
here is my function. (for security reasons I did not add my APIkey in the post
const pool = require("../db");
const fetch = require('node-fetch');
exports.getOneBooksbyName = (req, res, next) => {
const title = req.params;
const APIKey = "";
fetch("https://www.googleapis.com/books/v1/volumes?q=" +title+ "&key="+APIKey)
.then(res => {
const data = res.json();
res.status(200).json(data);
}
)
.catch(err =>{
res.status(500).json({message:'error'})
})
};
and then my route
const express = require('express');
const router = express.Router();
const {getOneBooksbyName} = require('../controllers/books');
router.get('/?title', getOneBooksbyName);
module.exports = router;
and finally my app.js
const express = require("express");
const pool = require("./db.js")
const UserRoutes = require("./routes/user.js");
const app = express();
var bodyParser = require('body-parser');
const BookRoutes = require("./routes/book.js");
app.use(express.json()); //pour gerer les requetes POST
app.use(bodyParser.urlencoded({
extended: true
}));
app.use((req,res,next)=>{// POUR CONTOUNER LA SECURITE CORS
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
next();
});
app.use('/api/users' , UserRoutes);
app.use('/api/books' , BookRoutes);
module.exports = app;
I use java script and jquery to achieve this
Javascript function using jquery ajax to call API via URL and return result
function api_fetch(url) {
var result = 0;
$.ajax({
url:url,
type: 'GET',
async: false,
dataType: 'html',
success: function (response) {
console.log(`response from fetch ${response}`)
result = response
},
error: function (error)
{
console.log(`response from fetch ${error}`)
result = error
}
})
return result
}
I personally created a Django API, and I need to check if there is a record for a number in a database, so I implemented another js function to call the API
function check_number(number) {
let get = api_fetch(`/api/verifnum/${number}`)
console.log(`check number fetch ${get}`)
}
when I console log check number it gives me desired result
check_number('number') // returns number of record if exist or 0

Undefined body of a fetch request (arraybuffer body) in node server

I've read a lot of similar questions, but any answer worked for me.
I'm trying to send an audio in the body of a fetch request (in vuejs) as an ArrayBuffer, but when I print it in the server side, the body is undefined.
Client code:
export async function makeQuery(data) {
let bufferAudio = await data.arrayBuffer();
console.log(bufferAudio);
const response = await fetch(`/api/query`, {
method: 'POST',
//headers: {'Content-Type': 'audio/mp3'},
body: bufferAudio,
})
.catch(function(e) {
console.log("error", e);
});
return response;
}
Node Server code:
const express = require('express');
const path = require('path');
const app = express(), port = 3080;
app.post('/api/query', async (req, res) => {
query = req.body;
console.log('query ', query); // Here the body is undefined
/*
Do some processing...
*/
});
When I send a simple json string in the request body (and app.use(express.json()) in the server)it works. But not with the arraybuffer audio. Thanks in advance

Twilio throws access denied error when trying to access by using fetch method

Good Evening,
I am experimenting with using APIs and rendering that data in an EJS template.
I am trying to get a specific message from Twilio using the URL.
I downloaded node-fetch so I can use fetch with nodejs.
If I use the URL Twilio wants me to use it says access denied.
URL: https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/Messages/{Message Id};
If I put my auth token in before or after the account sid, it says that it cant find the message.
URL: 'https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/{Auth token}/Messages/{Message Id}';
I have added my nodejs code below, any help is much appreciated.
/* Imports */
var express = require('express');
var router = express.Router();
var path = require('path');
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
/* .env import */
require('dotenv').config();
/* This parses the JSON from the AJAX req */
router.use(bodyParser.json());
/* Inputing the API keys for Twilio, they are in a .env file */
var accountSid = process.env.ACCOUNT_SID; // Your Account SID from www.twilio.com/console
var authToken = process.env.AUTH_TOKEN; // Your Auth Token from www.twilio.com/console
/* Creating boilerplate Twilio */
var twilio = require('twilio');
const { data } = require('jquery');
var client = new twilio(accountSid, authToken);
/* GET home page */
router.get('/', async (req, res, next) => {
const url_api = 'https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/Messages/{Message Id}';
/* Test */
const test = 'https://httpbin.org/get'
try {
await fetch(url_api)
.then(res => res.json())
.then(data => {
const body = body;
console.log(body);
res.render('index', {
body: body
});
})
} catch (error) {
console.log(error);
}
});
/*Twilio
1. Create a message on Twilio and send the message
2. The body is JSON from the AJAX request
*/
router.post('/', (req, res, next) => {
client.messages.create({
body: `${req.body.message}`,
to: `${req.body.number}`, // Text this number
from: process.env.PHONE_NUMBER // From a valid Twilio number
})
.then((message) => console.log(message.sid));
next();
})
module.exports = router;
After hours of working with the API, I found the solution.
The try method is where the magic happens. This gets the most recent message sent to the Twilio number and allows the body of the message to be available to the EJS template
/* GET home page */
router.get('/', async (req, res, next) => {
const url_api = 'https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/Messages/SM025191920c117b50102d09f0c1200ed3.json';
/*The try is where the magic happens. This gets the most recent message sent to the Twilio number and allows the body of the message to be available to the EJS template*/
try {
client.messages
.list({
from: '+17185412931',
limit: 1
})
.then(messages => messages.forEach(m =>
res.render('index', {
messagesId: m.body
})));
} catch (error) {
console.log(error);
}
});

Express.js Csurf working in postman but not React.js

I'm trying to setup CSRF tokens so that I can do a number of checks before issueing a token to the client to use in future requests.
Taking the guidance from the csurf documentation, I've setup my express route with the following:
const express = require('express');
const router = express.Router({mergeParams: true});
const csurf = require('csurf');
const bodyParser = require('body-parser');
const parseForm = bodyParser.urlencoded({ extended: false });
const ErrorClass = require('../classes/ErrorClass');
const csrfMiddleware = csurf({
cookie: true
});
router.get('/getCsrfToken', csrfMiddleware, async (req, res) => {
try {
// code for origin checks removed for example
return res.json({'csrfToken': req.csrfToken()});
} catch (error) {
console.log(error);
return await ErrorClass.handleAsyncError(req, res, error);
}
});
router.post('/', [csrfMiddleware, parseForm], async (req, res) => {
try {
// this returns err.code === 'EBADCSRFTOKEN' when sending in React.js but not Postman
} catch (error) {
console.log(error);
return await ErrorClass.handleAsyncError(req, res, error);
}
});
For context, the React.js code is as follows, makePostRequest 100% sends the _csrf token back to express in req.body._csrf
try {
const { data } = await makePostRequest(
CONTACT,
{
email: values.email_address,
name: values.full_name,
message: values.message,
_csrf: csrfToken,
},
{ websiteId }
);
} catch (error) {
handleError(error);
actions.setSubmitting(false);
}
Postman endpoint seems to be sending the same data, after loading the /getCsrfToken endpoint and I manually update the _csrf token.
Is there something I'm not doing correctly? I think it may be to do with Node.js's cookie system.
I think your problem is likely to be related to CORS (your dev tools will probably have sent a warning?).
Here's the simplest working back-end and front-end I could make, based on the documentation:
In Back-End (NodeJS with Express) Server:
In app.js:
var cookieParser = require('cookie-parser')
var csrf = require('csurf')
var bodyParser = require('body-parser')
var express = require('express')
const cors = require('cors');
var csrfProtection = csrf({ cookie: true })
var parseForm = bodyParser.urlencoded({ extended: false })
var app = express()
const corsOptions = {
origin: "http://localhost:3000",
credentials: true,
}
app.use(cors(corsOptions));
app.use(cookieParser())
app.get('/form', csrfProtection, function (req, res) {
res.json({ csrfToken: req.csrfToken() })
})
app.post('/process', parseForm, csrfProtection, function (req, res) {
res.send('data is being processed')
})
module.exports = app;
(make sure you update the corsOptions origin property to whatever your localhost is in React.
In Index.js:
const app = require('./app')
app.set('port', 5000);
app.listen(app.get('port'), () => {
console.log('App running on port', app.get('port'));
});
In React:
Create file "TestCsurf.js" and populate with this code:
import React from 'react'
export default function TestCsurf() {
let domainUrl = `http://localhost:5000`
const [csrfTokenState, setCsrfTokenState] = React.useState('')
const [haveWeReceivedPostResponseState, setHaveWeReceivedPostResponseState] = React.useState("Not yet. No data has been processed.")
async function getCallToForm() {
const url = `/form`;
let fetchGetResponse = await fetch(`${domainUrl}${url}`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"xsrf-token": localStorage.getItem('xsrf-token'),
},
credentials: "include",
mode: 'cors'
})
let parsedResponse = await fetchGetResponse.json();
setCsrfTokenState(parsedResponse.csrfToken)
}
React.useEffect(() => {
getCallToForm()
}, [])
async function testCsurfClicked() {
const url = `/process`
let fetchPostResponse = await fetch(`${domainUrl}${url}`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"xsrf-token": csrfTokenState,
},
credentials: "include",
mode: 'cors',
})
let parsedResponse = await fetchPostResponse.text()
setHaveWeReceivedPostResponseState(parsedResponse)
}
return (
<div>
<button onClick={testCsurfClicked}>Test Csurf Post Call</button>
<p>csrfTokenState is: {csrfTokenState}</p>
<p>Have we succesfully navigates csurf with token?: {JSON.stringify(haveWeReceivedPostResponseState)}</p>
</div>
)
}
Import this into your app.js
import CsurfTutorial from './CsurfTutorial';
function App() {
return (
<CsurfTutorial></CsurfTutorial>
);
}
export default App;
That's the simplest solution I can make based on the CSURF documentations example. It's taken me several days to figure this out. I wish they'd give us a bit more direction!
I made a tutorial video in case it's of any help to anyone: https://youtu.be/N5U7KtxvVto

node js Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client and no javascript object in console

I'm really struggling with an example project for an online course and I think there's alot I'm doing wrong with the code. The example code I'm given in these example projects frequently don't work and I need to add/change/remove parts all over the place. I think I'm making alot of wrong changes. The first problem I'm having is that I get this error when I go to /addAnimal:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
The second problem I'm having is that when I go to /fakeAnimalData I see the data in the body of the HTML but not in the console as a javascript object. Then when I go to /addAnimal and submit the form I get the fav data in the body of the HTML but not in the console. The ultimate goal is to get the data from /fakeAnimalData AND the data (animal and fact) from the form in /addAnimal to show up in the console as a single javascript object with all three elements (animal, fact, fav). This is the code I have so far:
server.js:
/* Empty JS object to act as endpoint for all routes */
projectData = {};
/* Express to run server and routes */
const express = require('express');
/* Start up an instance of app */
const app = express();
/* Dependencies */
const bodyParser = require('body-parser')
/* Middleware*/
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const cors = require('cors');
app.use(cors());
/* Initialize the main project folder*/
app.use(express.static('project1'));
const port = 8000;
/* Spin up the server*/
const server = app.listen(port, listening);
function listening(){
// console.log(server);
console.log(`running on localhost: ${port}`);
};
// GET route
const animalData = [];
const fakeData = {animal: "lion", fact: "a lion's roar can be heard five miles away"};
app.get('/fakeAnimalData', getFakeData);
function getFakeData(req, res) {
res.send(fakeData)
};
app.get('/all', getData);
function getData(req, res){
res.send(animalData)
console.log(animalData)
}
// function sendData (request, response) {
// response.send(projectData);
// };
// POST route
app.post('/add', callBack);
function callBack(req,res){
res.send('POST received');
}
// POST an animal
const data = [];
// TODO-Call Function
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(addAnimal)
function addAnimal(req, res){
newEntry = {
animal: req.body.animal,
facts: req.body.fact,
fav: req.body.fav
}
data.push(req.body);
res.status(200).send(req.body);
animalData.push(newEntry)
res.send(animalData)
console.log(animalData)
};
app.js:
function performActuion(e){
const fav = document.getElementById('fav').value;
const getAnimal = async (url) =>{
const res = await fetch(url);
try {
const data = await res.json();
console.log(data)
return data;
} catch(error) {
console.log()
}
};
/* Function to POST data */
const postData = async ( url = '', data = {})=>{
console.log(data);
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
try {
const newData = await response.json();
console.log(newData);
// console.log(newData);
return newData.json()
console.log(await response.json());
return await response.json()
}catch(error) {
console.log("error", error);
// appropriately handle the error
};
};
// TODO-Call Function
getAnimal('/fakeAnimalData')
.then(async function(data){
console.log(data)
let res = await postData('/addAnimal', (animal: data.animal, fact: "lions are fun", fav: fav));;
console.log(res);
})();
Any guidence at all would be much, much appreciated.
Thanks,
Mike
function addAnimal(req, res){
newEntry = {
animal: req.body.animal,
facts: req.body.fact,
fav: req.body.fav
}
data.push(req.body);
// >>>>res.status(200).send(req.body);
animalData.push(newEntry)
res.send(animalData)
console.log(animalData)
};
You can't modify the res object after it has been already been sent, thus the error

Categories

Resources