Koa.js – Resources

Koa.js – Resources ”; Previous Next Following is a list of resources we have used while developing this tutorial − Koajs.com Koajs – Examples A list of examples created by the community List of official and 3rd party middlewares. A CRUD API using koa.js – A short screencast that goes through creating a CRUD API in Koa.js Koa.js Quickstart screencast Introduction to Koa.js and generators Print Page Previous Next Advertisements ”;

Koa.js – Request Object

Koa.js – Request Object ”; Previous Next A Koa Request object is an abstraction on top of node”s vanilla request object, providing additional functionality that is useful for everyday HTTP server development. The Koa request object is embedded in the context object, this. Let’s log out the request object whenever we get a request. var koa = require(”koa”); var router = require(”koa-router”); var app = koa(); var _ = router(); _.get(”/hello”, getMessage); function *getMessage(){ console.log(this.request); this.body = ”Your request has been logged.”; } app.use(_.routes()); app.listen(3000); When you run this code and navigate to https://localhost:3000/hello, then you will receive the following response. On your console, you”ll get the request object logged out. { method: ”GET”, url: ”/hello/”, header: { host: ”localhost:3000”, connection: ”keep-alive”, ”upgrade-insecure-requests”: ”1”, ”user-agent”: ”Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36”, accept: ”text/html,application/xhtml+xml, application/xml;q = 0.9,image/webp,*/*;q = 0.8”, dnt: ”1”, ”accept-encoding”: ”gzip, deflate, sdch”, ”accept-language”: ”en-US,en;q = 0.8” } } We have access to many useful properties of the request using this object. Let us look at some examples. request.header Provides all the request headers. request.method Provides the request method(GET, POST, etc.) request.href Provides the full request URL. request.path Provides the path of the request. Without query string and base url. request.query Gives the parsed query string. For example, if we log this on a request such as https://localhost:3000/hello/?name=Ayush&age=20&country=India, then we”ll get the following object. { name: ”Ayush”, age: ”20”, country: ”India” } request.accepts(type) This function returns true or false based on whether the requested resources accept the given request type. You can read more about the request object in the docs at Request. Print Page Previous Next Advertisements ”;

Koa.js – Generators

Koa.js – Generators ”; Previous Next One of the most exciting new features of JavaScript ES6 is a new breed of function, called a generator. Before generators, the whole script was used to usually execute in a top to bottom order, without an easy way to stop code execution and resuming with the same stack later. Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances. Generators allow us to stop code execution in between. Hence, let’s take a look at a simple generator. var generator_func = function* (){ yield 1; yield 2; }; var itr = generator_func(); console.log(itr.next()); console.log(itr.next()); console.log(itr.next()); When running the above code, following will be the result. { value: 1, done: false } { value: 2, done: false } { value: undefined, done: true } Let’s look inside the above code. We first create a generator called generator_func(). We created an instance of this weird looking function and assigned it to itr. Then we started calling next() on this itr variable. Calling next() starts the generator and it runs until it hits a yield. Then it returns the object with value and done, where the value has the expression value. This expression can be anything. At this point, it pauses execution. Again when we call this function(next), the generator resumes execution from the last yield point with the function state being the same at the time of pause, till the next yield point. This is done till there are no more yield points in the code. Generators in Koa So why are we discussing generators in this tutorial. As you might remember from the hello world program, we used a function* () notation to pass a callback to app.use(). Koa is an object, which contains an array of middleware generator functions, all of which are composed and executed in a stack-like manner upon each request. Koa also implements downstreaming followed by upstreaming of control flow. Take a look at the following example to understand this in a better way. var koa = require(”koa”); var app = koa(); app.use(function* (next) { //do something before yielding to next generator function //in line which will be 1st event in downstream console.log(“1”); yield next; //do something when the execution returns upstream, //this will be last event in upstream console.log(“2”); }); app.use(function* (next) { // This shall be 2nd event downstream console.log(“3”); yield next; // This would be 2nd event upstream console.log(“4”); }); app.use(function* () { // Here it would be last function downstream console.log(“5”); // Set response body this.body = “Hello Generators”; // First event of upstream (from the last to first) console.log(“6″); }); app.listen(3000); When running the above code and navigating to https://localhost:3000/ we get the following output on our console. 1 3 5 6 4 2 This is essentially how Koa uses generators. It allows us to create compact middleware using this property and write code for both upstream and downstream functionalities, thus saving us from callbacks. Print Page Previous Next Advertisements ”;

Koa.js – Compression

Koa.js – Compression ”; Previous Next Compression is a simple, effective way to save bandwidth and speed up your site. It is only compatible with modern browsers and should be used with caution if your users use legacy browsers as well. When sending responses from the server, if compression is used, it can greatly improve the load time. We”ll be using a middleware called koa-compress to take care of the compression of files as well as setting appropriate headers. Go ahead and install the middleware using − $ npm install –save koa-compress Now in your app.js file, add the following code − var koa = require(”koa”); var router = require(”koa-router”); var app = koa(); var Pug = require(”koa-pug”); var pug = new Pug({ viewPath: ”./views”, basedir: ”./views”, app: app //Equivalent to app.use(pug) }); app.use(compress({ filter: function (content_type) { return /text/i.test(content_type) }, threshold: 2048, flush: require(”zlib”).Z_SYNC_FLUSH })); var _ = router(); //Instantiate the router _.get(”/”, getRoot); function *getRoot(next){ this.render(”index”); } app.use(_.routes()); //Use the routes defined using the router app.listen(3000); This puts our compression middleware in place. The filter option is a function that checks the response content type to decide whether to compress. The threshold option is the minimum response size in bytes to compress. This ensures we don’t compress every little response. Following is a response without compression. Following is the similar response with compression. If you look at the size tab at the bottom, you can very well see the difference between the two. There is more than 150% improvement, when we compress the files. Print Page Previous Next Advertisements ”;

Koa.js – Scaffolding

Koa.js – Scaffolding ”; Previous Next Scaffolding allows us to easily create a skeleton for a web application. We manually created our public directory, added middleware, created separate route files, etc. A scaffolding tool sets up all these things for us so that we can directly get started with building our application. The scaffolder we”ll use is called Yeoman. It is a scaffolding tool built for Node.js but also has generators for several other frameworks (such as flask, rails, django, etc.). To install yeoman, enter the following command in your terminal. $ npm install -g yeoman Yeoman uses generators to scaffold out applications. To check out the generators available on npm to use with yeoman, head over here. For the purpose of this tutorial, we”ll use the ”generator-koa”. To install this generator, enter the following command in your terminal. $ npm install -g generator-koa To use this generator, enter − yo koa Then it”ll create a directory structure and will create the following files for you. It”ll also install the necessary npm modules and bower components for you. create package.json create test/routeSpec.js create views/layout.html create views/list.html create public/styles/main.css create public/scripts/.gitkeep create controllers/messages.js create app.js create .editorconfig create .jshintrc I”m all done. Running npm install & bower install for you to install the required dependencies. If this fails, try running the command yourself. This generator creates a very simple structure for us. . ├── controllers │ └── messages.js ├── public | ├── scripts | └── styles | └── main.css ├── test | └── routeSpec.js ├── views | ├── layout.html | └── list.html ├── .editorconfig ├── .jshintrc ├── app.js └── package.json Explore the many generators available for Koa and choose the one that fits you right. Steps to working with all generators is the same. You”ll need to install a generator, run it using yeoman, it”ll ask you some questions and then create a skeleton for your application based on your answers. Print Page Previous Next Advertisements ”;

Koa.js – Authentication

Koa.js – Authentication ”; Previous Next Authentication is a process in which the credentials provided are compared to those on file in the database of authorized users” information on a local operating system or within an authentication server. If the credentials match, the process is completed and the user is granted authorization for access. We”ll be creating a very basic authentication system that”ll use Basic HTTP Authentication. This is the simplest possible way to enforce access control as it doesn”t require cookies, sessions, or anything else. To use this, the client has to send the Authorization header along with every request it makes. The username and password are not encrypted, but are concatenated in a single string like the following. username:password This string is encoded with Base64, and the word Basic is put before this value. For example, if your username is Ayush and password India, then the string “Ayush:India” would be sent as encoded in the authorization header. Authorization: Basic QXl1c2g6SW5kaWE= To implement this in your koa app, you”ll need the koa-basic-auth middleware. Install it using − $ npm install –save koa-basic-auth Now open your app.js file and enter the following code in it. //This is what the authentication would be checked against var credentials = { name: ”Ayush”, pass: ”India” } var koa = require(”koa”); var auth = require(”koa-basic-auth”); var _ = require(”koa-router”)(); var app = koa(); //Error handling middleware app.use(function *(next){ try { yield next; } catch (err) { if (401 == err.status) { this.status = 401; this.set(”WWW-Authenticate”, ”Basic”); this.body = ”You have no access here”; } else { throw err; } } }); // Set up authentication here as first middleware. // This returns an error if user is not authenticated. _.get(”/protected”, auth(credentials), function *(){ this.body = ”You have access to the protected area.”; yield next; }); // No authentication middleware present here. _.get(”/unprotected”, function*(next){ this.body = “Anyone can access this area”; yield next; }); app.use(_.routes()); app.listen(3000); We have created an error handling middleware to handle all authentication related errors. Then, we have created 2 routes − /protected − This route can only be accessed if the user sends the correct authentication header. For all others, it”ll give an error. /unprotected − This route can be accessed by anyone, with or without the authentication. Now if you send a request to /protected without an authentication header or with the wrong credentials, you”ll receive an error. For example, $ curl https://localhost:3000/protected You”ll receive the response as − HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic Content-Type: text/plain; charset=utf-8 Content-Length: 28 Date: Sat, 17 Sep 2016 19:05:56 GMT Connection: keep-alive Please authenticate yourself However, with the right credentials, you”ll get the expected response. For example, $ curl -H “Authorization: basic QXl1c2g6SW5kaWE=” https://localhost:3000/protected -i You”ll get the response as − HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 38 Date: Sat, 17 Sep 2016 19:07:33 GMT Connection: keep-alive You have access to the protected area. The /unprotected route is still accessible to everyone. Print Page Previous Next Advertisements ”;

Koa.js – HTTP Methods

Koa.js – HTTP Methods ”; Previous Next The HTTP method is supplied in the request and specifies the operation that the client has requested. The following table summarizes the commonly used HTTP methods. Sr.No. Method & Description 1 GET The GET method requests a representation of the specified resource. Requests using GET should only retrieve data and should have no other effect. 2 POST The POST method requests that the server accept the data enclosed in the request as a new object/entity of the resource identified by the URI. 3 PUT The PUT method requests that the server accept the data enclosed in the request as a modification to the existing object identified by the URI. If it does not exist, then PUT method should create one. 4 DELETE The DELETE method requests that the server delete the specified resource. These are the most common HTTP methods. To learn more about them, head over to https://www.tutorialspoint.com/http/http_methods.htm. Print Page Previous Next Advertisements ”;

Koa.js – Form Data

Koa.js – Form Data ”; Previous Next Forms are an integral part of the web. Almost every website we visit offers us forms that submit or fetch some information for us. To get started with forms, we will first install the koa-body. To install this, go to your terminal and use − $ npm install –save koa-body Replace your app.js file contents with the following code. var koa = require(”koa”); var router = require(”koa-router”); var bodyParser = require(”koa-body”); var app = koa(); //Set up Pug var Pug = require(”koa-pug”); var pug = new Pug({ viewPath: ”./views”, basedir: ”./views”, app: app //Equivalent to app.use(pug) }); //Set up body parsing middleware app.use(bodyParser({ formidable:{uploadDir: ”./uploads”}, multipart: true, urlencoded: true })); _.get(”/”, renderForm); _.post(”/”, handleForm); function * renderForm(){ this.render(”form”); } function *handleForm(){ console.log(this.request.body); console.log(this.req.body); this.body = this.request.body; //This is where the parsed request is stored } app.use(_.routes()); app.listen(3000); The new things we are doing here are importing the body parser and multer. We are using the body parser for parsing json and x-www-form-urlencoded header requests, while we use multer for parsing multipart/form-data. Let us create a html form to test this out! Create a new view named form.pug with the following code. html head title Form Tester body form(action = “/”, method = “POST”) div label(for = “say”) Say: input(name = “say” value = “Hi”) br div label(for = “to”) To: input(name = “to” value = “Koa form”) br button(type = “submit”) Send my greetings Run your server using − nodemon index.js Now go to localhost:3000/ and fill the form as you like, and submit it. You”ll receive the response as − Take a look at your console, it”ll show you the body of your request as a JavaScript object. For example − The this.request.body object contains your parsed request body. To use fields from that object, just use them as normal JS objects. This is just one way to send a request. There are many other ways, but those are irrelevant to cover here, because our Koa app will handle all those requests in the same way. To read more about different ways to make a request, have a look at this page. Print Page Previous Next Advertisements ”;

Koa.js – Database

Koa.js – Database ”; Previous Next We are receiving the requests, but are not storing them anywhere. We need a Database to store the data. We”ll use a famous NoSQL database called MongoDB. To install and read about Mongo, head over to this link. In order to use Mongo with Koa, we need a client API for the node. There are multiple options for us, however for this tutorial we”ll stick to mongoose. Mongoose is used for document modeling in Node for MongoDB. Document modeling means that, we will create a Model (much like a class in document-oriented programming), and then we will produce documents using this Model (like we create documents of a class in OOP). All our processing will be done on these “documents”, then finally, we will write these documents in our database. Setting Up Mongoose Now that we have Mongo installed, let us install mongoose, the same way we have been installing our other node packages. $ npm install –save mongoose Before we start using mongoose, we have to create a database using the Mongo shell. To create a new database, open your terminal and enter “mongo”. A Mongo shell will start, enter the following. use my_db A new database will be created for you. Whenever you open the Mongo shell, it”ll default to “test” db and you”ll have to change to your database using the same command as above. To use mongoose, we will require it in our app.js file and then connect to the mongod service running on mongodb://localhost var koa = require(”koa”); var _ = require(”koa-router”)(); var app = koa(); var mongoose = require(”mongoose”); mongoose.connect(”mongodb://localhost/my_db”); app.use(_.routes()); app.listen(3000); Now our app is connected to our database, let’s create a new Model. This model will act as a collection in our database. To create a new Model, use the following code, before defining any routes. var koa = require(”koa”); var _ = require(”koa-router”)(); var app = koa(); var mongoose = require(”mongoose”); mongoose.connect(”mongodb://localhost/my_db”); var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model(“Person”, personSchema); app.use(_.routes()); app.listen(3000); The above code defines the schema for a person and is used to create a mongoose Model Person. Saving Documents Now we will create a new html form, which will get the details of a person and save it to our database. To create the form, create a new view file called person.pug in the views directory with the following content. html head title Person body form(action = “/person”, method = “POST”) div label(for = “name”) Name: input(name = “name”) br div label(for = “age”) Age: input(name = “age”) br div label(for = “nationality”) Nationality: input(name = “nationality”) br button(type = “submit”) Create new person Also add a new get route in index.js to render this document. var koa = require(”koa”); var _ = require(”koa-router”)(); var app = koa(); var mongoose = require(”mongoose”); mongoose.connect(”mongodb://localhost/my_db”); var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model(“Person”, personSchema); _.get(”/person”, getPerson); function *getPerson(next){ this.render(”person”); yield next; } app.use(_.routes()); app.listen(3000); Go to localhost:3000/person to check if our form is displaying right. Note that this is just the UI, it’s not working yet. This is how our form looks. We”ll now define a post route handler at ”/person” which will handle this request. var koa = require(”koa”); var _ = require(”koa-router”)(); var app = koa(); var mongoose = require(”mongoose”); mongoose.connect(”mongodb://localhost/my_db”); var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model(“Person”, personSchema); _.post(”/person”, createPerson); function *createPerson(next){ var self = this; var personInfo = self.request.body; //Get the parsed information if(!personInfo.name || !personInfo.age || !personInfo.nationality){ self.render( ”show_message”, {message: “Sorry, you provided wrong info”, type: “error”}); } else { var newPerson = new Person({ name: personInfo.name, age: personInfo.age, nationality: personInfo.nationality }); yield newPerson.save(function(err, res) { if(err) self.render(”show_message”, {message: “Database error”, type: “error”}); else self.render(”show_message”, {message: “New person added”, type: “success”, person: personInfo}); }); } } app.use(_.routes()); app.listen(3000); In the above code, if we receive any empty field or do not receive any field, we will send an error response. However, if we receive a well-formed document, then we create a newPerson document from the Person model and save it to our DB using newPerson.save() function. This is defined in mongoose and accepts a callback as argument. This callback has two arguments, error and response. This will render show_message view, so we need to create that as well. To show the response from this route, we will also need to create a show_message view. Create a new view with the following code. html head title Person body if(type = “error”) h3(style = “color:red”) #{message} else h3 New person, name: #{person.name}, age: #{person.age} and nationality: #{person.nationality} added! Following is the response we receive on successfully submitting the form (show_message.pug). We now have an interface to create persons! Retrieving Documents Mongoose provides a lot of functions for retrieving documents, we will focus on three of those. All these functions also take a callback as the last parameter, and just like the save function, their arguments are error and response. The three functions are − Model.find(conditions, callback) This function finds all the documents matching the fields in conditions object. Same operators used in Mongo also work in mongoose. For example, this will fetch all the documents from the persons’ collection. Person.find(function(err, response){ console.log(response); }); This will fetch all documents where the field name is “Ayush” and age is 20. Person.find({name: “Ayush”, age: 20}, function(err, response){ console.log(response); }); We can also provide the projection we need, i.e., the fields we need. For example, if we want only the names of the people whose nationality is “Indian”, we use − Person.find({nationality: “Indian”}, “name”, function(err, response) { console.log(response); }); Model.findOne(conditions, callback) This functions always fetches a single, most relevant document. It has the same exact arguments as Model.find(). Model.findById(id, callback) This function takes in the _id (defined by mongo) as the first argument, an optional projection string and a callback to handle the response. For example, Person.findById(“507f1f77bcf86cd799439011”, function(err,

Koa.js – Logging

Koa.js – Logging ”; Previous Next Logging is quite useful when creating web applications as they tell us where exactly things went wrong. We also get the context for the things that went wrong and can come up with possible solutions for the same. To enable logging in Koa, we need the middleware, koa-logger. Install it using the following command. $ npm install –save-dev koa-logger Now in your application, add the following code to enable logging. var logger = require(”koa-logger”) var koa = require(”koa”) var app = koa() app.use(logger()) app.use(function*(){ this.body = “Hello Logger”; }) app.listen(3000) Run this server and visit any route on the server. You should see the logs like − Now if you get an error on a specific route or request, these logs should help you figure out what went wrong in each of them. Print Page Previous Next Advertisements ”;