public
Last active

A Sinatra proxy to be used over a neo4j ReST API

  • Download Gist
web.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
# 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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.