Permalink
Browse files

Merge branch 'release/0.2.5'

  • Loading branch information...
2 parents 2a1eb70 + 14fccdc commit e4fe3d6cce4874d6999dcba88340f1b7ecafdebf @aseemk aseemk committed Mar 1, 2012
Showing with 84 additions and 22 deletions.
  1. +6 −0 CHANGELOG.md
  2. +8 −8 lib/GraphDatabase_.coffee
  3. +8 −9 lib/Node_.coffee
  4. +2 −2 lib/PropertyContainer_.coffee
  5. +1 −2 lib/Relationship_.coffee
  6. +58 −0 lib/util_.coffee
  7. +1 −1 package.json
View
@@ -1,3 +1,9 @@
+## Version 0.2.5 — March 1, 2012
+
+ - Added support for HTTP Basic Auth by working around the fact that Neo4j
+ doesn't maintain the username and password in the URLs it returns (#7).
+ Many thanks to @anatoliychakkaev for finding this and suggesting the fix.
+
## Version 0.2.4 — January 29, 2012
- Updated library to support Neo4j 1.6. Still supports 1.5 and 1.4. No
View
@@ -5,7 +5,6 @@
# we're returning immediately: process.nextTick _
status = require 'http-status'
-request = require 'request'
util = require './util_'
adjustError = util.adjustError
@@ -16,6 +15,7 @@ Node = require './Node_'
module.exports = class GraphDatabase
constructor: (url) ->
@url = url
+ @_request = util.wrapRequestForAuth url
# Cache
@_root = null
@@ -31,7 +31,7 @@ module.exports = class GraphDatabase
return @_root
try
- response = request.get @url, _
+ response = @_request.get @url, _
if response.statusCode isnt status.OK
throw response
@@ -48,7 +48,7 @@ module.exports = class GraphDatabase
try
root = @_getRoot _
- response = request.get root.data, _
+ response = @_request.get root.data, _
if response.statusCode isnt status.OK
throw response
@@ -79,7 +79,7 @@ module.exports = class GraphDatabase
getNode: (url, _) ->
try
- response = request.get url, _
+ response = @_request.get url, _
if response.statusCode isnt status.OK
@@ -115,7 +115,7 @@ module.exports = class GraphDatabase
val = encodeURIComponent value
url = "#{services.node_index}/#{index}/#{key}/#{val}"
- response = request.get url, _
+ response = @_request.get url, _
if response.statusCode isnt status.OK
# Database error
@@ -146,7 +146,7 @@ module.exports = class GraphDatabase
getRelationship: (url, _) ->
try
- response = request.get url, _
+ response = @_request.get url, _
if response.statusCode isnt status.OK
# TODO: Handle 404
@@ -184,7 +184,7 @@ module.exports = class GraphDatabase
if not endpoint
throw new Error 'Cypher plugin not installed'
- response = request.post
+ response = @_request.post
uri: endpoint
json: {query}
, _
@@ -227,7 +227,7 @@ module.exports = class GraphDatabase
services = @getServices _
url = "#{services.node_index}/#{index}?query=#{encodeURIComponent query}"
- response = request.get url, _
+ response = @_request.get url, _
if response.statusCode isnt status.OK
# Database error
View
@@ -1,5 +1,4 @@
status = require 'http-status'
-request = require 'request'
util = require './util_'
adjustError = util.adjustError
@@ -19,7 +18,7 @@ module.exports = class Node extends PropertyContainer
try
# TODO: check for actual modification
if @exists
- response = request.put
+ response = @_request.put
uri: "#{@self}/properties"
json: @data
, _
@@ -35,7 +34,7 @@ module.exports = class Node extends PropertyContainer
else
services = @db.getServices _
- response = request.post
+ response = @_request.post
uri: services.node
json: @data
, _
@@ -103,7 +102,7 @@ module.exports = class Node extends PropertyContainer
otherNodeURL = to.self
if createRelationshipURL? and otherNodeURL
- response = request.post
+ response = @_request.post
url: createRelationshipURL
json:
to: otherNodeURL
@@ -166,7 +165,7 @@ module.exports = class Node extends PropertyContainer
if not relationshipsURL
throw new Error 'Couldn\'t find URL of relationships endpoint.'
- resp = request.get relationshipsURL, _
+ resp = @_request.get relationshipsURL, _
if resp.statusCode is status.NOT_FOUND
throw new Error 'Node not found.'
@@ -213,7 +212,7 @@ module.exports = class Node extends PropertyContainer
max_depth: maxDepth
algorithm: algorithm
- res = request.post
+ res = @_request.post
url: pathURL
json: data
, _
@@ -262,7 +261,7 @@ module.exports = class Node extends PropertyContainer
if not traverseURL
throw new Error 'Traverse not available.'
- resp = request.post
+ resp = @_request.post
url: traverseURL
json:
'max_depth': 1
@@ -298,14 +297,14 @@ module.exports = class Node extends PropertyContainer
encodedValue = encodeURIComponent value
url = "#{services.node_index}/#{index}/#{encodedKey}/#{encodedValue}"
- response = request.post
+ response = @_request.post
url: url
json: @self
, _
# new API:
else
- response = request.post
+ response = @_request.post
url: "#{services.node_index}/#{index}"
json:
key: key
@@ -1,12 +1,12 @@
status = require 'http-status'
-request = require 'request'
util = require './util_'
adjustError = util.adjustError
module.exports = class PropertyContainer
constructor: (db, data) ->
@db = db
+ @_request = db._request # convenience alias
@_data = data or {}
@_data.self = data?.self or null
@@ -35,7 +35,7 @@ module.exports = class PropertyContainer
return
try
- response = request.del @self, _
+ response = @_request.del @self, _
if response.statusCode isnt status.NO_CONTENT
# database error
View
@@ -1,5 +1,4 @@
status = require 'http-status'
-request = require 'request'
util = require './util_'
adjustError = util.adjustError
@@ -26,7 +25,7 @@ module.exports = class Relationship extends PropertyContainer
try
# TODO: check for actual modification
if @exists
- response = request.put
+ response = @_request.put
uri: "#{@self}/properties"
json: @data
, _
View
@@ -1,4 +1,62 @@
constants = require 'constants'
+request = require 'request'
+URL = require 'url'
+
+#-----------------------------------------------------------------------------
+#
+# HTTP Basic Auth support
+#
+#-----------------------------------------------------------------------------
+
+# wrapping request methods to support HTTP Basic Auth, since Neo4j doesn't
+# preserve the username and password in the URLs! This code derived from:
+# https://github.com/thingdom/node-neo4j/issues/7 (by @anatoliychakkaev)
+# returns a minimal wrapper (HTTP methods only) around request so that each
+# method ensures that URLs include HTTP Basic Auth usernames/passwords.
+exports.wrapRequestForAuth = (url) ->
+ # parse auth info, and short-circuit if we have none:
+ auth = URL.parse(url).auth
+ return request if not auth
+
+ # updates the args to ensure that the URL arg has username/password:
+ fixArgs = (args) ->
+ # the URL may be the first arg alone, as a string, or an options obj:
+ # update: it may also be called 'uri' instead of 'url'!
+ if typeof args[0] is 'string'
+ url = args[0]
+ else
+ url = args[0].url or args[0].uri
+
+ if not url
+ console.log 'UH OH:'
+ console.log args
+
+ # ensure auth info is included in the URL:
+ url = URL.parse url
+ if not url.auth
+ # XXX argh, just setting url.auth isn't picked up by URL.format()!
+ # it relies first on just url.host, so update that instead:
+ # TODO account for case where url.auth is set, but different?
+ url.host = "#{auth}@#{url.host}"
+ url = URL.format url
+
+ # then update the original args:
+ if typeof args[0] is 'string'
+ args[0] = url
+ else
+ args[0].url = args[0].uri = url
+
+ return args
+
+ # wrap each method to fix its args before calling real method:
+ wrapper = {}
+ for verb in ['get', 'post', 'put', 'del', 'head']
+ do (verb) -> # freaking closures!
+ wrapper[verb] = (args...) ->
+ request[verb].apply request, fixArgs args
+
+ # and return this set of wrapped methods:
+ return wrapper
#-----------------------------------------------------------------------------
#
View
@@ -1,7 +1,7 @@
{
"name": "neo4j",
"description": "Neo4j driver (REST API client) for Node.js",
- "version": "0.2.4",
+ "version": "0.2.5",
"author": "The Thingdom <info@thethingdom.com>",
"contributors": [
{"name": "Daniel Gasienica", "email": "daniel@gasienica.ch"},

0 comments on commit e4fe3d6

Please sign in to comment.