• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Writing RESTful web services using Node.js
 

Writing RESTful web services using Node.js

on

  • 20,655 views

by Jakob Mattsson on Frontend DEV Conf'13

by Jakob Mattsson on Frontend DEV Conf'13
http://bit.ly/Jakob_Mattsson

Statistics

Views

Total Views
20,655
Views on SlideShare
19,815
Embed Views
840

Actions

Likes
46
Downloads
264
Comments
2

11 Embeds 840

http://www.scoop.it 597
http://lanyrd.com 227
https://twitter.com 5
http://imperavi.com 3
http://premiumsoftware.net 2
http://jejacks0n.github.io 1
http://www.tinymce.com 1
http://webcache.googleusercontent.com 1
http://plus.url.google.com 1
http://www.linkedin.com 1
http://news.google.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

12 of 2 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Writing RESTful web services using Node.js Writing RESTful web services using Node.js Presentation Transcript

    • @jakobmattsson
    • Started out doing consulting
    • 3 startups:RecruitingAdvertisingFeedback
    • 2 000 000 000 writes/day!
    • Back to square one
    • Writing RESTfulweb servicesusing Node.js
    • ComparisonRocket scienceProduct demoSilver bullet
    • ComparisonRocket scienceProduct demoSilver bulletNOT
    • What is it then?
    • ImaginationQuantityBottom upPrinciples
    • Also... CoffeeScript
    • Node.js
    • Node.js is a platform built on ChromesJavaScript runtime for easily building fast,scalable network applications.Node.js uses an event-driven, non-blocking I/Omodel that makes it lightweight and efficient,perfect for data-intensive real-time applicationsthat run across distributed devices.
    • Node.js is a platform built on ChromesJavaScript runtime for easily building fast,scalable network applications.Node.js uses an event-driven, non-blocking I/Omodel that makes it lightweight and efficient,perfect for data-intensive real-time applicationsthat run across distributed devices.
    • fs = require(fs)fs.readFile meaning_of_life.txt, utf-8, (err, data) ->console.log(data)console.log(end)
    • end42
    • Several protocols,including TCP and HTTP,are built in to node.
    • http = require(http)onRequest = (req, res) ->res.writeHead(200, { Content-Type: text/plain })res.end(Hello Worldn)http.createServer(onRequest).listen(1337)
    • npm
    • npm is a package manager for node.You can use it to install and publish your node programs.”It manages dependencies and does other cool stuff.”
    • npm install underscore
    • _ = require(underscore)numbers = _.range(1, 10)console.log(_.last(numbers))
    • Connect
    • Connect is a midleware framework for node.It’s shipping with over 18 bundled middleware.It has a rich selection of 3rd-party middleware.
    • npm install connect
    • connect = require(connect)app = connect()app.listen(3000)// last line equivalent to// http.createServer(app).listen(3000);
    • connect = require(connect)app = connect()app.use connect.basicAuth (user, pass) ->return user == jakob && pass == fdc13app.use (req, res) ->res.writeHead(200, { Content-Type: text/plain })res.end(Hello Worldn)app.listen(3000)
    • loggercsrfcompressbasicAuthbodyParserjsonurlencodedmultipartcookieParsersessioncookieSessionmethodOverrideresponseTimestaticCachestaticdirectoryvhostfaviconlimitqueryerrorHandlerRequest logger with custom format supportCross-site request forgery protectionGzip compression middlewareBasic http authenticationExtensible request body parserApplication/json parserApplication/x-www-form-urlencoded parserMultipart/form-data parserCookie parserSession management support with bundled MemoryStoreCookie-based session supportFaux HTTP method supportCalculates response-time and exposes via X-Response-TimeMemory cache layer for the static() middlewareStreaming static file server supporting Range and moreDirectory listing middlewareVirtual host sub-domain mapping middlewareEfficient favicon server (with default icon)Limit the bytesize of request bodiesAutomatic querystring parser, populating req.queryFlexible error handler
    • Express
    • High performancehigh class web developmentfor Node.js
    • npm install express
    • express = require(express)app = express.createServer()app.get /, (req, res) ->res.send(Hello World)app.get /users/:id, (req, res) ->res.send(user + req.params.id)app.listen(3000)
    • express = require(express)app = express.createServer()before1 = (req, res, next) ->req.foo = barnext()before2 = (req, res, next) ->res.header(X-Time, new Date().getTime())next()app.get /, before1, (req, res) ->res.send(Hello World)app.get /users/:id, [before1, before2], (req, res) ->console.log(req.foo)res.send(user + req.params.id)app.listen(3000)
    • Data storage
    • But which one?
    • Schemaless is a lie
    • Mongoose
    • Mongoose is a MongoDB object modeling tooldesigned to work in an asynchronous environment.
    • npm install mongoose
    • mongoose = require mongoosemongoose.connect mongodb://localhost/tamblrmodel = (name, schema) ->mongoose.model name, new mongoose.Schema schema,strict: trueusers = model usersname:type: Stringdefault: bio:type: Stringdefault: IE6-loverage:type: Numberdefault: null
    • blogs = model blogsname:type: Stringdefault: description:type: Stringdefault: users:type: ObjectIdref: users
    • posts = model poststitle:type: Stringdefault: body:type: Stringdefault: published:type: Dateblogs:type: ObjectIdref: blogs
    • list = (model, callback) ->model.find {}, callbackget = (model, id, callback) ->model.findById id, callbackdel = (model, id, callback) ->model.remove { _id: id }, callbackput = (model, id, data, callback) ->model.update { _id: id }, data, { multi: false }, callbackpost = (model, data, callback) ->new model(data).save callback
    • app.get /users/:id, (req, res) ->get users, req.params.id, (err, data) ->res.json data
    • copy-paste!
    • POST /usersGET /usersGET /users/42DELETE /users/42PUT /users/42POST /blogsGET /blogsGET /blogs/42DELETE /blogs/42PUT /blogs/42POST /postsGET /postsGET /posts/42DELETE /posts/42PUT /posts/42
    • or should we?
    • models = [users, blogs, posts]Object.keys(models).forEach (modelName) ->app.get "/#{modelName}", (req, res) ->list models[modelName], (err, data) ->res.json dataapp.get "/#{modelName}/:id", (req, res) ->get models[modelName], req.params.id, (err, data) ->res.json dataapp.post "/#{modelName}", (req, res) ->post models[modelName], req.body, (err, data) ->res.json dataapp.del "/#{modelName}/:id", (req, res) ->del models[modelName], req.parmas.id, (err, count) ->res.json { count: count }app.put "/#{modelName}/:id", (req, res) ->put models[modelName], req.params.id, req.body, (err, count) ->res.json { count: count }
    • POST /usersGET /usersGET /users/42DELETE /users/42PUT /users/42POST /blogsGET /blogsGET /blogs/42DELETE /blogs/42PUT /blogs/42POST /postsGET /postsGET /posts/42DELETE /posts/42PUT /posts/42
    • But what about the relations/associations?
    • POST /users/42/blogsGET /users/42/blogsPOST /blogs/42/postsGET /blogs/42/posts
    • paths = models[modelName].schema.pathsowners = Object.keys(paths).filter (p) ->paths[p].options.type == ObjectId &&typeof paths[p].options.ref == string.map (x) -> paths[x].options.refowners.forEach (owner) ->app.get "/#{owner}/:id/#{name}", (req, res) ->listSub models[name], owner, req.params.id, (err, data) ->res.json dataapp.post "/#{owner}/:id/#{name}", (req, res) ->postSub models[name], req.body, owner, req.params.id, (err, data) ->res.json data
    • POST /users/42/blogsGET /users/42/blogsPOST /blogs/42/postsGET /blogs/42/posts
    • Keep on generating!
    • Authentication
    • npm install passportnpm install passport-local
    • passport = require(passport)passportLocal = require(passport-local)passport.use new passportLocal.Strategy (user, pass, done) ->findUserPlz { username: user, password: pass }, (err, user) ->done(err, user)app.use(passport.initialize())app.use(passport.authenticate(local))
    • npm install passport-twitter
    • passport = require(passport)twitter = require(passport-twitter)keys = {consumerKey: TWITTER_CONSUMER_KEYconsumerSecret: TWITTER_CONSUMER_SECRETcallbackURL: "http://127.0.0.1:3000/auth/twitter/callback"}passport.use new twitter.Strategy keys, (t, ts, profile, done) ->findOrCreateUserPlz { twitterId: profile.id }, (err, user) ->done(err, user)app.use(passport.initialize())app.use(passport.authenticate(twitter))
    • Part 2Convention
    • ALL CHARACTERS ANDEVENTS IN THIS SHOW--EVENT THOSE BASED ON REALPEOPLE--ARE ENTIRELY FICTIONAL.ALL CELEBERTY VOICES AREIMPERSONATED.....POORLY. THEFOLLOWING PROGRAM CONTAINSCOARSE LANGUAGE AND DUE TOITS CONTENT IT SHOULD NOT BEVIEWED BE ANYONE
    • Verbs vs Nouns
    • /users/users/42/blogs/blogs/73/posts/posts/314
    • GET /usersGET /users/42POST /usersPUT /users/42DELETE /usersDELETE /users/42
    • Associations
    • /users/blogs/posts
    • /users/blogs/posts/users/42/blogs/blogs/314/posts
    • /users/blogs/posts/users/42/blogs/blogs/314/posts/users/42/blogs/314/posts
    • /users/blogs/posts/users/42/blogs/blogs/314/posts/users/42/blogs/314/posts
    • /users/blogs/posts/users/42/blogs/blogs/314/posts/users/42/blogs/314/postsKeep URLs short. Don’t overqualify.
    • GET /blogs/42/posts?tag=javascript
    • Versions
    • GET /v1/users
    • Partial responses
    • GET /users?fields=email,ageGET /users?limit=10&offset=0
    • Verbs
    • /convert?from=EUR&to=BYR&amount=100
    • Content-types
    • GET /v1/users/42.xml
    • Attributes
    • {"userId": 1,"firstName": "Jakob","lastName": "Mattsson"}
    • Search
    • GET /search?q=javascriptGET /blog/42/posts?q=javascript
    • Authentication
    • Part 3Conclusion
    • It goes for ideas too!Reuse convention.
    • Reuse code.Resuse ideas.Build new things.
    • ”MOST IMPORTANT STEPFOR BUILD PRODUCTIS BUILD PRODUCT”- @fakegrimlock
    • @jakobmattssonThank you!