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
Related
I made get request to Serp api, but learned that it is not possible to directly make fetch to Serp from React application, so I created local server and wrote logic for it, then I tested it with Postman and everything is fine. Then I had problems with CORS, I(guess) fixed them, but now I receive rejected promise on response and can't get rid of this. It gives
Unexpected end of input
Here is my server:
const SerpApi = require('google-search-results-nodejs');
const search = new SerpApi.GoogleSearch("myApiKey");
const express = require('express');
const app = express();
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.get('/:id', function (req, res) {
console.log("Made request");
const searchText = req.params.id;
const params = {
q: searchText,
tbm: "shop",
};
const callback = function (data) {
const objects = [...data["shopping_results"]];
console.log("call back worked");
if (!objects) {
console.log("ERROR 404");
res.status(404).send();
}
res.status(200).send(objects);
};
// Show result as JSON
search.json(params, callback);
});
app.use(allowCrossDomain);
app.listen(3001, function () {
console.log("App is listening for queries");
})
and my fetch:
import updateOnSearchRequest from '../redux/actions/updateOnSearchRequest';
export default function searchRequestToApi(queryText, dispatch) {
fetch(`http://localhost:3001/${queryText}`, {
mode: 'no-cors',
})
.then(res => console.log(res.json()))
.then(data => data ? dispatch(updateOnSearchRequest(data)) : {});
}
I receive error at console.log(res.json()) even though server works fine and doesnt give any errors
First of all, you need to remove mode: "no-cors", as mentioned in this answer, using it will give you an opaque response, which doesn't seem to return data in the body.
Second, move your app.use(allowCrossDomain); to the top so it's higher than app.get("/:id", function (req, res) {....
And lastly, you must remove console.log from .then(res => console.log(res.json())).
In summary, your server should be:
const SerpApi = require("google-search-results-nodejs");
const search = new SerpApi.GoogleSearch("myApiKey");
const express = require("express");
const app = express();
var allowCrossDomain = function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type");
next();
};
app.use(allowCrossDomain);
app.get("/:id", function (req, res) {
console.log("Made request");
const searchText = req.params.id;
const params = {
q: searchText,
tbm: "shop",
};
const callback = function (data) {
const objects = [...data["shopping_results"]];
console.log("call back worked");
if (!objects) {
console.log("ERROR 404");
res.status(404).send();
}
res.status(200).send(objects);
};
// Show result as JSON
search.json(params, callback);
});
app.listen(3001, function () {
console.log("App is listening for queries");
});
And your fetch should be:
fetch(`http://localhost:3001/${queryText}`)
.then(res => res.json())
.then(data => data ? dispatch(updateOnSearchRequest(data)) : {});
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.
greeting kings
i have api request that have cors problem. I'm able to solve by using proxy setup using nodejs. Unfortunately im trying to pass certain query parameter from my main js to app.js(nodejs proxy) so my api can have certain value from main js. How to solve this or should point me where should i read more.below is my code
main js
const inputValue = document.querySelector('input').value
//this value is maybeline
app.js(node.js proxy)
const express = require('express')
const request = require('request');
const app = express()
app.use((req,res,next)=>{
res.header('Access-Control-Allow-Origin', '*');
next();
})
app.get('/api', (req, res) => {
request(
{ url: 'https://makeup-api.herokuapp.com/api/v1/products.json?brand=covergirl' },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: err.message });
}
res.json(JSON.parse(body));
}
)
});
const port = process.env.PORT || 5500
app.listen(5500,()=>console.log(`listening ${port}`))
I want to pass inputValue as query to api in app.js
as
https://makeup-api.herokuapp.com/api/v1/products.json?brand=${type}
How to do it or point me any direction?
note:this api work withour cors problem.This is an example api..tq
You can use stringify method from qs module.
const { stringify } = require("qs");
app.get("/api", (req, res) => {
request(
{
url: `https://makeup-api.herokuapp.com/api/v1/products.json?${stringify(
req.params
)}`,
}
/// Rest of the code
);
});
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
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