Questions on to use Node.js as local server with Braintree? - javascript

I'm not new to JavaScript but I am new to Node.js and back end languages. I have a very simple question.
I've installed and setup Node.js on my computer and I'm attempting to get a server going between my static files & directory(s) and my browser to be able to send and receive requests. I've downloaded Braintree's free Sandbox (found here) for practice to get some faux transactions going just to gain a better understanding of how this can work.
I set up a local server by running npm install -g http-server on my command line and then http-server to set it up.
I then received the following message in my command line:
Starting up http-server, serving ./public
Available on:
http://127.0.0.1:8080
http://10.0.1.4:8080
Hit CTRL-C to stop the server
So, with this setup...if I wanted to do get() and post() methods and see it rendered and communicating between my "server" and my static files. How do I do this? For example, if I were to set up Braintree's sandboxed environment and then create a clientToken using the following code from Braintree's website
const http = require('http'),
url = require('url'),
fs = require('fs'),
express = require('express'),
braintree = require('braintree');
const gateway = braintree.connect({
environment: braintree.Environment.Sandbox,
merchantId: "xxxxx",
publicKey: "xxxxx",
privateKey: "xxxxx" //blocked out real numbers for privacy
});
Here is the remaining code I hae to create a "client Token" for a transaction...and here is the guide I'm following via Braintree's website...
http.createServer((req,res) => {
gateway.clientToken.generate({
},(err, response) => {
if(err){
throw new Error(err);
}
if(response.success){
var clientToken = response.clientToken
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(clientToken);
res.end("<p>This is the end</p>");
} else {
res.writeHead(500, {'Content-Type': 'text/html'});
res.end('Whoops! Something went wrong.');
}
});
}).listen(8080,'127.0.0.1');
So, my question is...if I wanted to generate send a token to a client using the get() method...how would I do that? Would it have to be a separate js file? How would they be linked? If they're in the same directory will they just see each other?
Here is an example on Braintree's website of how a client token may be sent:
app.get("/client_token", function (req, res) {
gateway.clientToken.generate({}, function (err, response) {
res.send(response.clientToken);
});
});
How could this be integrated into my current code and actually work? I apologize if these are elementary questions, but I would like to gain a better understanding of this. Thanks a lot in advance!

I don't know much about braintree, but usually you would use somthing like express.js to handel stuff like this. So I'll give you some quick examples from an app I have.
#!/usr/bin/env node
var http = require('http');
var app = require('../server.js');
var models = require("../models");
models.sync(function () {
var server = http.createServer(app);
server.listen(4242, function(){
console.log(4242);
});
});
So that's the file that gets everything started. Don't worry about models, its just syncing the db.
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
// share public folder
app.use(express.static(path.join(__dirname, 'public')));
require('./router.js')(app);
module.exports = app;
next up is the server.js that ties eveything together. app.use() lines are for adding middleware and the app.use(logger('dev')); sets the route logger for what your looking for.
app.use(express.static(path.join(__dirname, 'public'))); shares out all files in the public directory and is what your looking for for static files
var path = require('path');
module.exports = function(app){
//catch
app.get('*', function(req, res){
res.sendFile(path.join(__dirname, '..', 'public', 'index.html'));
});
}
last piece is the router.js. This is were you would put all of you get and post routes. generally I've found that if you see app.get or app.post in examples there talking about express stuff. It's used a lot with node and just makes routing way easier.
Also if your using tokens a route would look like this.
app.get('/print', checkToken, function(req, res){
print.getPrinters(function(err, result){
response(err, result, req, res);
});
});
function checkToken(req, res, next){
models.Tokens.findOne({value: req.headers.token}, function(err, result){
if(err){
res.status(500).send(err);
}else if(result == null){
console.log(req.headers);
res.status(401).send('unauthorized');
}else{
next();
}
});
}
so any route you want to make sure had a token you would just pass that function into it. again models is for db

Related

Why am I getting "name undefined" when trying to post using Express and Body Parser

I'm attempting to build a MEAN app and trying to test POSTing with POSTMAN. When I do, I keep getting the dreaded "TypeError: Cannot read property 'name' of undefined". If I type in a simple string, the POST goes through fine. But when I use "req.body.name" I get the error. I've looked in every place and I'm not seeing my mistake. I even followed the suggestions on this thread with no luck. Any help or suggestions would be greatly appreciated.
Here's the code I am currently working with in my server.js file:
const express = require('express');
var bodyParser = require('body-parser');
var Bear = require('./models/bear')
var path = require('path');
var mongoose = require('mongoose');
var router = express.Router();
var app = express();
var staticAssets = __dirname + '/public';
app.use(express.static(staticAssets));
app.use('/api', router)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// Routes for my API
//===================================
// middleware to use for all requests
router.use(function(req,res,next){
// logging happens here
console.log('Something will happen.');
next(); // Head to the next router...don't stop here
});
// Test router to make sure everything is working (accessed at GET http://localhost:3000/api)
router.get('/', function(req, res){
res.json({message: 'hooray! welcome to our api!'})
})
//More routes will happen here with routes that end in "/bears"
router.route('/bears')
//Create a bear (accessed at POST http://localhost:3000/api/bears)
.post(function(req,res){
var bear = new Bear(); // Create a new instance of the bear model
console.log(req);
bear.name = req.body.name; // set the bears name (comes from the request)
//res.send(200, req.body);
bear.save(function(err){
if (err)
res.send(err);
res.json({message: 'Bear Created!!'});
});
});
//======================================
//var Products = require('./products.model.js');
var Product = require('./models/product.model');
var db = 'mongodb://localhost/27017';
mongoose.connect(db);
var server = app.listen(3000);
console.log("App is listening on port 3000");
Thanks.
Also, the url I'm trying to use inside of POSTMAN is http://localhost:3000/api/bears
Express processes requests Top-Down, meaning if you require a piece of functionality to be applied to all routes via middleware, than that middleware needs to be added to your app before any routes that require it. This is usually the case for middleware such as body-parser.
When using Router Middleware, you don't typically construct the router in the same file as the actual Express app that will use it as middleware. Instead, place it in a separate file and/or directory for organization purposes, this is considered a best practice.
Express Apps can be structured like so
/lib
/models
bear.js
product.js
/node_modules
/public
/css
/routes
api.js
package.json
server.js
The routes directory is where you would place any applicable Router Middleware files such as your api router. server.js is your main Express App and public is where your static assets are stored. lib is directory that contains any business logic files and models.
The actual Express app and Router files should look something like this
server.js
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const apiRouter = require('./routes/api');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, public)));
app.use(/api, apiRouter);
app.listen(port, () => {
console.log(`Listening on port ${port});
});
module.exports = app;
routes/api.js
'use strict';
const router = require('express').Router();
const Bear = require('./lib/models/bear');
router.use((req, res, next) => {
// logging happens here
console.log('Something will happen.');
next(); // Head to the next router...don't stop here
});
router.get('/', (req, res) => {
return res.json({ message: 'hooray! welcome to our api!'})
});
router.route('/bears')
//Create a bear (accessed at POST http://localhost:3000/api/bears)
.post((req, res) => {
var bear = new Bear(); // Create a new instance of the bear model
console.log(req);
bear.name = req.body.name; // set the bears name (comes from the request)
//res.send(200, req.body);
bear.save((err) => {
if (err)
return res.send(err);
return res.json({message: 'Bear Created!!'});
});
});
module.exports = router;
To note, you could break up your API even further to increase the amount of decoupling. An example of this would be to move the /api/bear route to its own router middleware and into its own route file. Then simply add it to your routes/api.js router as a middleware like you would in server.js. If your app is going to have a decent sized API, then this would be the best approach because it would allow the most flexibility when it comes to applying middleware to only certain routes and would make maintaining the source much easier.

node.js serving up HTML documents in server directory

So I have a pretty simple question, at the moment my server file and HTML documents all live in the same directory. However, I've realised this has lead to quite an annoying problem. If I user were to type:
http://localhost:3000/HTML/homepage.html
The server serves them the HTML document, where usually they'd have to go through sign in, and have their session ID verified before they could access the homepage.
Is there any way to deny access to files held in the server directory?
Example of how my code currently runs:
var http = require('http'),
fs = require('fs');
var path = require("path");
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser')
var session = require('express-session')
var sqlite3 = require('sqlite3').verbose();
var express = require('express');
var app = express();
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
app.use(bodyParser());
app.use(express.static(__dirname));
app.get('/signin', function (req, res) {
res.sendFile(path.join(__dirname + '/HTML/signin'));
});
app.post('/signin', function (req, res) {
var email = req.body.email;
var password = req.body.password;
if (email!="" || password != ""){
req.session.sessID = email //using email for example purposes
res.setHeader('Content-Type', 'application/json' );
res.send(JSON.stringify({
success: true //the client then catches the JSON, and will redirect to http://localhost:3000/homepage
}));
}
}
app.get('/homepage', function(req, res){
if (req.session.sessID == undefined){
res.send("You must login first!")
}else{
res.sendFile(path.join(__dirname + '/HTML/homepage.html'));
}
}
The source of your problem is this:
app.use(express.static(__dirname));
This tells express to serve ANY file it can find on your hard drive from the app directory on down. This is not advisable. This will even serve up your private server source code files if the right path is entered into the browser.
You should distinguish between your static files and your dynamically handled routes and you should make sure there is no possibility of conflict between them.
A common design is to designate a separate directory on your hard drive for static HTML files (not your app directory) and then set up express static routing to there. And, make sure that none of your dynamic routes will ever be satisfied with the static routing.
For example, if your static HTML files are in a sub-directory HTML which is below your __dirname directory, then you can do this:
app.use(express.static(path.join(__dirname, "HTML")));
And, then make sure none of your dynamic HTML files such as homepage.html are in that directory (put them somewhere else that express.static() will not ever see).
If you don't actually want the user to be able to see anything except your custom routes, then get rid of the app.use(express.static(__dirname)); line entirely and just create custom routes for each page you are serving.

Passing req.body through Express middleware to routes

I'm using the body-parser npm package to parse POST data in Application/JSON format and using a few different express routers to modularize the routes I'm creating. Here's the important info in my main server.js file:
server.js
var express = require('express');
var bodyParser = require('body-parser');
app.use(bodyParser.json());
// I'm using a sessionId to identify a person in this dummy app instead of adding in authentication. So the API call is sent to http://localhost:5000/johndoe/todo
app.use('/:sessionId/todo', require('./routes/todoRoutes'));
var port = process.env.PORT || 9191;
app.listen(port, function () {
console.log('Express server listening on port ' + port);
});
todoRoutes.js:
var todoRouter = require('express').Router();
todoRouter.post('/', function (req, res) {
console.log("This is the post data:");
console.log(req.body);
});
module.exports = todoRouter;
req.body seems to be getting lost through the middleware; it logs {} to the console. However, on a whim I added the following to my bodyParsing middleware in server.js:
app.use(bodyParser.json(), function (req, res, next) {
next();
});
And now it's passing req.body through to todoRoutes.js. (It now logs {title: 'Testing'}, etc. to the console like I need it to.)
What's going on here? And what's the best way to structure this so that it works the way it's supposed to? I'm new to Express, so I admit I could be structuring this all wrong.
Ugh, nevermind. I was an idiot and found that the Content-Type Header of application/JSON got turned off in Postman (read: I must have turned it off at some point) and so the bodyParser was never being used.
Dammit.
Thanks for the help to those who responded!

Redirect all URLs to index.html on Parse.com

I suppose there are people who worked or played with Parse.com site hosting for there single-page apps. I have a webapp which is a SPA with main index.html file. I use pushState in the application and I want users to be redirected to index.html wherever they enter some url on my site, like '/profile', '/projects' and so on.
I configured it on my local machine with Express but as Parse has its own rules and environment, I think I need a specific solution that will work with it.
Please advise.
Have Express render your index.html as if it were an EJS view.
Either copy your index.html to cloud/views/index.ejs or sym-link it to the same location.
// app.js
var express = require('express');
var app = express();
app.set('views','cloud/views');
app.set('view engine', 'ejs');
app.get('/*', function(req, res) {
res.render('index.ejs');
});
app.listen();
I'd been looking for an answer to this question FOREVER, and turns out the Google Group for Parse.com seems more active than Parsers on Stack Overflow. Found this answer here. Replace 'YOUR_URL' with your URL.
******* EDIT *******
I now use the 2nd answer on the same Google Group since it seems to work better:
var express = require('express');
var app = module.exports = express();
app.express = express;
//push state interceptors
var pushUrlPrefixes = [""];
var index = null;
function getIndex(cb) {
return function(req, res) {
Parse.Cloud.httpRequest({
url: 'YOUR_URL',
success: function(httpResponse) {
index = httpResponse.text;
cb(req, res);
},
error: function(httpResponse) {
res.send("We're very busy at the moment, try again soon.");
}
});
}
}
pushUrlPrefixes.forEach(function(path) {
app.get("/"+path+"*", getIndex(function(req, res) {
res.set('Content-Type', 'text/html');
res.status(200).send(index);
}));
});
//redirect requests here, instead of parse hosting
app.listen();

Javascript file not loading in MEAN stack application

I am playing around and trying to learn the MEAN stack to create a single page application. I was able to get my back-end routes to work correctly. I've tested it using Postman and get the results I expect, however I cannot get my front-end to talk to the back-end correctly.
I reduced my front-end to very basic html and javascript, but still get a syntax error "Unexpected token <". When I inspect my coreTest.js file in the browser, I see that it's just a copy of my html file, rather than javascript code.
When I run index.html by itself (without server.js) coreTest.js runs just fine. I'm not sure why, when running my server.js file, my coreTest.js file doesn't work properly.
server.js
// Setup
var express = require('express');
var app = express(); // create app w/ express
var mongoose = require('mongoose'); // used for MongoDB connection
var morgan = require('morgan'); // log requests to the console
var bodyParser = require('body-parser'); // pull information from HTML POST
var methodOverride = require('method-override'); // simulate DELETE and PUT requests
// Configure
mongoose.connect('localhost:27017/test'); // connect to localhost db "test"
// varify connection
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error: '));
app.use(express.static(__dirname + '/public')); // set static files location
app.use(morgan('dev')); // log every request to console
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-url
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse vnd.api+json as json
app.use(methodOverride());
// define db model
var Todo = mongoose.model('Todo', {
text: String
});
var router = express.Router();
router.route("/todos")
.get(function(req, res) {
Todo.find(function(err, todos) {
if (err)
res.send(err);
res.json(todos);
});
})
.post(function(req, res) {
var todo = new Todo();
todo.text = req.body.text;
todo.save(function(err) {
if (err)
res.send(err);
res.json({mes: "Todo item created"});
})
});
router.route("/todos/:todo_id")
.delete(function(req, res) {
Todo.remove( {
_id: req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
res.json({mes: "Successfully deleted"});
});
});
// route to application
router.route("*")
.get(function(req, res) {
res.sendfile('./public/index.html');
});
// Register our routes
app.use('/api', router);
// Listen, start node app
app.listen(8080);
console.log("app listening on port 8080");
coreTest.js
alert("ping");
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Starter MEAN Single Page Application</title>
<script type="text/javascript" src="coreTest.js"></script>
</head>
<body>
I did it!! Wooo!!
</body>
</html>
I suspect the problem is between
app.use(express.static(__dirname + '/public'));
and
// route to application
router.route("*")
.get(function(req, res) {
res.sendfile('./public/index.html');
});
When you're running the server, your client-side code is trying to load "coreTest.js", which is matched by the last rule ; and so the server returns the content of index.html.
I'm not sure what you mean about "runing index.html by itself" ; if you mean "visiting file://..../public/index.html", it works because the browser will try to load coreTest.js from your file system.
Try using the "static" plugin only to serve files from "public", and use this prefix in the client side code :
app.use("/public", express.static(...))
and in the client
<script type=".." src="public/coreTest.js"></script>
Getting the path rights will depend on what's on your disk.
This might help, too : static files with express.js
I was able to solve my issue using what phtrivier recommended.
Instead of serving my files from "public" I chose to serve them from "api" because I already set my router to take requests from that path as well.
app.use("/api", express.static(__dirname + '/public'));
I didn't need to change my reference to coreTest.js in the html because my files were organized with coreTest already in the root directory like this:
public
-index.html
-coreTest.js

Categories