Module: Soap4r::Middleware

Includes:
SOAP
Included in:
Base
Defined in:
lib/soap4r-middleware.rb,
lib/soap4r-middleware/version.rb

Defined Under Namespace

Modules: ClassMethods Classes: Base

Constant Summary collapse

VERSION =
"0.8.2"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(klass) ⇒ Object



7
8
9
# File 'lib/soap4r-middleware.rb', line 7

def self.included(klass)
  klass.send(:extend, ::Soap4r::Middleware::ClassMethods)
end

Instance Method Details

#call(env) ⇒ Object



15
16
17
18
19
20
21
22
23
24
# File 'lib/soap4r-middleware.rb', line 15

def call(env)
  if env['PATH_INFO'].match(self.class.endpoint)
    handle(env)
  else
    # we can act as both a middleware and an app
    @app ?
      @app.call(env) :
      ( return 404, { "Content-Type" => "text/plain" }, ["404 - Not Found"] )
  end
end

#handle(env) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/soap4r-middleware.rb', line 26

def handle(env)
  # yeah, all soap calls are over POST
  if env['REQUEST_METHOD'] != 'POST'
    return 405, { 
      'Allow' => 'POST',
      'Content-Type' => 'text/plain' }, ["405 - Method Not Allowed"]
  end

  conn_data = ::SOAP::StreamHandler::ConnectionData.new
  setup_request(conn_data, env)
  conn_data = self.class.router.route(conn_data)
  status, headers, body = setup_response(conn_data, env)
  [ status, headers, body ]
rescue
  raise # TODO -- do we 500 right here, or let the exception bubble up?
end

#initialize(app = nil) ⇒ Object



11
12
13
# File 'lib/soap4r-middleware.rb', line 11

def initialize(app = nil)
  @app = app
end

#parse_soapaction(soapaction) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/soap4r-middleware.rb', line 74

def parse_soapaction(soapaction)
  if !soapaction.nil? and !soapaction.empty?
    if /\A"(.+)"\z/ =~ soapaction
      return $1
    end
  end
  nil
end

#setup_request(conn_data, env) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/soap4r-middleware.rb', line 43

def setup_request(conn_data, env)
  # TODO: we're reading the whole input here, which kind of stinks if rack is
  # reading from the client on demand. We can't just pass in the rack input
  # object, since REXML needs an IO that responds to :eof? -- we'd need a
  # wrapper IO-like object.
  conn_data.receive_string = env['rack.input'].read
  conn_data.receive_contenttype = env['CONTENT_TYPE']
  conn_data.soapaction = parse_soapaction(env['HTTP_SOAPAction'])
end

#setup_response(conn_data, env) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/soap4r-middleware.rb', line 53

def setup_response(conn_data, env)
  status = 200
  headers = {}
  body = []
  headers['content-type'] = conn_data.send_contenttype
  # TODO: cookies?
  if conn_data.is_nocontent
    status = 202 # ACCEPTED
  elsif conn_data.is_fault
    # rather than sending the 500 here, let's bubble up the exception so the
    # parent application can do with it what it will. The only downside is
    # soap4r has already converted the exception into a soap response body at
    # this point, which isn't what we want at all.
    # maybe someday i'll re-parse the response or something. but not today.
    raise conn_data.send_string
  else
    body << conn_data.send_string
  end
  return status, headers, body
end