I am trying to get PUT working with httpi. I am using curb (curl) as my adapter with gss negotiation (I need to use a Kerberos token). I am able to GET the article_to_update and I'm able to POST new articles using almost the exact same code (remove article_to_update from the URL and change put to post). With the code below I'm getting 408 errors: "Server timeout waiting for the HTTP request from the client." I've also tried an empty body and got the same results.
Any ideas on how to get this working or to debug further?
Alternate (non-rails) solutions for kerberos-authenticated GET/PUT/POST implementations are welcomed as well. This is for a REST API but I didn't see if/how the rest-client gem supported kerberos.
require 'curb'
require 'httpi'
require 'json'
HTTPI.adapter = :curb
url = URI.escape('https://myserver.com/rest/article/article_to_update')
request = HTTPI::Request.new(url: url, open_timeout: 30)
request.headers['Content-Type'] = 'application/json'
request.headers['Accept'] = 'application/json'
request.auth.gssnegotiate
request.body = JSON.dump(
name: 'discovery',
owner: 'greg'
)
response = HTTPI.put(request)
Related
I am simply trying to do an HTTP PUT request using a Ruby script, and I am literally copying and pasting 100% of the same thing from Hubspot's example. It's working in Hubspot's example, but not mine.
For example, here's the 99% full code from HubSpot API (with my API key redacted):
# https://rubygems.org/gems/hubspot-api-client
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://api.hubapi.com/crm/v3/objects/deals/4104381XXXX/associations/company/530997XXXX/deal_to_company?hapikey=XXXX")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Put.new(url)
request["accept"] = 'application/json'
response = http.request(request)
puts response.read_body
When initiated by hubspot, the response is an HTTP 201, but in my Ruby script it's giving me the following error:
=> #<Net::HTTPUnsupportedMediaType 415 Unsupported Media Type readbody=true>
I have tried directly copying and pasting the exact same thing, but no luck. I would copy what I'm using, but it's 100% the same code as above except for the redacted API, deal, and company IDs. I have copied and pasted HubSpot's example directly into my rails console, but I get an unsupported media type error.
I have also tried adding a body to the request, such as request.body = "hello" and nothing.
Any suggestion would be greatly appreciated.
After analyzing a working cURL request and the ruby script via BurpSuite, I determined that the following HTTP header in the request was the culprit:
Content-Type: application/x-www-form-urlencoded
For whatever reason, the Ruby code in the original post uses this content-type by default, even though the user doesn't specify it. Makes no sense.
Question
Why, suddenly, do all calls to Firebase Cloud Function webhooks timeout when made via ruby's standard HTTP library (Net::HTTP)?
Background
This works just fine:
require 'net/http'
require 'json'
uri = URI("https://postb.in/1570228026855-4628713761921?hello=world")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req.body = {a: 1}.to_json
http.request(req)
end
However the same script does not work with a Cloud Function URL in place of the postb.in one.
Making the same POST request to the Cloud Function URL via cURL works. It's only when made via ruby Net:HTTP library where it's timing out:
/usr/lib/ruby/2.5.0/net/http.rb:937:in `initialize': execution expired (Net::OpenTimeout)
This function has been called many times per second over the past several months, from a Ruby Net:HTTP Post without issue. And it suddenly stopped working last night. I've tested on multiple servers with ruby versions 2.3.8 and also 2.5.
The Cloud Function code is:
export const testHook = functions.https.onRequest((request, response) => {
console.log(request)
response.status(200).send('works')
})
The answer ended up being to add require 'resolv-replace' to the ruby script making use of Net::HTTP to make the HTTP POST. Found that thanks to: Ruby Net::OpenTimeout: execution expired
Why Net:HTTP is able to resolve postbin URLs but not Firebase ones, and why it was able to resolve Firebase ones successfully for many months until suddenly not, I can't explain.
I'm using the ruby rest-client to send requests to a web service. My requests are working, but I'd like to see the actual request that was sent to the service.
I can't do this with Wireshark or tcpdump because I'm using https and don't have access to the servers private key.
In php, when I've used the SoapClient in the past, I've been able to use the __getLastRequest function to see what xml is sent (http://www.php.net/manual/en/soapclient.getlastrequest.php).
Does anyone know the best way for me to see the actual packets sent to the server?
Many thanks,
D.
You can set the environment variable RESTCLIENT_LOG to stdout, stderr or a file name:
test.rb:
require 'rest-client'
RestClient.get "http://www.google.de"
Call:
RESTCLIENT_LOG=stderr ruby test.rb
Output:
RestClient.get "http://www.google.de", "Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate"
# => 200 OK | text/html 10941 bytes
If you use Net::HTTP instead of rest-client, you can use http.set_debug_output $stderr to see the contents of the request and response:
require 'net/http'
require 'openssl'
uri = URI('https://myserverip/myuri')
http = Net::HTTP.new(uri.host, uri.port)
http.set_debug_output $stderr
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
request.basic_auth 'username', 'password'
response = http.request(request)
#data = response.body
puts response.body
In addition, using Net::HTTP, I can also get it to use a proxy by using something like http = Net::HTTP::Proxy('127.0.0.1','8888').new(uri.host, uri.port).
You can also do the same with rest-client by using RestClient.proxy = "http://127.0.0.1:8888/" just before your RestClient.get(url) etc..
This way I can send the traffic via a tool like Fiddler2 on Windows and then see all the detail I need.
It's just a shame I can't find an equivalent to Fiddler for the Mac since that's where I want to write the code.
It Looks like I'll either have to rewrite my code to use HTTP::Net instead of rest-client, or switch to Windows full time ;), unless anyone has any other thoughts.
I'm trying to do a PUT call on a Google Groups API using Ruby and the OAuth2 GEM. I've managed to authenticate OK, and the GET call works properly, but I can't seem to get the call to use the PUT method. I thought the following would work, since OAuth2 uses Faraday, but I just keep getting the 400 message back, with an indication that something's "required":
data = access_token.put('https://www.googleapis.com/groups/v1/groups/{email address}?alt=json').parsed do |request|
request.params['email'] = "{email address}"
end
Has anyone got a working example of passing parameters to a PUT request?
OK. Looks like the ".parsed" was interfering with the call here's what works, with some additions to the request object:
response = access_token.put('https://www.googleapis.com/groups/v1/groups/{email address}') do |request|
request.headers['Content-Type'] = 'application/json'
request.body='{"email": "{email address}"}'
end
# check this
puts response.status
# works if it's 200
I have obtained a valid api key from Google Places API. I need to use this on the backend, so I get a server-side key. However, the call does not work using curl nor the Rails console.
It DOES, however, work thru the browser. That said, I have triple checked that I am using the server-side key that I generated. I'm also only using the sample URL that is in the Google places documentation, so all params should be correct. Here is my curl:
curl -v https://maps.googleapis.com/maps/api/place/search/xml?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=my_key
Also, in (Ruby) Rails console:
Net::HTTP.get_response(URI.parse("https://maps.googleapis.com/maps/api/place/search/xml?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=my_key"))
Any ideas? It seems like multiple people have had issues, but there is nothing specific out there for server keys not working.
Thanks!
With CURL, be sure to put quotes around the URL. Otherwise, if you're working in Linux, the URL will be truncated after the first ampersand, which will cause a REQUEST_DENIED response.
For HTTPS with Ruby, the following should work (ref http://www.rubyinside.com/nethttp-cheat-sheet-2940.html):
require "net/https"
require "uri"
uri = URI.parse("https://maps.googleapis.com/maps/api/place/search/xml?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=...")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
print response.body