HTTParty.get is adding parameters multiple times to the URI it sends. Has anyone else come across this before?
def initialize(address)
self.address = address
self.base_uri = 'https://api.randomapi.com/street-address'
end
def get
response = HTTParty.get(base_uri, :query => {
:street => address.street.strip,
})
end
If this I format a request this way:
HTTParty.get(base_uri, :query => {:street=>"random street"})
This is the URI is sends. Note how many times the street param is added.
#<URI::HTTPS:0x007fbc78582d70 URL:https://api.randomapi.com/street-address?street=random%20street&street=random%20street&street=random%20street&street=random%20street>
Turns out it was a bug in the gem(https://github.com/jnunemaker/httparty/issues/185 , https://github.com/jnunemaker/httparty/pull/189). I upgraded to 0.11 and it fixed the duplicate parameters problem.
Related
Context:
I need to send bulk-email using send grid in a rails app.
I will be sending emails to maybe around 300 subscribers.
I have read that it can be accomplished using
headers["X-SMTPAPI"] = { :to => array_of_recipients }.to_json
I have tried following that.
The following is my ActionMailer:
class NewJobMailer < ActionMailer::Base
default from: "from#example.com"
def new_job_post(subscribers)
#greeting = "Hi"
headers['X-SMTPAPI'] = { :to => subscribers.to_a }.to_json
mail(
:to => "this.will#be.ignored.com",
:subject => "New Job Posted!"
)
end
end
I call this mailer method from a controller
..
#subscribers = Subscriber.where(activated: true)
NewJobMailer.new_job_post(#subscribers).deliver
..
The config for send-grid is specified in the config/production.rb file and is correct, since I am able to send out account activation emails.
Problem:
The app works fine without crashing anywhere, but the emails are not being sent out.
I am guessing the headers config is not being passed along ?
How can I correct this ?
UPDATE:
I checked for email activity in the send grid dashboard.
Here is a snapshot of one of the dropped emails:
You are grabbing an array of ActiveRecord objects with
#subscribers = Subscriber.where(activated: true)
and passing that into the smtpapi header. You need to pull out the email addresses of those ActiveRecord objects.
Depending on what you called the email field, this can be done with
headers['X-SMTPAPI'] = { :to => subscribers.map(&:email) }.to_json
this newbie here is smacking his head with webservices over Rails.
Perhaps someone could ease my pain?
I've created a simple rails app, and generated the scaffold MyRecords. Then I'm trying to create a record over irb with the code below :
testWS.rb
require 'HTTParty'
class MyRecordCreate
include HTTParty
base_uri 'localhost:3000'
def initialize(u, p)
#auth = {:username => u, :password => p}
end
def post(text)
options = { :body => { name:text} }
self.class.post('/my_records', options)
end
end
response = HTTParty.get("http://localhost:3000/my_records/new.json")
print response
record = MyRecordCreate.new("","").post("test remote record")
print record
With the code above, I managed to create a record. the thing is that my Record (which only has the column "name") is created with an empty name!
Any suggestions on this one?
I'm longing to slice this despair piece by piece.
Thank you for your contribute.
Try adding these two lines to your HTTParty class:
format :json
headers "Accept" => "application/json"
These tell httparty and the remote service to which it connects to send and receive JSON. For your example (with .json at the end of the URL) it isn't necessary to add the second line, but I find it is good practice and keep it anyway.
The next problem is that Rails expects your uploaded data to be inside the top level name of your object. So, for your example, the options line should look something like:
options = { :body => { :person => { :name => text } } }
Replace person with the name of the model that you are attempting to create.
I'm working with the Buffer App API with HTTParty to try and add posts via the /updates/create method, but the API seems to ignore my "text" parameter and throws up an error. If I do it via cURL on the command line it works perfectly. Here's my code:
class BufferApp
include HTTParty
base_uri 'https://api.bufferapp.com/1'
def initialize(token, id)
#token = token
#id = id
end
def create(text)
BufferApp.post('/updates/create.json', :query => {"text" => text, "profile_ids[]" => #id, "access_token" => #token})
end
end
And I'm running the method like this:
BufferApp.new('{access_token}', '{profile_id}').create('{Text}')
I've added debug_output $stdout to the class and it seems to be posting OK:
POST /1/updates/create.json?text=Hello%20there%20why%20is%20this%20not%20working%3F&profile_ids[]={profile_id}&access_token={access_token} HTTP/1.1\r\nConnection: close\r\nHost: api.bufferapp.com\r\n\r\n"
But I get an error. Am I missing anything?
I reviewed the API, and the updates expect the JSON to be in the POST body, not the query string. Try :body instead of :query:
def create(text)
BufferApp.post('/updates/create.json', :body => {"text" => text, "profile_ids[]" => #id, "access_token" => #token})
end
I would like to connect to an API using Ruby On Rails 2.3.8 and HTTParty gem.
My model is the following:
class Onnion < ActiveRecord::Base
require 'net/http'
include HTTParty
base_uri 'http://myapiurl.com'
digest_auth 'user', 'password'
disable_rails_query_string_format
def self.create_rma(order)
put('/orders/rma', :query => {:action => 'put', :data => {:api_key => 'user', :onnion_order_id => order.id, :customer_rma => order.saving.profile.user.id, :comments => ''}})
end
end
What I would like to do is to call a method of the API called Put, with certain parameters grouped within data parameter.
After executing this method I'm getting a 401 Unauthorized error message.
What am I doing wrong? This is the first time I'm trying to do something like this.
What version of HTTParty are you using, and have you tried using the very latest version from Github? There were some fixes to do with digest auth security a little while ago in version 0.7.3.
If that doesn't work it could be that the server you're attempting to talk to isn't following protocol correctly. I've had this happen before, had to monkey patch HTTParty to get it to login correctly. I'll put the patch I used here in-case it works for you...
module Net
module HTTPHeader
class DigestAuthenticator
# use NC = 1 instead of 0
def authorization_header
#cnonce = md5(random)
header = [%Q(Digest username="#{#username}"),
%Q(realm="#{#response['realm']}"),
%Q(nonce="#{#response['nonce']}"),
%Q(uri="#{#path}"),
%Q(response="#{request_digest}")]
[%Q(cnonce="#{#cnonce}"),
%Q(opaque="#{#response['opaque']}"),
%Q(qop="#{#response['qop']}"),
%Q(nc="1")].each { |field| header << field } if qop_present?
header
end
private
def request_digest
a = [md5(a1), #response['nonce'], md5(a2)]
a.insert(2, "1", #cnonce, #response['qop']) if qop_present?
md5(a.join(":"))
end
end
end
end
module HTTParty
class Request
def setup_digest_auth
# issue a get instead of a head request
res = http.get(uri.request_uri, options[:headers]||{})
if res['www-authenticate'] != nil && res['www-authenticate'].length > 0
#raw_request.digest_auth(username, password, res)
end
end
end
end
The changes made were to send NC 1 and not NC 0, and also to do a GET request, rather than a HEAD request in setup_digest_auth
I'm attempting to add a subscription to Google Reader, using it's API, however I'm getting the following error:
execution expired
I've had no problems reading (using 'get') a list of subscriptions or tags. But it times out when I attempt to add a sub (using 'post')
The code is written in Ruby on Rails and I'm using HTTParty to handle the communication with the web service.
My code is as follows (I'm still new to Ruby/Rails so sorry for any bad practices included below. I'm more than happy to have them pointed out to me):
class ReaderUser
# Include HTTParty - this handles all the GET and POST requests.
include HTTParty
...
def add_feed(feed_url)
# Prepare the query
url = "http://www.google.com/reader/api/0/subscription/quickadd?client=scroll"
query = { :quickadd => feed_url, :ac => 'subscribe', :T => #token }
query_as_string = "quickadd=#{CGI::escape(feed_url)}&ac=subscribe&T=#{CGI::escape(#token.to_s)}"
headers = { "Content-type" => "application/x-www-form-urlencoded; charset=UTF-8", "Content-Length" => query_as_string.length.to_s, "Authorization" => "GoogleLogin auth=#{#auth}" }
# Execute the query
self.class.post(url, :query => query, :headers => headers)
end
...
end
For reference, this is how I'm obtaining the token:
# Obtains a token from reader
# This is required to 'post' items
def get_token
# Populate #auth
get_auth
# Prepare the query
url = 'http://www.google.com/reader/api/0/token'
headers = {"Content-type" => "application/x-www-form-urlencoded", "Authorization" => "GoogleLogin auth=#{#auth}" }
# Execute the query
#token = self.class.get(url, :headers => headers)
end
# Obtains the auth value.
# This is required to obtain the token and for other queries.
def get_auth
# Prepare the query
url = 'https://www.google.com/accounts/ClientLogin'
query = { :service => 'reader', :Email => #username, :Passwd => #password }
# Execute the query
data = self.class.get(url, :query => query)
# Find the string positions of AUTH
auth_index = data.index("Auth=") + 5
# Now extract the values of the auth
#auth = data[auth_index,data.length]
end
I'd be happy to provide any additional information required.
Thanks in advance!
After a great deal of messing around, I've found the solution!
I simply had to set the Content-Length to "0". Previously I was setting it to the length of the 'query' as per the PHP class I was basing it on (greader.class.php). I mention this just in case someone else has the same problem.