JsHttpRequest: JavaScript "AJAX" data loader @license LGPL @author Dmitry Koterov, http://en.dklab.ru/lib/JsHttpRequest/ @version 5.x $Id$ This document describes the protocol used by JsHttpRequest library. Backend -> Frontend ------------------- JsHttpRequest library uses 3 slightly different version of output protocol depending on the loader used. - SCRIPT loader: Content-type: text/javascript; charset=... JsHttpRequest.dataReady({ id: ..., js: ..., text: ...}) The charset is always set equal to the base backend charset. - XML loader: Content-type: text/plain; charset=... { id: ..., js: ..., text: ...} The charset may be UTF-8 (of the backend supports JSON conversion functions) or the base backend charset. We have to use text/plain because of some Opera 8 bugs. - FORM loader: Content-type: text/html; charset=... The charset is always set equal to the base backend charset. Note that we use text/html Content-type, because the result is loaded into dynamically created IFRAME and must be valid HTML. (Note that you may always use a fixed charset in your backends, e.g. UTF-8. The frontend is a fully Unicode supporting library.) The common part of all these constructions is always represented as a plain JavaScript object: { id: , js: , text: } Meanings of object properties are: - id: ID of the loading passed by a frontend. This ID is used to associate the resulting data with corresponding onreadystatechange handler and generated automatically. - js: a JavaScript object representing multi-dimensional array passed from the backend to a frontend. - text: other backend data (usually captured STDOUT). Note that for XML the loader ID is always equals to 0, because we do not need an explicit binding between a result data and a loader: binding is performed automatically by ActiveX or XMLHttpRequest. ATTENTION! If you want to create your own backend, you should guarantee that the following formats are satisfied, else you may get a JavaScript backend exception. E.g., if your script dies with some error, it should pass the message to the "text" property, not write it to the output directly. In PHP backend it is done via ob_start() handlers. Frontend -> Backend ------------------- The protocol is very simple and fully compatible with standard PHP's features. Frontend passes to backend a list of key=value pairs using GET or POST method. 1. Auxiliary information Each loading process is supplied with a piece of information appended to the end of QUERY_STRING: PHPSESSID=&JsHttpRequest=- - PHPSESSID= is the session information. (Of course you may use another name instead of PHPSESSID, it is tuned inside the JsHttpRequest object.) Here is the session identifier extracted from document cookies or from the current document URL. This method is fully comatible with PHP sessions support. - is the name of a loader used. E.g.: "xml", "script", "form". - is the loading ID. It is generated automatically and unique for each of the loading process. (Exception is the XML loader: it always uses zero ID.) This ID is passed back by a backend to determine which result is binded to which callback action (see above). 2. Character conversions Each character of a key/value is encoded by JavaScript standard escape() function (with exception for "+": it is converted to "%2B"). That means: - Unicode non-ASCII character (e.g. with code 0x1234) is encoded to e.g. %u1234. - Character "+" is converted to "%2B". - URL-allowed characters (e.g. letters, digits etc.) remain unchanged. - Other ASCII character (e.g. 0x15) is converted to e.g. %15. Samples: - "проба" -> "%u043F%u0440%u043E%u0431%u0430" - "abcde" -> "abcde" - "a[x]" -> "a%5Bx%5D" - "a+b" -> "a%2Bb" 3. Array conversions JsHttpRequest supports multi-dimensional associative arrays created from standard JavaScript objects. Each key of the key=value pair is created based on all parents of the corresponding object property. PHP notation of multi-dimensional arrays is used. Samples: - JavaScript: { a: 123, b: { c: 456, d: 789 } } - GET/POST data: a=123&b[c]=456&b[d]=789 - PHP's array: array('a' => 123, 'b' => array('c' => 456, 'd' => 789)) - JavaScript: { a: 123, b: [4, 5] } - GET/POST data: a=123&b[]=4&b[]=5 - PHP's array: array('a' => 123, 'b' => arrat(4, 5)) You see that JavaScript objects are 1:1 converted to PHP's arrays, and an array encoding format is compatible with such behaviour. 4. Content-type header Available Content-type headers generated by a frontend depend on a loader and a method used. Samples (format: .): - application/x-www-form-urlencoded: script.*, xml.GET, form.GET - multipart/form-data: form.POST - application/octet-stream: xml.POST Please note that xml.POST generates application/octet-stream, but NOT application/x-www-form-urlencoded. It is needed to avoid the standard PHP behavior of POST data parsing, because we have to process the data encoding manually (PHP does not support JavaScript escape() encoding directly). Also note that multipart/form-data format used for FORM loader, because this is the only way to support file uploads.