Class: Stark::Rack

Inherits:
Object
  • Object
show all
Includes:
ContentNegotiation
Defined in:
lib/stark/rack/content_negotiation.rb,
lib/stark/rack/logging_processor.rb,
lib/stark/rack/verbose_protocol.rb,
lib/stark/rack/metadata.rb,
lib/stark/rack/rest.rb,
lib/stark/rack.rb

Defined Under Namespace

Modules: ContentNegotiation, Metadata Classes: LoggingProcessor, REST, VerboseProtocol, VerboseProtocolFactory

Constant Summary collapse

VERSION =
'1.0.3'
FORMAT =
%{when: %0.4f, client: "%s", path: "%s%s", type: "%s", name: "%s", seqid: %d, error: %s\n}
TYPES =
{
  1 => "CALL",
  2 => "REPLY",
  3 => "EXCEPTION",
  4 => "ONEWAY"
}

Constants included from ContentNegotiation

ContentNegotiation::THRIFT_CONTENT_TYPE, ContentNegotiation::THRIFT_JSON_CONTENT_TYPE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ContentNegotiation

#accept_json?, #headers, #protocol_factory

Constructor Details

#initialize(processor, options = {}) ⇒ Rack

Returns a new instance of Rack.



21
22
23
24
25
# File 'lib/stark/rack.rb', line 21

def initialize(processor, options={})
  @log = options[:log]
  @logger = STDERR
  @app_processor = processor
end

Instance Attribute Details

#logObject

Returns the value of attribute log.



27
28
29
# File 'lib/stark/rack.rb', line 27

def log
  @log
end

Instance Method Details

#_call(env) ⇒ Object



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
# File 'lib/stark/rack.rb', line 37

def _call(env)
  path = env['PATH_INFO'] || ""
  path << "/" if path.empty?

  if env["REQUEST_METHOD"] != "POST"
    return [405, {"Content-Type" => "text/plain"},
            ["Method #{env["REQUEST_METHOD"]} not allowed, must be POST\n"]]
  end

  unless path == "/"
    return [404, {"Content-Type" => "text/plain"}, ["Nothing at #{path}\n"]]
  end

  out = StringIO.new

  transport = Thrift::IOStreamTransport.new env['rack.input'], out
  protocol  = protocol_factory(env).get_protocol transport

  if @log
    name, type, seqid, err = processor.process protocol, protocol

    @logger.write FORMAT % [
      Time.now.to_f,
      env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
      env["PATH_INFO"],
      env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
      TYPES[type],
      name,
      seqid,
      err ? "'#{err.message} (#{err.class})'" : "null"
    ]
  else
    processor.process protocol, protocol
  end

  [status_from_last_error(env), headers(env), [out.string]]
end

#call(env) ⇒ Object



33
34
35
# File 'lib/stark/rack.rb', line 33

def call(env)
  dup._call(env)
end

#error_captureObject



75
76
77
78
79
80
81
82
# File 'lib/stark/rack.rb', line 75

def error_capture
  lambda do |m,*args|
    @last_error = [m, args]
  end.tap do |x|
    (class << x; self; end).instance_eval {
      alias_method :method_missing, :call }
  end
end

#processorObject



29
30
31
# File 'lib/stark/rack.rb', line 29

def processor
  @processor ||= LoggingProcessor.new(@app_processor, error_capture)
end

#status_from_last_error(env) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/stark/rack.rb', line 84

def status_from_last_error(env)
  return 200 if @last_error.nil? || @last_error.first == :success
  x = @last_error.last[3]
  env['rack.exception'] = x.cause.nil? ? x : x.cause
  case x.type
  when Thrift::ApplicationException::UNKNOWN_METHOD
    404
  else
    500
  end
end