Skip to content

Commit

Permalink
Merge pull request #424 from hoodiehq/feat-revised-routes
Browse files Browse the repository at this point in the history
feat(api): revised routes
  • Loading branch information
boennemann committed Nov 24, 2015
2 parents b94f3db + 67f6b68 commit 5cb348c
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 196 deletions.
12 changes: 7 additions & 5 deletions lib/hapi/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function register (server, options, next) {

server.route([{
method: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
path: '/_api/{p*}',
path: '/hoodie/{p*}',
handler: {
proxy: {
passThrough: true,
Expand All @@ -34,17 +34,19 @@ function register (server, options, next) {
}
}, {
method: 'GET',
path: '/_api/_all_dbs',
handler: internals.notFound
path: '/hoodie/_all_dbs',
handler: function (request, reply) {
reply({error: 'not found'}).code(404)
}
}, {
method: 'GET',
path: '/_api/_files/hoodie.js',
path: '/hoodie/bundle.js',
handler: {
file: path.join(clientPath, 'dist/hoodie.js')
}
}, {
method: 'GET',
path: '/_api/_files/hoodie.min.js',
path: '/hoodie/bundle.min.js',
handler: {
file: path.join(clientPath, 'dist/hoodie.min.js')
}
Expand Down
82 changes: 14 additions & 68 deletions lib/hapi/api/internals.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,93 +5,39 @@ var Wreck = require('wreck')

module.exports = {
addCorsAndBearerToken: function (err, res, request, reply) {
if (err) {
reply(err).code(500)
return
}
if (err) return reply(err).code(500)

Wreck.read(res, {
json: true
}, function (err, data) {
var resp
var allowedHeaders = [
'authorization',
'content-length',
'content-type',
'if-match',
'if-none-match',
'origin',
'x-requested-with'
]

function addAllowedHeaders (arr) {
for (var i = 0; i < arr.length; i++) {
if (allowedHeaders.indexOf(arr[i].trim().toLowerCase()) === -1) {
allowedHeaders.push(arr[i].trim().toLowerCase())
}
if (err) return reply(err).code(500)

if (data &&
request.method === 'post' &&
request.path === '/hoodie/_session' &&
Array.isArray(res.headers['set-cookie'])) {
var result = /AuthSession=(.*?);/.exec(res.headers['set-cookie'][0])
if (result && result.length > 1) {
data.bearerToken = result[1]
}
}

if (err) {
reply(err).code(500)
return
}

var isSess = request.method === 'post' && request.path === '/_api/_session'

if (data && isSess && Array.isArray(res.headers['set-cookie'])) {
data.bearerToken = extractToken(res.headers['set-cookie'])
delete res.headers['set-cookie']
}

addAllowedHeaders(Object.keys(request.headers))

if (request.method === 'options') {
res.statusCode = 200

if (request.headers['Allow-Control-Request-Headers']) {
addAllowedHeaders(request.headers['Allow-Control-Request-Headers'].split(','))
}
}

// hapi eats newlines. We like newlines. For POSIX and such.
// data = data + '\n'
resp = reply(data).code(res.statusCode).hold()
var resp = reply(data).code(res.statusCode).hold()
resp.headers = res.headers
resp.headers['content-length'] = data ? data.length : 0
resp.headers['access-control-allow-origin'] = request.headers.origin || '*'
resp.headers['access-control-allow-headers'] = allowedHeaders.join(', ')
resp.headers['access-control-expose-headers'] = 'content-type, content-length, etag'
resp.headers['access-control-allow-methods'] = 'GET, PUT, POST, DELETE'
resp.headers['access-control-allow-credentials'] = 'true'
resp.send()
})
},
extractToken: extractToken,
mapProxyPath: function (db, request, callback) {
// use the bearer token as the cookie AuthSession for couchdb:
delete request.headers.cookie
if (request.headers.authorization && request.headers.authorization.substring(0, 'Bearer '.length) === 'Bearer ') {
request.headers.cookie = 'AuthSession=' + request.headers.authorization.substring('Bearer '.length)
} else {
delete request.headers.cookie
}

// TODO: This is just a temporary fix for PouchDB
delete request.headers['accept-encoding']
request.headers.host = [db.hostname, db.port].join(':')
callback(null, url.resolve(url.format(_.omit(db, 'auth')), request.url.path.substr('/_api'.length)), request.headers)
},
notFound: notFound
}

function extractToken (cookieHeader) {
var result = /AuthSession=(.*?);/.exec(cookieHeader[0])
if (result && result.length > 1) {
return result[1]
callback(null, url.resolve(url.format(_.omit(db, 'auth')), request.url.path.substr('/hoodie'.length)), request.headers)
}
}

function notFound (request, reply) {
reply({
'error': 'not found'
}).code(404)
}
6 changes: 3 additions & 3 deletions lib/hapi/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ module.exports = function (env_config) {
}
}
}), [{
register: require('hapi-couchdb-store/lib/routes/couchdb-proxy'),
register: require('hoodie-server-store'),
options: _.defaults({prefix: '/hoodie/store'}, defaultOpts)
}, {
register: require('hapi-couchdb-account/lib/routes/session'),
register: require('hoodie-server-account/routes/session'),
options: defaultOpts
}, {
register: require('hapi-couchdb-account/lib/routes/account'),
register: require('hoodie-server-account/routes/account'),
options: defaultOpts
}])
}
5 changes: 4 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ module.exports = function (options, callback) {
if (err) return callback(err)

server.connection({
port: env_config.app.port
port: env_config.app.port,
routes: {
cors: true
}
})

log.silly('hapi', 'Registering internal plugins')
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"good-squeeze": "^2.1.0",
"h2o2": "^4.0.1",
"hapi": "^11.0.3",
"hapi-couchdb-account": "^1.0.0",
"hapi-couchdb-store": "^1.1.1",
"hoodie-server-account": "^1.0.0",
"hoodie-server-store": "^1.0.1",
"inert": "^3.1.0",
"lodash": "^3.10.1",
"mkdirp": "^0.5.1",
Expand Down
22 changes: 1 addition & 21 deletions test/integration/cors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,15 @@ var test = tap.test
var startServerTest = require('./lib/start-server-test')

startServerTest(test, 'setting CORS headers', function (t, env_config, end) {
t.test('should respond to OPTIONS with the right CORS headers when no origin is given', function (tt) {
request.get(url.format(env_config.app) + '/_api/_session/', {
headers: {
'transfer-encoding': 'chunked'
}
}, function (error, res) {
if (error) throw error
tt.is(res.headers['access-control-allow-origin'], '*')
tt.is(res.headers['access-control-allow-headers'], 'authorization, content-length, content-type, if-match, if-none-match, origin, x-requested-with, transfer-encoding, host, connection')
tt.is(res.headers['access-control-expose-headers'], 'content-type, content-length, etag')
tt.is(res.headers['access-control-allow-methods'], 'GET, PUT, POST, DELETE')
tt.is(res.headers['access-control-allow-credentials'], 'true')
tt.is(res.statusCode, 200)
tt.end()
})
})
t.test('should echo the origin back if one is given', function (tt) {
request.get(url.format(env_config.app) + '/_api/_session/', {
request.get(url.format(env_config.app) + '/hoodie/_session/', {
headers: {
origin: 'http://some.app.com/',
'transfer-encoding': 'chunked'
}
}, function (error, res) {
if (error) throw error
tt.is(res.headers['access-control-allow-origin'], 'http://some.app.com/')
tt.is(res.headers['access-control-allow-headers'], 'authorization, content-length, content-type, if-match, if-none-match, origin, x-requested-with, transfer-encoding, host, connection')
tt.is(res.headers['access-control-expose-headers'], 'content-type, content-length, etag')
tt.is(res.headers['access-control-allow-methods'], 'GET, PUT, POST, DELETE')
tt.is(res.headers['access-control-allow-credentials'], 'true')
tt.is(res.statusCode, 200)
tt.end()
})
Expand Down
6 changes: 3 additions & 3 deletions test/integration/force-gzip.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var startServerTest = require('./lib/start-server-test')
startServerTest(test, 'handle forced gzip', function (t, env_config, end) {
t.test('should receive gzip when gzip accept header sent', function (tt) {
tt.plan(3)
request.get(url.format(env_config.app) + '/_api/', {
request.get(url.format(env_config.app) + '/hoodie/', {
headers: {
'Accept-Encoding': 'gzip, deflate'
}
Expand All @@ -28,15 +28,15 @@ startServerTest(test, 'handle forced gzip', function (t, env_config, end) {
}))
})
t.test('should receive no gzip when no gzip accept header sent', function (tt) {
request.get(url.format(env_config.app) + '/_api/')
request.get(url.format(env_config.app) + '/hoodie/')
.on('response', function (res) {
tt.notOk(res.headers['content-encoding'])
tt.end()
})
})
t.test('should receive gzip when no gzip accept header sent but force query param', function (tt) {
tt.plan(3)
request.get(url.format(env_config.app) + '/_api/?force_gzip=true')
request.get(url.format(env_config.app) + '/hoodie/?force_gzip=true')
.on('response', function (res) {
tt.is(res.headers['content-encoding'], 'gzip')
})
Expand Down
6 changes: 3 additions & 3 deletions test/integration/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ var app = require('../../lib')
var startServerTest = require('./lib/start-server-test')

startServerTest(test, 'block _all_dbs', function (t, env_config, end) {
t.test('should 404 on /_api/_all_dbs', function (tt) {
request.get(url.format(env_config.app) + '/_api/_all_dbs', function (error, res) {
t.test('should 404 on /hoodie/_all_dbs', function (tt) {
request.get(url.format(env_config.app) + '/hoodie/_all_dbs', function (error, res) {
tt.error(error)
tt.is(res.statusCode, 404)
tt.end()
})
})

t.test('should log into admin', function (tt) {
request.post(url.format(env_config.app) + '/_api/_session', {
request.post(url.format(env_config.app) + '/hoodie/_session', {
form: {
name: 'admin',
password: env_config.admin.password
Expand Down
Loading

0 comments on commit 5cb348c

Please sign in to comment.