Class: Wunderbar::CGI
- Inherits:
-
Object
- Object
- Wunderbar::CGI
- Defined in:
- lib/wunderbar/script.rb,
lib/wunderbar/polymer.rb,
lib/wunderbar/cgi-methods.rb
Class Method Summary collapse
- .call(scope) ⇒ Object
-
.headers(headers) ⇒ Object
map Ruby CGI headers to Rack headers.
Instance Method Summary collapse
- #call(scope) ⇒ Object
-
#html(scope, *args, &block) ⇒ Object
produce html/xhtml.
- #html2pdf(input = nil, &block) ⇒ Object
-
#json(scope, &block) ⇒ Object
produce json.
-
#out?(scope, headers, &block) ⇒ Boolean
Conditionally provide output, based on ETAG.
- #polymer_element(scope, *args, &block) ⇒ Object
- #ruby2js(scope, *args, &block) ⇒ Object
-
#text(scope, &block) ⇒ Object
produce text.
Class Method Details
.call(scope) ⇒ Object
115 116 117 |
# File 'lib/wunderbar/cgi-methods.rb', line 115 def self.call(scope) new.call(scope) end |
.headers(headers) ⇒ Object
map Ruby CGI headers to Rack headers
200 201 202 203 204 205 206 207 |
# File 'lib/wunderbar/cgi-methods.rb', line 200 def self.headers(headers) result = headers.dup type = result.delete('type') || 'text/html' charset = result.delete('charset') type = "#{type}; charset=#{charset}" if charset result['Content-Type'] ||= type result end |
Instance Method Details
#call(scope) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/wunderbar/cgi-methods.rb', line 119 def call(scope) # asset support for Rack request = (scope.respond_to? :request) ? scope.request : nil if request and request.path =~ %r{/assets/\w[-.\w]+} path = '.' + scope.request.path headers = {'type' => 'text/plain'} headers['type'] = 'application/javascript' if path =~ /\.js$/ out?(scope, headers) { File.read path if File.exist? path } return end env = scope.env accept = env['HTTP_ACCEPT'].to_s path_info = env['PATH_INFO'].to_s # implied request types text = Wunderbar::Options::TEXT || (accept =~ /plain/ && accept !~ /html/) xhr_json = Wunderbar::Options::XHR_JSON || (accept =~ /json/) xhr_json ||= !text && env['HTTP_X_REQUESTED_WITH'].to_s=='XMLHttpRequest' @xhtml = (accept =~ /xhtml/ or accept == '') @pdf = (accept =~ /pdf/) # parse json arguments if xhr_json and request and request.respond_to? :body if env['CONTENT_TYPE'] =~ %r{^application/json(;.*)?$} scope.params.merge! JSON.parse(scope.request.body.read) end end # overrides via the command line xhtml_override = ARGV.include?('--xhtml') html_override = ARGV.include?('--html') @pdf ||= ARGV.include?('--pdf') # overrides via the uri query parameter # xhr_json ||= (path_info.end_with? '.json') text ||= (path_info.end_with? '.text') @pdf ||= (path_info.end_with? '.pdf') xhtml_override ||= (path_info.end_with? '.xhtml') html_override ||= (path_info.end_with? '.html') # disable conneg if only one handler is provided if Wunderbar.queue.length == 1 htype = Wunderbar.queue.first.first xhr_json = (htype == :json) text = (htype == :text) end Wunderbar.queue.each do |type, args, block| case type when :html, :xhtml unless xhr_json or text if type == :html @xhtml = false unless xhtml_override else @xhtml = false if html_override end self.html(scope, *args, &block) return end when :json if xhr_json self.json(scope, *args, &block) return end when :text if text self.text(scope, *args, &block) return end when Proc unless xhr_json or text instance_exec scope, args, block, &type return end end end end |
#html(scope, *args, &block) ⇒ Object
produce html/xhtml
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/wunderbar/cgi-methods.rb', line 89 def html(scope, *args, &block) headers = { 'type' => 'text/html', 'charset' => 'UTF-8' } headers['type'] = 'application/xhtml+xml' if @xhtml x = HtmlMarkup.new(scope) begin if @pdf x._.pdf = true if @pdf headers = { 'type' => 'application/pdf' } output = html2pdf {x.html(*args, &block)} else output = x.html(*args, &block) end rescue ::Exception => exception headers['status'] = Wunderbar::ServerError.text x.clear! output = x.html(*args) do _h1 'Internal Server Error' _exception exception end end out?(scope, headers) { output } end |
#html2pdf(input = nil, &block) ⇒ Object
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 |
# File 'lib/wunderbar/cgi-methods.rb', line 53 def html2pdf(input=nil, &block) require 'thread' require 'open3' require 'stringio' display=":#{rand(999)+1}" pid = fork do # close open files STDIN.reopen '/dev/null' STDOUT.reopen '/dev/null', 'a' STDERR.reopen STDOUT Process.setsid Wunderbar.error Process.exec("Xvfb #{display}") Process.exit end Process.detach(pid) ENV['DISPLAY']=display input ||= block.call output = StringIO.new Open3.popen3('wkhtmltopdf - -') do |pin, pout, perr| [ Thread.new { pin.write input; pin.close }, Thread.new { IO.copy_stream(pout, output) }, Thread.new { perr.readpartial(4096) until perr.eof? } ].map(&:join) end output.string ensure Process.kill 'INT', pid rescue nil end |
#json(scope, &block) ⇒ Object
produce json
7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/wunderbar/cgi-methods.rb', line 7 def json(scope, &block) headers = { 'type' => 'application/json', 'charset' => 'UTF-8', 'Cache-Control' => 'no-cache' } builder = JsonBuilder.new(scope) output = builder.encode(&block) headers['status'] = "404 Not Found" if output == {} rescue Exception => exception headers['status'] = Wunderbar::ServerError.text builder._! Hash.new unless builder.target? Hash builder._exception exception ensure out?(scope, headers) { builder.target! } end |
#out?(scope, headers, &block) ⇒ Boolean
Conditionally provide output, based on ETAG
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/wunderbar/cgi-methods.rb', line 35 def out?(scope, headers, &block) content = block.call etag = Digest::MD5.hexdigest(content) if scope.env['HTTP_IF_NONE_MATCH'] == etag.inspect headers['Date'] = ::CGI.rfc1123_date(Time.now) scope.out headers.merge('status' => '304 Not Modified') do '' end else scope.out headers.merge('Etag' => etag.inspect) do content end end rescue Exception => exception Wunderbar.fatal exception.inspect end |
#polymer_element(scope, *args, &block) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/wunderbar/polymer.rb', line 24 def polymer_element(scope, *args, &block) headers = { 'type' => 'text/html', 'charset' => 'UTF-8' } x = HtmlMarkup.new(scope) begin element = x._polymer_element *args do x.instance_eval(&block) end output = element.serialize.join("\n") + "\n" rescue ::Exception => exception headers['status'] = Wunderbar::ServerError.text x.clear! output = x.html(*args) do _h1 'Internal Server Error' _exception exception end end out?(scope, headers) { output } end |
#ruby2js(scope, *args, &block) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/wunderbar/script.rb', line 56 def ruby2js(scope, *args, &block) headers = { 'type' => 'application/javascript', 'charset' => 'UTF-8' } begin output = Ruby2JS.convert(block) + "\n" rescue Parser::SyntaxError => exception headers['status'] = Wunderbar::ServerError.text location = exception.diagnostic.location output = "// Syntax Error: line #{location.line}, " + "column: #{location.column}\n#{exception}\n" rescue ::Exception => exception headers['status'] = Wunderbar::ServerError.text output = "// Internal Server Error: #{exception}\n" exception.backtrace.each do |frame| next if CALLERS_TO_IGNORE.any? {|re| frame =~ re} output += " #{frame}\n" end end out?(scope, headers) { output } end |
#text(scope, &block) ⇒ Object
produce text
22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/wunderbar/cgi-methods.rb', line 22 def text(scope, &block) headers = {'type' => 'text/plain', 'charset' => 'UTF-8'} builder = TextBuilder.new(scope) output = builder.encode(&block) headers['status'] = "404 Not Found" if output == '' rescue Exception => exception headers['status'] = Wunderbar::ServerError.text builder._exception exception ensure out?(scope, headers) { builder.target! } end |