Faraday using `get` for PUT/DELETE requests

(Pure Sin) #1


We have a hosted discuss at http://discuss.codecademy.com. We have a few groups that we add users to based on their status on our site. A few weeks back we noticed users weren’t being added these additional groups.

So I tried using the api to add a test user to a group:

@client = DiscourseApi::Client.new(config['api_url'])
@client.api_key = config['api_key']
@client.api_username =  config['api_username']

@client.user('kelvin14') # => {"id"=>7..... my user
@client.groups # {"id"=>51, "automatic"=>false, "name"=>"test_group", ... the group

@client.group_add(51, {usernames: ['kelvin14']}) 

the returned response is:

#<Faraday::Env @method=:get @body="" @url=#<URI::HTTPS https://discuss.codecademy.com/admin/groups/51/members.json?api_key=....> @request=#<Faraday::RequestOptions (empty)> @request_headers={"Accept"=>"application/json", "User-Agent"=>"DiscourseAPI Ruby Gem 0.10.1", "Content-Type"=>"application/x-www-form-urlencoded"} @ssl=#<Faraday::SSLOptions verify=true> @response=#<Faraday::Response:0x007ff975e667b8 @on_complete_callbacks=[], @env=#<Faraday::Env @method=:get @body="" @url=#<URI::HTTPS https://discuss.codecademy.com/admin/groups/51/members.json?api_key=...... "strict-transport-security"=>"max-age=31415926"} @status=200>

Note the method is :get. Even though in discourse_api’s groups.rb the request is put("/admin/groups/#{group_id}/members.json", users) I see this happening with all requests are using get (deleting groups, etc)

Eventually I tried removing conn.use FaradayMiddleware::FollowRedirects, limit: 5 in client.rb which I see the requests actually using :put but status is 301 instead.

Any idea on why this is happening?


(cpradio) #2

Please delete that API Key from your live/staging site and regen it. Google has likely picked it up by now.

I’ll see if anything else stands out with your api request later tonight/tomorrow

(cpradio) #3

Is this an issue with the API you are using? As the Discourse Web App doesn’t submit a request to /admin/groups/51/members.json, instead it submits the request to /groups/51/members.json

I see the Discourse API repo references /admin/groups/, but that definitely isn’t being used by the Discourse App

From the /groups/special page as a Group Owner/Admin

From the /admin/groups/custom/Special page as an Admin

Both used the following relevant Request Headers

(Pure Sin) #4

Yes I noticed the same thing and took a look at the discourse repo, the /admin/groups are aliased to /groups

In routes.rb line 388

# aliases so old API code works
  delete "admin/groups/:id/members" => "groups#remove_member", constraints: AdminConstraint.new
  put "admin/groups/:id/members" => "groups#add_members", constraints: AdminConstraint.new

And that’s whats on the master branch of discourse_api: discourse_api/groups.rb at ba8a75d088f2b5ca94c31a1daed17fcbf1491e50 · discourse/discourse_api · GitHub

I tried removing the admin and making the call but got InvalidAccess error

(Pure Sin) #5

hi @cpradio any update on this issue? Thanks.

(cpradio) #6

Unfortunately no further progress so far. I can’t find anything indicating an issue and I haven’t had time to try and create an app to add a user to a group.

(Pure Sin) #7

Is it possible for me to get an api for http://try.discourse.org/ to see if I can replicate the issue there?

(Rafael dos Santos Silva) #8

The code below works for me

conn = Faraday.new(:url => 'https://forum.com.br/') do |faraday|
  faraday.request  :url_encoded             # form-encode POST params
  faraday.response :logger                  # log requests to STDOUT
  faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
  faraday.options.params_encoder = Faraday::FlatParamsEncoder

payload = { api_key: 'asdasdasdasdasdasdasdasdasd', api_username: 'qweqweqwe' }

payload[:group_id] = 55

payload['users[]'] = ['asdasdasdasd', 'gfghghf']

conn.put '/admin/groups/bulk', payload

(Pure Sin) #9

@Falco can you try the request again with the following options for faraday (copied from the discourse_api gem)

# Follow redirects
        faraday.use FaradayMiddleware::FollowRedirects, limit: 5 
        # Convert request params to "www-form-encoded"
        faraday.request :url_encoded
        # Parse responses as JSON
        faraday.use FaradayMiddleware::ParseJson, content_type: 'application/json'
        # Use Faraday's default HTTP adapter
        faraday.adapter :net_http

(Jeff Atwood) #10

Did you get this to work, finally?

(Pure Sin) #11

Yes, the cause was our config still used http version of the url instead of the https version. Caused Faraday to only work on Get requests for put/delete/post will get redirected.

(Jeff Atwood) #12