Faraday using `get` for PUT/DELETE requests

Hi,

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?

Thanks

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

4 Likes

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

1 Like

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

hi @cpradio any update on this issue? Thanks.

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.

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

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
end


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

payload[:group_id] = 55

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

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

2 Likes

@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

Did you get this to work, finally?

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.

2 Likes