HTTParty authentication problem - ruby

I am trying to log in with HTTParty.
I followed the instruction and still can't get it to work.
require 'rubygems'
require 'httparty'
class LAShowRoom
include HTTParty
base_uri 'www.lashowroom.com'
#debug_output
def initialize email, password
#email = email
response = self.class.get('/login.php')
response = self.class.post(
'/login.php',
:body => { :login_id => email, :login_key => password, :submit_login => 'Log In' },
:headers => {'Cookie' => response.headers['Set-Cookie']}
)
#response = response
#cookie = response.request.options[:headers]['Cookie']
end
def login_response
#response
end
def welcome_page
self.class.get("/announce.php", :headers => {'Cookie' => #cookie})
end
def logged_in?
welcome_page.include? "Kevin"
end
end
la_show_room = LAShowRoom.new('my_email', 'my_password')
puts "Logged in: #{la_show_room.logged_in?}"
As far as I know, HTTParty handles https automatically.
Am I missing something?
Thanks.
Sam

Yes, HTTParty handles HTTPS automatically, but you still need to declare HTTPS. Try
base_uri 'https://…'
How else is HTTParty supposed to know? ;-)

Related

Ruby base_auth with net/http - undefined method `user' for String

I've got pure Ruby app where I want to create request to external API. To do so I'm using standard Ruby Net::HTTP like below:
require 'net/http'
require 'uri'
class Api
BASE_URI = 'https://staging.test.com'
WORKFLOW = 'tests'
QUIZ_PATH = "/v3/accounts/workflows/#{WORKFLOW}/conversations"
def initialize(payload:)
#payload = payload
end
def post_quiz
handle_response(Net::HTTP.post_form("#{BASE_URI}#{QUIZ_PATH}", options))
end
attr_reader :payload
private
def options
{
basic_auth: basic_auth,
body: payload.to_json,
headers: headers
}
end
def basic_auth
{
username: Settings.ln_username,
password: Settings.ln_password
}
end
def headers
{
'User-Agent' => 'Mozilla/5.0',
'Accept-Language' => 'en-US,en;q=0.5',
'Content-Type' => 'application/json'
}
end
def handle_response(response)
return response.body if response.success?
end
end
But instead of response I'm getting an error:
NoMethodError: undefined method `user' for #String:0x00007f80eef9e6f8
Did you mean? super
/Users/usr/.rvm/rubies/ruby-2.7.0/lib/ruby/2.7.0/net/http.rb:527:in `post_form'
I don't have any user there, what is it?
Net::HTTP.post_form is used to send FormData pairs - its not what you want to send JSON and it doesn't even allow you to send headers (You're actually putting them in the request body!).
If you want to send a POST request with HTTP Basic auth and custom headers and JSON body you need to create the request object manually:
require 'net/http'
require 'uri'
class Api
BASE_URI = 'https://staging.test.com'
WORKFLOW = 'tests'
QUIZ_PATH = "/v3/accounts/workflows/#{WORKFLOW}/conversations"
attr_reader :payload
def initialize(payload:)
#payload = payload
end
def post_quiz
url = URI.join(BASE_URI, QUIZ_PATH)
request = Net::HTTP::Post.new(url, headers)
request.basic_auth = Settings.ln_username, Settings.ln_password
request.body = #payload.to_json
# open a connection to the server
response = Net::HTTP.start(url.hostname, url.port, use_ssl: true) do |http|
http.request(request)
end
handle_response(response)
end
private
def headers
{
'User-Agent' => 'Mozilla/5.0',
'Accept-Language' => 'en-US,en;q=0.5',
'Content-Type' => 'application/json'
}
end
# How to respond from an API client is a whole topic in itself but a tuple or hash might
# be a better choice as it lets consumers decide what to do with the response and handle stuff like logging
# errors
def handle_response(response)
# Net::HTTP doesn't have a success? method - you're confusing it with HTTParty
case response
when Net::HTTPSuccess, Net::HTTPCreated
response.body
else
false
end
end
end
Here is the source code that raises the error:
def HTTP.post_form(url, params)
req = Post.new(url)
req.form_data = params
>> req.basic_auth url.user, url.password if url.user
start(url.hostname, url.port,
:use_ssl => url.scheme == 'https' ) {|http|
http.request(req)
}
end
From the docs:
post_form(url, params)
Posts HTML form data to the specified URI object. The form data must be provided as a Hash mapping from String to String.
That means Net::HTTP.post_form(URI("#{BASE_URI}#{QUIZ_PATH}"), options) fixes it. You are currently sending a string as url instead of a URI.

Ruby HTTP sending API key Basic_auth

I have been following a tutorial on GitHub Pages and
I am trying to pass an Apikey to a webservice as basic auth 'apiKey' => 'huda7da97hre3rhr1yrh0130409u1u' for example but I cannot work out how to implement it into the method, or even if that is the proper place for it.
I have a class called connection with my request method in it. I need to post 'apiKey' as header and not in the body. I have read the ruby docs but I cannot work out how to apply it to this specific class.
require "net/http"
require "uri"
require "ostruct"
require "json"
class Connection
ENDPOINT = "http://localhost"
APP_LOCATION = "/task_manager/v1/"
VERB_MAP = {
:get => Net::HTTP::Get,
:post => Net::HTTP::Post,
:put => Net::HTTP::Put,
:delete => Net::HTTP::Delete
}
def initialize(endpoint = ENDPOINT)
uri = URI.parse(endpoint)
#http = Net::HTTP.new(uri.host, uri.port)
end
def get(path, params)
request_json :get, path, params
end
def post(path, params)
request_json :post, APP_LOCATION + path, params
end
def put(path, params)
request_json :put, path, params
end
def delete(path, params)
request_json :delete, path, params
end
private
def request_json(method, path, params)
response = request(method, path, params)
body = JSON.parse(response.body)
OpenStruct.new(:code => response.code, :body => body)
rescue JSON::ParserError
response
end
def request(method, path, params = {})
case method
when :get
full_path = encode_path_params(path, params)
request = VERB_MAP[method.to_sym].new(full_path)
else
request = VERB_MAP[method.to_sym].new(path)
request.set_form_data(params)
end
#http.request(request)
end
def encode_path_params(path, params)
encoded = URI.encode_www_form(params)
[path, encoded].join("?")
end
end
If I post to the server using Advanced Rest Client and put the apikey in the
http://localhost/task_manager/v1/tasks?=
header
Authorization: 9c62acdda8fe12507a435345bb9b2338
and in the body
email=free%40mail.com&password=free&task=test
then I get
{
error: false
message: "Task created successfully"
task_id: 5
}
So how can I post it using this class?.
connection = Connection.new
result = connection.post("task", {'task' => 'task'})
Basic Authentication example:
req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass'
http://docs.ruby-lang.org/en/trunk/Net/HTTP.html#class-Net::HTTP-label-Basic+Authentication
Or if you want to add a raw Authorization header in your request method you can do
request.add_field 'Authorization', 'huda7da97hre3rhr1yrh0130409u1u'
But basic authentication normally means that there is a user name and a password. With your API key - I am not sure you actually need basic authentication. I do not know what you API actually requires but if you have not tried it yet you can try sending the api key as an additional parameter
result = connection.post("register", {'email' => email, 'name' => name, 'password' => password, 'apiKey' => 'huda7da97hre3rhr1yrh0130409u1u' })

Receiving RequestError when using the twilio-ruby gem

I am try to use the twilio-ruby gem, but got a Twilio::REST::RequestError. What does this mean? Here's the code I'm using:
Controller
Class UserController < ApplicationController
def new
#user = User.new
end
def createUser
#user = User.new(user_params)
if #user.save
render text: "Thank you! You will receive sms notification"
account_sid = '*****'
auth_token = '*****'
#client = Twilio::REST::Client.new account_sid, auth_token
##client = Twilio::REST::Client.new account_sid, auth_token
#client = Twilio::REST::Client.new(TWILIO_CONFIG['sid'], TWILIO_CONFIG['token'])
# Create and send an SMS message
#client.account.messages.create
({
:from => '+127*****',
:to => #user.phone,
:body => "Hello"
})
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :phone)
end
end
Why is this generating an error?
A RequestError means that we couldn't send the SMS message. It may mean you don't have international permissions to send to the number in question, or you are trying to use a Caller ID for a phone number that you don't own, or you're trying to send to a landline, or any number of problems.
Here is an example of how to catch a RequestError and view the attached error message.
require 'twilio-ruby'
begin
client = Twilio::REST::Client.new account_sid, auth_token
client.account.sms.messages.create(
from => from_number,
to => to_number,
body => "Hello World"
)
rescue Twilio::REST::RequestError => e
puts e.message
end

400 Bad Request Nestful Ruby

I'm trying to use the Pocket API to authorize my application. So I'm using Nestful to send HTTP requests. And everytime I try sending a request I get a 400 Bad Request. The Pocket documentation says that it could be that it's either a missing consumer key or a missing redirect url.
But now I'm looking at the network tab in Chrome and it says that there is a 500 Internal Service Error. What are these things, and how can I fix them?
My code:
require "nestful"
require "sinatra"
require "uri"
get '/' do
params = {
:consumer_key => '******************************',
:redirect_uri => 'http://localhost:4567/callback'
}
response = Nestful.post 'https://www.getpocket.com/v3/oauth/request',
:params => params,
:format => :json
response.body
response.headers
end
get '/callback' do
"hello world"
end
So I got help on my problem. It turns out that params was already a hash, and so I did not need to say :params => params because that would be redundant.
Before
response = Nestful.post 'https://www.getpocket.com/v3/oauth/request',
:params => params,
:format => :json
After
response = Nestful.post 'https://getpocket.com/v3/oauth/request',
params,
:format => :json

How can I use Digest and Basic authentications with HTTParty in the same class?

I have the following class performing some requests:
the first request uses a digest auth
the second request uses a basic auth
When I run the second request I have the following error:
only one authentication method, :basic_auth or :digest_auth may be used at a time
How can I invalidate the digest_auth prior to running the second request?
class Test
include HTTParty
debug_output $stdout
digest_auth 'login', 'pass'
def first_request(href)
self.class.base_uri "SERVER:PORT"
response = self.class.get(href, {:query => {}})
response
end
def second_request(href)
auth = {:username => "USERNAME", :password => "PASSWORD"}
options = { :body => xml_string, :basic_auth => auth }
response = self.class.post('', options)
response
end
end
When you use basic_auth or digest_auth, HTTParty stores the information internally in the #default_options hash. Here is the source for basic_auth:
# File 'lib/httparty.rb', line 102
def basic_auth(u, p)
default_options[:basic_auth] = {:username => u, :password => p}
end
You can get access to that hash using the default_options method:
# File 'lib/httparty.rb', line 452
def default_options #:nodoc:
#default_options
end
I'd try:
default_options.delete(:basic_auth)
or:
default_options.delete(:digest_auth)
prior to using the other authentication method.
This is untested code but looks 'bout right:
class Test
include HTTParty
debug_output $stdout
def first_request(href)
klass = self.class
klass.base_uri "SERVER:PORT"
klass.default_options.delete(:basic_auth)
klass.digest_auth 'login', 'pass'
klass.get(href, {:query => {}})
end
def second_request(href)
klass = self.class
klass.default_options.delete(:digest_auth)
klass.post(
'',
{
:body => xml_string,
:basic_auth => {
:username => "USERNAME",
:password => "PASSWORD"
}
}
)
end
end

Resources