Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SavonRB uses dirty http request, leading to incorrect Content-Length header #237

Closed
timcharper opened this issue Nov 1, 2011 · 4 comments
Milestone

Comments

@timcharper
Copy link

Given I execute some code as follows:

    require "savon"

    # create a client for your SOAP service
    client = Savon::Client.new("http://service.example.com?wsdl")

    client.wsdl.soap_actions
    # => [:create_user, :get_user, :get_all_users]

    # execute a SOAP request to call the "getUser" action
    response = client.request(:get_user) do
      soap.body = { :id => 1 }
    end

    # ... do stuff with response...

    # update the user
    response = client.request(:update_user) do
      soap.body = { :id => user.id, :email => "cornholio@email.com", :name => "Alter Ego" }
    end

The second call to client.request ends up using a recycled http object.

It's allocated here:

https://github.com/rubiii/savon/blob/6b6fe262/lib/savon/client.rb#L45

Then used here:

https://github.com/rubiii/savon/blob/6b6fe262/lib/savon/client.rb#L79

Then it's ultimately configured here:

https://github.com/rubiii/savon/blob/6b6fe262/lib/savon/soap/request.rb#L40-43

The problem is with this:

    http.headers["Content-Length"] ||= soap.to_xml.length.to_s

Since the header was sent from the first request (the call to get_user), the call to update_user inherits the content length. Ultimately, this causes the server to receive truncated XML, because the call to update_user in fact has a longer content length, so the server usually returns a 400 (malformed) response.

I'm not sure what the best way to fix this is. As it stands, I see two options:

  1. Change the '||=' default assignment operators to '=' assignment operators here:

https://github.com/rubiii/savon/blob/6b6fe262/lib/savon/soap/request.rb#L40-43

  1. Instantiate a new HTTP object in client.rb with each request. This would mean storing the cookie in another object and setting the cookie each time.

What way do you think is better? I tend to think #2 is better, but #1 is obviously the easiest fix.

@timcharper
Copy link
Author

I am using the latest Savon 1.0.0 from git (as of now, revision 6b6fe26).

@timcharper
Copy link
Author

This workaround takes approach #1 outlined above, and works for the time being:

    require 'savon/soap/request'
    Savon::SOAP::Request.class_eval do
      def configure(http)
        http.url = soap.endpoint
        http.body = soap.to_xml
        http.headers["Content-Type"] = ContentType[soap.version]
        http.headers["Content-Length"] = soap.to_xml.length.to_s

        http
      end
    end

rubiii added a commit that referenced this issue Nov 5, 2011
always set both Content-Type and Content-Length headers.
@rubiii
Copy link
Contributor

rubiii commented Nov 5, 2011

thanks tim!

@rubiii rubiii closed this as completed Nov 5, 2011
@rubiii
Copy link
Contributor

rubiii commented Feb 15, 2012

released with v0.9.8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants