Where does the /api directory come from in an Express application? - node.js

For example:
router.get('/api/todos', function (req, res){
db.todos.find(function (err, data){
res.json(data);
});
});
I am having a hard time understanding what '/api/todos/ actually means. I don't have a directory name either one of these in my application. What exactly is this and where is it?

/api/todos/ does not refer to a local file, it corresponds to a URL request. In the function you provided, if you were to add this route to an express app then visit http://localhost/api/todos, the server would respond with the JSON data returned from the database query you are making.
router.get('/api/todos', function (req, res){
This first line accepts all GET requests to /api/todos, and passes the req and res objects into a callback for you to work with. See http://www.murvinlai.com/req-and-res-in-nodejs.html for an explanation of those objects.
db.todos.find(function (err, data){
Here, it is assumed that you have a db object which may perform database lookups based on some kind of input parameters.
res.json(data);
The res.json method simply sends the JSON back to the client that requested it.
See https://www.packtpub.com/books/content/understanding-express-routes for further info on routing in express.

That's not a directory. That's a URL. Routers route URLs to resources. It could be files, it could be other URLs or most commonly it could be some javascript logic that generates the response you want (JSON, XML, HTML, PDF etc.)

Related

Socket.io and request and response objects

I'm quite new on node.js and now I'm learning socket.io.
I'm developing an app step by step so, at this time, I have an app that can login an user, do crud operation in mysql and mongodb and upload files, all these operations are manage with some web pages with HTML and javascript technologies launched directly from restify.
After that I'm tring to add socket functionality to, at this time, simple print who is online.
So, before I have something like:
server.get('/login', function(req, res, next){ ... });
and now I have something like:
socket.on("login", function (req, res, next){ ... });
but, naturally, req and res are undefined!
Are there the same objects into socket.io?
To my understanding, you want to pass values back and forth in your request and response using socket.io.
Yes it is possible to do that and you syntax should be something like this...
Using express.js:
io.on('login', function(req){
client.emit('response event', { some: 'data' });
Note: when using emit you send the data to everyone, you have other methods like .broadcast(), .to(), etc.. for other use cases refer to socket.io github for better understanding
And lastly, inside emit you define the function you want to call on the client side and the data you want to send to the client.

POST Request creates file, followed by GET Request to download

Trying to do something seemingly basic.
I'd like to create a POST request through which I'll be sending JSONs. These JSONs will be created into files, which I'd like to return to the user via download.
The use case for this is that I'm building an application which takes a form and converts it into a JSON for upload to a MongoDB database. Users can load these JSONs into the application to re-load their old records as templates.
This is how I'm approaching it as of now:
// Download JSON Previews
var jsondownload = {};
// Grabs the JSON from POST request
app.post('/api/download', function(req, res, next){
jsondownload = {};
var json = req.body;
jsondownload = json;
res.json(jsondownload);
next();
});
// Immediately downloads the JSON thereafter
app.get('/api/download', function(req, res){
res.set({"Content-Disposition":"attachment; filename='test.json'"});
res.send(jsondownload);
});
What's the right way to do this?
There is no one "right" way to do it, but a few solutions include:
Remove the GET route handler (and the jsondownload variable) completely and just respond immediately with the Content-Disposition set appropriately. This is the better of the 3 because it reduces code and keeps things simple.
Use a simple redirect in your POST route handler. Instead of responding with the JSON immediately, you would do res.redirect('/api/download').
Do more or less what currently doing, but move the logic (the res.set() and res.send()) to a separate function that gets called from both route handlers.

How to push a sequence of html pages after one request using NodeJS and ExpressJS

I am turning around in stackoverflow without finding an answer to my question. I have used expressJS fur several days in order to make an access webpage that returns first an interstitial and then a webpage depending on several informations I can get from the requester IP and so on.
My first idea for the interstitial was to use this piece of code:
var interstitial = function(req, res, next) {
res.render('interstitial');
next();
}
router.get('/', interstitial, nextPage);
setting a timeout on the next nextPage callback function of router.get().
However it looks that I could not do that. I had an error "Error: Can't set headers after they are sent.". I suppose this is due to the fact that res.render already give a response to the request and in the philosophy of express, the next function is passing the req, res args for another reply to another function that possibly could do it. Am I right?
In that case, is there a way to give several answer, with timeout to one request? (a res.render, and after that in the next callback a rest.send...).
Or is this mandatory to force client to ask a request to give back another response? (using js on the client side for instance, or timers on client side, or maybe discussing with client script using socket.io).
Thanks
Not sure I fully understand, but you should be placing all your deterministic logic within the function of the handler you're using for your endpoint.
Kinda like so:
router.get('/', function(req, res){
var origin = request.origin;
if (origin == '11.22.33.44'){
res.send('Interstitial Page.');
}else{
res.send('Home Page');
}
});
You would replace the simple text responses with your actual pages, but the general idea is that once that endpoint is handled you can't next() it to secondary handler.

What does the first string parameter of app.post do?

I saw an example of app.post() function. What does the '/' mean? Are we required to use post and get methods in conjunction or can we just use one method?
app.post('/', function(req, res){
return;
});
The '/' is the root directory of your website. So that function would handle post requests for foobar.com/ . You don't have to use post and get methods in conjunction. Normally I use get and only use post for routes that I want to receive post data.
The code you posted means you're setting up the server to "listen" to the root url and execute the callback when the browser hits that url.
So, assuming you're using port 80, your url would be: http://localhost:80/
Since you're using the post method, then the callback will be executed when a post request is received on that url.
If you were to instead, use the get method, then you could just navigate to that url writing it on your browser address bar.
That way you can set all the endpoints for your web app.
Edit
If you want to know when to use post, get, and the other methods, you might want to check out this answer: Understanding REST: Verbs, error codes, and authentication
when you call app.post or app.get, you are listening for post or get requests, respectively. The first argument to these calls is the route at which you are listening for the request. so in the code below:
app.post('/', function (req,res) {
res.send("hello");
}
you are telling the server to call that function when someone makes a post request to the root of your domain (mydomain.com/).
likewise, the code below would tell the server to listen for get requests at "/getroute" (mydomain.com/getroute).
app.get('/getroute', function (req, res) {
res.send('hello');
}
post requests and get requests can be used seperately and do not have to be used in conjunction on the same route.
Look, the first parameter of app.post() is the route at which post data is received, which is sent by HTML form(action = '/') mean action attribute of your form tag, it is the route at which your HTML form will send your data. So, it no connection with the app.get parameter.

Some Connect terminology

Here are three pieces of terminology used in documentation relating to ConnectJS for NodeJS that keeps getting used, but that I don't completely undertand:
1) views and controllers
2) partials and collections
3) Middleware
Let's start from the bottom up.
Level 0: built-in http module
In the beginning, there is node.js's built-in http.Server written by Ryan Dahl. You write a function(req, res), and Node will call your function each time a new connection is accepted:
// Hello world HTTP server using http module:
var http = require('http');
var app = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello, world.');
});
app.listen(8080, '127.0.0.1');
Level 1: Connect
Connect, written by Tim Caswell, is simply a subclass of http.Server that makes it easier to organize your code. Instead of writing a single callback that handles every request, you chain together some middleware. Each middleware is a function(req, res, next) that handles the request if possible, or calls next(error) if it did not finish handling the user's request. The middleware handlers are called in the order of their use; you should call the catch-all app.use(connect.errorHandler()) at the end.
One important middleware is the router, which allows you to filter some middleware based on a pattern of the URL path. The syntax for the route patterns is based on ruby's Sinatra routes. When I use the filter /hello/:name, req.params.name will be set to the matching part of the URL.
var connect = require('connect');
var app = connect.createServer();
app.use(connect.favicon());
app.use(connect.logger());,
app.use(connect.router(function(app) {
app.get('/hello/:name', function(req, res, next) {
try {
if (Math.random() > 0.5) {
throw new Error('Random error!');
}
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello, ' + req.params.name);
} catch (e) {
return next(e);
}
});
}));
app.listen(8080, '127.0.0.1');
In Connect, every handler is middleware! You use whichever functionality you need like bodyParser or cookieParser, and your own business logic is also a middleware function with the same signature function(req, res, next). The connect homepage gives a list of the built-in middleware.
Level 2: Express.js
Express's http server, written by TJ Holowaychuk, is in turn a subclass of Connect that forces the Sinatra style more. In Connect, there was no magic you didn't ask for, but in Express, the router and qs parser (which sets req.query) are automatically used. The router syntax is cleaned up; you call app.get, app.post, etc. directly (and the router is positioned at the first call) rather than putting them inside a function.
Express also contains many other well-documented features and helper functions to extend app, req, and res.
One feature of Express is res.render, which renders the given template file (relative to app.set('views') or $PWD/views) using the template engine implied by the extension, and res.partial, which calls render on each element of a collection (which is just any arraylike object). But I haven't used this optional feature; if you don't care for express's templates you can just res.send data yourself.
Here are some comments. If you have more specific questions, we can try to address them.
1) views and controllers
Views just means a template that can be used to render a response, which is usually HTML but could be plain text or some other format. There are many different templating syntaxes and systems out there. Some work in NodeJS as well as in web browsers. That's all there is to views.
Controllers are the "C" in the MVC design pattern and are responsible as an intermediary between views and models. They are basically the glue that handles some basic things like formatting choices that don't belong in the model code.
2) partials and collections
(Side comment, these are really part of Express.js, not Connect, but they are sibling libraries)
Partials is a document template representing a small portion or snippet of a document, as opposed to a complete HTML document. Partials can be included by other templates and are often re-used by multiple containing templates. Collections go hand in hand with them. For example, you might have a partial to display a "President" object and in that partial you'd have markup for a photo, dates he served as president, political party, etc. You could use that same partial throughout your site whenever you wanted to display a "President" record/object. If you had a collection of several "President" objects, "collections" give you an easy way to say "render a president partial for each president object in this list".
3) middleware
The way connect handles responding to HTTP requests is to route the request through a series of functions called middleware. Each middleware function adheres to a basic API of (req, res, next) and a few behavioral requirements. Each piece of middleware can do one specific bit of processing, then when it's done, call next() to tell connect to move on to the next middleware function in the chain. Connect comes with a bunch of middleware modules which you can see on github. Middleware can do whatever it wants. For example, parse JSON request bodies, search the filesystem for a matching static file to serve, check for session cookies, log to a log file, and so on. This design makes it really easy to re-use code as well as to combine separate middleware functions in novel combinations. Some middleware functions deal with parsing and processing the request, some deal with generating the response. Typically you can find existing middleware functions that do a lot of request processing (parsing, logging, decoding, converting, etc), and you provide your own middleware to actually render the response, which is also usually the last middleware in the chain.

Resources