Top Level Namespace

Defined Under Namespace

Modules: Builder, CgiSpa

Constant Summary collapse

SELF =

quick access to request_uri

ENV['REQUEST_URI'].to_s

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.body?(args = {}) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/cgi-spa/html-methods.rb', line 68

def $x.body? args={}
  traceback_class = args.delete('traceback_class')
  traceback_style = args.delete('traceback_style')
  traceback_style ||= 'background-color:#ff0; margin: 1em 0; padding: 1em; ' +
    'border: 4px solid red; border-radius: 1em'
  $x.body(args) do
    begin
      yield
    rescue Exception => exception
      text = exception.inspect
      exception.backtrace.each {|frame| text += "\n  #{frame}"}

      if traceback_class
        $x.pre text, :class=>traceback_class
      else
        $x.pre text, :style=>traceback_style
      end
    end
  end
end

.htmlObject

produce html/xhtml



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/cgi-spa/cgi-methods.rb', line 84

def $cgi.html
  return if $XHR_JSON or $TEXT
  if $XHTML
    $cgi.out? 'type' => 'application/xhtml+xml', 'charset' => 'UTF-8' do
      $x.declare! :DOCTYPE, :html
      $x.html :xmlns => 'http://www.w3.org/1999/xhtml' do
        yield $x
      end
    end
  else
    $cgi.out? 'type' => 'text/html', 'charset' => 'UTF-8' do
      $x.declare! :DOCTYPE, :html
      $x.html do
        yield $x
      end
    end
  end
end

.html!(&block) ⇒ Object

produce html and quit



104
105
106
107
108
# File 'lib/cgi-spa/cgi-methods.rb', line 104

def $cgi.html! &block
  return if $XHR_JSON or $TEXT
  html(&block)
  Process.exit
end

.jsonObject

produce json



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/cgi-spa/cgi-methods.rb', line 2

def $cgi.json
  return unless $XHR_JSON
  output = yield
rescue Exception => exception
  Kernel.print "Status: 500 Internal Error\r\n"
  output = {
    :exception => exception.inspect,
    :backtrace => exception.backtrace
  }
ensure
  if $XHR_JSON
    Kernel.print "Status: 404 Not Found\r\n" unless output
    $cgi.out? 'type' => 'application/json', 'Cache-Control' => 'no-cache' do
      begin
        JSON.pretty_generate(output)+ "\n"
      rescue
        output.to_json + "\n"
      end
    end
  end
end

.json!(&block) ⇒ Object

produce json and quit



25
26
27
28
29
# File 'lib/cgi-spa/cgi-methods.rb', line 25

def $cgi.json! &block
  return unless $XHR_JSON
  json(&block)
  Process.exit
end

.method_missing(name) ⇒ Object

fast path for accessing CGI parameters



36
37
38
39
40
41
42
43
44
# File 'lib/cgi-spa/environment.rb', line 36

def $param.method_missing(name)
  if has_key? name.to_s
    if self[name.to_s].length == 1
      self[name.to_s].first.extend(CgiSpa::Untaint)
    else
      self[name.to_s].join 
    end
  end
end

.out?(headers, &block) ⇒ Boolean

Conditionally provide output, based on ETAG

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/cgi-spa/cgi-methods.rb', line 69

def $cgi.out?(headers, &block)
  content = block.call
  require 'digest/md5'
  etag = Digest::MD5.hexdigest(content)

  if ENV['HTTP_IF_NONE_MATCH'] == etag.inspect
    Kernel.print "Status: 304 Not Modified\r\n\r\n"
  else
    $cgi.out headers.merge('Etag' => etag.inspect) do
      content
    end
  end
end

.postObject

post specific logic (doesn’t produce output)



111
112
113
# File 'lib/cgi-spa/cgi-methods.rb', line 111

def $cgi.post
  yield if $HTTP_POST
end

.post!(&block) ⇒ Object

post specific content (produces output)



116
117
118
# File 'lib/cgi-spa/cgi-methods.rb', line 116

def $cgi.post! &block
  html!(&block) if $HTTP_POST
end

.script!(text) ⇒ Object

smart script, knows that the content is indented text/data



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/cgi-spa/html-methods.rb', line 15

def $x.script!(text)
  text.slice! /^\n/
  text.slice! /[ ]+\z/
  $x.script :lang => "text/javascript" do
    if $XHTML
      indented_text! text
    else
      indented_data! text
    end
  end
end

.style!(text) ⇒ Object

smart style, knows that the content is indented text/data



2
3
4
5
6
7
8
9
10
11
12
# File 'lib/cgi-spa/html-methods.rb', line 2

def $x.style!(text)
  text.slice! /^\n/
  text.slice! /[ ]+\z/
  $x.style :type => "text/css" do
    if $XHTML
      indented_text! text
    else
      indented_data! text
    end
  end
end

.system!(command, opts = {}) ⇒ Object

execute a system command, echoing stdin, stdout, and stderr



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
# File 'lib/cgi-spa/html-methods.rb', line 28

def $x.system!(command, opts={})
  require 'open3'
  output_class = opts[:class] || {}
  stdin  = output_class[:stdin]  || 'stdin'
  stdout = output_class[:stdout] || 'stdout'
  stderr = output_class[:stderr] || 'stderr'

  $x.pre command, :class=>stdin unless opts[:echo] == false

  require 'thread'
  semaphore = Mutex.new
  Open3.popen3(command) do |pin, pout, perr|
    [
      Thread.new do
        until pout.eof?
          out_line = pout.readline.chomp
          semaphore.synchronize { $x.pre out_line, :class=>stdout }
        end
      end,

      Thread.new do
        until perr.eof?
          err_line = perr.readline.chomp
          semaphore.synchronize { $x.pre err_line, :class=>stderr }
        end
      end,

      Thread.new do
        if opts[:stdin].respond_to? :read
          require 'fileutils'
          FileUtils.copy_stream opts[:stdin], pin
        elsif opts[:stdin]
          pin.write opts[:stdin].to_s
        end
        pin.close
      end
    ].each {|thread| thread.join}
  end
end

.text(&block) ⇒ Object

produce text



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
# File 'lib/cgi-spa/cgi-methods.rb', line 32

def $cgi.text &block
  return unless $TEXT
  @output = []
  def $cgi.puts(line='')
    @output << line + "\n"
  end
  def $cgi.print(line=nil)
    @output << line
  end
  self.instance_eval &block
rescue Exception => exception
  Kernel.print "Status: 500 Internal Error\r\n"
  @output << "\n" unless @output.empty?
  @output << exception.inspect + "\n"
  exception.backtrace.each {|frame| @output << "  #{frame}\n"}
ensure
  class << $cgi
    undef puts
    undef print
  end
  if $TEXT
    Kernel.print "Status: 404 Not Found\r\n" if @output.empty?
    $cgi.out? 'type' => 'text/plain', 'Cache-Control' => 'no-cache' do
      @output.join
    end
    @output = nil
  end
end

.text!(&block) ⇒ Object

produce text and quit



62
63
64
65
66
# File 'lib/cgi-spa/cgi-methods.rb', line 62

def $cgi.text! &block
  return unless $TEXT
  json(&block)
  Process.exit
end

Instance Method Details

#SELF?Boolean

Returns:

  • (Boolean)


57
58
59
60
61
62
63
# File 'lib/cgi-spa/environment.rb', line 57

def SELF?
  if SELF.include? '?'
    SELF
  else
    SELF + "?" # avoids spoiling the cache
  end
end

#submit(cmd = nil) ⇒ Object

run command/block as a background daemon



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
# File 'lib/cgi-spa/job-control.rb', line 2

def submit(cmd=nil)
  fork do
    # detach from tty
    Process.setsid
    fork and exit

    # clear working directory and mask
    Dir.chdir '/'
    File.umask 0000

    # close open files
    STDIN.reopen '/dev/null'
    STDOUT.reopen '/dev/null', 'a'
    STDERR.reopen STDOUT

    # clear environment of cgi cruft
    ENV.keys.to_a.each do |key|
      ENV.delete(key) if key =~ /HTTP/ or $cgi.respond_to? key.downcase
    end

    # setup environment
    ENV['USER'] ||= $USER
    ENV['HOME'] ||= $HOME

    # run cmd and/or block
    system cmd if cmd
    yield if block_given?
  end
end