Skip to content

Instantly share code, notes, and snippets.

@andytill
Created November 18, 2012 21:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andytill/4107546 to your computer and use it in GitHub Desktop.
Save andytill/4107546 to your computer and use it in GitHub Desktop.
A Sinatra proxy to be used over a neo4j ReST API
# web proxy for a neo4j database, using Heroku but could be easily modified for anything else
# this code is a modified version of the code found here https://github.com/akollegger/nosql-now/blob/master/web.rb
# the main changes are...
# - authentication required for modification, although viewing is allowed without authentication (auth can be added by calling protected! in the get method)
# - the domain returned in the data is replaced with the proxy domain instead of being removed which was causing errors in the java jersey library
# - modified post routing, this wasn't catching all POST requests
require 'sinatra'
require 'rest-client'
require 'json'
neo4j_db_url = ENV['NEO4J_URL'] || "http://localhost:7474"
neo4j_db_url_noauth = neo4j_db_url.gsub /http:\/\/\w+:\w+@/, "http://"
# SECRET STUFF! put your user name and password and URL for the Heroku app here
neo4j_user = ""
neo4j_password = ""
HEROKU_APP_HOST = ""
REPLACE_DB_HOST = /(#{neo4j_db_url})|(#{neo4j_db_url_noauth})/
REST = RestClient::Resource.new neo4j_db_url, neo4j_user, neo4j_password
helpers do
def protected!
unless authorized?
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
end
def authorized?
@auth ||= Rack::Auth::Basic::Request.new(request.env)
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [neo4j_user, neo4j_password]
end
end
get '/' do
if request.accept.include?("application/json") || request.accept.include?("text/javascript")
pass_to_neo4j
else
# TODO return not found?
end
end
get /\/webadmin.*/ do
protected!
pass_to_neo4j
end
get /\/db\/.*/ do
pass_to_neo4j
end
options /\/db\/.*/ do
pass_to_neo4j
end
post '/db/data/*' do
protected!
pass_to_neo4j
end
post "/db/manage/server/console/" do
protected!
data = JSON.parse request.body.read
if data["engine"] == "gremlin"
content_type "application/json"
["Security-Constraint: Gremlin is DISABLED", ""].to_json
else
pass_to_neo4j data.to_json
end
end
post "/db/manage/server/jmx/query" do
protected!
pass_to_neo4j
end
def pass_to_neo4j(data=nil)
request_method = request.request_method
#puts "#{request_method} #{request.path}"
request_method = request_method.downcase.to_sym
request_headers = {
:accept => "application/json",
:content_type => "application/json",
:cookies => request.cookies
}
if request_method == :get
proxy_response = REST[request.path].get(request_headers)
else
data = data || request.body.read
proxy_response = REST[request.path].send(request_method, data, request_headers)
end
cookies = proxy_response.cookies
response.set_cookie("JSESSIONID", :value => cookies["JSESSIONID"], :path => cookies["Path"]) if cookies
content_type proxy_response.headers[:content_type]
if %W(application/json application/x-javascript text/css text/html).include? proxy_response.headers[:content_type]
# replace the host name of the neo4j database with the host name of the proxy so we're in the middle of future calls
proxy_response.gsub REPLACE_DB_HOST, HEROKU_APP_HOST
else
proxy_response
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment