Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

restl

Package Overview
Dependencies
Maintainers
2
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

restl - npm Package Compare versions

Comparing version 0.1.2 to 0.2.0

test/integration/fetch-api.js

8

changelog.md
ChangeLog
=========
0.2.0 (2017-04-21)
------------------
* #17: Now using the Fetch API instead of the requests library. The requests
library is kept around for BC purposes, but this will eventually be removed.
* #25: the resourceCache was accidentally shared between Client instances.
0.1.2 (2017-04-19)

@@ -5,0 +13,0 @@ ------------------

59

lib/client.js

@@ -5,27 +5,40 @@ var url = require('url');

var package = require('../package.json');
var fetch = require('node-fetch');
var Client = function(bookMark, requestOptions) {
var Client = function(bookMark, options) {
if (typeof requestOptions === 'undefined') {
requestOptions = {};
if (typeof options === 'undefined') {
options = {};
}
this.resourceCache = {};
if (options.accept) {
this.accept = options.accept;
} else {
this.accept = 'application/hal+json, application/json';
}
/* Note: all the following settings exists solely to provide backwards
* compatibility for the Requests library, and will eventually be removed.
*/
// json-promise-any setting, makes sure that we're getting whole responses
// and not just the response body.
requestOptions.resolveWithFullResponse = true;
options.resolveWithFullResponse = true;
if (!requestOptions.headers) {
requestOptions.headers = {};
if (!options.headers) {
options.headers = {};
}
if (!requestOptions.headers['User-Agent']) {
requestOptions.headers['User-Agent'] = 'Restl/' + package.version;
if (!options.headers['User-Agent']) {
options.headers['User-Agent'] = 'Restl/' + package.version;
}
if (!requestOptions.headers.Accept) {
requestOptions.headers.Accept = 'application/hal+json, application/json';
if (!options.headers.Accept) {
options.headers.Accept = 'application/hal+json, application/json';
}
// Parsing json by default.
requestOptions.json = true;
this.request = request.defaults(requestOptions);
options.json = true;
this.request = request.defaults(options);
this.bookMark = bookMark;
};

@@ -40,3 +53,3 @@

*/
resourceCache : {},
resourceCache : null,

@@ -72,2 +85,22 @@ /**

},
/**
* This function does an arbitrary request using the fetch API.
*
* Every request in restl is routed through here so it can be initialized
* with some useful defaults.
*/
fetch : function(input, init) {
var request = new fetch.Request(input, init);
if (!request.headers.has('User-Agent')) {
request.headers.set('User-Agent', 'Restl/' + require('../package.json').version);
}
if (!request.headers.has('Accept')) {
request.headers.set('Accept', this.accept);
}
return fetch(request);
}

@@ -74,0 +107,0 @@

@@ -7,2 +7,3 @@ 'use strict';

var Promise = require('bluebird');
var fetch = require('node-fetch');

@@ -36,8 +37,14 @@ var Resource = function(client, uri) {

return this.request({
method: 'PUT',
uri: this.uri,
body: body
}).then(function() {
return this.fetch(
this.uri,
{
method: 'PUT',
body: JSON.stringify(body)
}
).then(function(response) {
if (!response.ok) {
throw new Error('HTTP error: ' + response.statusCode);
}
// Wipe out the local cache

@@ -54,10 +61,15 @@ this.repr = null;

*/
delete: function(body) {
delete: function() {
return this.request({
method: 'DELETE',
uri: this.uri,
body: body
}).then(function() {
return this.fetch(
this.uri,
{
method: 'DELETE',
}
).then(function(response) {
if (!response.ok) {
throw new Error('HTTP error: ' + response.statusCode);
}
// Wipe out the local cache

@@ -86,16 +98,26 @@ this.repr = null;

return this.request({
method: 'POST',
uri: this.uri,
body: body
}).then(function(response) {
if (response.headers.location) {
return this.fetch(
this.uri,
{
method: 'POST',
body: JSON.stringify(body)
}
).then(function(response) {
if (!response.ok) {
throw new Error('HTTP error: ' + response.statusCode);
}
if (response.headers.has('location')) {
return this.client.getResource(
url.resolve(
this.uri,
response.headers.location
response.headers.get('location')
)
);
}
return null;
}.bind(this));
},

@@ -109,10 +131,16 @@

return this.request({
method: 'GET',
uri: this.uri
}).then(function(response) {
var response;
return this.fetch(this.uri, {method: 'GET' })
.then(function(r) {
response = r;
if (!response.ok) {
throw new Error('HTTP error: ' + response.statusCode);
} else {
return response.json();
}
}).then(function(jsonBody) {
this.repr = new Representation(
this.uri,
response.headers['content-type'],
response.body
jsonBody
);

@@ -215,2 +243,18 @@ // Parsing and storing embedded uris

/**
* Does an arbitrary HTTP request on the resource using the Fetch API.
*/
fetch: function(input, init) {
if (typeof input === 'string') {
input = url.resolve(this.uri, input);
} else {
input.url = url.resolve(this.uri, input.url);
}
var request = new fetch.Request(input, init);
return this.client.fetch(request);
},
/**
* Does an arbitrary HTTP request on the resource, and returns the HTTP

@@ -217,0 +261,0 @@ * response object from the Request library, wrapped in a Promise.

{
"name": "restl",
"version": "0.1.2",
"version": "0.2.0",
"description": "Opiniated HAL client.",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -22,39 +22,26 @@ Restl - A hypermedia client for nodejs

npm install --save restl
npm install --save restl
Goals
-----
Features overview
-----------------
### For 1.0:
Restl is a library that sits on top of a HTTP client (currently Request, but
soon the Fetch API).
* Expand CURIES automatically.
* Support HTTP `Link` header.
* Support non-JSON resources, including things like images.
* Parse [HTML5 links][1].
* Parse [Atom][5].
* Built-in OAuth2.
It provides some useful abstractions that make it easier to work with true
hypermedia / HATEAOS servers. It currently parses [HAL][2] and has a deep
understanding of links and embedded resources.
Using this library it becomes very easy to follow links from a single bookmark,
and discover resources and features on the server. Embedded resources are
completely hidden. Embedded resources just show up as links, but when you're
asking for the representation, the response to the `GET` request will be
served from a cache.
### Post 1.0
This feature allows HAL servers to upgrade links to embedded resources, and
allows any client to transparently take advantage of this change and issue
less HTTP requests.
* Support for [HAL Forms][4].
* Parse and respect HTTP Cache headers.
* Support [`Prefer: return=representation`][6].
* Browser support (nodejs only at the moment, but only because of the Request
library.)
* Unittests
### Already done:
* Following links.
* Basic HAL parsing.
* Normalizing `_links` and `_embedded`.
* `PUT` request.
* `DELETE` request.
* `POST` request
* Global resource cache.
* Resolve every URI to an absolute URI.
* Figuring caching resources from `_embedded`.
Usage

@@ -150,4 +137,2 @@ -----

#### Constructor
```js

@@ -337,4 +322,2 @@ var client = new Client(bookMark, options);

[3]: https://www.npmjs.com/package/request
[4]: https://rwcbook.github.io/hal-forms/ "HAL Forms"
[5]: https://bitworking.org/projects/atom/rfc5023.html "AtomPub"
[6]: https://tools.ietf.org/html/rfc7240 "Prefer Header for HTTP"

@@ -10,4 +10,8 @@ {

"_links" : {
"self": { "href" : "/hal1.json" },
"next" : { "href" : "/hal2.json" }
"self" : { "href" : "/hal1.json" },
"next" : { "href" : "/hal2.json" },
"collection" : { "href" : "/hal-collection.json" },
"headerTest": { "href" : "/headers" },
"error400" : { "href" : "/error/400" },
"redirect" : { "href" : "/redirect" }
},

@@ -14,0 +18,0 @@ "title" : "Hal 1",

@@ -5,3 +5,7 @@ {

"next" : { "href" : "/hal2.json" },
"collection" : { "href" : "/hal-collection.json" }
"collection" : { "href" : "/hal-collection.json" },
"headerTest": { "href" : "/headers" },
"error400" : { "href" : "/error/400" },
"redirect" : { "href" : "/redirect" },
"echo": { "href" : "/echo" }
},

@@ -8,0 +12,0 @@ "title" : "Hal 1",

@@ -36,2 +36,8 @@ const Client = require('../../lib/client');

after( async() => {
await client.getResource('/reset').post({});
});
});

@@ -12,2 +12,12 @@ const Koa = require('koa');

app.use(
route('/headers')
.get(ctx => {
ctx.response.status = 200;
ctx.response.body = ctx.request.headers;
})
);
// Reset the server to the beginning state

@@ -23,3 +33,30 @@ app.use(

// HTTP errors as a service
app.use(
route('/error/:code')
.get(ctx => {
ctx.response.status = parseInt(ctx.params.code);
ctx.response.body = '';
})
);
// Redirect testing
app.use(
route('/redirect')
.get(ctx => {
ctx.response.redirect('/hal2.json');
})
);
// Return request body as we received it
app.use(
route('/echo')
.post(ctx => {
ctx.response.statusCode = 200;
ctx.response.type = ctx.request.headers['content-type'];
ctx.response.body = ctx.req;
})
);
// Rest stuff!

@@ -26,0 +63,0 @@ app.use(

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc