Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing RESTful web services using Node.js - jsDay 2012, Verona

Writing RESTful web services using Node.js - jsDay 2012, Verona

Title says it all. Presented at JSDay 2012 in Verona.

Jakob Mattsson

May 17, 2012
Tweet

More Decks by Jakob Mattsson

Other Decks in Programming

Transcript

  1. Node.js is a platform built on Chrome's JavaScript runtime for

    easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices. torsdag den 17 maj 2012
  2. Node.js is a platform built on Chrome's JavaScript runtime for

    easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices. torsdag den 17 maj 2012
  3. http = require('http') onRequest = (req, res) -> res.writeHead(200, {

    'Content-Type': 'text/plain' }) res.end('Hello World\n') http.createServer(onRequest).listen(1337) torsdag den 17 maj 2012
  4. 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.” torsdag den 17 maj 2012
  5. Connect is a midleware framework for node. It’s shipping with

    over 18 bundled middleware. It has a rich selection of 3rd-party middleware. torsdag den 17 maj 2012
  6. connect = require('connect') app = connect() app.listen(3000) // last line

    equivalent to // http.createServer(app).listen(3000); torsdag den 17 maj 2012
  7. connect = require('connect') app = connect() app.use connect.basicAuth (user, pass)

    -> return user == 'jakob' && pass == 'jsday' app.use (req, res) -> res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('Hello World\n') app.listen(3000) torsdag den 17 maj 2012
  8. logger csrf compress basicAuth bodyParser json urlencoded multipart cookieParser session

    cookieSession methodOverride responseTime staticCache static directory vhost favicon limit query errorHandler Request logger with custom format support Cross-site request forgery protection Gzip compression middleware Basic http authentication Extensible request body parser Application/json parser Application/x-www-form-urlencoded parser Multipart/form-data parser Cookie parser Session management support with bundled MemoryStore Cookie-based session support Faux HTTP method support Calculates response-time and exposes via X-Response-Time Memory cache layer for the static() middleware Streaming static file server supporting Range and more Directory listing middleware Virtual host sub-domain mapping middleware Efficient favicon server (with default icon) Limit the bytesize of request bodies Automatic querystring parser, populating req.query Flexible error handler torsdag den 17 maj 2012
  9. 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) torsdag den 17 maj 2012
  10. express = require('express') app = express.createServer() before1 = (req, res,

    next) -> req.foo = 'bar' next() 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) torsdag den 17 maj 2012
  11. Mongoose is a MongoDB object modeling tool designed to work

    in an asynchronous environment. torsdag den 17 maj 2012
  12. mongoose = require 'mongoose' mongoose.connect 'mongodb://localhost/tamblr' model = (name, schema)

    -> mongoose.model name, new mongoose.Schema schema, strict: true users = model 'users' name: type: String default: '' bio: type: String default: 'IE6-lover' age: type: Number default: null torsdag den 17 maj 2012
  13. logs = model 'blogs' name: type: String default: '' description:

    type: String default: '' users: type: ObjectId ref: 'users' torsdag den 17 maj 2012
  14. posts = model 'posts' title: type: String default: '' body:

    type: String default: '' published: type: Date blogs: type: ObjectId ref: 'blogs' torsdag den 17 maj 2012
  15. list = (model, callback) -> model.find {}, callback get =

    (model, id, callback) -> model.findById id, callback del = (model, id, callback) -> model.remove { _id: id }, callback put = (model, id, data, callback) -> model.update { _id: id }, data, { multi: false }, callback post = (model, data, callback) -> new model(data).save callback torsdag den 17 maj 2012
  16. POST /users GET /users GET /users/42 DELETE /users/42 PUT /users/42

    POST /blogs GET /blogs GET /blogs/42 DELETE /blogs/42 PUT /blogs/42 POST /posts GET /posts GET /posts/42 DELETE /posts/42 PUT /posts/42 torsdag den 17 maj 2012
  17. models = [users, blogs, posts] Object.keys(models).forEach (modelName) -> app.get "/#{modelName}",

    (req, res) -> list models[modelName], (err, data) -> res.json data app.get "/#{modelName}/:id", (req, res) -> get models[modelName], req.params.id, (err, data) -> res.json data app.post "/#{modelName}", (req, res) -> post models[modelName], req.body, (err, data) -> res.json data app.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 } torsdag den 17 maj 2012
  18. POST /users GET /users GET /users/42 DELETE /users/42 PUT /users/42

    POST /blogs GET /blogs GET /blogs/42 DELETE /blogs/42 PUT /blogs/42 POST /posts GET /posts GET /posts/42 DELETE /posts/42 PUT /posts/42 torsdag den 17 maj 2012
  19. paths = models[modelName].schema.paths owners = Object.keys(paths).filter (p) -> paths[p].options.type ==

    ObjectId && typeof paths[p].options.ref == 'string' .map (x) -> paths[x].options.ref owners.forEach (owner) -> app.get "/#{owner}/:id/#{modelName}", (req, res) -> listSub models[modelName], owner, req.params.id, (err, data) -> res.json data app.post "/#{owner}/:id/#{modelName}", (req, res) -> postSub models[modelName], req.body, owner, req.params.id, (err, data) -> res.json data torsdag den 17 maj 2012
  20. 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')) torsdag den 17 maj 2012
  21. passport = require('passport') twitter = require('passport-twitter') keys = { consumerKey:

    TWITTER_CONSUMER_KEY consumerSecret: TWITTER_CONSUMER_SECRET callbackURL: "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')) torsdag den 17 maj 2012
  22. ALL CHARACTERS AND EVENTS IN THIS SHOW-- EVENT THOSE BASED

    ON REAL PEOPLE--ARE ENTIRELY FICTIONAL. ALL CELEBERTY VOICES ARE IMPERSONATED.....POORLY. THE FOLLOWING PROGRAM CONTAINS COARSE LANGUAGE AND DUE TO ITS CONTENT IT SHOULD NOT BE VIEWED BE ANYONE torsdag den 17 maj 2012
  23. GET /users GET /users/42 POST /users PUT /users/42 DELETE /users

    DELETE /users/42 torsdag den 17 maj 2012