0
@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 us...
Node.js is a platform built on ChromesJavaScript runtime for easily building fast,scalable network applications.Node.js us...
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.cre...
npm
npm is a package manager for node.You can use it to install and publish your node programs.”It manages dependencies and do...
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-par...
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...
loggercsrfcompressbasicAuthbodyParserjsonurlencodedmultipartcookieParsersessioncookieSessionmethodOverrideresponseTimestat...
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, (re...
express = require(express)app = express.createServer()before1 = (req, res, next) ->req.foo = barnext()before2 = (req, res,...
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 mo...
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, i...
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 /blog...
or should we?
models = [users, blogs, posts]Object.keys(models).forEach (modelName) ->app.get "/#{modelName}", (req, res) ->list models[...
POST /usersGET /usersGET /users/42DELETE /users/42PUT /users/42POST /blogsGET /blogsGET /blogs/42DELETE /blogs/42PUT /blog...
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 ...
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, do...
npm install passport-twitter
passport = require(passport)twitter = require(passport-twitter)keys = {consumerKey: TWITTER_CONSUMER_KEYconsumerSecret: TW...
Part 2Convention
ALL CHARACTERS ANDEVENTS IN THIS SHOW--EVENT THOSE BASED ON REALPEOPLE--ARE ENTIRELY FICTIONAL.ALL CELEBERTY VOICES AREIMP...
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!
Writing RESTful web services using Node.js
Writing RESTful web services using Node.js
Writing RESTful web services using Node.js
Writing RESTful web services using Node.js
Writing RESTful web services using Node.js
Writing RESTful web services using Node.js
Upcoming SlideShare
Loading in...5
×

Writing RESTful web services using Node.js

28,921

Published on

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

Published in: Technology, Business
2 Comments
57 Likes
Statistics
Notes
No Downloads
Views
Total Views
28,921
On Slideshare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
403
Comments
2
Likes
57
Embeds 0
No embeds

No notes for slide

Transcript of "Writing RESTful web services using Node.js"

  1. 1. @jakobmattsson
  2. 2. Started out doing consulting
  3. 3. 3 startups:RecruitingAdvertisingFeedback
  4. 4. 2 000 000 000 writes/day!
  5. 5. Back to square one
  6. 6. Writing RESTfulweb servicesusing Node.js
  7. 7. ComparisonRocket scienceProduct demoSilver bullet
  8. 8. ComparisonRocket scienceProduct demoSilver bulletNOT
  9. 9. What is it then?
  10. 10. ImaginationQuantityBottom upPrinciples
  11. 11. Also... CoffeeScript
  12. 12. Node.js
  13. 13. 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.
  14. 14. 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.
  15. 15. fs = require(fs)fs.readFile meaning_of_life.txt, utf-8, (err, data) ->console.log(data)console.log(end)
  16. 16. end42
  17. 17. Several protocols,including TCP and HTTP,are built in to node.
  18. 18. http = require(http)onRequest = (req, res) ->res.writeHead(200, { Content-Type: text/plain })res.end(Hello Worldn)http.createServer(onRequest).listen(1337)
  19. 19. npm
  20. 20. 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.”
  21. 21. npm install underscore
  22. 22. _ = require(underscore)numbers = _.range(1, 10)console.log(_.last(numbers))
  23. 23. Connect
  24. 24. Connect is a midleware framework for node.It’s shipping with over 18 bundled middleware.It has a rich selection of 3rd-party middleware.
  25. 25. npm install connect
  26. 26. connect = require(connect)app = connect()app.listen(3000)// last line equivalent to// http.createServer(app).listen(3000);
  27. 27. 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)
  28. 28. 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
  29. 29. Express
  30. 30. High performancehigh class web developmentfor Node.js
  31. 31. npm install express
  32. 32. 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)
  33. 33. 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)
  34. 34. Data storage
  35. 35. But which one?
  36. 36. Schemaless is a lie
  37. 37. Mongoose
  38. 38. Mongoose is a MongoDB object modeling tooldesigned to work in an asynchronous environment.
  39. 39. npm install mongoose
  40. 40. 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
  41. 41. blogs = model blogsname:type: Stringdefault: description:type: Stringdefault: users:type: ObjectIdref: users
  42. 42. posts = model poststitle:type: Stringdefault: body:type: Stringdefault: published:type: Dateblogs:type: ObjectIdref: blogs
  43. 43. 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
  44. 44. app.get /users/:id, (req, res) ->get users, req.params.id, (err, data) ->res.json data
  45. 45. copy-paste!
  46. 46. 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
  47. 47. or should we?
  48. 48. 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 }
  49. 49. 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
  50. 50. But what about the relations/associations?
  51. 51. POST /users/42/blogsGET /users/42/blogsPOST /blogs/42/postsGET /blogs/42/posts
  52. 52. 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
  53. 53. POST /users/42/blogsGET /users/42/blogsPOST /blogs/42/postsGET /blogs/42/posts
  54. 54. Keep on generating!
  55. 55. Authentication
  56. 56. npm install passportnpm install passport-local
  57. 57. 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))
  58. 58. npm install passport-twitter
  59. 59. 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))
  60. 60. Part 2Convention
  61. 61. 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
  62. 62. Verbs vs Nouns
  63. 63. /users/users/42/blogs/blogs/73/posts/posts/314
  64. 64. GET /usersGET /users/42POST /usersPUT /users/42DELETE /usersDELETE /users/42
  65. 65. Associations
  66. 66. /users/blogs/posts
  67. 67. /users/blogs/posts/users/42/blogs/blogs/314/posts
  68. 68. /users/blogs/posts/users/42/blogs/blogs/314/posts/users/42/blogs/314/posts
  69. 69. /users/blogs/posts/users/42/blogs/blogs/314/posts/users/42/blogs/314/posts
  70. 70. /users/blogs/posts/users/42/blogs/blogs/314/posts/users/42/blogs/314/postsKeep URLs short. Don’t overqualify.
  71. 71. GET /blogs/42/posts?tag=javascript
  72. 72. Versions
  73. 73. GET /v1/users
  74. 74. Partial responses
  75. 75. GET /users?fields=email,ageGET /users?limit=10&offset=0
  76. 76. Verbs
  77. 77. /convert?from=EUR&to=BYR&amount=100
  78. 78. Content-types
  79. 79. GET /v1/users/42.xml
  80. 80. Attributes
  81. 81. {"userId": 1,"firstName": "Jakob","lastName": "Mattsson"}
  82. 82. Search
  83. 83. GET /search?q=javascriptGET /blog/42/posts?q=javascript
  84. 84. Authentication
  85. 85. Part 3Conclusion
  86. 86. It goes for ideas too!Reuse convention.
  87. 87. Reuse code.Resuse ideas.Build new things.
  88. 88. ”MOST IMPORTANT STEPFOR BUILD PRODUCTIS BUILD PRODUCT”- @fakegrimlock
  89. 89. @jakobmattssonThank you!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×