Get image from url with cookies in ruby - ruby

As you know, some captchas are generating using user session, and i must to somehow save to computer this image, for testing our app, but how, and what better to choise?
For example on http::get i have such code, with cookies:
http = Net::HTTP.new('***', 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
path = '****'
# GET request -> so the host can set his cookies
resp, data = http.get(path)
body_text = resp.body
#puts "Body = #{body_text}"
cookie = resp.response['set-cookie'].split('; ')[0]
#captcha_url = (/BotDetectCaptcha.ashx?get=image&c=***;t=(.*)" \/>/.match body_text)
# POST request -> logging in
puts "captcha_url = #{#captcha_url}"
data = 'BotDetectCaptcha.ashx?get=image&c=****&t=#{#captcha_url}'
headers = {
'Cookie' => cookie,
'Referer' => '****',
'Content-Type' => 'image-jpeg'
}
resp, data = http.post(path, data, headers)
so, perhaps, i have image that i need, but! how can i save it? All google'd articles say me, that i must use open-uri, but how to be, when i have to use session also? Maybe i could do it somehow with http class from ruby?
So how can i download image from loaded page, or via url?

You can get image to variable and save it:
IMG_PATH = '/var/www/pics/'
Class Img
def self.download(data, filename)
open(IMG_PATH + filename, 'wb') do |file|
file << open(data).read
end
return true
end
end
img = Img.download(data, filename)

Related

Got the error File type is not supported when uploading a file in ruby on rails

url = URI("https://api.podium.com/v4/messages/attachment")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "multipart/form-data"
request["Authorization"] = "Bearer #{access_token}"
form_data = [["attachment",File.open('D:\proj\v5\ap\fl\Screenshot (1).png')],['data', "#{request_data}"]]
request.set_form(form_data, 'multipart/form-data')
response = https.request(request)
response_body = JSON.parse(response.body)
if response.code == '200' || response.code == '201'
return response_body,'success'
else
return response_body,"#{response.message}"
end
rescue Exception => ex
return ex,'Exception'
end
**
When i am sending the request i got the error like
{"code"=>"invalid_request_values", "message"=>"File type is not supported.", "moreInfo"=>"https://docs.podium.com/docs/errors#invalid_request_values"}
**
Here are a couple of things you could try:
The podium documentation says that the images cannot be above 5mb in size. You can verify if this is the case.
https://help.podium.com/hc/en-us/articles/360039896873-Sending-Messages#Attach%20media%20to%20a%20message
I noticed the code snippet you've shared does set have this line as mentioned in their documentation here https://docs.podium.com/reference/messagesend_with_attachment
request["accept"] = 'application/json'
Maybe adding this header might fix it for you, as you are saying that it is working for you in Postman but not in Ruby.
Try uploading the file from the API Doc reference page itself and check out the code sample they provide there. There are some differences in the code sample you've shared, and the one that podium shows in their doc.

Why mechanize failed to login website ruby

I'm trying to make an account to website "vpnstaticip.com" using mechanize
but I've always got unknown error that
ERROR: Email is too long
after submiting.
The error never happend in the browser
I've tried to submit without any input and same thing happend
require "mechanize"
$url = "https://vpnstaticip.com/create-account.php?trial=1"
$m = Mechanize.new
$page1 = $m.get($url)
$form1 = $page1.form_with(:id => "pro_form1")
$form1.field_with(:name => "name").value = "name"
$form1.field_with(:name => "email").value = "me#mail.com"
$form1.field_with(:name => "country").options[217].click #United States
$form1.field_with(:name => "username").value = "Username"
$form1.checkbox_with(:name => "terms").check
$page2 = $m.submit($form1)
$file1 = open("vpnstaticip.html","w")
$file1.write($page2.parser)
$file1.close()
Looks like this form submitted by js, but the mechanize is not working with js actually
onclick="document.getElementById('pro_form1').submit();"
perhaps the changed of driver will help (selenium or poltergeist) with the creation of Capybara browser session.
or, as an option, just try to ignore SSL errors:
$m.verify_mode = OpenSSL::SSL::VERIFY_NONE
or i think, match better to use here the net-post request without mechanize, for me it's work fine:
url = URI("https://vpnstaticip.com/create-account.php?trial=1")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request.body = "name=name&email=me%2540mail.com&country=217&username=Username&terms=1&nospam=nospam&submitted=1"
response = http.request(request)
puts response.read_body
=> ERROR: Username already exists. Try different one
besides, i can't reproduce the "Email is too long" error, so please, let me know if the problem is still persist, thanks

net/http PUT with body causes problems

I want to use the Cloudera API from ruby. Therefore I want to
update the configuration of the cloudera manager, which is done
with an HTTP PUT request containing some json data.
The URL is http://localhost:7180/api/v11/cm/config, my first approach was the following code:
require 'net/http'
require 'base64'
port = 7180
host = 'localhost'
req = Net::HTTP::Put.new('/api/v11/cm/config')
req.body = '{"items":[{"name":"TSQUERY_STREAMS_LIMIT","value":1000},{"name":"parcel_proxy_server","value":"proxy"},{"name":"parcel_proxy_port","value":"8080"},{"name":"parcel_update_freq","value":"1"}]}'
req['Content-Type'] = 'application/json'
req['Authorization'] = "Basic #{Base64.encode64('admin:admin')}"
client = Net::HTTP.new(host, port)
resp = client.request(req)
puts resp
puts resp.to_hash
puts resp.body
This variant returns a 400 Bad Request response with the message
"message" : "No content to map due to end-of-input\n at [Source: org.apache.cxf.transport.http.AbstractHTTPDestination$1#4561cbc9; line: 1, column: 1]"
If I want to trace this in wireshark with the setting tcp.port == 7180, this request does somehow not show up.
Then I switched to using Net::HTTP.start with the following source code:
require 'net/http'
require 'base64'
port = 7180
host = 'localhost'
req = Net::HTTP::Put.new('/api/v11/cm/config')
req.body = '{"items":[{"name":"TSQUERY_STREAMS_LIMIT","value":1000},{"name":"parcel_proxy_server","value":"proxy"},{"name":"parcel_proxy_port","value":"8080"},{"name":"parcel_update_freq","value":"1"}]}'
req['Content-Type'] = 'application/json'
req['Authorization'] = "Basic #{Base64.encode64('admin:admin')}"
resp = Net::HTTP.start(host, port) { |client| client.request(req) }
puts resp
puts resp.to_hash
puts resp.body
This thing also returned a bad request, but without any body or else. In contrast to the first approach, this one showed up in wireshark but the body it posted was depicted as with Hypertext-Transfer-Protocol. If I do the same request with cURL, the request body is correctly shown as JavaScript Object Notation.
Does anybody know what the problem of my requests is?
Ok so I tried around for several hours but this behavior is rather strange:
To resolve this I first used Net::HTTP.start instead of Net::HTTP.new. Second and even more important:
I used to do basic authentication by setting the header value manually as you could see in
req['Authorization'] = "Basic #{Base64.encode64('admin:admin')}"
But Net::HTTP::Put already provides a basic_auth method. If this one is not used, strange errors as the ones that I got will occur.
So the working version looks like this:
req = Net::HTTP::Put.new('/api/v11/cm/config')
req.body = '{"items":[{"name":"TSQUERY_STREAMS_LIMIT","value":1000},{"name":"parcel_proxy_server","value":"proxy"},{"name":"parcel_proxy_port","value":"8080"},{"name":"parcel_update_freq","value":"1"}]}'
req['Content-Type'] = 'application/json'
req.basic_auth 'admin', 'admin'
resp = Net::HTTP.start(host, port) { |client| client.request(req) }

Ruby Http Post Parameters

How can I add post parameters to what I have right now:
#toSend = {
"nonce" => Time.now.to_i,
"command" => "returnCompleteBalances"
}.to_json
uri = URI.parse("https://poloniex.com/tradingApi")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
req.set_form_data({"nonce" => Time.now.to_i, "command" => "returnCompleteBalances"})
req['Key'] = '******-N4WZI2OG-******-10RX5JYR'
req['Sign'] = 'secret_key'
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "Response #{res.code} #{res.message}: #{res.body}"
These are the params I want to send:
"nonce" => Time.now.to_i,
"command" => "returnCompleteBalances"
Thank you.
It appears that you're trying to use Poloniex's trading API. If this is your primary goal, you might wish to consider using a library to handle the nitty-gritty details. For example:
https://github.com/Lowest0ne/poloniex
If your primary goal is not simply to use the API, but to use this as a learning experience, here are a few pointers:
The API documentation indicates that the API accepts form-encoded POST data (not JSON) but responds with JSON.
The key parameter ("Key") is like your user id. It allows Poloniex to understand who is attempting to make a request against the API.
The signature parameter ("Sign") is an HMAC generated from the contents of your secret key and the contents of your message (the encoded form data). This produces a sort of fingerprint that only you and Poloniex have the information to reproduce, giving some level of assurance that your request originated from the owner of the secret key. Of course, this assumes that your secret key is indeed only known by you.
I don't use the Poloniex exchange and cannot test this code, but I believe this is close to what you're attempting to accomplish:
require 'net/http'
require 'openssl'
secret = 'your-secret-key'
api_key = 'your-api-key'
uri = URI('https://poloniex.com/tradingApi')
http = Net::HTTP.new(uri.host)
request = Net::HTTP::Post.new(uri.request_uri)
form_data = URI.encode_www_form({:command => 'returnBalances', :nonce => Time.now.to_i * 1000 })
request.body = form_data
request.add_field('Key', api_key)
request.add_field('Sign', OpenSSL::HMAC.hexdigest( 'sha512', secret, form_data))
res = http.request(request)
puts res.body

How to add "Content-type" header in HTTP POST

I keep getting a
400 "Bad Request" (Net::HTTPServerException)
error whenever I try to add a content-type header from various methods.
I've seen several different examples and I can't get any to work. My goal is to add a content type of JSON to my request. Without the header, my request doesn't error:
def post_data(notice)
uri = URI('my uri is here')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new("#{uri.path}?#{uri.query}")
text = notice
req.add_field('Content-Type', 'application/json')
req.body = "{\"sensu_payload\" = #{payload(text).to_json}}"
response = http.request(req)
verify_response(response)
end
I've also tried this method of adding a header:
request = Net::HTTP::Post.new(#path, initheader = {'Content-Type' =>'application/json'})
Use uri.path instead of #path:
request = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
Instead of add_field, I think you should use the hash [] form:
req['Content-Type'] = 'application/json'
See the "Setting Headers" example in the documentation and []=.
Also, using:
"#{uri.path}?#{uri.query}"
is never a good idea. String concatenation can't manage the complexities of correctly encoding illegal values in a query, which can break a request. Consider doing something like this instead:
require 'uri'
require 'uri'
foo = URI('http://www.example.com') # => #<URI::HTTP http://www.example.com>
foo.query = URI::encode_www_form({'bar' => 'path/to/file', 'baz' => 'this & that'})
foo.to_s # => "http://www.example.com?bar=path%2Fto%2Ffile&baz=this+%26+that"
Beyond that, I'd recommend using any of the other HTTP-client gems available. They make it much easier to deal with unexpected situations, like redirects and retries than Net::HTTP. It's more like the building block for features that aren't available other ways.

Resources