How to perform a savon client.call use a GET request with a payload instead of a POST? - ruby

I'm using savonrb (2.1.2) to perform my SOAP requests against a Web Service.
The problem I came into is that it looks like I do not have any chance to perform an HTTP GET request instead of a POST request using this library.
Please, note that even though I can agree with the fact that a SOAP over HTTP done through a GET method, instead that through a POST, might look unconventional or even an error, but
I cannot modify the server side, and, as client, I MUST accept this behavior as a matter of fact.
How can I overcome this problem?
Standing to what I've seen so far inside the code of savon, it looks like it is an immutable design decision:
# operation.rb
module Savon
class Operation
...
def call_with_logging(request)
#logger.log(request) { HTTPI.post(request, #globals[:adapter]) }
end
...
end
end
I just wonder if there should be a trick, through the mechanism of the savon adapters, to avoid this kind of (bad) solution.

Related

What HTTP Protocol can I use if I need to GET something from the server but I also need to send a requestbody?

I am using SpringBoot...
I can not use GET protocol and include a body, but I am not going to create or update anything on the server so I do not want to use POST or PUT, any other protocol that acts like a GET with body?
if you wonder what I need to send in that body it is an url parameter, like for example http://somewebsite.com/stuff/etc and I feel that putting this inside a request body is better than putting it as a requestparam
I can not use GET protocol and include a body, but I am not going to create or update anything on the server so I do not want to use POST or PUT, any other protocol that acts like a GET with body?
Your best bet, where suitable, would be to mimic how HTML forms work; which is to say having a family of resources with identifiers that are filled in by the client (in general, via URI templates -- often via query parameters as would happen with an HTML form).
When that's not appropriate: as of 2022-11, your best bet is POST. It's not a great answer (in particular, general purpose HTTP components won't know that the semantics of the request are safe), but it is the best option available of the registered methods.
POST serves many useful purposes in HTTP, including the general purpose of "
"this action isn’t worth standardizing." -- Roy Fielding, 2009
Eventually, the HTTPbis-wg will finalize the safe-method-with-a-body proposal, and at that point that will become a much better option than POST (for the cases that match the new semantics).

Google Api Ruby Client to return the actual HTTP response, not the helper object

Is there an easy way to ask the google api ruby client to just give you back the stock HTTP response, rather than to perform the lovely, but slightly limiting translation into one of their ruby representable objects?
e.g.
response = Gmail.client.get_user_message("me", id)
=> #<Google::Apis::GmailV1::Message
response = Gmail.client.list_user_messages("me")
=> #<Google::Apis::GmailV1::ListMessagesResponse
but
response = Gmail.client.delete_user_message("me", id)
=>nil #successfully deleted
Now that's all fine and dandy, except that sometimes I just want to know what sort of response is going to come back. i.e. an HTTP response with maybe some JSON in the body. And then I'll worry about what I do with it...
I can take the response and use the
response.to_json
to get the body of the json that would have come back (though I still won't have the response code, and I need to KNOW that it's one of those objects first).
The client library is definitely getting that, it's just converting it into these objects before it lets me see it. And if I don't know that it's a google object (and not nil) I can't run that to_json consistently....
Any ideas other than second guess what google is going to send me back?
(I should note that this has come about when trying to move a library from dealing with their 0.8 api to their 0.9 api, so call me a cynic if you must but my faith that google won't make breaking changes to those objects returned is at a low ebb...
As far as I know, it is possible to ask the server to send only the fields you really need and get a partial response instead of the default full response as mentioned in Performance Tips.
However, I suggest that you please check the documentation for the specific API you are using to see if the field you're looking for is currently supported. For the Gmail API, you may go through Working with partial resources.
Here are the two types of partial requests that you can use:
Partial response: A request where you specify which fields to include in the response (use the fields request parameter).
Patch: An update request where you send only the fields you want to change (use the PATCH HTTP verb).
Hope that helps!

Ruby Sinatra: Can I update a view template multiple times within one client request

I want to do this:
get '/test' do
#dog = 'WOOF'
erb :test
sleep(1)
#dog = 'BOWWOW'
erb :test
sleep(1)
#dog = 'ARF'
erb :test
end
Is it possible to do something like this where the client sees each update or no, I've tried but can't get it to work.
In short: no.
I think you're confusing the way HTTP works. First, HTTP is stateless. This means that multiple requests know nothing about each other (this is mitigated by the use of sessions via cookies, or possibly HTTP basic auth).
Further, you cannot resend the HTTP body like you're doing. Once it's sent there's no going back. Techniques like long-polling delay sending the body so they can send it whenever they like, but once they send something the request is complete and a new one must be started. Thus, once you've rendered the body once via erb, you're request is finished.
What it seems like you're trying to achieve can only be done via Javascript with AJAX, or with completely separate full-page requests.

How do I parse a POST to my Rails 3.1 server manually?

Scenario:
I have a Board model in my Rails server side, and an Android device is trying to post some content to a specific board via a POST. Finally, the server needs to send back a response to the Android device.
How do I parse the POST manually (or do I need to)? I am not sure how to handle this kind of external request. I looked into Metal, Middleware, HttpParty; but none of them seems to fit what I am trying to do. The reason I want to parse it manually is because some of the information I want will not be part of the parameters.
Does anyone know a way to approach this problem?
I am also thinking about using SSL later on, how might this affect the problem?
Thank you in advance!! :)
I was trying to make a cross-domain request from ie9 to my rails app, and I needed to parse the body of a POST manually because ie9's XDR object restricts the contentType that we can send to text/plain, rather than application/x-www-urlencoded (see this post). Originally I had just been using the params hash provided by the controller, but once I restricted the contentType and dataType in my ajax request, that hash no longer contained the right information.
Following the URL in the comment above (link), I learned the how to recover that information. The author mentions that in a rails controller we always have access to a request variable that gives us an instance of the ActionDispatch::Request object. I tried to use request.query_string to get at the request body, but that just returned an empty string. A bit of snooping in the API, though, uncovered the raw_post method. That method returned exactly what I needed!
To "parse it manually" you could iterate over the string returned by request.raw_post and do whatever you want, but I don't recommend it. I used Rack::Utils.parse_nested_query, as suggested in Arthur Gunn's answer to this question, to parse the raw_post into a hash. Once it is in hash form, you can shove whatever else you need in there, and then merge it with the params hash. Doing this meant I didn't have to change much else in my controller!
params.merge!(Rack::Utils.parse_nested_query(request.raw_post))
Hope that helps someone!
Not sure exactly what you mean by "manually", posts are normally handled by the "create" or "update" methods in the controller. Check out the controller for your Board model, and you can add code to the appropriate method. You can access the params with the params hash.
You should be more specific about what you are trying to do. :)

In Savon with wsse authentication, my nonce token gets reused on subsequent requests

Perhaps I'm just not writing idiomatic code for savon, so please feel free to straighten me out, but I was trying to make multiple requests on the same client, as demonstrated in
client=Savon::Client.new {
wsdl.document=wsdl_path
}
r1=client.request(:company_get_report_suites) do
wsse.credentials APP_CONFIG['omniture']['username'],APP_CONFIG['omniture']['shared_secret'],:digest
end
r2=client.request(:scheduling_get_reports_run_history) do
wsse.credentials APP_CONFIG['omniture']['username'],APP_CONFIG['omniture']['shared_secret'],:digest
end
The second request ends up reusing the nonce. The point of the wsse nonce is to use it only once, so the service I'm calling complains that I've reused it and refuses to service the request. My first thought was to add a timestamp, but that didn't help; in fact, the source code shows the nonce is used if set, and generated only if not previously set.
Obviously, if I must, I can create a new client, but that's a rather heavy-weight operation and seems unlikely to be the normal way to create multiple requests off of the same client.
Is there a sensible workaround?
This makes me feel dirty, but if no one can suggest a better alternative, this does the trick:
class Savon::WSSE
def reset_nonce
#nonce=nil
#nonce=nonce
end
end
r1=client.request(:company_get_report_suites) do
wsse.reset_nonce
end

Resources