Writing RESTful web services using Node.js
Upcoming SlideShare
Loading in...5
×
 

Writing RESTful web services using Node.js

on

  • 22,085 Views

by Jakob Mattsson on Frontend DEV Conf'13

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

Statistiken

Views

Gesamtviews
22,085
Views auf SlideShare
21,206
Views einbetten
879

Actions

Gefällt mir
47
Downloads
286
Kommentare
2

11 Einbettungen 879

http://www.scoop.it 633
http://lanyrd.com 227
https://twitter.com 8
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
Mehr ...

Zugänglichkeit

Kategorien

Details hochladen

Uploaded via as Adobe PDF

Benutzerrechte

© Alle Rechte vorbehalten

Report content

Als unangemessen gemeldet Als unangemessen melden
Als unangemessen melden

Wählen Sie Ihren Grund, warum Sie diese Präsentation als unangemessen melden.

Löschen
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Ihre Nachricht erscheint hier
    Processing...
Kommentar posten
Kommentar bearbeiten

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!