class Wunderbar::CGI
Public Class Methods
call(scope)
click to toggle source
# File lib/wunderbar/cgi-methods.rb, line 115 def self.call(scope) new.call(scope) end
headers(headers)
click to toggle source
Public Instance Methods
call(scope)
click to toggle source
# 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)
click to toggle source
produce html/xhtml
# 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)
click to toggle source
# 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)
click to toggle source
produce json
# 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)
click to toggle source
Conditionally provide output, based on ETAG
# 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)
click to toggle source
# 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)
click to toggle source
# File lib/wunderbar/script.rb, line 58 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)
click to toggle source
produce text
# 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