Socket
Socket
Sign inDemoInstall

get-uri

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

get-uri - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

test/data.js

6

file.js

@@ -7,3 +7,3 @@

var fs = require('fs');
var path = require('path');
var uri2path = require('file-uri-to-path');
var NotFoundError = require('./notfound');

@@ -35,4 +35,4 @@ var NotModifiedError = require('./notmodified');

// convert URI → Path
// TODO: will probably need better Windows support for this someday (see #3)
var filepath = path.normalize(decodeURIComponent(parsed.pathname));
var uri = parsed.href;
var filepath = uri2path(uri);
debug('normalized pathname: %j', filepath);

@@ -39,0 +39,0 @@

0.1.1 / 2014-02-05
==================
* http: initial shot at "cached redirects" logic
* package: pin "ftpd" version to v0.2.4 (for tests)
* test: refactor tests into their own files
* file: remove unused `path` require
* test: fix "file:" URI tests on Windows
* file: add better Windows support for file:// URIs
* http: add the Cache-Control and Expires respecting logic
* http: clean up logic a bit
0.1.0 / 2014-01-12

@@ -3,0 +15,0 @@ ==================

@@ -37,4 +37,15 @@

if (cache && isFresh(cache)) {
debug('cache is "fresh" due to previous Expires and/or Cache-Control response headers');
return fn(new NotModifiedError());
// check for a 3xx "redirect" status code on the previous cache
var location = cache.headers.location;
var type = (cache.statusCode / 100 | 0);
if (3 == type && location) {
debug('cached redirect');
fn(new Error('TODO: implement cached redirects!'));
} else {
// otherwise we assume that it's the destination endpoint,
// since there's nowhere else to redirect to
fn(new NotModifiedError());
}
return;
}

@@ -57,9 +68,13 @@

if (!options.headers) options.headers = {};
if (cache.headers['last-modified']) {
options.headers['If-Modified-Since'] = cache.headers['last-modified'];
debug('added "If-Modified-Since" request header: %j', options.headers['If-Modified-Since']);
var lastModified = cache.headers['last-modified'];
if (lastModified != null) {
options.headers['If-Modified-Since'] = lastModified;
debug('added "If-Modified-Since" request header: %j', lastModified);
}
if (cache.headers.etag) {
options.headers['If-None-Match'] = cache.headers.etag;
debug('added "If-None-Match" request header: %j', cache.headers.etag);
var etag = cache.headers.etag;
if (etag != null) {
options.headers['If-None-Match'] = etag;
debug('added "If-None-Match" request header: %j', etag);
}

@@ -157,9 +172,38 @@ }

var cacheControl = cache.headers['cache-control'];
var expires = cache.headers.expires;
var fresh;
if (cacheControl) {
// for Cache-Control rules, see: http://www.mnot.net/cache_docs/#CACHE-CONTROL
debug('Cache-Control: %s', cacheControl);
}
var expires = cache.headers.expires;
if (expires) {
var parts = cacheControl.split(/,\s*?\b/);
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
var subparts = part.split('=');
var name = subparts[0];
switch (name) {
case 'max-age':
var val = +subparts[1];
expires = new Date(+cache.date + (val * 1000));
fresh = new Date() < expires;
if (fresh) debug('cache is "fresh" due to previous "%s" Cache-Control param', part);
return fresh;
case 'must-revalidate':
// XXX: what we supposed to do here?
break;
case 'no-cache':
case 'no-store':
debug('cache is "stale" due to explicit "%s" Cache-Control param', name);
return false;
}
}
} else if (expires) {
// for Expires rules, see: http://www.mnot.net/cache_docs/#EXPIRES
debug('Expires: %s', expires);
fresh = new Date() < new Date(expires);
if (fresh) debug('cache is "fresh" due to previous Expires response header');
return fresh;
}

@@ -166,0 +210,0 @@

{
"name": "get-uri",
"version": "0.1.0",
"version": "0.1.1",
"description": "Returns a `stream.Readable` from a URI string",

@@ -35,3 +35,3 @@ "main": "index.js",

"stream-to-array": "~1.0.0",
"ftpd": "~0.2.4",
"ftpd": "0.2.4",
"st": "~0.2.3"

@@ -43,3 +43,4 @@ },

"debug": "~0.7.4",
"extend": "~1.2.1"
"extend": "~1.2.1",
"file-uri-to-path": "0"
},

@@ -46,0 +47,0 @@ "optionalDependencies": {

@@ -32,7 +32,25 @@ get-uri

To simply get a `stream.Readable` instance from a `file:` URI, try something like:
``` js
var getUri = require('get-uri');
// maps to a `fs.ReadStream` instance
// `file:` maps to a `fs.ReadStream` instance…
getUri('file:///Users/nrajlich/wat.json', function (err, rs) {
if (err) throw err;
rs.pipe(process.stdout);
});
```
Missing Endpoints
-----------------
When you pass in a URI in which the resource referenced does not exist on the
destination server, then a `NotFoundError` will be returned. The `code` of the
error instance is set to `"ENOTFOUND"`, so you can special-case that in your code
to detect when a bad filename is requested:
``` js
getUri('http://example.com/resource.json', function (err, rs) {
if (err) {

@@ -47,21 +65,3 @@ if ('ENOTFOUND' == err.code) {

rs.pipe(process.stdout);
// ... some time later, we need to get this same URI again, pass in the
// previous `stream.Readable` instance as `cache` option to potentially
// receive "ENOTMODIFIED" responses:
getUri('file:///Users/nrajlich/wat.json', { cache: rs }, function (err, rs2) {
if (err) {
if ('ENOTFOUND' == err.code) {
// bad file path requested
} else if ('ENOTMODIFIED' == err.code) {
// source file has not been modified since last time it was requested,
// so `rs2` is undefined and you are expected to re-use results from
// a previous call to `getUri()`
} else {
// something else bad happened...
throw err;
}
}
});
// your app code…
});

@@ -85,18 +85,34 @@ ```

When the `"ENOTMODIFIED"` error occurs, then you can safely re-use the
results from the previous `getUri()` call for that same URI.
results from the previous `getUri()` call for that same URI:
``` js
// maps to a `fs.ReadStream` instance
getUri('http://example.com/resource.json', function (err, rs) {
if (err) throw err;
Missing Endpoints
-----------------
// … some time later, if you need to get this same URI again, pass in the
// previous `stream.Readable` instance as `cache` option to potentially
// receive an "ENOTMODIFIED" response:
getUri('http://example.com/resource.json', function (err, rs2) {
if (err) {
if ('ENOTFOUND' == err.code) {
// bad file path requested
} else if ('ENOTMODIFIED' == err.code) {
// source file has not been modified since last time it was requested,
// so `rs2` is undefined and you are expected to re-use results from
// a previous call to `getUri()`
} else {
// something else bad happened...
throw err;
}
}
});
});
```
When you pass in a URI in which the resource referenced does not exist on the
destination server, then a `NotFoundError` will be returned. The `code` of the
error instance is set to `"ENOTFOUND"`, so you can special-case that in your code
to detect when a bad filename is requested.
API
---
### getUri(String uri[, Object options]) → stream.Readable
### getUri(String uri[, Object options,] Function callback)

@@ -111,2 +127,5 @@ A `uri` String is required. An optional `options` object may be passed in:

Invokes the given `callback` function with a `stream.Readable` instance to
read the resource at the given `uri`.
License

@@ -113,0 +132,0 @@ -------

@@ -32,283 +32,2 @@

describe('"data:" protocol', function () {
var cache;
it('should work for URL-encoded data', function (done) {
getUri('data:,Hello%2C%20World!', function (err, rs) {
if (err) return done(err);
cache = rs;
streamToArray(rs, function (err, array) {
if (err) return done(err);
var buf = Buffer.concat(array);
assert.equal('Hello, World!', buf.toString());
done();
});
});
});
it('should work for base64-encoded data', function (done) {
getUri('data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D', function (err, rs) {
if (err) return done(err);
streamToArray(rs, function (err, array) {
if (err) return done(err);
var buf = Buffer.concat(array);
assert.equal('Hello, World!', buf.toString());
done();
});
});
});
it('should return ENOTMODIFIED for the same URI with `cache`', function (done) {
getUri('data:,Hello%2C%20World!', { cache: cache }, function (err, rs) {
assert(err);
assert.equal('ENOTMODIFIED', err.code);
done();
});
});
});
describe('"file:" protocol', function () {
var cache;
it('should work for local files', function (done) {
var uri = 'file://' + __filename;
fs.readFile(__filename, 'utf8', function (err, real) {
if (err) return done(err);
getUri(uri, function (err, rs) {
if (err) return done(err);
cache = rs;
streamToArray(rs, function (err, array) {
if (err) return done(err);
var str = Buffer.concat(array).toString('utf8');
assert.equal(str, real);
done();
});
});
});
});
it('should return ENOTFOUND for bad filenames', function (done) {
var uri = 'file://' + __filename + 'does-not-exist';
getUri(uri, function (err, rs) {
assert(err);
assert.equal('ENOTFOUND', err.code);
done();
});
});
it('should return ENOTMODIFIED for the same URI with `cache`', function (done) {
var uri = 'file://' + __filename;
getUri(uri, { cache: cache }, function (err, rs) {
assert(err);
assert.equal('ENOTMODIFIED', err.code);
done();
});
});
});
describe('"ftp:" protocol', function () {
var port;
var cache;
var server;
before(function (done) {
var options = {
logLevel: -1,
getInitialCwd: function (socket, fn) {
fn(null, '/');
},
getRoot: function (socket) {
return __dirname;
}
};
var host = '127.0.0.1';
server = new ftpd.FtpServer(host, options);
server.on('client:connected', function(conn){
var username;
conn.on('command:user', function(user, success, failure) {
username = user;
success();
});
conn.on('command:pass', function(pass, success, failure){
success(username);
});
});
server.listen(0, function () {
port = server.server.address().port;
done();
});
});
after(function (done) {
server.server.once('close', function () {
done();
});
server.server.close();
});
it('should work for ftp endpoints', function (done) {
var uri = 'ftp://127.0.0.1:' + port + '/test.js';
fs.readFile(__filename, 'utf8', function (err, real) {
if (err) return done(err);
getUri(uri, function (err, rs) {
if (err) return done(err);
cache = rs;
streamToArray(rs, function (err, array) {
if (err) return done(err);
var str = Buffer.concat(array).toString('utf8');
assert.equal(str, real);
done();
});
});
});
});
it('should return ENOTFOUND for bad filenames', function (done) {
var uri = 'ftp://127.0.0.1:' + port + '/does-not-exist';
getUri(uri, function (err, rs) {
assert(err);
assert.equal('ENOTFOUND', err.code);
done();
});
});
it('should return ENOTMODIFIED for the same URI with `cache`', function (done) {
var uri = 'ftp://127.0.0.1:' + port + '/test.js';
getUri(uri, { cache: cache }, function (err, rs) {
assert(err);
assert.equal('ENOTMODIFIED', err.code);
done();
});
});
});
describe('"http:" protocol', function () {
var port;
var cache;
var server;
before(function (done) {
// setup target HTTP server
server = http.createServer(st(__dirname));
server.listen(function () {
port = server.address().port;
done();
});
});
after(function (done) {
server.once('close', function () { done(); });
server.close();
});
it('should work for HTTP endpoints', function (done) {
var uri = 'http://127.0.0.1:' + port + '/test.js';
fs.readFile(__filename, 'utf8', function (err, real) {
if (err) return done(err);
getUri(uri, function (err, rs) {
if (err) return done(err);
cache = rs;
streamToArray(rs, function (err, array) {
if (err) return done(err);
var str = Buffer.concat(array).toString('utf8');
assert.equal(str, real);
done();
});
});
});
});
it('should return ENOTFOUND for bad filenames', function (done) {
var uri = 'http://127.0.0.1:' + port + '/does-not-exist';
getUri(uri, function (err, rs) {
assert(err);
assert.equal('ENOTFOUND', err.code);
done();
});
});
it('should return ENOTMODIFIED for the same URI with `cache`', function (done) {
var uri = 'http://127.0.0.1:' + port + '/test.js';
getUri(uri, { cache: cache }, function (err, rs) {
assert(err);
assert.equal('ENOTMODIFIED', err.code);
done();
});
});
});
describe('"https:" protocol', function () {
var port;
var cache;
var server;
before(function (done) {
// setup target HTTPS server
var options = {
key: fs.readFileSync(__dirname + '/server.key'),
cert: fs.readFileSync(__dirname + '/server.crt')
};
server = https.createServer(options, st(__dirname));
server.listen(function () {
port = server.address().port;
done();
});
});
after(function (done) {
server.once('close', function () { done(); });
server.close();
});
it('should work for HTTPS endpoints', function (done) {
var uri = 'https://127.0.0.1:' + port + '/test.js';
fs.readFile(__filename, 'utf8', function (err, real) {
if (err) return done(err);
getUri(uri, { rejectUnauthorized: false }, function (err, rs) {
if (err) return done(err);
cache = rs;
streamToArray(rs, function (err, array) {
if (err) return done(err);
var str = Buffer.concat(array).toString('utf8');
assert.equal(str, real);
done();
});
});
});
});
it('should return ENOTFOUND for bad filenames', function (done) {
var uri = 'https://127.0.0.1:' + port + '/does-not-exist';
getUri(uri, { rejectUnauthorized: false }, function (err, rs) {
assert(err);
assert.equal('ENOTFOUND', err.code);
done();
});
});
it('should return ENOTMODIFIED for the same URI with `cache`', function (done) {
var uri = 'https://127.0.0.1:' + port + '/test.js';
getUri(uri, { cache: cache, rejectUnauthorized: false }, function (err, rs) {
assert(err);
assert.equal('ENOTMODIFIED', err.code);
done();
});
});
});
});
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