Oscar Tong
Everything that has a beginning has an end.
Ajax & WebSocket
- Oscar Tong / @oscartong
How it works ?
//create a XHR instance var request = new XMLHttpRequest(); //listen for readyStateChange event request.onreadystatechange = function(e){ if(request.readyState === 4 && request.status === 200){ console.log(request.responseText); } }; //send request request.open('GET', 'http://www.example.com/foo', true); request.send();
//initiate a XMLHttpRequest and handle timeout situation var xhr = new XMLHttpRequest(); xhr.open('GET', 'foo'); xhr.timeout = 3000; xhr.onload = onLoad; xhr.ontimeout = onTimeout; xhr.send(); //timeout event handler function onTimeout(event){ var xhr = event.target; //set a higher timeout value and resend the request xhr.timeout = 6000; xhr.open('GET', 'foo'); xhr.send(); }
//create a form and append data var formdata = new FormData(); formdata.append('username', 'Oscar Tong'); formdata.append('id', 1234); //number 1234 is converted to string '1234' formdata.append('file', someFileInput.files[0]); //create a request and post formdata var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://www.foo.com/bar.php'); xhr.send(formdata);
var xhr = new XMLHttpRequest(); xhr.open('GET', 'foo'); //set responseType as arraybuffer to send/receive binary data xhr.responseType = 'arraybuffer'; xhr.onload = function(){ var arraybuffer = xhr.response; //not responseText .... }; xhr.send();
//handle progress and other level2 events var xhr = new XMLHttpRequest(); xhr.addEventListener('progress', onProgress); xhr.addEventListener('load', onComplete); xhr.addEventListener('error', onError); xhr.addEventListener('abort', onCanceled); function onProgress(event){ if(event.lengthComputable){ console.log('percent complete:', event.loaded / event.total); } else{ //total size is unknown yet } } function onComplete(event){ ... } function onError(event){ ... } function onCanceled(event){ ... }
//CORS means Cross Origin Resource Sharing function createCORSRequest(method, url){ var xhr = new XMLHttpRequest(); if('withCredentials' in xhr){ //check if the XMLHttpRequest object has a 'withCredentials' property //which only exists on XMLHttpRequest Level 2 object xhr.open(method, url, true); } else if(typeof XDomainRequest != 'undefined'){ //otherwise check if XDomainRequest exists //XDomainRequest only exists in IE, it is IE's way of making CORS request xhr = new XDomainRequest(); xhr.open(method, url); } else{ //sorry, your browser does not supports CORS xhr = null; } }
//creating and sending a CORS request
var xhr = createCORSRequest('GET', 'http://api.twitter.com/foo');
xhr.send();
HTTP Request:
GET /foo HTTP/1.1 Origin: http://www.example.com Host: http://api.twitter.com Accept-Language: en-US User-Agent: Mozilla/5.0 ... HTTP Response: ... Access-Control-Allow-Origin: http://www.example.com Access-Control-Allow-Credentials: true Acceee-Control-Expose-Headers: Foo,Bar Content-Type: text/html; charset=utf-8 ...
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Origin: http://example.com Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
Server > Client
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' Sec-WebSocket-Accept = base64( sha1( Sec-WebSocketKey + GUID ) )
0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-------+-+-------------+------------------------------+ |F|R|R|R| Opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16 or 64) | |N|V|V|V| |S| | (if payload len == 126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+------------------------------+ | Extended payload length continued, if payload len == 127 | +-------------------------------+------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+------------------------------+ | Masking-key continued | Payload Data | +-------------------------------+------------------------------+ : Payload Data continued ... : +--------------------------------------------------------------+ | Payload Data continued ... | +--------------------------------------------------------------+
0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-------+-+-------------+------------------------------+ |F|R|R|R| Opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16 or 64) | |N|V|V|V| |S| | (if payload len == 126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+------------------------------+ ... Text frame: +-+-+-+-+-------+-+-------------+-----------+ |1|0|0|0| 0x1 |0| 11 |Hello World| +-+-+-+-+-------+-+-------------+-----------+
0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-------+-+-------------+------------------------------+ |F|R|R|R| Opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16 or 64) | |N|V|V|V| |S| | (if payload len == 126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+------------------------------+ ... Close frame: +-+-+-+-+-------+-+-------------+ |1|0|0|0| 0x8 |0| 0 | +-+-+-+-+-------+-+-------------+
//creating a WebSocket instance and try connect to the server var socket = new WebSocket('ws://www.example.com/socketserver'); //open event is fired when WebSocket is connected socket.onopen = function(event){ socket.send('Hello Server. How are you?'); }; //message event is fire when message is received from server socket.onmessage = function(event){ console.log('Server said:', event.data); }; ... //close the WebSocket connection socket.close();
Demo(Telnet Client)
By Oscar Tong