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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Writing RESTful web services using Node.js

27,011
views

Published on

by Jakob Mattsson on Frontend DEV Conf'13 …

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

Published in: Technology, Business

2 Comments
54 Likes
Statistics
Notes
No Downloads
Views
Total Views
27,011
On Slideshare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
362
Comments
2
Likes
54
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

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