Express app body parser doesnt work with certain api.s - javascript

SO i have an express app that I have been building an app that uses a body parser that works with my entire app client side. ( receive post req data )
but app.use(bodyParser.json()); seemed to cause issues with apis which is why i commented it out. now that I dont use it, i cant receive post data from my website.. What should I do so that apis and my website works?
// APP
var app = express();
//app.use(bodyParser.json()); //ISSUE: this is breaks API post //but i need it to recieve MY post req data
app.use(bodyParser.urlencoded({ extended: true }));
app.use(fileUpload());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});

A simple kludge would be to define the routes that twilio uses before you activate the bodyParser middleware. Without knowing more about why exactly the bodyparser prevents twilio from working, that's the best I can do.

In generell I alway suggest to not register body parsers globally for all follow up routes, but directly with the route or only locally for one router (path prefix) where it is required.
Moving the routers of twilio before registering the bodyParser for all following routes will also work, but it is less maintainable.
So if you need json data in on specific route, then write it that way:
app.post('/some/route', bodyParser.json(), (req, res, next) => {
// processing of your json
});
The reason why I suggest this is, because the body that is submitted to the server is provided as stream. Whenever you register a middleware that will process the body then it will consume the whole content, and you cannot use any other middleware that will also process the body after that. Using it only for the route where you need this parser eliminates this problem, and allows you to use different body parsers depending on the route.
The larger your project becomes the more likely it is that you come to a situation where you need an other body parsers, then you will be most likely at a point where moving the routes would not work anymore.

Related

How to integrate express.js with your website

I built a simple web portfolio page with html, css and javascript. I did it with no framework like angular or react. I used bootstrap for my footer alone.
I used webpack as my bundler and everything is working just perfect but my problem right now is that I want to integrate express.js with my app and I have no idea how to do that, I'm about finishing Server side programming with Nodejs and Express course from Coursera. I have searched through google but couldn't find what I want.
There are different ways to integrate your backend with your frontend. You said you were finishing up a course on Node JS and Express on Coursera so I'll assume you already know how to set up your server and whatnot.
If you're starting out and just want to have your data coming from a database and have it populated in the actual HTML I would take a look at EJS. It allows you to embed data into an HTML page, that way you can generate a finished HTML page with all the data you need. This is great for things like SEO.
Another way is to have some client-side Javascript that queries your backend via a REST API in some way like:
In Express:
async function getSomethingFromDB(req, res) {
const data = await getDataFromDb()
res.send(data)
}
app.get("/something", getSomethingFromDB)
In your frontend JS:
async function fetchDataFromBackend() {
const res = await fetch(`/something`)
const data = await res.json()
return data
}
You can call fetchDataFromBackend however you want and do whatever you need with data, such as populating your website with this data. This approach is great to make interactive applications but has its own problems regarding SEO and I would advise the first method, using this technique once you require AJAX in your website.
I hope this helps!
Install in your backend project folder, in console: npm install express --save
var express = require('express');
var app = express();
// Configure headers y cors
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
res.header('Allow', 'GET, POST, OPTIONS, PUT, DELETE');
next();
});
app.use('/api', project_routes);
If you want to expose your back-end API to your front-end in a simple way, can I suggest using api-mount which is based on express under the hood.
Should you need to customize express, introduce additional middlewares or similar - api-mount allows that.
The downside is that your back-end would not be RESTfull and you would learn less about express itself. Still, try it out - you might like it :)

Form Submit shows strange error in console

I'm working on a small ToDo app where I've Angular as front-end and Node.js/Express/Mongo as middleware/backend.
While I submit Login in my Login form, it hits the login API, however it returns one strange output in the console saying
OPTIONS http://localhost:3000/api/v1/users/login/ 0 {}
(see screenshot below) which doesn't allow me to get the dashboard even after successful login.
I've enabled CORS through installing the cors NPM module. and I've checked RESTFul services in Postman, and all are working fine.
[Updated] This is how I've enabled the CORS in my express.js's app.js file.
let cors = require('cors');
app.use(cors());
app.options('*', cors());
before a CORS request is sent to the server, clients will always send this "OPTIONS" request as a "preflight request", soliciting supported methods from the server.
This request being blocked may be an indicator of a wrong CORS configuration or an explicit block of all "OPTIONS" requests from the server. (CORS needs to be configured on the server as well).
More information can be found here
It seems that this is a known nodejs issue that is still open.
Based on the open github, seems that the best recommendation is to try something like this:
you need to allow both:
// Http.OPTIONS method for request that is hitting " apiUrl =https://127.0.0.1:3000/login".
// Allow CORS like below:
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'content-type');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
Another great idea is to use the angular proxy settings for local development so that you will not need to add CORS for localhost at all.
Very good guidance in this SO answer here on setting up a proxy for angular If this work, then you can make 100% sure that it is indeed a CORS problem.
To handle CORS in express you dont need to add any dependency.
Notice that http://localhost:4200 is you angular app.
This worked for me:
//Add here whatever route you are using for the api.
app.use('/api', (req, res, next) => {
//Where http://localhost:4200 is the angular app
res.header('Access-Control-Allow-Origin', 'http://localhost:4200'),
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
})
Note:
This goes after the place where you import the routes and before where you use them. kind of like:
const apiRouter = require('./app_api/routes/api_routes');
//The code i posted here
app.use('/api', apiRouter);

Nodejs: Middleware for only page loading

I'm working with nodejs and ejs template. I want to set a middleware which will be called only when page loading, not when I send request from code.
Example:
app.use(function(req, res, next){
if(req.session){
console.log("OKAY");
}
next();
});
I want this log appears only on page loading, not when I send request from code like below
$.get( "/users", function( data ) {
console.log(data);
});
How can I do this ?
Thank you
You have a couple options:
In your middleware, you can check req.path to see if it's a path that you should apply the middleware to or not and use an if in your middlware to either just call next() without doing anything or to do whatever the middleware is designed to do.
You can design your routes to that page routes and ajax routes are on separate paths and then design a router for page routes and a router for ajax routes and put the middleware only on the page router.
It will really help you a lot (with either option above) if you design your URLs so it's easy for your server to distinguish whether this is a URL that should or should not have the middleware applied. Usually, the simplest way to do that is to use a known prefix on one or both branches of your URL design. For example, all ajax URLs could start with /api and then you can easily shunt all API calls off to a special router and all other URLs are non-API URLs (probably page URLs).
Here's an example of the separate API router:
// split off all API calls to a separate router
let apiRouter = express.Router();
app.use('/api', apiRouter);
// handle /api/users
apiRouter.get('/users', handleUserAjaxRequest);
// handle all other /api/xxx routes that don't have their own handler
apiRouter.use(function(req, res, next) {
// if /api request not handled by here, then don't allow it to propagate further
// it must be a invalid /api/xxx URL, so do a 404
res.status(404).end();
});
// this won't get called if there's a /api/xxx URL because that will have
// already been handled by the apiRouter
app.use(someMiddleware);
app.get('/somepage', handleSomePageURL);
You could also use a separate router for all your page requests which might make modularity a little cleaner with all the API routes in one module and all the page routes in another module, each exporting their own router.
I'm using JQuery to send request from client and I saw from jfriend00's link that req.xhr returns a Boolean property that is true if the request’s X-Requested-With header field is “XMLHttpRequest”, indicating that the request was issued by a client library such as jQuery.
app.use(function(req, res, next){
if(req.xhr){
console.log("FROM CLIENT LIBRARY");
}
next();
});
Thank you jfriend00

Getting Spotify API access token from frontend JavaScript code

I have a web app that allows people to generate a list of songs by artists that are related to a particular artist. I want to be able to connect to the user's Spotify account and create a playlist for them from that list of songs, but I need to get an access token. I have a developer account and client ID and am trying to work through the Authorization Flow, but it's not working for me. Instead, I get this error: XMLHttpRequest cannot load https://accounts.spotify.com/authorize/?client_id=d137fe25b31c4f3ba9e29d85f…:3000/callback&scope=user-read-private%20user-read-email&state=34fFs29kd09. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
This is a portion of my scripts.js file (i'm using the spotify-web-api-js node module):
$('#spotify').on('click', function() {
$.support.cors = true;
$.getJSON("https://accounts.spotify.com/authorize/?client_id=d137fe25b31c4f3ba9e29d85f4e47c66&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&scope=user-read-private%20user-read-email&state=34fFs29kd09", function(json2){
$.getJSON("https://accounts.spotify.com/api/token/?grant_type=authorization_code&code=" + json2.code + "&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=d137fe25b31c4f3ba9e29d85f4e47c66&client_secret={...}", function(json3) {
s.setAccessToken(json3.access_token);
});
});
});
});
According to my research, it's a CORS-related issue. I'm making edits to my ExpressJS server to remedy this cross-origin problem and installed the cors node module, but I'm still getting the same error.
index.js server:
var express = require('express');
var cors = require('cors');
var app = express();
var port = 3000;
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(express.static(__dirname + '/public')); // looks in public directory, not root directory (protects files)
app.get('/', function(req, res) {
res.send(__dirname + '\\index.html')
});
app.listen(port, function() {
console.log('CORS-enabled web server listening on port ' + port);
});
When I go to the URL in question directly through my browser, it gives me the expected "Do you authorize this app to use your Spotify information" form.
Should I require 'cors' in 'scripts.js' for it to work? Does anyone have any other suggestions?
I believe the issue here is that you're attempting to retrieve JSON data from the endpoint where you should direct your users. So instead of making a request to it, you should supply a button on your page that links to your https://accounts.spotify.com/authorize/{...} URL. The user will proceed to give your application the permissions you've requested as specified in the scope parameter, and will be directed back to the URL you've specified in the redirect_uri parameter. This is where you get the authorization code, which you can use in the https://accounts.spotify.com/api/token/{...} endpoint. Read more about the Authorization Code flow in the Authorization Guide.
Spotify Web API support three different oAuth flows, and you might be interested in Implicit Grant. Examples of all of these flows written in Javascript using Node is available at https://github.com/spotify/web-api-auth-examples.

How can a Node.js library register for HTTP requests on a particular URL path?

I am writing a library for a web service in Node.js. My library needs to handle all HTTP requests with a particular URL prefix (Eg, /_docs/*).
I want people to be able to use my library without changing much of their code.
The API should look something like this:
server = http.createServer(function(req, res) { ... });
...
myLibrary.listen(server, '_docs/');
or
server = new http.Server();
myLibrary.listen(server, '_docs/');
server.on('request', function(req, res) { ... });
If I merely register another event handler on the server object, the user's http request handler will be called on all HTTP requests as well. My code will race with the user's 404 handler.
Socket.io has a similar problem, and they solve it by making their .listen() function move all existing http request handlers into a private array. When HTTP requests come in, if their code doesn't handle the URL it calls the listeners in the array. However, as far as I can tell this wouldn't work in the second example I've shown above.
Whats the best way to make this work?
What about Connect? Router middleware provides rich Sinatra / Express-like routing.
Example
connect.router(function(app){
app.get('/user/:id', function(req, res, next){
// populates req.params.id
});
app.put('/user/:id', function(req, res, next){
// populates req.params.id
});
})
For advanced use look at http://expressjs.com/guide.html#routing.

Categories