Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Message in a Bottle
1. Message in a bottle
Client-Client and Client-Server communication with HTML5
Zohar Arad. October 2011
2. Introduction
Background - Front-end and Web developer since 2004
Metacafe, Rounds, Newsgeek, 106fm, Quicklizard,
Crossrider, Superfly and others
Client-Side and UI architecting
Client-Server integration
HTML & CSS, JS, Ruby, Node
3. We’re going to talk about...
Passing message in the browser
• To the user (Desktop notifications)
• To the browser (postMessage)
• To the server (CORS)
• From the server (Server-Side Events)
5. Desktop Notifications
Lets us display a notification message to the user
Displays the message in the context of the browser
application, rather than the active window
Non-blocking (unlike alert / confirm)
Supports HTML content
6. Desktop Notifications
Still not part of HTML5
Only supported by Chrome
Very useful for browser-based apps
Requires explicit user permission (same as Geo API)
7. function RequestPermission(callback){
window.webkitNotifications.requestPermission(callback);
}
function showNotification(){
if (window.webkitNotifications.checkPermission() > 0) {
RequestPermission(showNotification);
} else {
window.webkitNotifications.createNotification(
"http://www.mysite/images/some_image.png",
"My Title",
"Hello stranger"
).show();
}
}
8. Desktop Notifications - API
checkPermission - Check notification permissions
requestPermission(callback) - Ask for notifications
permissions
createNotification(image, title, text) - create text
notification
createHTMLNotification(html_url) - create HTML
notification
9. Desktop Notifications - API
show - Show a created notification
cancel - Hide a created notification
10. Desktop Notifications - Flow
Check notification permissions (domain-specific)
Ask for notification permissions if needed
Create a notification object
Display the notification
Hide when appropriate
12. Posting messages between windows
We have two windows under our control
They don’t necessarily reside under the same domain
How can we pass messages from one window to the
other?
13. We used to hack it away
Change location.hash
Change document.domain (if subdomain is different)
Use opener reference for popups
Throw something really heavy, really hard
14. No more evil hacks
postMessage brings balance to the force
18. postMessage - Sending to iframes
var el = document.getElementById(‘my_iframe’);
var win = el.contentWindow;
win.postMessage(‘Hi from iframe parent’,
‘http://www.mydomain.com’);
19. postMessage - Sending to popup
var popup = window.open(......);
popup.postMessage(‘Hi from iframe parent’,
‘http://www.mydomain.com’);
20. When should you use it?
Browser extensions
Embedded iframes (if you must use such evil)
Flash to Javascript
22. In the good ol’ days...
We had XHR (Thank you Microsoft)
We could make requests from the client to the server
without page reload
We were restricted to the same-origin security policy - No
cross-domain requests
23. This led to things like
JSONP
Flash-driven requests
Server-side proxy
Using iframes (express your frustration here)
26. CORS is the new AJAX
Cross-domain requests are allowed
Server is responsible for defining the security policy
Client is responsible for enforcing the security policy
Works over standard HTTP
27. CORS - Client Side
var xhr = new XMLHttpRequest();
xhr.open(‘get’,
‘http://www.somesite.com/some_resource/’,
true);
xhr.onload = function(){ //instead of onreadystatechange
};
xhr.send(null);
29. CORS - Client Side (IE)
var xhr = new XDomainRequest();
xhr.open(‘get’,‘http://www.somesite.com/some_resource/’);
xhr.onload = function(){ //instead of onreadystatechange
};
xhr.send();
30. CORS - Client Side API
abort() - Stop request that’s already in progress
onerror - Handle request errors
onload - Handle request success
send() - Send the request
responseText - Get response content
31. CORS - Access Control Flow
The client sends ‘Access-Control’ headers to the server
during request preflight
The server checks whether the requested resource is
allowed
The client checks the preflight response and decides
whether to allow the request or not
32. CORS - Server Side
Use Access-Control headers to allow
Origin - Specific request URI
Method - Request method(s)
Headers - Optional custom headers
Credentials - Request credentials (cookies, SSL, HTTP
authentication (not supported in IE)
33. CORS - Server Side
Access-Control-Allow-Origin: http://www.somesite.com/some_resource
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: NCZ
Access-Control-Max-Age: 84600
Access-Control-Allow-Credentials: true
34. CORS - Recap
Client sends a CORS request to the server
Server checks request headers for access control
according to URI, method, headers and credentials
Server responds to client with an access control response
Client decides whether to send the request or not
35. CORS - Why should you use it?
It works on all modern browser (except IE7 and Opera)
It doesn’t require a lot of custom modifications to your code
Its the new AJAX (just like the new Spock)
You can fall back to JSONP or Flash
Using CORS will help promote it
Works on Mobile browsers (WebKit)
37. Server-Side Events
Stream data from the server to the client
Works over plain HTTP. No special protocol required
Half-duplex - You can give but you cannot receive
Not as full-featured as WS but just as useful
38. Server-Side Events - Client
var source = new EventSource(‘/path/to/stream’);
source.addEventListener(‘open’, function(e) {
// Connection was opened.
}, false);
source.addEventListener(‘error’, function(e) {
if (e.eventPhase == EventSource.CLOSED) {
// Connection was closed.
}
}, false);
44. Server-Side Events - Recap
Works over plain old HTTP
Half-Duplex - Only from server to client
Messages are sent in plain text with text/event-stream
content-type
Supported by Chrome, Safari 5+, FF 6+, Opera 11+
45. When should I use SSE?
Whenever full-duplex communication is not required
Push data application
Sending data to server can be done over plain XHR
When implementing as a separate service is not feasible
When Web-Sockets are not an option