mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
Moving original pages to a node server from s3. Still needs conversion from s3.
This commit is contained in:
parent
48d0afd6a2
commit
a00c462457
189 changed files with 16495 additions and 18 deletions
|
@ -2,6 +2,7 @@ import datetime
|
|||
import time
|
||||
import boto
|
||||
import redis
|
||||
import requests
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
@ -590,24 +591,39 @@ def load_feed_page(request, feed_id):
|
|||
|
||||
feed = Feed.get_by_id(feed_id)
|
||||
|
||||
if (feed and feed.has_page and
|
||||
not feed.has_page_exception and
|
||||
settings.BACKED_BY_AWS['pages_on_s3'] and
|
||||
feed.s3_page):
|
||||
if settings.PROXY_S3_PAGES:
|
||||
key = settings.S3_PAGES_BUCKET.get_key(feed.s3_pages_key)
|
||||
if key:
|
||||
compressed_data = key.get_contents_as_string()
|
||||
response = HttpResponse(compressed_data, mimetype="text/html; charset=utf-8")
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
if feed and feed.has_page and not feed.has_page_exception:
|
||||
if settings.BACKED_BY_AWS.get('pages_on_node'):
|
||||
url = "http://%s/original_page/%s" % (
|
||||
settings.ORIGINAL_PAGE_SERVER,
|
||||
feed.pk,
|
||||
)
|
||||
import pdb; pdb.set_trace()
|
||||
page_response = requests.get(url, headers={
|
||||
'If-None-Match': request.headers,
|
||||
})
|
||||
response = HttpResponse(page_response.content, mimetype="text/html; charset=utf-8")
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
response['Last-Modified'] = page_response.headers.get('Last-modified')
|
||||
response['Etag'] = page_response.headers.get('Etag')
|
||||
response['Content-Length'] = str(len(page_response.content))
|
||||
logging.user(request, "~FYLoading original page, proxied from node: ~SB%s bytes" %
|
||||
(len(page_response.content)))
|
||||
return response
|
||||
elif settings.BACKED_BY_AWS['pages_on_s3'] and feed.s3_page:
|
||||
if settings.PROXY_S3_PAGES:
|
||||
key = settings.S3_PAGES_BUCKET.get_key(feed.s3_pages_key)
|
||||
if key:
|
||||
compressed_data = key.get_contents_as_string()
|
||||
response = HttpResponse(compressed_data, mimetype="text/html; charset=utf-8")
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
|
||||
logging.user(request, "~FYLoading original page, proxied: ~SB%s bytes" %
|
||||
(len(compressed_data)))
|
||||
return response
|
||||
else:
|
||||
logging.user(request, "~FYLoading original page, non-proxied")
|
||||
return HttpResponseRedirect('//%s/%s' % (settings.S3_PAGES_BUCKET_NAME,
|
||||
feed.s3_pages_key))
|
||||
logging.user(request, "~FYLoading original page, proxied: ~SB%s bytes" %
|
||||
(len(compressed_data)))
|
||||
return response
|
||||
else:
|
||||
logging.user(request, "~FYLoading original page, non-proxied")
|
||||
return HttpResponseRedirect('//%s/%s' % (settings.S3_PAGES_BUCKET_NAME,
|
||||
feed.s3_pages_key))
|
||||
|
||||
data = MFeedPage.get_data(feed_id=feed_id)
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import gzip
|
|||
import StringIO
|
||||
from boto.s3.key import Key
|
||||
from django.conf import settings
|
||||
from django.utils.text import compress_string
|
||||
from utils import log as logging
|
||||
from apps.rss_feeds.models import MFeedPage
|
||||
from utils.feed_functions import timelimit, mail_feed_error_to_admin
|
||||
|
@ -175,7 +176,15 @@ class PageImporter(object):
|
|||
|
||||
def save_page(self, html):
|
||||
if html and len(html) > 100:
|
||||
if settings.BACKED_BY_AWS.get('pages_on_s3'):
|
||||
if settings.BACKED_BY_AWS.get('pages_on_node'):
|
||||
url = "http://%s/original_page/%s" % (
|
||||
settings.ORIGINAL_PAGE_SERVER,
|
||||
self.feed.pk,
|
||||
)
|
||||
requests.post(url, files={
|
||||
'original_page': compress_string(html),
|
||||
})
|
||||
elif settings.BACKED_BY_AWS.get('pages_on_s3'):
|
||||
k = Key(settings.S3_PAGES_BUCKET)
|
||||
k.key = self.feed.s3_pages_key
|
||||
k.set_metadata('Content-Encoding', 'gzip')
|
||||
|
|
2
fabfile.py
vendored
2
fabfile.py
vendored
|
@ -62,6 +62,7 @@ env.roledefs ={
|
|||
'ec2-184-72-214-147.compute-1.amazonaws.com',
|
||||
'ec2-107-20-103-16.compute-1.amazonaws.com',
|
||||
'ec2-50-17-12-16.compute-1.amazonaws.com',
|
||||
'ec2-54-242-34-138.compute-1.amazonaws.com',
|
||||
'ec2-184-73-2-61.compute-1.amazonaws.com',
|
||||
],
|
||||
'vps': ['task01.newsblur.com',
|
||||
|
@ -643,6 +644,7 @@ def setup_db_firewall():
|
|||
sudo('ufw allow proto tcp from 107.20.103.16 to any port 5432,27017,6379,11211')
|
||||
sudo('ufw allow proto tcp from 50.17.12.16 to any port 5432,27017,6379,11211')
|
||||
sudo('ufw allow proto tcp from 184.73.2.61 to any port 5432,27017,6379,11211')
|
||||
sudo('ufw allow proto tcp from 54.242.34.138 to any port 5432,27017,6379,11211')
|
||||
sudo('ufw --force enable')
|
||||
|
||||
def setup_db_motd():
|
||||
|
|
|
@ -87,10 +87,13 @@ REDIS = {
|
|||
}
|
||||
|
||||
BACKED_BY_AWS = {
|
||||
'pages_on_node': False,
|
||||
'pages_on_s3': False,
|
||||
'icons_on_s3': False,
|
||||
}
|
||||
|
||||
ORIGINAL_PAGE_SERVER = "127.0.0.1:3060"
|
||||
|
||||
# ===========
|
||||
# = Logging =
|
||||
# ===========
|
||||
|
|
2
node/node_modules/mkdirp/.npmignore
generated
vendored
Normal file
2
node/node_modules/mkdirp/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
npm-debug.log
|
4
node/node_modules/mkdirp/.travis.yml
generated
vendored
Normal file
4
node/node_modules/mkdirp/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
21
node/node_modules/mkdirp/LICENSE
generated
vendored
Normal file
21
node/node_modules/mkdirp/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
Copyright 2010 James Halliday (mail@substack.net)
|
||||
|
||||
This project is free software released under the MIT/X11 license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
61
node/node_modules/mkdirp/README.markdown
generated
vendored
Normal file
61
node/node_modules/mkdirp/README.markdown
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
mkdirp
|
||||
======
|
||||
|
||||
Like `mkdir -p`, but in node.js!
|
||||
|
||||
[](http://travis-ci.org/substack/node-mkdirp)
|
||||
|
||||
example
|
||||
=======
|
||||
|
||||
pow.js
|
||||
------
|
||||
var mkdirp = require('mkdirp');
|
||||
|
||||
mkdirp('/tmp/foo/bar/baz', function (err) {
|
||||
if (err) console.error(err)
|
||||
else console.log('pow!')
|
||||
});
|
||||
|
||||
Output
|
||||
pow!
|
||||
|
||||
And now /tmp/foo/bar/baz exists, huzzah!
|
||||
|
||||
methods
|
||||
=======
|
||||
|
||||
var mkdirp = require('mkdirp');
|
||||
|
||||
mkdirp(dir, mode, cb)
|
||||
---------------------
|
||||
|
||||
Create a new directory and any necessary subdirectories at `dir` with octal
|
||||
permission string `mode`.
|
||||
|
||||
If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
|
||||
|
||||
`cb(err, made)` fires with the error or the first directory `made`
|
||||
that had to be created, if any.
|
||||
|
||||
mkdirp.sync(dir, mode)
|
||||
----------------------
|
||||
|
||||
Synchronously create a new directory and any necessary subdirectories at `dir`
|
||||
with octal permission string `mode`.
|
||||
|
||||
If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
|
||||
|
||||
Returns the first directory that had to be created, if any.
|
||||
|
||||
install
|
||||
=======
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
npm install mkdirp
|
||||
|
||||
license
|
||||
=======
|
||||
|
||||
MIT/X11
|
6
node/node_modules/mkdirp/examples/pow.js
generated
vendored
Normal file
6
node/node_modules/mkdirp/examples/pow.js
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
var mkdirp = require('mkdirp');
|
||||
|
||||
mkdirp('/tmp/foo/bar/baz', function (err) {
|
||||
if (err) console.error(err)
|
||||
else console.log('pow!')
|
||||
});
|
82
node/node_modules/mkdirp/index.js
generated
vendored
Normal file
82
node/node_modules/mkdirp/index.js
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
|
||||
|
||||
function mkdirP (p, mode, f, made) {
|
||||
if (typeof mode === 'function' || mode === undefined) {
|
||||
f = mode;
|
||||
mode = 0777 & (~process.umask());
|
||||
}
|
||||
if (!made) made = null;
|
||||
|
||||
var cb = f || function () {};
|
||||
if (typeof mode === 'string') mode = parseInt(mode, 8);
|
||||
p = path.resolve(p);
|
||||
|
||||
fs.mkdir(p, mode, function (er) {
|
||||
if (!er) {
|
||||
made = made || p;
|
||||
return cb(null, made);
|
||||
}
|
||||
switch (er.code) {
|
||||
case 'ENOENT':
|
||||
mkdirP(path.dirname(p), mode, function (er, made) {
|
||||
if (er) cb(er, made);
|
||||
else mkdirP(p, mode, cb, made);
|
||||
});
|
||||
break;
|
||||
|
||||
// In the case of any other error, just see if there's a dir
|
||||
// there already. If so, then hooray! If not, then something
|
||||
// is borked.
|
||||
default:
|
||||
fs.stat(p, function (er2, stat) {
|
||||
// if the stat fails, then that's super weird.
|
||||
// let the original error be the failure reason.
|
||||
if (er2 || !stat.isDirectory()) cb(er, made)
|
||||
else cb(null, made);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mkdirP.sync = function sync (p, mode, made) {
|
||||
if (mode === undefined) {
|
||||
mode = 0777 & (~process.umask());
|
||||
}
|
||||
if (!made) made = null;
|
||||
|
||||
if (typeof mode === 'string') mode = parseInt(mode, 8);
|
||||
p = path.resolve(p);
|
||||
|
||||
try {
|
||||
fs.mkdirSync(p, mode);
|
||||
made = made || p;
|
||||
}
|
||||
catch (err0) {
|
||||
switch (err0.code) {
|
||||
case 'ENOENT' :
|
||||
made = sync(path.dirname(p), mode, made);
|
||||
sync(p, mode, made);
|
||||
break;
|
||||
|
||||
// In the case of any other error, just see if there's a dir
|
||||
// there already. If so, then hooray! If not, then something
|
||||
// is borked.
|
||||
default:
|
||||
var stat;
|
||||
try {
|
||||
stat = fs.statSync(p);
|
||||
}
|
||||
catch (err1) {
|
||||
throw err0;
|
||||
}
|
||||
if (!stat.isDirectory()) throw err0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return made;
|
||||
};
|
40
node/node_modules/mkdirp/package.json
generated
vendored
Normal file
40
node/node_modules/mkdirp/package.json
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "mkdirp",
|
||||
"description": "Recursively mkdir, like `mkdir -p`",
|
||||
"version": "0.3.4",
|
||||
"author": {
|
||||
"name": "James Halliday",
|
||||
"email": "mail@substack.net",
|
||||
"url": "http://substack.net"
|
||||
},
|
||||
"main": "./index",
|
||||
"keywords": [
|
||||
"mkdir",
|
||||
"directory"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/substack/node-mkdirp.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap test/*.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "~0.2.4"
|
||||
},
|
||||
"license": "MIT/X11",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_id": "mkdirp@0.3.4",
|
||||
"dependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.12",
|
||||
"_nodeVersion": "v0.6.14",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "5673ccb5622bbdab381ce014eecea71cd14209af"
|
||||
},
|
||||
"_from": "mkdirp"
|
||||
}
|
38
node/node_modules/mkdirp/test/chmod.js
generated
vendored
Normal file
38
node/node_modules/mkdirp/test/chmod.js
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
var mkdirp = require('../').mkdirp;
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
var ps = [ '', 'tmp' ];
|
||||
|
||||
for (var i = 0; i < 25; i++) {
|
||||
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
ps.push(dir);
|
||||
}
|
||||
|
||||
var file = ps.join('/');
|
||||
|
||||
test('chmod-pre', function (t) {
|
||||
var mode = 0744
|
||||
mkdirp(file, mode, function (er) {
|
||||
t.ifError(er, 'should not error');
|
||||
fs.stat(file, function (er, stat) {
|
||||
t.ifError(er, 'should exist');
|
||||
t.ok(stat && stat.isDirectory(), 'should be directory');
|
||||
t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('chmod', function (t) {
|
||||
var mode = 0755
|
||||
mkdirp(file, mode, function (er) {
|
||||
t.ifError(er, 'should not error');
|
||||
fs.stat(file, function (er, stat) {
|
||||
t.ifError(er, 'should exist');
|
||||
t.ok(stat && stat.isDirectory(), 'should be directory');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
37
node/node_modules/mkdirp/test/clobber.js
generated
vendored
Normal file
37
node/node_modules/mkdirp/test/clobber.js
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
var mkdirp = require('../').mkdirp;
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
var ps = [ '', 'tmp' ];
|
||||
|
||||
for (var i = 0; i < 25; i++) {
|
||||
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
ps.push(dir);
|
||||
}
|
||||
|
||||
var file = ps.join('/');
|
||||
|
||||
// a file in the way
|
||||
var itw = ps.slice(0, 3).join('/');
|
||||
|
||||
|
||||
test('clobber-pre', function (t) {
|
||||
console.error("about to write to "+itw)
|
||||
fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
|
||||
|
||||
fs.stat(itw, function (er, stat) {
|
||||
t.ifError(er)
|
||||
t.ok(stat && stat.isFile(), 'should be file')
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
test('clobber', function (t) {
|
||||
t.plan(2);
|
||||
mkdirp(file, 0755, function (err) {
|
||||
t.ok(err);
|
||||
t.equal(err.code, 'ENOTDIR');
|
||||
t.end();
|
||||
});
|
||||
});
|
28
node/node_modules/mkdirp/test/mkdirp.js
generated
vendored
Normal file
28
node/node_modules/mkdirp/test/mkdirp.js
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('woo', function (t) {
|
||||
t.plan(2);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var file = '/tmp/' + [x,y,z].join('/');
|
||||
|
||||
mkdirp(file, 0755, function (err) {
|
||||
if (err) t.fail(err);
|
||||
else path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, 0755);
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
32
node/node_modules/mkdirp/test/perm.js
generated
vendored
Normal file
32
node/node_modules/mkdirp/test/perm.js
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('async perm', function (t) {
|
||||
t.plan(2);
|
||||
var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
|
||||
|
||||
mkdirp(file, 0755, function (err) {
|
||||
if (err) t.fail(err);
|
||||
else path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, 0755);
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
test('async root perm', function (t) {
|
||||
mkdirp('/tmp', 0755, function (err) {
|
||||
if (err) t.fail(err);
|
||||
t.end();
|
||||
});
|
||||
t.end();
|
||||
});
|
39
node/node_modules/mkdirp/test/perm_sync.js
generated
vendored
Normal file
39
node/node_modules/mkdirp/test/perm_sync.js
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('sync perm', function (t) {
|
||||
t.plan(2);
|
||||
var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
|
||||
|
||||
mkdirp.sync(file, 0755);
|
||||
path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, 0755);
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
test('sync root perm', function (t) {
|
||||
t.plan(1);
|
||||
|
||||
var file = '/tmp';
|
||||
mkdirp.sync(file, 0755);
|
||||
path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
41
node/node_modules/mkdirp/test/race.js
generated
vendored
Normal file
41
node/node_modules/mkdirp/test/race.js
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
var mkdirp = require('../').mkdirp;
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('race', function (t) {
|
||||
t.plan(4);
|
||||
var ps = [ '', 'tmp' ];
|
||||
|
||||
for (var i = 0; i < 25; i++) {
|
||||
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
ps.push(dir);
|
||||
}
|
||||
var file = ps.join('/');
|
||||
|
||||
var res = 2;
|
||||
mk(file, function () {
|
||||
if (--res === 0) t.end();
|
||||
});
|
||||
|
||||
mk(file, function () {
|
||||
if (--res === 0) t.end();
|
||||
});
|
||||
|
||||
function mk (file, cb) {
|
||||
mkdirp(file, 0755, function (err) {
|
||||
if (err) t.fail(err);
|
||||
else path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, 0755);
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
if (cb) cb();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
32
node/node_modules/mkdirp/test/rel.js
generated
vendored
Normal file
32
node/node_modules/mkdirp/test/rel.js
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('rel', function (t) {
|
||||
t.plan(2);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var cwd = process.cwd();
|
||||
process.chdir('/tmp');
|
||||
|
||||
var file = [x,y,z].join('/');
|
||||
|
||||
mkdirp(file, 0755, function (err) {
|
||||
if (err) t.fail(err);
|
||||
else path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
process.chdir(cwd);
|
||||
t.equal(stat.mode & 0777, 0755);
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
25
node/node_modules/mkdirp/test/return.js
generated
vendored
Normal file
25
node/node_modules/mkdirp/test/return.js
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('return value', function (t) {
|
||||
t.plan(4);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var file = '/tmp/' + [x,y,z].join('/');
|
||||
|
||||
// should return the first dir created.
|
||||
// By this point, it would be profoundly surprising if /tmp didn't
|
||||
// already exist, since every other test makes things in there.
|
||||
mkdirp(file, function (err, made) {
|
||||
t.ifError(err);
|
||||
t.equal(made, '/tmp/' + x);
|
||||
mkdirp(file, function (err, made) {
|
||||
t.ifError(err);
|
||||
t.equal(made, null);
|
||||
});
|
||||
});
|
||||
});
|
24
node/node_modules/mkdirp/test/return_sync.js
generated
vendored
Normal file
24
node/node_modules/mkdirp/test/return_sync.js
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('return value', function (t) {
|
||||
t.plan(2);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var file = '/tmp/' + [x,y,z].join('/');
|
||||
|
||||
// should return the first dir created.
|
||||
// By this point, it would be profoundly surprising if /tmp didn't
|
||||
// already exist, since every other test makes things in there.
|
||||
// Note that this will throw on failure, which will fail the test.
|
||||
var made = mkdirp.sync(file);
|
||||
t.equal(made, '/tmp/' + x);
|
||||
|
||||
// making the same file again should have no effect.
|
||||
made = mkdirp.sync(file);
|
||||
t.equal(made, null);
|
||||
});
|
18
node/node_modules/mkdirp/test/root.js
generated
vendored
Normal file
18
node/node_modules/mkdirp/test/root.js
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('root', function (t) {
|
||||
// '/' on unix, 'c:/' on windows.
|
||||
var file = path.resolve('/');
|
||||
|
||||
mkdirp(file, 0755, function (err) {
|
||||
if (err) throw err
|
||||
fs.stat(file, function (er, stat) {
|
||||
if (er) throw er
|
||||
t.ok(stat.isDirectory(), 'target is a directory');
|
||||
t.end();
|
||||
})
|
||||
});
|
||||
});
|
32
node/node_modules/mkdirp/test/sync.js
generated
vendored
Normal file
32
node/node_modules/mkdirp/test/sync.js
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('sync', function (t) {
|
||||
t.plan(2);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var file = '/tmp/' + [x,y,z].join('/');
|
||||
|
||||
try {
|
||||
mkdirp.sync(file, 0755);
|
||||
} catch (err) {
|
||||
t.fail(err);
|
||||
return t.end();
|
||||
}
|
||||
|
||||
path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, 0755);
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
28
node/node_modules/mkdirp/test/umask.js
generated
vendored
Normal file
28
node/node_modules/mkdirp/test/umask.js
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('implicit mode from umask', function (t) {
|
||||
t.plan(2);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var file = '/tmp/' + [x,y,z].join('/');
|
||||
|
||||
mkdirp(file, function (err) {
|
||||
if (err) t.fail(err);
|
||||
else path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, 0777 & (~process.umask()));
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
32
node/node_modules/mkdirp/test/umask_sync.js
generated
vendored
Normal file
32
node/node_modules/mkdirp/test/umask_sync.js
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
var mkdirp = require('../');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var test = require('tap').test;
|
||||
|
||||
test('umask sync modes', function (t) {
|
||||
t.plan(2);
|
||||
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
|
||||
|
||||
var file = '/tmp/' + [x,y,z].join('/');
|
||||
|
||||
try {
|
||||
mkdirp.sync(file);
|
||||
} catch (err) {
|
||||
t.fail(err);
|
||||
return t.end();
|
||||
}
|
||||
|
||||
path.exists(file, function (ex) {
|
||||
if (!ex) t.fail('file not created')
|
||||
else fs.stat(file, function (err, stat) {
|
||||
if (err) t.fail(err)
|
||||
else {
|
||||
t.equal(stat.mode & 0777, (0777 & (~process.umask())));
|
||||
t.ok(stat.isDirectory(), 'target not a directory');
|
||||
t.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
49
node/original_page.coffee
Normal file
49
node/original_page.coffee
Normal file
|
@ -0,0 +1,49 @@
|
|||
express = require 'express'
|
||||
path = require 'path'
|
||||
fs = require 'fs'
|
||||
mkdirp = require 'mkdirp'
|
||||
|
||||
app = express.createServer()
|
||||
app.use express.bodyParser()
|
||||
|
||||
app.get /^\/original_page\/(\d+)\/?/, (req, res) =>
|
||||
feedId = parseInt(req.params, 10)
|
||||
etag = req.header('If-None-Match')
|
||||
lastModified = req.header('If-Modified-Since')
|
||||
feedIdDir = splitFeedId feedId
|
||||
filePath = "originals/#{feedIdDir}.zhtml"
|
||||
|
||||
path.exists filePath, (exists, err) ->
|
||||
console.log "Req: #{feedId} (#{filePath}), etag: #{etag}"
|
||||
if not exists
|
||||
return res.send 404
|
||||
fs.stat filePath, (err, stats) ->
|
||||
if not err and etag and stats.mtime == etag
|
||||
return res.send 304
|
||||
if not err and lastModified and stats.mtime == lastModified
|
||||
return res.send 304
|
||||
|
||||
fs.readFile filePath, (err, content) ->
|
||||
res.header 'Etag', Date.parse(stats.mtime)
|
||||
res.send content
|
||||
|
||||
app.post /^\/original_page\/(\d+)\/?/, (req, res) =>
|
||||
feedId = parseInt(req.params, 10)
|
||||
feedIdDir = splitFeedId feedId
|
||||
html = req.param "original_page"
|
||||
filePath = "originals/#{feedIdDir}.zhtml"
|
||||
filePathDir = path.dirname filePath
|
||||
mkdirp filePathDir, (err) ->
|
||||
fs.rename req.files.original_page.path, filePath, (err) ->
|
||||
console.log err if err
|
||||
console.log " ---> Saving: #{feedId} (#{filePath})"
|
||||
res.send "OK"
|
||||
|
||||
splitFeedId = (feedId) ->
|
||||
feedId += ''
|
||||
# x2 = if feedId.length > 1 then '.' + feedId[1] else ''
|
||||
rgx = /(\d+)(\d{3})/
|
||||
feedId = feedId.replace rgx, '$1' + '/' + '$2' while rgx.test(feedId)
|
||||
return feedId;
|
||||
|
||||
app.listen 3060
|
75
node/original_page.js
Normal file
75
node/original_page.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var app, express, fs, mkdirp, path, splitFeedId,
|
||||
_this = this;
|
||||
|
||||
express = require('express');
|
||||
|
||||
path = require('path');
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
mkdirp = require('mkdirp');
|
||||
|
||||
app = express.createServer();
|
||||
|
||||
app.use(express.bodyParser());
|
||||
|
||||
app.get(/^\/original_page\/(\d+)\/?/, function(req, res) {
|
||||
var etag, feedId, feedIdDir, filePath, lastModified;
|
||||
feedId = parseInt(req.params, 10);
|
||||
etag = req.header('If-None-Match');
|
||||
lastModified = req.header('If-Modified-Since');
|
||||
feedIdDir = splitFeedId(feedId);
|
||||
filePath = "originals/" + feedIdDir + ".zhtml";
|
||||
return path.exists(filePath, function(exists, err) {
|
||||
console.log("Req: " + feedId + " (" + filePath + "), etag: " + etag);
|
||||
if (!exists) {
|
||||
return res.send(404);
|
||||
}
|
||||
return fs.stat(filePath, function(err, stats) {
|
||||
if (!err && etag && stats.mtime === etag) {
|
||||
return res.send(304);
|
||||
}
|
||||
if (!err && lastModified && stats.mtime === lastModified) {
|
||||
return res.send(304);
|
||||
}
|
||||
return fs.readFile(filePath, function(err, content) {
|
||||
res.header('Etag', Date.parse(stats.mtime));
|
||||
return res.send(content);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.post(/^\/original_page\/(\d+)\/?/, function(req, res) {
|
||||
var feedId, feedIdDir, filePath, filePathDir, html;
|
||||
feedId = parseInt(req.params, 10);
|
||||
feedIdDir = splitFeedId(feedId);
|
||||
html = req.param("original_page");
|
||||
filePath = "originals/" + feedIdDir + ".zhtml";
|
||||
filePathDir = path.dirname(filePath);
|
||||
return mkdirp(filePathDir, function(err) {
|
||||
return fs.rename(req.files.original_page.path, filePath, function(err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
console.log(" ---> Saving: " + feedId + " (" + filePath + ")");
|
||||
return res.send("OK");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
splitFeedId = function(feedId) {
|
||||
var rgx;
|
||||
feedId += '';
|
||||
rgx = /(\d+)(\d{3})/;
|
||||
while (rgx.test(feedId)) {
|
||||
feedId = feedId.replace(rgx, '$1' + '/' + '$2');
|
||||
}
|
||||
return feedId;
|
||||
};
|
||||
|
||||
app.listen(3060);
|
||||
|
||||
}).call(this);
|
6
node_modules/qs/.gitmodules
generated
vendored
Normal file
6
node_modules/qs/.gitmodules
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
[submodule "support/expresso"]
|
||||
path = support/expresso
|
||||
url = git://github.com/visionmedia/expresso.git
|
||||
[submodule "support/should"]
|
||||
path = support/should
|
||||
url = git://github.com/visionmedia/should.js.git
|
1
node_modules/qs/.npmignore
generated
vendored
Normal file
1
node_modules/qs/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
node_modules
|
4
node_modules/qs/.travis.yml
generated
vendored
Normal file
4
node_modules/qs/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
- 0.4
|
94
node_modules/qs/History.md
generated
vendored
Normal file
94
node_modules/qs/History.md
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
|
||||
0.5.3 2012-12-09
|
||||
==================
|
||||
|
||||
* add info to component.json
|
||||
* remove regular client-side ./querystring.js, fix component.json support
|
||||
|
||||
0.5.2 / 2012-11-14
|
||||
==================
|
||||
|
||||
* fix uri encoding of non-plain object string values
|
||||
|
||||
0.5.1 / 2012-09-18
|
||||
==================
|
||||
|
||||
* fix encoded `=`. Closes #43
|
||||
|
||||
0.5.0 / 2012-05-04
|
||||
==================
|
||||
|
||||
* Added component support
|
||||
|
||||
0.4.2 / 2012-02-08
|
||||
==================
|
||||
|
||||
* Fixed: ensure objects are created when appropriate not arrays [aheckmann]
|
||||
|
||||
0.4.1 / 2012-01-26
|
||||
==================
|
||||
|
||||
* Fixed stringify()ing numbers. Closes #23
|
||||
|
||||
0.4.0 / 2011-11-21
|
||||
==================
|
||||
|
||||
* Allow parsing of an existing object (for `bodyParser()`) [jackyz]
|
||||
* Replaced expresso with mocha
|
||||
|
||||
0.3.2 / 2011-11-08
|
||||
==================
|
||||
|
||||
* Fixed global variable leak
|
||||
|
||||
0.3.1 / 2011-08-17
|
||||
==================
|
||||
|
||||
* Added `try/catch` around malformed uri components
|
||||
* Add test coverage for Array native method bleed-though
|
||||
|
||||
0.3.0 / 2011-07-19
|
||||
==================
|
||||
|
||||
* Allow `array[index]` and `object[property]` syntaxes [Aria Stewart]
|
||||
|
||||
0.2.0 / 2011-06-29
|
||||
==================
|
||||
|
||||
* Added `qs.stringify()` [Cory Forsyth]
|
||||
|
||||
0.1.0 / 2011-04-13
|
||||
==================
|
||||
|
||||
* Added jQuery-ish array support
|
||||
|
||||
0.0.7 / 2011-03-13
|
||||
==================
|
||||
|
||||
* Fixed; handle empty string and `== null` in `qs.parse()` [dmit]
|
||||
allows for convenient `qs.parse(url.parse(str).query)`
|
||||
|
||||
0.0.6 / 2011-02-14
|
||||
==================
|
||||
|
||||
* Fixed; support for implicit arrays
|
||||
|
||||
0.0.4 / 2011-02-09
|
||||
==================
|
||||
|
||||
* Fixed `+` as a space
|
||||
|
||||
0.0.3 / 2011-02-08
|
||||
==================
|
||||
|
||||
* Fixed case when right-hand value contains "]"
|
||||
|
||||
0.0.2 / 2011-02-07
|
||||
==================
|
||||
|
||||
* Fixed "=" presence in key
|
||||
|
||||
0.0.1 / 2011-02-07
|
||||
==================
|
||||
|
||||
* Initial release
|
6
node_modules/qs/Makefile
generated
vendored
Normal file
6
node_modules/qs/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
test:
|
||||
@./node_modules/.bin/mocha \
|
||||
--ui bdd
|
||||
|
||||
.PHONY: test
|
58
node_modules/qs/Readme.md
generated
vendored
Normal file
58
node_modules/qs/Readme.md
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
# node-querystring
|
||||
|
||||
query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
|
||||
|
||||
## Installation
|
||||
|
||||
$ npm install qs
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
var qs = require('qs');
|
||||
|
||||
qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
|
||||
// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
|
||||
|
||||
qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
|
||||
// => user[name]=Tobi&user[email]=tobi%40learnboost.com
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Install dev dependencies:
|
||||
|
||||
$ npm install -d
|
||||
|
||||
and execute:
|
||||
|
||||
$ make test
|
||||
|
||||
browser:
|
||||
|
||||
$ open test/browser/index.html
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
node_modules/qs/benchmark.js
generated
vendored
Normal file
17
node_modules/qs/benchmark.js
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
var qs = require('./');
|
||||
|
||||
var times = 100000
|
||||
, start = new Date
|
||||
, n = times;
|
||||
|
||||
console.log('times: %d', times);
|
||||
|
||||
while (n--) qs.parse('foo=bar');
|
||||
console.log('simple: %dms', new Date - start);
|
||||
|
||||
var start = new Date
|
||||
, n = times;
|
||||
|
||||
while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
|
||||
console.log('nested: %dms', new Date - start);
|
9
node_modules/qs/component.json
generated
vendored
Normal file
9
node_modules/qs/component.json
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "querystring",
|
||||
"repo": "visionmedia/node-querystring",
|
||||
"description": "query-string parser / stringifier with nesting support",
|
||||
"version": "0.5.3",
|
||||
"keywords": ["querystring", "query", "parser"],
|
||||
"scripts": ["index.js"],
|
||||
"license": "MIT"
|
||||
}
|
51
node_modules/qs/examples.js
generated
vendored
Normal file
51
node_modules/qs/examples.js
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var qs = require('./');
|
||||
|
||||
var obj = qs.parse('foo');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('foo=bar=baz');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('users[]');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('name=tj&email=tj@vision-media.ca');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('a=a&a=b&a=c');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[tj]=tj&user[tj]=TJ');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[0]=tj&user[1]=TJ');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[0]=tj&user[]=TJ');
|
||||
console.log(obj)
|
||||
|
||||
var obj = qs.parse('user[0]=tj&user[foo]=TJ');
|
||||
console.log(obj)
|
||||
|
||||
var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }});
|
||||
console.log(str);
|
262
node_modules/qs/index.js
generated
vendored
Normal file
262
node_modules/qs/index.js
generated
vendored
Normal file
|
@ -0,0 +1,262 @@
|
|||
|
||||
/**
|
||||
* Object#toString() ref for stringify().
|
||||
*/
|
||||
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
* Cache non-integer test regexp.
|
||||
*/
|
||||
|
||||
var isint = /^[0-9]+$/;
|
||||
|
||||
function promote(parent, key) {
|
||||
if (parent[key].length == 0) return parent[key] = {};
|
||||
var t = {};
|
||||
for (var i in parent[key]) t[i] = parent[key][i];
|
||||
parent[key] = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
function parse(parts, parent, key, val) {
|
||||
var part = parts.shift();
|
||||
// end
|
||||
if (!part) {
|
||||
if (Array.isArray(parent[key])) {
|
||||
parent[key].push(val);
|
||||
} else if ('object' == typeof parent[key]) {
|
||||
parent[key] = val;
|
||||
} else if ('undefined' == typeof parent[key]) {
|
||||
parent[key] = val;
|
||||
} else {
|
||||
parent[key] = [parent[key], val];
|
||||
}
|
||||
// array
|
||||
} else {
|
||||
var obj = parent[key] = parent[key] || [];
|
||||
if (']' == part) {
|
||||
if (Array.isArray(obj)) {
|
||||
if ('' != val) obj.push(val);
|
||||
} else if ('object' == typeof obj) {
|
||||
obj[Object.keys(obj).length] = val;
|
||||
} else {
|
||||
obj = parent[key] = [parent[key], val];
|
||||
}
|
||||
// prop
|
||||
} else if (~part.indexOf(']')) {
|
||||
part = part.substr(0, part.length - 1);
|
||||
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
||||
parse(parts, obj, part, val);
|
||||
// key
|
||||
} else {
|
||||
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
||||
parse(parts, obj, part, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge parent key/val pair.
|
||||
*/
|
||||
|
||||
function merge(parent, key, val){
|
||||
if (~key.indexOf(']')) {
|
||||
var parts = key.split('[')
|
||||
, len = parts.length
|
||||
, last = len - 1;
|
||||
parse(parts, parent, 'base', val);
|
||||
// optimize
|
||||
} else {
|
||||
if (!isint.test(key) && Array.isArray(parent.base)) {
|
||||
var t = {};
|
||||
for (var k in parent.base) t[k] = parent.base[k];
|
||||
parent.base = t;
|
||||
}
|
||||
set(parent.base, key, val);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given obj.
|
||||
*/
|
||||
|
||||
function parseObject(obj){
|
||||
var ret = { base: {} };
|
||||
Object.keys(obj).forEach(function(name){
|
||||
merge(ret, name, obj[name]);
|
||||
});
|
||||
return ret.base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given str.
|
||||
*/
|
||||
|
||||
function parseString(str){
|
||||
return String(str)
|
||||
.split('&')
|
||||
.reduce(function(ret, pair){
|
||||
var eql = pair.indexOf('=')
|
||||
, brace = lastBraceInKey(pair)
|
||||
, key = pair.substr(0, brace || eql)
|
||||
, val = pair.substr(brace || eql, pair.length)
|
||||
, val = val.substr(val.indexOf('=') + 1, val.length);
|
||||
|
||||
// ?foo
|
||||
if ('' == key) key = pair, val = '';
|
||||
|
||||
return merge(ret, decode(key), decode(val));
|
||||
}, { base: {} }).base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given query `str` or `obj`, returning an object.
|
||||
*
|
||||
* @param {String} str | {Object} obj
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.parse = function(str){
|
||||
if (null == str || '' == str) return {};
|
||||
return 'object' == typeof str
|
||||
? parseObject(str)
|
||||
: parseString(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn the given `obj` into a query string
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var stringify = exports.stringify = function(obj, prefix) {
|
||||
if (Array.isArray(obj)) {
|
||||
return stringifyArray(obj, prefix);
|
||||
} else if ('[object Object]' == toString.call(obj)) {
|
||||
return stringifyObject(obj, prefix);
|
||||
} else if ('string' == typeof obj) {
|
||||
return stringifyString(obj, prefix);
|
||||
} else {
|
||||
return prefix + '=' + encodeURIComponent(String(obj));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stringify the given `str`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {String} prefix
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringifyString(str, prefix) {
|
||||
if (!prefix) throw new TypeError('stringify expects an object');
|
||||
return prefix + '=' + encodeURIComponent(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringify the given `arr`.
|
||||
*
|
||||
* @param {Array} arr
|
||||
* @param {String} prefix
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringifyArray(arr, prefix) {
|
||||
var ret = [];
|
||||
if (!prefix) throw new TypeError('stringify expects an object');
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
ret.push(stringify(arr[i], prefix + '[' + i + ']'));
|
||||
}
|
||||
return ret.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringify the given `obj`.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} prefix
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringifyObject(obj, prefix) {
|
||||
var ret = []
|
||||
, keys = Object.keys(obj)
|
||||
, key;
|
||||
|
||||
for (var i = 0, len = keys.length; i < len; ++i) {
|
||||
key = keys[i];
|
||||
ret.push(stringify(obj[key], prefix
|
||||
? prefix + '[' + encodeURIComponent(key) + ']'
|
||||
: encodeURIComponent(key)));
|
||||
}
|
||||
|
||||
return ret.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set `obj`'s `key` to `val` respecting
|
||||
* the weird and wonderful syntax of a qs,
|
||||
* where "foo=bar&foo=baz" becomes an array.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} key
|
||||
* @param {String} val
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function set(obj, key, val) {
|
||||
var v = obj[key];
|
||||
if (undefined === v) {
|
||||
obj[key] = val;
|
||||
} else if (Array.isArray(v)) {
|
||||
v.push(val);
|
||||
} else {
|
||||
obj[key] = [v, val];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate last brace in `str` within the key.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function lastBraceInKey(str) {
|
||||
var len = str.length
|
||||
, brace
|
||||
, c;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
c = str[i];
|
||||
if (']' == c) brace = false;
|
||||
if ('[' == c) brace = true;
|
||||
if ('=' == c && !brace) return i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode `str`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function decode(str) {
|
||||
try {
|
||||
return decodeURIComponent(str.replace(/\+/g, ' '));
|
||||
} catch (err) {
|
||||
return str;
|
||||
}
|
||||
}
|
43
node_modules/qs/package.json
generated
vendored
Normal file
43
node_modules/qs/package.json
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "qs",
|
||||
"description": "querystring parser",
|
||||
"version": "0.5.3",
|
||||
"keywords": [
|
||||
"query string",
|
||||
"parser",
|
||||
"component"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/visionmedia/node-querystring.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "*",
|
||||
"expect.js": "*"
|
||||
},
|
||||
"component": {
|
||||
"scripts": {
|
||||
"querystring": "querystring.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "TJ Holowaychuk",
|
||||
"email": "tj@vision-media.ca",
|
||||
"url": "http://tjholowaychuk.com"
|
||||
},
|
||||
"main": "index",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_id": "qs@0.5.3",
|
||||
"dependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"_engineSupported": true,
|
||||
"_npmVersion": "1.1.12",
|
||||
"_nodeVersion": "v0.6.14",
|
||||
"_defaultsLoaded": true,
|
||||
"dist": {
|
||||
"shasum": "c2cdb51268421f4fdd9350e2bf0594169efe1cba"
|
||||
},
|
||||
"_from": "qs"
|
||||
}
|
1202
node_modules/qs/test/browser/expect.js
generated
vendored
Normal file
1202
node_modules/qs/test/browser/expect.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
18
node_modules/qs/test/browser/index.html
generated
vendored
Normal file
18
node_modules/qs/test/browser/index.html
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Mocha</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="mocha.css" />
|
||||
<script src="jquery.js" type="text/javascript"></script>
|
||||
<script src="expect.js"></script>
|
||||
<script src="mocha.js"></script>
|
||||
<script>mocha.setup('bdd')</script>
|
||||
<script src="qs.js"></script>
|
||||
<script src="../parse.js"></script>
|
||||
<script src="../stringify.js"></script>
|
||||
<script>onload = mocha.run;</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
</body>
|
||||
</html>
|
8981
node_modules/qs/test/browser/jquery.js
generated
vendored
Normal file
8981
node_modules/qs/test/browser/jquery.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
163
node_modules/qs/test/browser/mocha.css
generated
vendored
Normal file
163
node_modules/qs/test/browser/mocha.css
generated
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
|
||||
body {
|
||||
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
padding: 60px 50px;
|
||||
}
|
||||
|
||||
#mocha h1, h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mocha h1 {
|
||||
margin-top: 15px;
|
||||
font-size: 1em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
#mocha .suite .suite h1 {
|
||||
margin-top: 0;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#mocha h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#mocha .suite {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#mocha .test {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#mocha .test:hover h2::after {
|
||||
position: relative;
|
||||
top: 0;
|
||||
right: -10px;
|
||||
content: '(view source)';
|
||||
font-size: 12px;
|
||||
font-family: arial;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha .test.pending:hover h2::after {
|
||||
content: '(pending)';
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
#mocha .test.pass.medium .duration {
|
||||
background: #C09853;
|
||||
}
|
||||
|
||||
#mocha .test.pass.slow .duration {
|
||||
background: #B94A48;
|
||||
}
|
||||
|
||||
#mocha .test.pass::before {
|
||||
content: '✓';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass .duration {
|
||||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
padding: 2px 5px;
|
||||
color: white;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass.fast .duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha .test.pending {
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.pending::before {
|
||||
content: '◦';
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.fail {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test.fail pre {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha .test.fail::before {
|
||||
content: '✖';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test pre.error {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test pre {
|
||||
display: inline-block;
|
||||
font: 12px/1.5 monaco, monospace;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom-color: #ddd;
|
||||
-webkit-border-radius: 3px;
|
||||
-webkit-box-shadow: 0 1px 3px #eee;
|
||||
}
|
||||
|
||||
#error {
|
||||
color: #c00;
|
||||
font-size: 1.5 em;
|
||||
font-weight: 100;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
#stats {
|
||||
position: fixed;
|
||||
top: 15px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#stats .progress {
|
||||
float: right;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#stats em {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#stats li {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
list-style: none;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
code .comment { color: #ddd }
|
||||
code .init { color: #2F6FAD }
|
||||
code .string { color: #5890AD }
|
||||
code .keyword { color: #8A6343 }
|
||||
code .number { color: #2F6FAD }
|
4201
node_modules/qs/test/browser/mocha.js
generated
vendored
Normal file
4201
node_modules/qs/test/browser/mocha.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
0
node_modules/qs/test/browser/qs.css
generated
vendored
Normal file
0
node_modules/qs/test/browser/qs.css
generated
vendored
Normal file
351
node_modules/qs/test/browser/qs.js
generated
vendored
Normal file
351
node_modules/qs/test/browser/qs.js
generated
vendored
Normal file
|
@ -0,0 +1,351 @@
|
|||
|
||||
/**
|
||||
* Require the given path.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Object} exports
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function require(p, parent){
|
||||
var path = require.resolve(p)
|
||||
, mod = require.modules[path];
|
||||
if (!mod) throw new Error('failed to require "' + p + '" in ' + parent);
|
||||
if (!mod.exports) {
|
||||
mod.exports = {};
|
||||
mod.client = true;
|
||||
mod.call(mod.exports, mod, mod.exports, require.relative(path));
|
||||
}
|
||||
return mod.exports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registered modules.
|
||||
*/
|
||||
|
||||
require.modules = {};
|
||||
|
||||
/**
|
||||
* Resolve `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Object} module
|
||||
* @api public
|
||||
*/
|
||||
|
||||
require.resolve = function(path){
|
||||
var orig = path
|
||||
, reg = path + '.js'
|
||||
, index = path + '/index.js';
|
||||
return require.modules[reg] && reg
|
||||
|| require.modules[index] && index
|
||||
|| orig;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register module at `path` with callback `fn`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Function} fn
|
||||
* @api public
|
||||
*/
|
||||
|
||||
require.register = function(path, fn){
|
||||
require.modules[path] = fn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines and executes anonymous module immediately, while preserving relative
|
||||
* paths.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Function} require ref
|
||||
* @api public
|
||||
*/
|
||||
|
||||
require.exec = function (path, fn) {
|
||||
fn.call(window, require.relative(path));
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a require function relative to the `parent` path.
|
||||
*
|
||||
* @param {String} parent
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
require.relative = function(parent) {
|
||||
return function(p){
|
||||
if ('.' != p[0]) return require(p);
|
||||
|
||||
var path = parent.split('/')
|
||||
, segs = p.split('/');
|
||||
path.pop();
|
||||
|
||||
for (var i = 0; i < segs.length; i++) {
|
||||
var seg = segs[i];
|
||||
if ('..' == seg) path.pop();
|
||||
else if ('.' != seg) path.push(seg);
|
||||
}
|
||||
|
||||
return require(path.join('/'), parent);
|
||||
};
|
||||
};
|
||||
// component qs: querystring
|
||||
require.register("querystring", function(module, exports, require){
|
||||
;(function(){
|
||||
|
||||
/**
|
||||
* Object#toString() ref for stringify().
|
||||
*/
|
||||
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
* Cache non-integer test regexp.
|
||||
*/
|
||||
|
||||
var isint = /^[0-9]+$/;
|
||||
|
||||
function promote(parent, key) {
|
||||
if (parent[key].length == 0) return parent[key] = {};
|
||||
var t = {};
|
||||
for (var i in parent[key]) t[i] = parent[key][i];
|
||||
parent[key] = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
function parse(parts, parent, key, val) {
|
||||
var part = parts.shift();
|
||||
// end
|
||||
if (!part) {
|
||||
if (Array.isArray(parent[key])) {
|
||||
parent[key].push(val);
|
||||
} else if ('object' == typeof parent[key]) {
|
||||
parent[key] = val;
|
||||
} else if ('undefined' == typeof parent[key]) {
|
||||
parent[key] = val;
|
||||
} else {
|
||||
parent[key] = [parent[key], val];
|
||||
}
|
||||
// array
|
||||
} else {
|
||||
var obj = parent[key] = parent[key] || [];
|
||||
if (']' == part) {
|
||||
if (Array.isArray(obj)) {
|
||||
if ('' != val) obj.push(val);
|
||||
} else if ('object' == typeof obj) {
|
||||
obj[Object.keys(obj).length] = val;
|
||||
} else {
|
||||
obj = parent[key] = [parent[key], val];
|
||||
}
|
||||
// prop
|
||||
} else if (~part.indexOf(']')) {
|
||||
part = part.substr(0, part.length - 1);
|
||||
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
||||
parse(parts, obj, part, val);
|
||||
// key
|
||||
} else {
|
||||
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
||||
parse(parts, obj, part, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge parent key/val pair.
|
||||
*/
|
||||
|
||||
function merge(parent, key, val){
|
||||
if (~key.indexOf(']')) {
|
||||
var parts = key.split('[')
|
||||
, len = parts.length
|
||||
, last = len - 1;
|
||||
parse(parts, parent, 'base', val);
|
||||
// optimize
|
||||
} else {
|
||||
if (!isint.test(key) && Array.isArray(parent.base)) {
|
||||
var t = {};
|
||||
for (var k in parent.base) t[k] = parent.base[k];
|
||||
parent.base = t;
|
||||
}
|
||||
set(parent.base, key, val);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given obj.
|
||||
*/
|
||||
|
||||
function parseObject(obj){
|
||||
var ret = { base: {} };
|
||||
Object.keys(obj).forEach(function(name){
|
||||
merge(ret, name, obj[name]);
|
||||
});
|
||||
return ret.base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given str.
|
||||
*/
|
||||
|
||||
function parseString(str){
|
||||
return String(str)
|
||||
.split('&')
|
||||
.reduce(function(ret, pair){
|
||||
try{
|
||||
pair = decodeURIComponent(pair.replace(/\+/g, ' '));
|
||||
} catch(e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
var eql = pair.indexOf('=')
|
||||
, brace = lastBraceInKey(pair)
|
||||
, key = pair.substr(0, brace || eql)
|
||||
, val = pair.substr(brace || eql, pair.length)
|
||||
, val = val.substr(val.indexOf('=') + 1, val.length);
|
||||
|
||||
// ?foo
|
||||
if ('' == key) key = pair, val = '';
|
||||
|
||||
return merge(ret, key, val);
|
||||
}, { base: {} }).base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given query `str` or `obj`, returning an object.
|
||||
*
|
||||
* @param {String} str | {Object} obj
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.parse = function(str){
|
||||
if (null == str || '' == str) return {};
|
||||
return 'object' == typeof str
|
||||
? parseObject(str)
|
||||
: parseString(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn the given `obj` into a query string
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var stringify = exports.stringify = function(obj, prefix) {
|
||||
if (Array.isArray(obj)) {
|
||||
return stringifyArray(obj, prefix);
|
||||
} else if ('[object Object]' == toString.call(obj)) {
|
||||
return stringifyObject(obj, prefix);
|
||||
} else if ('string' == typeof obj) {
|
||||
return stringifyString(obj, prefix);
|
||||
} else {
|
||||
return prefix + '=' + obj;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stringify the given `str`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {String} prefix
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringifyString(str, prefix) {
|
||||
if (!prefix) throw new TypeError('stringify expects an object');
|
||||
return prefix + '=' + encodeURIComponent(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringify the given `arr`.
|
||||
*
|
||||
* @param {Array} arr
|
||||
* @param {String} prefix
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringifyArray(arr, prefix) {
|
||||
var ret = [];
|
||||
if (!prefix) throw new TypeError('stringify expects an object');
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
ret.push(stringify(arr[i], prefix + '['+i+']'));
|
||||
}
|
||||
return ret.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringify the given `obj`.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} prefix
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringifyObject(obj, prefix) {
|
||||
var ret = []
|
||||
, keys = Object.keys(obj)
|
||||
, key;
|
||||
|
||||
for (var i = 0, len = keys.length; i < len; ++i) {
|
||||
key = keys[i];
|
||||
ret.push(stringify(obj[key], prefix
|
||||
? prefix + '[' + encodeURIComponent(key) + ']'
|
||||
: encodeURIComponent(key)));
|
||||
}
|
||||
|
||||
return ret.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set `obj`'s `key` to `val` respecting
|
||||
* the weird and wonderful syntax of a qs,
|
||||
* where "foo=bar&foo=baz" becomes an array.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} key
|
||||
* @param {String} val
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function set(obj, key, val) {
|
||||
var v = obj[key];
|
||||
if (undefined === v) {
|
||||
obj[key] = val;
|
||||
} else if (Array.isArray(v)) {
|
||||
v.push(val);
|
||||
} else {
|
||||
obj[key] = [v, val];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate last brace in `str` within the key.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function lastBraceInKey(str) {
|
||||
var len = str.length
|
||||
, brace
|
||||
, c;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
c = str[i];
|
||||
if (']' == c) brace = false;
|
||||
if ('[' == c) brace = true;
|
||||
if ('=' == c && !brace) return i;
|
||||
}
|
||||
}
|
||||
})();
|
||||
});
|
147
node_modules/qs/test/parse.js
generated
vendored
Normal file
147
node_modules/qs/test/parse.js
generated
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
|
||||
if (require.register) {
|
||||
var qs = require('querystring');
|
||||
} else {
|
||||
var qs = require('../')
|
||||
, expect = require('expect.js');
|
||||
}
|
||||
|
||||
describe('qs.parse()', function(){
|
||||
it('should support the basics', function(){
|
||||
expect(qs.parse('0=foo')).to.eql({ '0': 'foo' });
|
||||
|
||||
expect(qs.parse('foo=c++'))
|
||||
.to.eql({ foo: 'c ' });
|
||||
|
||||
expect(qs.parse('a[>=]=23'))
|
||||
.to.eql({ a: { '>=': '23' }});
|
||||
|
||||
expect(qs.parse('a[<=>]==23'))
|
||||
.to.eql({ a: { '<=>': '=23' }});
|
||||
|
||||
expect(qs.parse('a[==]=23'))
|
||||
.to.eql({ a: { '==': '23' }});
|
||||
|
||||
expect(qs.parse('foo'))
|
||||
.to.eql({ foo: '' });
|
||||
|
||||
expect(qs.parse('foo=bar'))
|
||||
.to.eql({ foo: 'bar' });
|
||||
|
||||
expect(qs.parse(' foo = bar = baz '))
|
||||
.to.eql({ ' foo ': ' bar = baz ' });
|
||||
|
||||
expect(qs.parse('foo=bar=baz'))
|
||||
.to.eql({ foo: 'bar=baz' });
|
||||
|
||||
expect(qs.parse('foo=bar&bar=baz'))
|
||||
.to.eql({ foo: 'bar', bar: 'baz' });
|
||||
|
||||
expect(qs.parse('foo=bar&baz'))
|
||||
.to.eql({ foo: 'bar', baz: '' });
|
||||
|
||||
expect(qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'))
|
||||
.to.eql({
|
||||
cht: 'p3'
|
||||
, chd: 't:60,40'
|
||||
, chs: '250x100'
|
||||
, chl: 'Hello|World'
|
||||
});
|
||||
})
|
||||
|
||||
it('should support encoded = signs', function(){
|
||||
expect(qs.parse('he%3Dllo=th%3Dere'))
|
||||
.to.eql({ 'he=llo': 'th=ere' });
|
||||
})
|
||||
|
||||
it('should support nesting', function(){
|
||||
expect(qs.parse('ops[>=]=25'))
|
||||
.to.eql({ ops: { '>=': '25' }});
|
||||
|
||||
expect(qs.parse('user[name]=tj'))
|
||||
.to.eql({ user: { name: 'tj' }});
|
||||
|
||||
expect(qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'))
|
||||
.to.eql({ user: { name: { first: 'tj', last: 'holowaychuk' }}});
|
||||
})
|
||||
|
||||
it('should support array notation', function(){
|
||||
expect(qs.parse('images[]'))
|
||||
.to.eql({ images: [] });
|
||||
|
||||
expect(qs.parse('user[]=tj'))
|
||||
.to.eql({ user: ['tj'] });
|
||||
|
||||
expect(qs.parse('user[]=tj&user[]=tobi&user[]=jane'))
|
||||
.to.eql({ user: ['tj', 'tobi', 'jane'] });
|
||||
|
||||
expect(qs.parse('user[names][]=tj&user[names][]=tyler'))
|
||||
.to.eql({ user: { names: ['tj', 'tyler'] }});
|
||||
|
||||
expect(qs.parse('user[names][]=tj&user[names][]=tyler&user[email]=tj@vision-media.ca'))
|
||||
.to.eql({ user: { names: ['tj', 'tyler'], email: 'tj@vision-media.ca' }});
|
||||
|
||||
expect(qs.parse('items=a&items=b'))
|
||||
.to.eql({ items: ['a', 'b'] });
|
||||
|
||||
expect(qs.parse('user[names]=tj&user[names]=holowaychuk&user[names]=TJ'))
|
||||
.to.eql({ user: { names: ['tj', 'holowaychuk', 'TJ'] }});
|
||||
|
||||
expect(qs.parse('user[name][first]=tj&user[name][first]=TJ'))
|
||||
.to.eql({ user: { name: { first: ['tj', 'TJ'] }}});
|
||||
|
||||
var o = qs.parse('existing[fcbaebfecc][name][last]=tj')
|
||||
expect(o).to.eql({ existing: { 'fcbaebfecc': { name: { last: 'tj' }}}})
|
||||
expect(Array.isArray(o.existing)).to.equal(false);
|
||||
})
|
||||
|
||||
it('should support arrays with indexes', function(){
|
||||
expect(qs.parse('foo[0]=bar&foo[1]=baz')).to.eql({ foo: ['bar', 'baz'] });
|
||||
expect(qs.parse('foo[1]=bar&foo[0]=baz')).to.eql({ foo: ['baz', 'bar'] });
|
||||
expect(qs.parse('foo[base64]=RAWR')).to.eql({ foo: { base64: 'RAWR' }});
|
||||
expect(qs.parse('foo[64base]=RAWR')).to.eql({ foo: { '64base': 'RAWR' }});
|
||||
})
|
||||
|
||||
it('should expand to an array when dupliate keys are present', function(){
|
||||
expect(qs.parse('items=bar&items=baz&items=raz'))
|
||||
.to.eql({ items: ['bar', 'baz', 'raz'] });
|
||||
})
|
||||
|
||||
it('should support right-hand side brackets', function(){
|
||||
expect(qs.parse('pets=["tobi"]'))
|
||||
.to.eql({ pets: '["tobi"]' });
|
||||
|
||||
expect(qs.parse('operators=[">=", "<="]'))
|
||||
.to.eql({ operators: '[">=", "<="]' });
|
||||
|
||||
expect(qs.parse('op[>=]=[1,2,3]'))
|
||||
.to.eql({ op: { '>=': '[1,2,3]' }});
|
||||
|
||||
expect(qs.parse('op[>=]=[1,2,3]&op[=]=[[[[1]]]]'))
|
||||
.to.eql({ op: { '>=': '[1,2,3]', '=': '[[[[1]]]]' }});
|
||||
})
|
||||
|
||||
it('should support empty values', function(){
|
||||
expect(qs.parse('')).to.eql({});
|
||||
expect(qs.parse(undefined)).to.eql({});
|
||||
expect(qs.parse(null)).to.eql({});
|
||||
})
|
||||
|
||||
it('should transform arrays to objects', function(){
|
||||
expect(qs.parse('foo[0]=bar&foo[bad]=baz')).to.eql({ foo: { 0: "bar", bad: "baz" }});
|
||||
expect(qs.parse('foo[bad]=baz&foo[0]=bar')).to.eql({ foo: { 0: "bar", bad: "baz" }});
|
||||
})
|
||||
|
||||
it('should support malformed uri chars', function(){
|
||||
expect(qs.parse('{%:%}')).to.eql({ '{%:%}': '' });
|
||||
expect(qs.parse('foo=%:%}')).to.eql({ 'foo': '%:%}' });
|
||||
})
|
||||
|
||||
it('should support semi-parsed strings', function(){
|
||||
expect(qs.parse({ 'user[name]': 'tobi' }))
|
||||
.to.eql({ user: { name: 'tobi' }});
|
||||
|
||||
expect(qs.parse({ 'user[name]': 'tobi', 'user[email][main]': 'tobi@lb.com' }))
|
||||
.to.eql({ user: { name: 'tobi', email: { main: 'tobi@lb.com' } }});
|
||||
})
|
||||
})
|
79
node_modules/qs/test/stringify.js
generated
vendored
Normal file
79
node_modules/qs/test/stringify.js
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
if (require.register) {
|
||||
var qs = require('querystring');
|
||||
} else {
|
||||
var qs = require('../')
|
||||
, expect = require('expect.js');
|
||||
}
|
||||
|
||||
var date = new Date(0);
|
||||
|
||||
var str_identities = {
|
||||
'basics': [
|
||||
{ str: 'foo=bar', obj: {'foo' : 'bar'}},
|
||||
{ str: 'foo=%22bar%22', obj: {'foo' : '\"bar\"'}},
|
||||
{ str: 'foo=', obj: {'foo': ''}},
|
||||
{ str: 'foo=1&bar=2', obj: {'foo' : '1', 'bar' : '2'}},
|
||||
{ str: 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F', obj: {'my weird field': "q1!2\"'w$5&7/z8)?"}},
|
||||
{ str: 'foo%3Dbaz=bar', obj: {'foo=baz': 'bar'}},
|
||||
{ str: 'foo=bar&bar=baz', obj: {foo: 'bar', bar: 'baz'}}
|
||||
],
|
||||
'escaping': [
|
||||
{ str: 'foo=foo%20bar', obj: {foo: 'foo bar'}},
|
||||
{ str: 'cht=p3&chd=t%3A60%2C40&chs=250x100&chl=Hello%7CWorld', obj: {
|
||||
cht: 'p3'
|
||||
, chd: 't:60,40'
|
||||
, chs: '250x100'
|
||||
, chl: 'Hello|World'
|
||||
}}
|
||||
],
|
||||
'nested': [
|
||||
{ str: 'foo[0]=bar&foo[1]=quux', obj: {'foo' : ['bar', 'quux']}},
|
||||
{ str: 'foo[0]=bar', obj: {foo: ['bar']}},
|
||||
{ str: 'foo[0]=1&foo[1]=2', obj: {'foo' : ['1', '2']}},
|
||||
{ str: 'foo=bar&baz[0]=1&baz[1]=2&baz[2]=3', obj: {'foo' : 'bar', 'baz' : ['1', '2', '3']}},
|
||||
{ str: 'foo[0]=bar&baz[0]=1&baz[1]=2&baz[2]=3', obj: {'foo' : ['bar'], 'baz' : ['1', '2', '3']}},
|
||||
{ str: 'x[y][z]=1', obj: {'x' : {'y' : {'z' : '1'}}}},
|
||||
{ str: 'x[y][z][0]=1', obj: {'x' : {'y' : {'z' : ['1']}}}},
|
||||
{ str: 'x[y][z]=2', obj: {'x' : {'y' : {'z' : '2'}}}},
|
||||
{ str: 'x[y][z][0]=1&x[y][z][1]=2', obj: {'x' : {'y' : {'z' : ['1', '2']}}}},
|
||||
{ str: 'x[y][0][z]=1', obj: {'x' : {'y' : [{'z' : '1'}]}}},
|
||||
{ str: 'x[y][0][z][0]=1', obj: {'x' : {'y' : [{'z' : ['1']}]}}},
|
||||
{ str: 'x[y][0][z]=1&x[y][0][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'w' : '2'}]}}},
|
||||
{ str: 'x[y][0][v][w]=1', obj: {'x' : {'y' : [{'v' : {'w' : '1'}}]}}},
|
||||
{ str: 'x[y][0][z]=1&x[y][0][v][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'v' : {'w' : '2'}}]}}},
|
||||
{ str: 'x[y][0][z]=1&x[y][1][z]=2', obj: {'x' : {'y' : [{'z' : '1'}, {'z' : '2'}]}}},
|
||||
{ str: 'x[y][0][z]=1&x[y][0][w]=a&x[y][1][z]=2&x[y][1][w]=3', obj: {'x' : {'y' : [{'z' : '1', 'w' : 'a'}, {'z' : '2', 'w' : '3'}]}}},
|
||||
{ str: 'user[name][first]=tj&user[name][last]=holowaychuk', obj: { user: { name: { first: 'tj', last: 'holowaychuk' }}}}
|
||||
],
|
||||
'errors': [
|
||||
{ obj: 'foo=bar', message: 'stringify expects an object' },
|
||||
{ obj: ['foo', 'bar'], message: 'stringify expects an object' }
|
||||
],
|
||||
'numbers': [
|
||||
{ str: 'limit[0]=1&limit[1]=2&limit[2]=3', obj: { limit: [1, 2, '3'] }},
|
||||
{ str: 'limit=1', obj: { limit: 1 }}
|
||||
],
|
||||
'others': [
|
||||
{ str: 'at=' + encodeURIComponent(date), obj: { at: date } }
|
||||
]
|
||||
};
|
||||
|
||||
function test(type) {
|
||||
return function(){
|
||||
var str, obj;
|
||||
for (var i = 0; i < str_identities[type].length; i++) {
|
||||
str = str_identities[type][i].str;
|
||||
obj = str_identities[type][i].obj;
|
||||
expect(qs.stringify(obj)).to.eql(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('qs.stringify()', function(){
|
||||
it('should support the basics', test('basics'))
|
||||
it('should support escapes', test('escaping'))
|
||||
it('should support nesting', test('nested'))
|
||||
it('should support numbers', test('numbers'))
|
||||
it('should support others', test('others'))
|
||||
})
|
BIN
originals/1.zhtml
Normal file
BIN
originals/1.zhtml
Normal file
Binary file not shown.
BIN
originals/1/135.zhtml
Normal file
BIN
originals/1/135.zhtml
Normal file
Binary file not shown.
BIN
originals/1/174.zhtml
Normal file
BIN
originals/1/174.zhtml
Normal file
Binary file not shown.
BIN
originals/1/194.zhtml
Normal file
BIN
originals/1/194.zhtml
Normal file
Binary file not shown.
BIN
originals/1/195.zhtml
Normal file
BIN
originals/1/195.zhtml
Normal file
Binary file not shown.
BIN
originals/1/257.zhtml
Normal file
BIN
originals/1/257.zhtml
Normal file
Binary file not shown.
BIN
originals/1/282.zhtml
Normal file
BIN
originals/1/282.zhtml
Normal file
Binary file not shown.
BIN
originals/1/305.zhtml
Normal file
BIN
originals/1/305.zhtml
Normal file
Binary file not shown.
BIN
originals/1/410.zhtml
Normal file
BIN
originals/1/410.zhtml
Normal file
Binary file not shown.
BIN
originals/1/510.zhtml
Normal file
BIN
originals/1/510.zhtml
Normal file
Binary file not shown.
BIN
originals/1/758.zhtml
Normal file
BIN
originals/1/758.zhtml
Normal file
Binary file not shown.
BIN
originals/1/795.zhtml
Normal file
BIN
originals/1/795.zhtml
Normal file
Binary file not shown.
BIN
originals/1/843.zhtml
Normal file
BIN
originals/1/843.zhtml
Normal file
Binary file not shown.
BIN
originals/1/884.zhtml
Normal file
BIN
originals/1/884.zhtml
Normal file
Binary file not shown.
BIN
originals/106.zhtml
Normal file
BIN
originals/106.zhtml
Normal file
Binary file not shown.
BIN
originals/107.zhtml
Normal file
BIN
originals/107.zhtml
Normal file
Binary file not shown.
BIN
originals/109.zhtml
Normal file
BIN
originals/109.zhtml
Normal file
Binary file not shown.
BIN
originals/110.zhtml
Normal file
BIN
originals/110.zhtml
Normal file
Binary file not shown.
BIN
originals/111.zhtml
Normal file
BIN
originals/111.zhtml
Normal file
Binary file not shown.
BIN
originals/113.zhtml
Normal file
BIN
originals/113.zhtml
Normal file
Binary file not shown.
BIN
originals/116.zhtml
Normal file
BIN
originals/116.zhtml
Normal file
Binary file not shown.
BIN
originals/117.zhtml
Normal file
BIN
originals/117.zhtml
Normal file
Binary file not shown.
BIN
originals/119.zhtml
Normal file
BIN
originals/119.zhtml
Normal file
Binary file not shown.
BIN
originals/12.zhtml
Normal file
BIN
originals/12.zhtml
Normal file
Binary file not shown.
1
originals/12/345.zhtml
Normal file
1
originals/12/345.zhtml
Normal file
|
@ -0,0 +1 @@
|
|||
yatta
|
BIN
originals/121.zhtml
Normal file
BIN
originals/121.zhtml
Normal file
Binary file not shown.
BIN
originals/122.zhtml
Normal file
BIN
originals/122.zhtml
Normal file
Binary file not shown.
BIN
originals/123.zhtml
Normal file
BIN
originals/123.zhtml
Normal file
Binary file not shown.
BIN
originals/124.zhtml
Normal file
BIN
originals/124.zhtml
Normal file
Binary file not shown.
BIN
originals/126.zhtml
Normal file
BIN
originals/126.zhtml
Normal file
Binary file not shown.
BIN
originals/128.zhtml
Normal file
BIN
originals/128.zhtml
Normal file
Binary file not shown.
BIN
originals/130.zhtml
Normal file
BIN
originals/130.zhtml
Normal file
Binary file not shown.
BIN
originals/132.zhtml
Normal file
BIN
originals/132.zhtml
Normal file
Binary file not shown.
BIN
originals/133.zhtml
Normal file
BIN
originals/133.zhtml
Normal file
Binary file not shown.
BIN
originals/136.zhtml
Normal file
BIN
originals/136.zhtml
Normal file
Binary file not shown.
BIN
originals/137.zhtml
Normal file
BIN
originals/137.zhtml
Normal file
Binary file not shown.
BIN
originals/138.zhtml
Normal file
BIN
originals/138.zhtml
Normal file
Binary file not shown.
BIN
originals/139.zhtml
Normal file
BIN
originals/139.zhtml
Normal file
Binary file not shown.
BIN
originals/14.zhtml
Normal file
BIN
originals/14.zhtml
Normal file
Binary file not shown.
BIN
originals/141.zhtml
Normal file
BIN
originals/141.zhtml
Normal file
Binary file not shown.
BIN
originals/142.zhtml
Normal file
BIN
originals/142.zhtml
Normal file
Binary file not shown.
BIN
originals/144.zhtml
Normal file
BIN
originals/144.zhtml
Normal file
Binary file not shown.
BIN
originals/146.zhtml
Normal file
BIN
originals/146.zhtml
Normal file
Binary file not shown.
BIN
originals/147.zhtml
Normal file
BIN
originals/147.zhtml
Normal file
Binary file not shown.
BIN
originals/148.zhtml
Normal file
BIN
originals/148.zhtml
Normal file
Binary file not shown.
BIN
originals/149.zhtml
Normal file
BIN
originals/149.zhtml
Normal file
Binary file not shown.
BIN
originals/150.zhtml
Normal file
BIN
originals/150.zhtml
Normal file
Binary file not shown.
BIN
originals/153.zhtml
Normal file
BIN
originals/153.zhtml
Normal file
Binary file not shown.
BIN
originals/156.zhtml
Normal file
BIN
originals/156.zhtml
Normal file
Binary file not shown.
BIN
originals/157.zhtml
Normal file
BIN
originals/157.zhtml
Normal file
Binary file not shown.
BIN
originals/16.zhtml
Normal file
BIN
originals/16.zhtml
Normal file
Binary file not shown.
BIN
originals/160.zhtml
Normal file
BIN
originals/160.zhtml
Normal file
Binary file not shown.
1
originals/162.zhtml
Normal file
1
originals/162.zhtml
Normal file
File diff suppressed because one or more lines are too long
BIN
originals/163.zhtml
Normal file
BIN
originals/163.zhtml
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue