ruby-on-railssoaprackactivesupportactionpack

wash_out parse failures: SOAP errors instead of HTML errors


So, when you use the wash_out gem in Rails, and a client sends bad XML, the response is like:

<html>…
  <body>
    <h1>REXML::ParseException</h1> 
    …

Instead of a correct SOAP response, like this:

<soap:Body>
  <soap:Fault>
    <faultcode>soap:Client</faultcode>
    …

I first attempted to patch wash_out itself. I managed to reproduce the REXML::ParseException from within its tests, but then found out to my dismay that Rails actually parses (and explodes on) bad XML before wash_out ever touches the params.

So, how should the wash_out gem hook into Rails so that it can rescue those exceptions, only for the routes that it owns?

Here is the backtrace we have to work with. I'm quite sure that there's some point in it that'd be perfect to hook into, but I don't yet know which:

malformed XML: missing tag start
Line: 13
Position: 558
Last 80 unconsumed characters:
<urn:                <Width xsi:type="xsd:int">1</Width>                <Height x
Line: 13
Position: 558
Last 80 unconsumed characters:
<urn:                <Width xsi:type="xsd:int">1</Width>                <Height x):
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/rexml/parsers/treeparser.rb:95:in `rescue in parse'
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/rexml/parsers/treeparser.rb:20:in `parse'
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/rexml/document.rb:231:in `build'
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/rexml/document.rb:43:in `initialize'
  activesupport (3.2.8) lib/active_support/xml_mini/rexml.rb:30:in `new'
  activesupport (3.2.8) lib/active_support/xml_mini/rexml.rb:30:in `parse'
  activesupport (3.2.8) lib/active_support/xml_mini.rb:80:in `parse'
  activesupport (3.2.8) lib/active_support/core_ext/hash/conversions.rb:90:in `from_xml'
  actionpack (3.2.8) lib/action_dispatch/middleware/params_parser.rb:41:in `parse_formatted_parameters'
  actionpack (3.2.8) lib/action_dispatch/middleware/params_parser.rb:17:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/flash.rb:242:in `call'
  rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context'
  rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/cookies.rb:339:in `call'
  activerecord (3.2.8) lib/active_record/query_cache.rb:64:in `call'
  activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:473:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
  activesupport (3.2.8) lib/active_support/callbacks.rb:405:in `_run__937528092__call__217727214__callbacks'
  activesupport (3.2.8) lib/active_support/callbacks.rb:405:in `__run_callback'
  activesupport (3.2.8) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
  activesupport (3.2.8) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.2.8) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/reloader.rb:65:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
  railties (3.2.8) lib/rails/rack/logger.rb:26:in `call_app'
  railties (3.2.8) lib/rails/rack/logger.rb:16:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/request_id.rb:22:in `call'
  rack (1.4.1) lib/rack/methodoverride.rb:21:in `call'
  rack (1.4.1) lib/rack/runtime.rb:17:in `call'
  activesupport (3.2.8) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
  rack (1.4.1) lib/rack/lock.rb:15:in `call'
  actionpack (3.2.8) lib/action_dispatch/middleware/static.rb:62:in `call'
  railties (3.2.8) lib/rails/engine.rb:479:in `call'
  railties (3.2.8) lib/rails/application.rb:223:in `call'
  rack (1.4.1) lib/rack/content_length.rb:14:in `call'
  railties (3.2.8) lib/rails/rack/log_tailer.rb:17:in `call'
  rack (1.4.1) lib/rack/handler/webrick.rb:59:in `service'
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
  /home/rking/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread' 

Thanks! —☈


Solution

  • This works:

    https://github.com/exad/wash_out/commit/7695dcf9214ab3176b6e3c795c1d309571f7854c

    Basically, we created a Rack Middleware layer and inserted that at the right place.