Taming client-server communication

476 views
405 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
476
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Taming client-server communication

  1. 1. Taming client-servercommunicationScott Andrews
  2. 2. About me• engineer @ SpringSource / Pivotal• contributor to cujoJS• drifter• application framework• open source commercial• client server• front-end back-end
  3. 3. A brief word from my sponsor• leader in Enterprise Java• now part of Pivotal• Spring• Cloud Foundry• Redis• RabbitMQ & SockJS• Groovy & Grails• Pivotal Labs
  4. 4. How can browserscommunicate?• HTTP (XMLHttpRequest)• WebSockets• WebRTC (are we there yet?)
  5. 5. How do applicationscommunicate from a browser?• how should they communicate?
  6. 6. We use jQuery, duh$.get(/usersList.php,function (response) { ... });
  7. 7. We use jQuery, duh$.get(/usersList.php).then(function (response) { ... });...not to start a holy war, but I like promises
  8. 8. Whats wrong here?$.ajax({url: /usersList.php,data: { page: 1, count: 50 }}).then(function (response) { ... },function (error) { ... });...lot of little nits, but its not too bad
  9. 9. Whats wrong here?$.ajax({url: /usersList.php,data: { page: 3, count: 50 }}).then(function (response) { ... },function (error) { ... });$.ajax({url: /usersList.php,data: { page: 5, count: 50 }}).then(function (response) { ... },function (error) { ... });$.ajax({url: /usersList.php,data: { page: 4, count: 50 }}).then(function (response) { ... },function (error) { ... });$.ajax({url: /usersList.php,data: { page: 1, count: 50 }}).then(function (response) { ... },function (error) { ... });$.ajax({url: /usersList.php,data: { page: 2, count: 50 }}).then(function (response) { ... },function (error) { ... });
  10. 10. Abstract the common bitsfunction loadUsers(pageNum) {return $.ajax({url: /usersList.php,data: { page: pageNum, count: 50 }});}loadUsers(1).then(function (response) { ... },function (error) { ... });
  11. 11. Poor abstractions• abstracts HTTP rather than embracing it• its not just jQuery• every Ajax lib suffers from this issue• should abstract interacting with resources rather thanmechanics of making requests
  12. 12. rest.js• very thin wrapper around a raw request/response• XHR, Node, JSONP, IE XDomainRequest• AMD and CommonJS/Node• MIT licensed, part of cujoJS
  13. 13. How do I use rest.js?var rest = require(rest);-- or --define([rest], function (rest) {...});
  14. 14. How do I use rest.js?rest(/usersList.php).then(function (response) { ... });...wait a minute
  15. 15. Richardson (REST) Maturity Modelhttp://martinfowler.com/articles/richardsonMaturityModel.html
  16. 16. rest.js• abstraction to work with resources, rather than just anabstraction to make requests• full access to all aspects of the request and response,including response headers• advanced behavior applied with interceptors• configure behavior once, share
  17. 17. What makes rest.js different?• Interceptors!• apply advanced behavior to the request/response• encapsulate configuration• use what you need
  18. 18. Whats an interceptor?var client = rest.chain(basicAuthInterceptor, {username: marisa,password: koala});client(/usersList.php).then(function (response) {... authenticated response...});
  19. 19. What can interceptors do?• almost anything• hook into the request/response lifecycle• augment or replace a request/response• provide an alternate client• detect and/or recover from errors• abort the request
  20. 20. What cant interceptors do?• alter a configured client
  21. 21. Provided interceptors• Common: Default Request, Entity, Path Prefix, Location• RESTful: Content negotiation, Hypermedia APIs• Authentication: Basic, OAuth• Error Detection and Recover: Error Code, Retry, Timeout• Fallbacks: JSONP, XDomainRequest (IE), ActiveX XHR (IE)
  22. 22. Custom interceptorsreturn interceptor({init: function (config) {return config;},request: function (request, config) {return request;},response: function (response, config, client) {return response;},success: function (response, config, client) {return response;},error: function (response, config, client) {return response;}});
  23. 23. A real interceptor: basic authreturn interceptor({request: function handleRequest(request, config) {var headers, username, password;headers = request.headers || (request.headers = {});username = request.username || config.username;password = request.password || config.password || ;if (username) {headers.Authorization =Basic + base64.encode(username + : + password);}return request;}});
  24. 24. Chaining interceptors• extend a client applying behavior to requests/responseresulting in a new client• client can be safely shared within an application• clients are immutable
  25. 25. Chaining interceptorsvar client = rest.chain(basicAuthInterceptor, {username: marisa,password: koala}).chain(errorCodeInterceptor, { code: 500 }).chain(mimeInterceptor, { mime: application/json }).chain(hateoasInterceptor);
  26. 26. Interceptors in practicevar client = rest.chain(basicAuthInterceptor, {username: marisa,password: koala}).chain(errorCodeInterceptor, { code: 500 }).chain(mimeInterceptor, { mime: application/json }).chain(hateoasInterceptor);...I heard about this OAuth thing, can you use it instead of whatever we currently do?
  27. 27. Interceptors in practicevar client = rest.chain(oAuthInterceptor, {clientId: myapp,scope: read,write,authorizationUrl: http://example.com/oauth,redirectUrl: http://myapp.com/oauth}).chain(errorCodeInterceptor, { code: 500 }).chain(mimeInterceptor, { mime: application/json }).chain(hateoasInterceptor);• replaced basic auth with OAuth• request is authenticated under the hood• other interceptors, consumers dont care
  28. 28. What about events?• no problem• let’s use WebSockets• bidirectional communication• server → client• client → server
  29. 29. The problem withWebSocket libraries• abstracts sending and receiving of messages• little support for interacting with messages
  30. 30. EnterpriseIntegrationPatterns• simple patterns for message orientedprogramming• dont let the enterprise word scare you• widely deployed server side
  31. 31. msgs.js• Enterprise Integration Patterns in action• provides core messaging patterns• adapters to other messaging APIs• supports browsers (AMD) and Node.js• MIT licensed, part of cujoJS
  32. 32. Hello Worldvar bus = require(msgs).bus();bus.channel(lowercase);bus.channel(uppercase);bus.transform(function (message) { return message.toUpperCase(); },{ input: lowercase, output: uppercase });bus.outboundAdapter(function (str) { console.log(str); },{ input: uppercase });bus.send(lowercase, hello world); // HELLO WORLD
  33. 33. • transformer• filter• router• splitter• aggregator• inboundAdapter• outboundAdapter• inboundGateway• outboundGatewayMessaging primitives• bus• channel• pubsubChannel• exchangeChannel• queueChannel• subscribe• unsubscribe• tap• untap
  34. 34. var bus = require(msgs).bus(),webSocketServer = ...;bus.pubsubChannel(fromClient);bus.pubsubChannel(toClient);webSocketServer.on(connection, function (connection) {bus.nodeStreamGateway(connection, {output: fromClient,input: toClient});});bus.forward(fromClient, toClient);Broadcast server
  35. 35. Scalable broadcast servervar bus = require(msgs).bus(),redis = require(redis),webSocketServer = ...;bus.pubsubChannel(fromClient);bus.pubsubChannel(toClient);webSocketServer.on(connection, function (connection) {bus.nodeStreamGateway(connection, {output: fromClient,input: toClient});});bus.redisGateway(redis.createClient, circles,{ output: toClient, input: fromClient });
  36. 36. Lets not forget about the clientvar bus = require(msgs).bus(),SockJS = require(sockjs);bus.channel(toServer);bus.channel(fromServer);bus.webSocketGateway(new SockJS(/msgs),{ output: fromServer, input: toServer });...Full source: https://github.com/know-cujojs/circlesSee it running: http://cujojs-circles.cloudfoundry.com/
  37. 37. ThanksScott Andrews@scothissandrews@gopivotal.comcujoJS http://cujojs.com/rest.js https://github.com/cujojs/restmsgs.js https://github.com/cujojs/msgs

×