phantom_proxy 1.2.17 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -12
- data/.rbenv-gemsets +1 -0
- data/.ruby-version +1 -1
- data/Gemfile +2 -3
- data/LICENSE.txt +22 -0
- data/Rakefile +2 -0
- data/bin/phantom_proxy +45 -52
- data/lib/phantom_proxy/helper/http.rb +46 -0
- data/lib/phantom_proxy/helper/jsonizer.rb +46 -0
- data/lib/phantom_proxy/helper/logable.rb +36 -0
- data/lib/phantom_proxy/helper/status_info.rb +42 -0
- data/lib/phantom_proxy/helper/template_renderer.rb +43 -0
- data/lib/phantom_proxy/phantomjs/phantomjs.rb +105 -0
- data/lib/phantom_proxy/proxy/proxy_api.rb +86 -0
- data/lib/phantom_proxy/router/app_router.rb +72 -0
- data/lib/phantom_proxy/scripts/proxy.js +93 -93
- data/lib/phantom_proxy/service.rb +21 -0
- data/lib/phantom_proxy/status/status_api.rb +43 -0
- data/lib/phantom_proxy/version.rb +3 -0
- data/lib/phantom_proxy.rb +95 -12
- data/phantom_proxy.gemspec +27 -26
- data/templates/views/error_page.erb +18 -0
- data/templates/views/status_page.erb +46 -0
- metadata +139 -86
- data/lib/phantom_proxy/config.ru +0 -10
- data/lib/phantom_proxy/install/etc/init.d/phproxy +0 -193
- data/lib/phantom_proxy/install/etc/phantom_proxy/config/example_config +0 -3
- data/lib/phantom_proxy/phantomjs.rb +0 -106
- data/lib/phantom_proxy/phantomjs_control_panel.rb +0 -58
- data/lib/phantom_proxy/phantomjsserver.rb +0 -194
- data/lib/phantom_proxy/web/control_panel.html +0 -44
- data/spec/test +0 -2
- data/tmp/.keep +0 -0
- data/tmp/run +0 -5
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54b0f0d023b215fda611a4fa487a2e7610ad3b29
|
4
|
+
data.tar.gz: 314bcd2a4a6551e9f741bb852dd57b108c87dd1e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4d98501212d94d5b96f304150b57c255a521af55855c63234d24faa11f5e2057b29196f97f485ae9aa652c7c96ac85d70ebc3f0e98997d1e1da8dcc70a144090
|
7
|
+
data.tar.gz: 245b3c3b6e7ef879309824b3dff8537d22262bb68bfc9e4b93eedd0cbcfd882b89dc24128e3975cab8a12c1d1f3879dcfbbbaa247b59593922bfdf2bd0ddf128
|
data/.gitignore
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
*.bundle
|
11
|
+
*.so
|
12
|
+
*.o
|
13
|
+
*.a
|
14
|
+
mkmf.log
|
data/.rbenv-gemsets
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
phantom_proxy2
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0-p481
|
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Suddani
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/phantom_proxy
CHANGED
@@ -1,60 +1,53 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
3
|
+
require "goliath/runner"
|
4
|
+
require "phantom_proxy"
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
module PhantomProxy
|
8
|
+
def self.load_config
|
9
|
+
options = {}
|
10
|
+
optparse = OptionParser.new do|opts|
|
11
|
+
opts.banner = "Usage: "
|
12
|
+
opts.on( '-l [FILE]', '--logfile [FILE]', 'Write log to FILE' ) do |file|
|
13
|
+
# PhantomProxy2.logger = Logger.new(file)
|
14
|
+
options[:log_file] = file
|
15
|
+
end
|
16
|
+
opts.on('--hmac [STRING]', 'Use a hmac key to secure the connection' ) do |hmac|
|
17
|
+
# PhantomProxy2.hmac_key = hmac
|
18
|
+
options[:hmac_key] = hmac
|
19
|
+
end
|
20
|
+
end
|
21
|
+
args = ARGV.dup
|
22
|
+
remaining = []
|
23
|
+
while !args.empty?
|
24
|
+
begin
|
25
|
+
head = args.shift
|
26
|
+
remaining.concat(optparse.parse([head, args].flatten))
|
27
|
+
rescue OptionParser::InvalidOption
|
28
|
+
remaining << head
|
29
|
+
retry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
PhantomProxy.logger = Logger.new(options[:log_file]) if options[:log_file]
|
33
|
+
PhantomProxy.hmac_key = options[:hmac_key] if options[:hmac_key]
|
34
|
+
remaining
|
35
|
+
end
|
36
|
+
def self.run_phantom_proxy(args)
|
37
|
+
puts "Run with #{args}"
|
38
|
+
runner = Goliath::Runner.new(args, nil)
|
39
|
+
runner.logger=PhantomProxy.logger
|
40
|
+
runner.port = PhantomProxy.port if PhantomProxy.respond_to?(:port)
|
41
|
+
runner.address = PhantomProxy.address if PhantomProxy.respond_to?(:address)
|
27
42
|
|
28
|
-
|
43
|
+
Goliath.env = PhantomProxy.env if PhantomProxy.respond_to?(:env)
|
29
44
|
|
30
|
-
|
31
|
-
|
32
|
-
last_arg = nil
|
33
|
-
ARGV.each { |arg|
|
34
|
-
if !/-hmac/.match(arg) && !/-hmac/.match(last_arg) && !/-self/.match(arg)
|
35
|
-
PARAMETERS << arg
|
36
|
-
end
|
37
|
-
phantom = true if /-self/.match(arg)
|
38
|
-
hmac_key = arg if /-hmac/.match(last_arg)
|
39
|
-
last_arg = arg
|
40
|
-
}
|
45
|
+
runner.api = PhantomProxy::Service.new
|
46
|
+
runner.app = Goliath::Rack::Builder.build(PhantomProxy::Service, runner.api)
|
41
47
|
|
42
|
-
|
43
|
-
|
44
|
-
Dir.mkdir("/tmp/phantom_proxy")
|
45
|
-
end
|
46
|
-
|
47
|
-
File.open("/tmp/phantom_proxy/key", 'w+') {|f| f.write(hmac_key) }
|
48
|
-
else
|
49
|
-
begin
|
50
|
-
File.delete("/tmp/phantom_proxy/key")
|
51
|
-
rescue
|
48
|
+
puts "Now starting PhantomProxy #{PhantomProxy::VERSION}...."
|
49
|
+
runner.run
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
55
|
-
|
56
|
-
startoptions = ["start", "-R", PhantomJSProxy::CONFIG, "-P", "/tmp/pids/phantom_proxy.pid", "--tag", "phantom_proxy"]+PARAMETERS
|
57
|
-
runner = Thin::Runner.new(startoptions).run!
|
58
|
-
else
|
59
|
-
Thin::Server.start(PhantomJSProxy::PhantomJSServer.new, ARGV[0], ARGV[1], ARGV[2])
|
60
|
-
end
|
53
|
+
PhantomProxy.run_phantom_proxy PhantomProxy.load_config
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
module Http
|
3
|
+
def self.renderer
|
4
|
+
@@renderer||=TemplateRenderer.create(binding)
|
5
|
+
end
|
6
|
+
def self.error_object_binding(obj)
|
7
|
+
obj||={}
|
8
|
+
def obj.get_binding
|
9
|
+
binding
|
10
|
+
end
|
11
|
+
def obj.title
|
12
|
+
self[:title]
|
13
|
+
end
|
14
|
+
def obj.content
|
15
|
+
self[:content]
|
16
|
+
end
|
17
|
+
def obj.error_code
|
18
|
+
self[:error_code]
|
19
|
+
end
|
20
|
+
obj.get_binding
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.error_massages
|
24
|
+
@error_massages||={"Not Found" => 404, "Server Error" => 500, "Not Allowed" => 403, "Not Authorized" => 401}
|
25
|
+
end
|
26
|
+
|
27
|
+
error_massages.each do |error_name, error_code|
|
28
|
+
define_singleton_method error_name.gsub(" ", "").to_sym do |data=error_name, content_type="text/html"|
|
29
|
+
Response(error_code, renderer.render("error_page", error_object_binding(:title=>error_name, :content=>data, :error_code => 404)), content_type)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.NextApi(data="Not Found", content_type="text/plain")
|
34
|
+
Response(600, data, content_type)
|
35
|
+
end
|
36
|
+
def self.OK(data="", content_type="text/plain")
|
37
|
+
Response(200, data, content_type)
|
38
|
+
end
|
39
|
+
def self.Response(status_code=200, data="", content_type="text/plain")
|
40
|
+
[status_code, {"Content-Type" => content_type}, data]
|
41
|
+
end
|
42
|
+
def self.OK_no_data(data="", content_type="text/plain")
|
43
|
+
[204, {}, ""]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
module Jsonizer
|
3
|
+
def json_var(*var_names)
|
4
|
+
@json_vars = (@json_vars||[])+var_names.flatten
|
5
|
+
end
|
6
|
+
|
7
|
+
def json_vars
|
8
|
+
@json_vars||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
module Methods
|
12
|
+
def render_json(obj=nil)
|
13
|
+
Http.OK (obj||self).to_json, "application/json"
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_xml(obj=nil)
|
17
|
+
obj = Nokogiri::XML::Builder.new do |xml|
|
18
|
+
yield xml
|
19
|
+
end if block_given?
|
20
|
+
Http.OK (obj||self).to_xml, "application/xml"
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_json
|
24
|
+
stuff = Hash.new
|
25
|
+
self.class.json_vars.each{|var_name|
|
26
|
+
stuff[var_name.to_sym]=send(var_name)# if respond_to?(var_name)
|
27
|
+
}
|
28
|
+
puts stuff
|
29
|
+
stuff.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_xml()
|
33
|
+
xml = Nokogiri::XML::Builder.new do |xml|
|
34
|
+
xml.PhantomProxyStatus() {
|
35
|
+
self.class.json_vars.each{|var_name|
|
36
|
+
var = send(var_name)
|
37
|
+
var = var.to_xml if var.respond_to?(:to_xml)
|
38
|
+
xml.send(var_name, var)# if respond_to?(var_name)
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
xml.to_xml
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
|
3
|
+
class PhantomProxyLogger
|
4
|
+
def initialize logger, req_id
|
5
|
+
@logger=logger
|
6
|
+
@req_id=req_id
|
7
|
+
end
|
8
|
+
def info msg
|
9
|
+
@logger.info "[#{@req_id}] -> #{msg}"
|
10
|
+
end
|
11
|
+
def warn msg
|
12
|
+
@logger.warn "[#{@req_id}] -> #{msg}"
|
13
|
+
end
|
14
|
+
def error msg
|
15
|
+
@logger.error "[#{@req_id}] -> #{msg}"
|
16
|
+
end
|
17
|
+
def debug msg
|
18
|
+
@logger.debug "[#{@req_id}] -> #{msg}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Logable
|
23
|
+
def logger
|
24
|
+
@logger ||= PhantomProxy.logger
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger=(_logger)
|
28
|
+
@logger=_logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.next_id
|
32
|
+
@req_id ||= 0
|
33
|
+
@req_id+=1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
module StatusInfo
|
3
|
+
def self.boot_up
|
4
|
+
@start_time=Time.now
|
5
|
+
end
|
6
|
+
boot_up
|
7
|
+
|
8
|
+
def self.uptime
|
9
|
+
Time.now-@start_time
|
10
|
+
end
|
11
|
+
def self.cache_hit
|
12
|
+
@cache_hit||=0
|
13
|
+
end
|
14
|
+
def self.cache_hit=(obj)
|
15
|
+
@cache_hit=obj
|
16
|
+
end
|
17
|
+
def self.cache_miss
|
18
|
+
@cache_miss||=0
|
19
|
+
end
|
20
|
+
def self.cache_miss=(obj)
|
21
|
+
@cache_miss=obj
|
22
|
+
end
|
23
|
+
def self.cache_error
|
24
|
+
@cache_error||=0
|
25
|
+
end
|
26
|
+
def self.cache_error=(obj)
|
27
|
+
@cache_error=obj
|
28
|
+
end
|
29
|
+
def self.cache_access
|
30
|
+
@cache_access||=0
|
31
|
+
end
|
32
|
+
def self.cache_access=(obj)
|
33
|
+
@cache_access=obj
|
34
|
+
end
|
35
|
+
def self.connections
|
36
|
+
@connections||=0
|
37
|
+
end
|
38
|
+
def self.connections=(obj)
|
39
|
+
@connections=obj
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
class ReloadTemplateRenderer
|
3
|
+
def initialize(binding_)
|
4
|
+
@binding = binding_
|
5
|
+
end
|
6
|
+
|
7
|
+
def render(template_name, bind=nil)
|
8
|
+
TemplateRenderer.new(bind||@binding).render(template_name)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class TemplateRenderer
|
13
|
+
def self.create(binding_)
|
14
|
+
(PhantomProxy.respond_to?(:env) && PhantomProxy.env == :production) ? TemplateRenderer.new(binding_) : ReloadTemplateRenderer.new(binding_)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(controller_binding_)
|
18
|
+
@controller_binding=controller_binding_
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(template_name, bind=nil)
|
22
|
+
template(template_name).result(bind||controller_binding)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def controller_binding
|
28
|
+
@controller_binding
|
29
|
+
end
|
30
|
+
|
31
|
+
def template(template_name)
|
32
|
+
begin
|
33
|
+
templates[template_name]||=::ERB.new(File.read(PhantomProxy.root.join("views", "#{template_name}.erb")))
|
34
|
+
rescue Errno::ENOENT => e
|
35
|
+
templates[template_name]||=::ERB.new(File.read(PhantomProxy.root_gem.join("templates/views", "#{template_name}.erb")))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def templates
|
40
|
+
@templates||={}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module PhantomProxy
|
4
|
+
class PhantomJS
|
5
|
+
attr_accessor :dom
|
6
|
+
attr_accessor :image
|
7
|
+
attr_accessor :ready
|
8
|
+
|
9
|
+
include ::PhantomProxy::Logable
|
10
|
+
|
11
|
+
def initialize()
|
12
|
+
@ready = 503
|
13
|
+
end
|
14
|
+
|
15
|
+
def getUrl(url, pictureOnly=true, loadIFrames=true)
|
16
|
+
logger.info("PhantomJS: "+url)
|
17
|
+
@ready = 503
|
18
|
+
|
19
|
+
pictureFile = nil
|
20
|
+
picture = "none"
|
21
|
+
|
22
|
+
loadFrames = "false"
|
23
|
+
|
24
|
+
if loadIFrames
|
25
|
+
loadFrames = "true"
|
26
|
+
end
|
27
|
+
|
28
|
+
if pictureOnly
|
29
|
+
pictureFile = Tempfile.new(["phantom_proxy_page", ".png"])
|
30
|
+
picture = pictureFile.path
|
31
|
+
end
|
32
|
+
|
33
|
+
url_args = ""
|
34
|
+
url_args_ = []
|
35
|
+
|
36
|
+
if /\?/.match(url)
|
37
|
+
url_args = url.split('?')[1]
|
38
|
+
url = url.split('?')[0]
|
39
|
+
|
40
|
+
if url_args
|
41
|
+
url_args_ = url_args.split('&')
|
42
|
+
url_args = url_args_.join(' ')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@dom = invokePhantomJS(PhantomProxy.script_path, [picture, loadFrames, "\""+url+"\"", url_args_.length, url_args])
|
47
|
+
|
48
|
+
logger.info("Opened page: "+ /Open page: (.*?) END/.match(@dom)[1])
|
49
|
+
|
50
|
+
@ready = 503
|
51
|
+
dom_text = "Failed to load page"
|
52
|
+
|
53
|
+
if /DONE_LOADING_URL/.match(@dom)
|
54
|
+
logger.info("LOAD_DOM_TEXT")
|
55
|
+
dom_text = getDOMText @dom
|
56
|
+
logger.info("LOAD_DOM_TEXT_DONE")
|
57
|
+
if pictureOnly && File.exist?(picture)
|
58
|
+
logger.info("File is there")
|
59
|
+
@image = File.open(picture, "rb")# {|f| f.read }
|
60
|
+
pictureFile.close!
|
61
|
+
else
|
62
|
+
logger.info("No file to load at: "+picture)
|
63
|
+
@image = ""
|
64
|
+
end
|
65
|
+
@ready = 200
|
66
|
+
end
|
67
|
+
if /URL_ERROR_CODE/.match(@dom)
|
68
|
+
logger.info("LOAD_ERROR_CODE")
|
69
|
+
@ready = getHTTPCode @dom
|
70
|
+
logger.info("LOAD_ERROR_CODE_DONE: #{@ready}")
|
71
|
+
end
|
72
|
+
@dom = dom_text
|
73
|
+
return @dom
|
74
|
+
end
|
75
|
+
|
76
|
+
def getDOMText data
|
77
|
+
tmp = data.split('PHANTOMJS_DOMDATA_WRITE:')[1];
|
78
|
+
tmp = tmp.split('PHANTOMJS_DOMDATA_END')[0]
|
79
|
+
tmp
|
80
|
+
end
|
81
|
+
|
82
|
+
def getHTTPCode data
|
83
|
+
tmp = data.split('URL_ERROR_CODE: ')[1];
|
84
|
+
tmp = tmp.split('URL_ERROR_CODE_END')[0]
|
85
|
+
#tmp = /FAILED_LOADING_URL: (.*?)FAILED_LOADING_URL_END/.match(data)[1]
|
86
|
+
tmp.to_i
|
87
|
+
end
|
88
|
+
|
89
|
+
def getAsImageResponse(type='png')
|
90
|
+
return "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: image/"+type+"\r\n\r\n"+@image;
|
91
|
+
end
|
92
|
+
|
93
|
+
def invokePhantomJS(script, args)
|
94
|
+
argString = " "+args.join(" ")
|
95
|
+
logger.info("Call phantomJS with: "+argString)
|
96
|
+
out = ""
|
97
|
+
|
98
|
+
IO.popen(PhantomProxy.phantomjs_bin+" --ignore-ssl-errors=yes --web-security=false "+script+argString) {|io|
|
99
|
+
out = io.readlines.join
|
100
|
+
}
|
101
|
+
#logger.info("PHANTOMJS_OUT: "+out)
|
102
|
+
return out
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
class ProxyApi < AppRouterBase
|
3
|
+
get "/*path", :handle_proxy_request
|
4
|
+
get "/", :handle_proxy_request
|
5
|
+
|
6
|
+
put "*any", :next_api
|
7
|
+
delete "*any", :next_api
|
8
|
+
head "*any", :next_api
|
9
|
+
post "*any", :next_api
|
10
|
+
|
11
|
+
private
|
12
|
+
def handle_proxy_request
|
13
|
+
return Http.NotAuthorized unless !PhantomProxy.hmac_key || check_request_security
|
14
|
+
phJS = PhantomJS.new
|
15
|
+
PhantomProxy.wait_for(lambda {
|
16
|
+
phJS.getUrl(canonical_url, as_image?, iframes?)
|
17
|
+
})
|
18
|
+
return image_response(phJS) if as_image?
|
19
|
+
html_response(phJS)
|
20
|
+
end
|
21
|
+
|
22
|
+
def html_response(phJS)
|
23
|
+
[phJS.ready > 0 ? phJS.ready : 404 , {'Content-Type' => 'text/html'}, phJS.dom]
|
24
|
+
end
|
25
|
+
|
26
|
+
def image_response(phJS)
|
27
|
+
[200 , {'Content-Type' => 'image/png'}, phJS.image]
|
28
|
+
end
|
29
|
+
|
30
|
+
def host
|
31
|
+
env['SERVER_NAME']
|
32
|
+
end
|
33
|
+
|
34
|
+
def path
|
35
|
+
env[nil] ? env[nil][:path] : ""
|
36
|
+
end
|
37
|
+
|
38
|
+
def iframes?
|
39
|
+
env["HTTP_GET_PAGE_WITH_IFRAMES"] == "true" || PhantomProxy.always_iframe?
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_image?
|
43
|
+
env["HTTP_GET_PAGE_AS_IMAGE"] == "true" || PhantomProxy.always_image?
|
44
|
+
end
|
45
|
+
|
46
|
+
def https?
|
47
|
+
env["SERVER_PORT"] == "443"
|
48
|
+
end
|
49
|
+
|
50
|
+
def protocoll
|
51
|
+
https? ? "https" : "http"
|
52
|
+
end
|
53
|
+
|
54
|
+
def canonical_path
|
55
|
+
["#{protocoll}://#{host}",path].join("/")
|
56
|
+
end
|
57
|
+
|
58
|
+
def canonical_url
|
59
|
+
[canonical_path, env["params"] ? env["params"].map{|k,v| "#{k}=#{v}"}.join('&') : nil].join("?")
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_request_security
|
63
|
+
if !hmac_hash || !hmac_time
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
|
67
|
+
client_time= Time.parse(hmac_time)
|
68
|
+
remote_time= Time.now
|
69
|
+
remote_key = PhantomProxy.hmac_key.update(env['REQUEST_URI']+env['HTTP_HMAC_TIME']).hexdigest
|
70
|
+
|
71
|
+
if (hmac_hash != remote_key || (remote_time-client_time).abs > 120)
|
72
|
+
# control_panel.add_special_request "@did not pass security check"
|
73
|
+
logger.info "@did not pass security check"
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
return true
|
77
|
+
end
|
78
|
+
|
79
|
+
def hmac_hash
|
80
|
+
env['HTTP_HMAC_KEY']
|
81
|
+
end
|
82
|
+
def hmac_time
|
83
|
+
env['HTTP_HMAC_TIME']
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module PhantomProxy
|
2
|
+
class AppRouterBase
|
3
|
+
|
4
|
+
extend Jsonizer
|
5
|
+
include Jsonizer::Methods
|
6
|
+
include Logable
|
7
|
+
|
8
|
+
attr_accessor :env
|
9
|
+
|
10
|
+
def initialize(env)
|
11
|
+
@env = env
|
12
|
+
end
|
13
|
+
|
14
|
+
def next_api
|
15
|
+
Http.NextApi
|
16
|
+
end
|
17
|
+
|
18
|
+
def renderer
|
19
|
+
@@renderer||=TemplateRenderer.create(binding)
|
20
|
+
end
|
21
|
+
|
22
|
+
def render(template_name, status_code=200, bind=nil)
|
23
|
+
begin
|
24
|
+
Http.Response(status_code, renderer.render(template_name, bind||binding), "html")
|
25
|
+
rescue Errno::ENOENT => e
|
26
|
+
Http.NotFound
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.options(opt)
|
31
|
+
opt = {:function => opt.to_sym} if opt.class != Hash
|
32
|
+
{:controller => self.name, :function => :call}.merge(opt)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.http_verbs
|
36
|
+
@http_verbs||=["GET", "POST", "PUT", "DELETE", "HEAD"]
|
37
|
+
end
|
38
|
+
|
39
|
+
http_verbs.each do |method|
|
40
|
+
define_singleton_method method.downcase.to_sym do |path, opt = {}|
|
41
|
+
path = Journey::Path::Pattern.new path
|
42
|
+
router.routes.add_route(lambda{|env| call_controller(options(opt), env)}, path, {:request_method => method}, {})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.call(env)
|
47
|
+
PhantomProxy::StatusInfo.connections+=1
|
48
|
+
print_ram_usage("RAM USAGE Before")
|
49
|
+
result=router.call(env)
|
50
|
+
print_ram_usage("RAM USAGE After")
|
51
|
+
PhantomProxy::StatusInfo.connections-=1
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.print_ram_usage(text)
|
56
|
+
PhantomProxy.logger.info "#{text}[#{Process.pid}]: " + `pmap #{Process.pid} | tail -1`[10,40].strip
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.call_controller(options, env)
|
60
|
+
options[:controller].respond_to?(options[:function]) ? options[:controller].send(options[:function], env) : PhantomProxy.const_get(options[:controller]).new(env).send(options[:function])
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def self.routes()
|
65
|
+
(@@routes ||= {})[self.name] ||= Journey::Routes.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.router()
|
69
|
+
(@@router ||= {})[self.name] ||= Journey::Router.new routes, {}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|