UNPKG

17.5 kBMarkdownView Raw
1rest.js
2=======
3
4Just enough client, as you need it. Make HTTP requests from a browser or Node.js applying only the client features you need. Configure a client once, and share it safely throughout your application. Easily extend with interceptors that wrap the request and/or response, or MIME type converters for rich data formats.
5
6
7Build Status
8------------
9
10<table>
11 <tr><td>Master</td><td><a href="http://travis-ci.org/cujojs/rest" target="_blank"><img src="https://secure.travis-ci.org/cujojs/rest.png?branch=master" /></a></tr>
12 <tr><td>Development</td><td><a href="http://travis-ci.org/cujojs/rest" target="_blank"><img src="https://secure.travis-ci.org/cujojs/rest.png?branch=dev" /></a></tr>
13</table>
14
15
16Usage
17-----
18
19Using rest.js is easy. The core clients provide limited functionality around the request and response lifecycle. The request and response objects are normalized to support portability between different JavaScript environments.
20
21The return value from a client is a promise that is resolved with the response when the remote request finishes.
22
23The core client behavior can be augmented with [interceptors](docs/interceptors.md#interceptor-principals). An interceptor wraps the client and transforms the request and response. For example: an interceptor may authenticate a request, or reject the promise if an error is encountered. Interceptors may be combined to create a client with the desired behavior. A configured interceptor acts just like a client. The core clients are basic, they only know the low level mechanics of making a request and parsing the response. All other behavior is applied and configured with interceptors.
24
25Interceptors are applied to a client by wrapping. To wrap a client with an interceptor, call the `wrap` method on the client providing the interceptor and optionally a configuration object. A new client is returned containing the interceptor's behavior applied to the parent client. It's important to note that the behavior of the original client is not modified, in order to use the new behavior, you must use the returned client.
26
27
28### Making a basic request: ###
29
30```javascript
31var rest = require('rest');
32
33rest('/').then(function(response) {
34 console.log('response: ', response);
35});
36```
37
38In this example, you can see that the request object is very simple, it just a string representing the path. The request may also be a proper [object containing other HTTP properties](docs/interfaces.md#interface-request).
39
40The response should look familiar as well, it contains all the fields you would expect, including the response headers (many clients ignore the headers).
41
42
43### Working with JSON: ###
44
45If you paid attention when executing the previous example, you may have noticed that the response.entity is a string. Often we work with more complex data types. For this, rest.js supports a rich set of [MIME type conversions](docs/mime.md) with the [MIME Interceptor](docs/interceptors.md#module-rest/interceptor/mime). The correct converter will automatically be chosen based on the `Content-Type` response header. Custom converts can be registered for a MIME type, more on that later...
46
47```javascript
48var rest, mime, client;
49
50rest = require('rest'),
51mime = require('rest/interceptor/mime');
52
53client = rest.wrap(mime);
54client({ path: '/data.json' }).then(function(response) {
55 console.log('response: ', response);
56});
57```
58
59Before an interceptor can be used, it needs to be configured. In this case, we will accept the default configuration, and obtain a client. Now when we see the response, the entity will be a JS object instead of a String.
60
61
62### Composing Interceptors: ###
63
64```javascript
65var rest, mime, errorCode, client;
66
67rest = require('rest'),
68mime = require('rest/interceptor/mime');
69errorCode = require('rest/interceptor/errorCode');
70
71client = rest.wrap(mime)
72 .wrap(errorCode, { code: 500 });
73client({ path: '/data.json' }).then(
74 function(response) {
75 console.log('response: ', response);
76 },
77 function(response) {
78 console.error('response error: ', response);
79 }
80);
81```
82
83In this example, we take the client create by the [MIME Interceptor](docs/interceptors.md#module-rest/interceptor/mime), and wrap it with the [Error Code Interceptor](https://github.com/s2js/rest/blob/cujojs/docs/interceptors.md#module-rest/interceptor/errorCode). The error code interceptor accepts a configuration object that indicates what status codes should be considered an error. In this case we override the default value of <=400, to only reject with 500 or greater status code.
84
85Since the error code interceptor can reject the response promise, we also add a second handler function to receive the response for requests in error.
86
87Clients can continue to be composed with interceptors as needed. At any point the client as configured can be shared. It is safe to share clients and allow other parts of your application to continue to compose other clients around the shared core. Your client is protected from additional interceptors that other parts of the application may add.
88
89
90### Declarative Interceptor Composition: ###
91
92First class support is provided for [declaratively composing interceptors using wire.js](docs/wire.md). wire.js is an dependency injection container; you specify how the parts of your application interrelate and wire.js takes care of the dirty work to make it so.
93
94Let's take the previous example and configure the client using a wire.js specification instead of imperative code.
95
96```javascript
97{
98 ...,
99 client: {
100 rest: [
101 { module: 'rest/interceptor/mime' },
102 { module: 'rest/interceptor/errorCode', config: { code: 500 } }
103 ]
104 },
105 $plugins: [{ module: 'rest/wire' }]
106}
107```
108
109There are a couple things to notice. First is the '$plugins' section, by declaring the `rest/wire` module, the `rest` factory becomes available within the specification. The second thing to notice is that we no longer need to individually `require()` interceptor modules; wire.js is smart enough to automatically fetch the modules. The interceptors are then wrapped in the order they are defined and provided with the corresponding config object, if it's defined. The resulting client can then be injected into any other object using standard wire.js facilities.
110
111
112### Custom MIME Converters: ###
113
114```javascript
115var registry = require('rest/mime/registry');
116
117registry.register('application/vnd.com.example', {
118 read: function(str) {
119 var obj;
120 // do string to object conversions
121 return obj;
122 },
123 write: function(obj) {
124 var str;
125 // do object to string conversions
126 return str;
127 }
128});
129```
130
131Registering a custom converter is a simple as calling the register function on the [mime registry](docs/mime.md#module-rest/mime/registry) with the type and converter. A converter has just two methods: `read` and `write`. Read converts a String to a more complex Object. Write converts an Object back into a String to be sent to the server. HTTP is fundamentally a text based protocol after all.
132
133Built in converters are available under `rest/mime/type/{type}`, as an example, JSON support is located at `rest/mime/type/application/json`. You never need to know this as a consumer, but it's a good place to find examples.
134
135
136Supported Environments
137----------------------
138
139Our goal is to work in every major JavaScript environment; Node.js and major browsers are actively tested and supported.
140
141If your preferred environment is not supported, please let us know. Some features may not be available in all environments.
142
143Tested environments:
144- Node.js (0.6, 0.8. 0.10)
145- Chrome (stable)
146- Firefox (stable, ESR, should work in earlier versions)
147- IE (6-11)
148- Safari (5-8, iOS 4-8.1, should work in earlier versions)
149- Android (4.0-5.0, should work in earlier versions)
150- Opera (11, 12, should work in earlier versions)
151
152Specific browser test are provided by [Travis CI](https://travis-ci.org/cujojs/rest) and [Sauce Labs' Open Sauce Plan](https://saucelabs.com/opensource). You can see [specific browser test results](https://saucelabs.com/u/cujojs-rest), although odds are they do not reference this specific release/branch/commit.
153
154
155Getting Started
156---------------
157
158rest.js can be installed via [npm](https://npmjs.org/), [Bower](http://bower.io/), [jspm](http://jspm.io/), or from source.
159
160To install without source:
161
162 $ npm install --save rest
163
164or
165
166 $ bower install --save rest
167
168or
169
170 $ jspm install rest
171
172From source:
173
174 $ npm install
175
176rest.js is designed to run in a browser environment, utilizing [AMD modules](https://github.com/amdjs/amdjs-api/wiki/AMD), or within [Node.js](http://nodejs.org/) as CommonJS modules. Any module loader capable of loading either AMD or CommonJS modules should be able to load rest.js. cujoJS [curl.js](https://github.com/cujojs/curl) is actively tested.
177
178An ECMAScript 5 compatible environment is assumed. Older browsers, ::cough:: IE, that do not support ES5 natively can be shimmed. Any shim should work, although we test with cujoJS [poly.js](https://github.com/cujojs/poly)
179
180
181Documentation
182-------------
183
184Full project documentation is available in the [docs directory](docs).
185
186
187Running the Tests
188-----------------
189
190The test suite can be run in two different modes: in node, or in a browser. We use [npm](https://npmjs.org/) and [Buster.JS](http://busterjs.org/) as the test driver, buster is installed automatically with other dependencies.
191
192Before running the test suite for the first time:
193
194 $ npm install
195
196To run the suite in node:
197
198 $ npm test
199
200To run the suite in a browser:
201
202 $ npm start
203 browse to http://localhost:8282/ in the browser(s) you wish to test. It can take a few seconds to start.
204
205
206Get in Touch
207------------
208
209You can find us on the [cujojs mailing list](https://groups.google.com/forum/#!forum/cujojs), or the #cujojs IRC channel on freenode.
210
211Please report issues on [GitHub](https://github.com/cujojs/rest/issues). Include a brief description of the error, information about the runtime (including shims) and any error messages.
212
213Feature requests are also welcome.
214
215
216Contributors
217------------
218
219- Scott Andrews <scothis@gmail.com>
220- Jeremy Grelle <jeremy.grelle@gmail.com>
221- John Hann <john@unscriptable.com>
222- Michael Jackson <mjijackson@gmail.com>
223
224Please see CONTRIBUTING.md for details on how to contribute to this project.
225
226
227Copyright
228---------
229
230Copyright 2012-2015 the original author or authors
231
232rest.js is made available under the MIT license. See LICENSE.txt for details.
233
234
235Change Log
236----------
237
2381.3.1
239- fix to allow numbers and boolean values as parameters to URI Template expansion.
240
2411.3.0
242- response.follow() for easy traversal of hypermedia APIs
243- application/hal mime converter supports templated URLs, and resource.requestFor('relationship', request)
244- full URI Template (rfc6570) support in rest/util/uriTemplate
245- section aware URI encoding in rest/util/uriEncoder
246- best fit MIME type resolution, including by suffix (i.e. '+json'). Parsed MIME type provided to converters
247- installation via jspm and loader support for System.js
248- support for Android 4.0-5.0 (no code changes required, now actively testing)
249- support for Safari 8, iOS 8.0 and 8.1 (no code changes required, now actively testing)
250- raw configuration objects are retained by interceptors, config objects are no longer begotten
251- transient timeouts via config.transient on rest/interceptor/timeout, allows retry interceptor to wrap timeout
252- extend JSON converter for custom reviver and replacers
253- request.mixin properties attempt setting before before and after opening the request. Some browsers (IE) are sensitive to when the properties are set.
254- wire.js rest factory interceptors now wire configuration objects
255- normalize responses for linked and embedded resources from application/hal mime converter to always be a ResponsePromise
256
2571.2.0
258- deprecated rest/interceptor/entity: instead use response.entity()
259- deprecated and removed wire.js reference resolves 'client!' and 'resource!', instead use the 'rest/wire' factory
260- deprecated and removed Dojo store support
261- separate browser and node main modules, browser consumers should switch their main module from 'rest/rest' to 'rest/browser'. This allows tools such as browerify and webpack to more intelligently reason about the module structure.
262- Multipart requests for browsers that support FormData (sorry IE 6-9). Thanks @mjackson
263- mixin property support in defaultRequest interceptor. Thanks @jiangtyd
264- allow location interceptor to be applied based on the status code. Thanks @phillipj
265- better support for file:// URL via the XHR client
266
2671.1.1
268- support for IE 11, Safari 7 and iOS 7 (no code changes required, now actively testing)
269- Node specific configuration options via request.mixin. Particularly useful for https clients. Thanks @wwwdata
270- basic support for Browserify. Note: Browserify is not yet a tested environment
271
2721.1.0
273- bump when.js version to ~3, 2.x is no longer supported
274- perfer `client.wrap()` to `client.chain()`, `chain` is now deprecated
275- add HTTP specific methods to the promises returned from clients: .entity(), .status(), .headers(), .header(name)
276- mime converters may return a promise. Thanks @phillipj
277- removed 'rest/util/beget' favor Object.create
278
2791.0.3
280- add moduleType for bower (node and amd). Thanks @briancavalier
281- doc polish. Thanks @gogamoga
282
2831.0.2
284- restore client.chain() to the default client
285
2861.0.1
287- handle exceptions thrown from MIME converters
288- allow overriding the default client
289- allow AMD loaders to load node client. Useful when using an AMD loader with Node. Thanks @unscriptable
290
2911.0.0
292- JSON HAL mime serializer for application/hal+json
293- the third argument to the interceptor request/response callbacks is not an object instead of the client, the client is a property on that object
294- HATEOAS interceptor defaults to indexing relationships directly on the host entity instead of the '_links' child object. A child object may still be configured.
295- HATEOAS interceptor returns same promise on multiple relationship property accesses
296- 'file:' scheme URL support in rest/UrlBuilder
297- bump when.js version to 2.x
298- drop support for bower pre 1.0
299
3000.9.4
301- CSRF protection interceptor
302- support bower 0.10+, older versions of bower continue to work
303
3040.9.3
305- fixes issues with uglified JSONP client in IE 8
306
3070.9.2
308- allow strings to represent request objects, the string value is treated as the path property
309- parsing 'Link' response headers in hateoas interceptor (rfc5988)
310
3110.9.1
312- add Node 0.10 as a tested environment
313- restore when.js 1.8 compat, when.js 2.0 is still preferred
314
3150.9.0
316- moving from the 's2js' to the 'cujojs' organization
317- new reference documentation in the docs directory
318- Interceptor configuration chaining `rest.chain(interceptor, config).chain(interceptor, config)...`
319- wire.js factory
320- hateoas and location interceptors default to use request.originator
321- defaultRequest interceptor, provide default values for any portion of a request
322- XDomainRequest support for IE 8 and 9
323- XHR fall back interceptor for older IE
324- allow child MIME registries and configurable registry for the mime interceptor
325- SimpleRestStore that provides the functionality of RestStore without Dojo's QueryResults
326- rename UrlBuilder's 'absolute()' to 'fullyQualify()'
327- added 'isAbsolute()', 'isFullyQualified()', 'isCrossOrigin()' and 'parts()' to UrlBuilder
328- access to the originating client as request.originator
329- shared 'this' between request/response phases of a single interceptor per request
330- 'init' phase for interceptors, useful for defaulting config properties
331- interceptor config object is now begotten, local modifications will not collide between two interceptors with the same config obj
332- cleaned up interceptor's request handler for complex requests
333- mutli-browser testing with Sauce Labs
334
3350.8.4
336- Bower installable, with dependencies
337- node client's response.raw includes ClientResquest and ClientResponse objects
338- basicAuth interceptor correctly indicates auth method
339
3400.8.3
341- moving from the 'scothis' to the 's2js' organization, no functional changes
342
3430.8.2
344- requests may be canceled
345- timeout incerceptor that cancels the request unless it finishes before the timeout
346- retry interceptor handles error respones by retrying the request after an elapsed period
347- error interceptor handlers may recover from errors, a rejected promise must be returned in order to preserve the error state
348- response objects, with an error property, are used for client errors instead of the thrown value
349- interceptor response handlers recieve the interceptor's client rather then the next client in the chain
350- interceptor request handlers may provide a response
351- convert modules to UMD format; no functional impact
352- replaced rest/util/base64 with an MIT licenced impl; no functional impact
353
3540.8.1
355- fixed bug where http method may be overwritten
356
3570.8.0
358- npm name change 'rest-template' -> 'rest'
359- introduced experimental HATEOAS support
360- introduced 'location' interceptor which follows Location response headers, issuing a GET for the specified URL
361- default method to POST when request contains an entity
362- response handlers now have access to the request client to issue subsequent requests
363- interceptors may specify their default client
364- renamed `rest/interceptor/_base` to `rest/interceptor`
365
3660.7.5
367- Initial release, everything is new