Strange Rails behavior with custom mime types - ruby-on-rails

I am using Ruby on Rails 4.1 and I am trying to implement an API with a custom mime type. That is, in config/initializers/mime_types.rb I register an alias as like the following:
Mime::Type.register_alias 'application/json', :my_json
From another system I am trying to access the API with curl by running a HTTP PUT request, this way:
curl http://www.my_api.org/articles.my_json --request PUT --header "Content-Type: application/json" --data-binary '{\"key\": {\"a\": \"1\", \"b\": \"2\"}}'
However, by inspecting the ArticlesController parameters in my Rails application, I get the following output (note: article parameters are "unwanted" and those duplicate the "wanted" key parameters):
Parameters: {"key": { "a"=>"1", "b"=>"2" }, "article": { "a"=>"1", "b"=>"2" }}
What is the problem? Is it a bug? How can I solve that?
Note: I have implemented and access other similar API by executing HTTP GET requests and all works as expected. The problem seems to happens only when I execute HTTP PUT requests.

#rafaelfranca - No it is not a bug. It is how wrap_parameters works. You can disable at this file in your application config/initializers/wrap_parameters.rb.
See github.

Related

HTTP_ORIGIN always returning nil

I'm trying to get the origin of the request cross-site, I found this answer How to get "Origin" request header in Rails which suggest using
request.headers['origin']
I also tried
request.headers['HTTP_ORIGIN']
but both seem to return nil
I'm running this on Rails 6 app
There is nothing wrong with your code.
To get a header in Rails, just access it inside request.headers.
For example, to get User-Agent:
request.headers['User-Agent']
And since rails 5, we have the HTTP_ version also:
request.headers['HTTP_USER_AGENT']
The problem with the Origin header is that it does not always appear in request headers from the browser. It's just needed when the browser sending a cross-origin request.
You can try with some other tools like Postman or curl to see the header is really there:
curl -H "Origin: http://yourserver.com" http://yourserver.com

How to call Twitter's POST /statuses/filter with 5000 user ids?

Both GET and POST methods supported by the endpoint. The POST method is recommended to call endpoint with a huge number of user ids to follow, because the GET method will lead to an oversized URL that the server can't handle. How the "follow" parameter can be passed in the body of the request?
UPD: here is what I've already tried using Insomnia (the URL is always 'https://stream.twitter.com/1.1/statuses/filter.json' and the method is always 'POST' and the server response is always "No filter parameters found. Expect at least one parameter: follow track locations"):
A plain text body with Content-Type: text/html
follow=2731236345
A json body with Content-Type: application/json
{
"follow": "2731236345"
}
Another json body
{
"follow": [
2731236345
]
}
However, when I use form-url-encoded with field "follow" and the value "2731236345" I receive the response "Unauthorized".
First of all, consider looking at the Twitter Developer Labs new endpoint, because this existing API will be retired, likely (but not yet confirmed) in 2020.
When you say "without any success", what libraries are you using, and at what levels of query parameters - you're not being very clear about what is not working here. 5000 user IDs is very large. Can you please be more specific about the errors you're seeing, and the code you're trying to run?
I've managed to connect using curl:
curl --request POST \
--url 'https://stream.twitter.com/1.1/statuses/filter.json' \
--header 'authorization: <censored>' \
--data 'follow=2731236345'
The same request doesn't work in Insomnia for some reason, but it doesn't matter for the goal of this post.

Replicate curl command to access Smartsheet in Rails

I am trying to access Smartsheet through API 2.0 in a Ruby-on-Rails app. I can get he following curl command to work
curl --request GET https://api.smartsheet.om/2.0/sheets -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxx"
All attempts to replicate in Ruby code have failed. Can anyone help convert to Ruby?
Thanks!
You have a handful of options to accomplish that. If you want to keep close to curl as you have proposed, you could capture the response of the curl command wraping it with backticks
response = `curl --request GET https://api.smartsheet.om/2.0/sheets -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxx"`
I'd recommend, however, use something like CURB, which provides Ruby binding for libcurl. It would add some syntax sugar, so your request would look like
response = Curl.get("https://api.smartsheet.om/2.0/sheets") do |http|
http.headers['Authorization'] = 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxx'
end
Yet another option would be ditching curl altogether and use a gem like HTTParty. It makes use of Ruby's net/http to make requests.
That would be something along these lines:
response = HTTParty.get("https://api.smartsheet.om/2.0/sheets",
headers: 'Authorization' => 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxx')

Is this Calendly.com URL Valid?

I am using webhooks for the first time with calendly.com. I would like to create a subscription as described here. When I get to doing this
curl --header "X-TOKEN: <your_token>" --data "url=https://blah.foo/bar&events[]=invitee.created" https://calendly.com/api/v1/hooks
I am concerned that the url is not in a valid format. I tried replacing the & with a ? as in here
curl --header "X-TOKEN: <your_token>" --data "url=https://blah.foo/bar?events[]=invitee.created" https://calendly.com/api/v1/hooks
but I receive this error
{"events":{"events":["can't be blank]}}
Likewise, I try to leave the & and everything after it blank and it give the same error as above.
But using a url with the & and everything in it gives a 404 not found error. Can a url even have the format they are saying is required?
But using a url with the & and everything in it gives a 404 not found error.
The URL part in the following is just the https://blah.foo/bar part before the & character.
curl --header "X-TOKEN: <your_token>" --data "url=https://blah.foo/bar&events[]=invitee.created" https://calendly.com/api/v1/hooks
The events[]=invitee.created part is a separate parameter and value. It’s not part of the url.
See the Create A Webhook Subscription page in the calendy docs:
So the URL is the site that runs your webhook; you don’t send the events parameter/value back to that site—instead you’re sending both the url param and events param to the calendly API endpoint at https://calendly.com/api/v1/hooks. The calendly backend presumably then calls to https://mywebsite.com/webhooks/invitee_created or https://blah.foo/bar whatever url you’ve given it—but without the events parameter, which is for calendly’s internal use.

Grails 3.1.9 : POST not recognized

I'm using Grails 3.1.9 with the rest-api profile.
After creating models and controllers (by grails CLI) and started the application.
I cannot create POST by Postman/Curl etc..
If I try to call the save method directly, eg:
http://localhost:8080/mymodel/create
All works fine. But if I try to call it by POST, the method save() will never be called (index is the default action).
p.s. I have this on my controller:
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
Why this happens?
You should invoke save() method by POST, not create() which is usually used just to show form view of created element. So instead executing
curl -H "Content-Type: application/json" -X POST -d '{"foo":"bar"}' http://localhost:8080/mymodel/create
use:
curl -H "Content-Type: application/json" -X POST -d '{"foo":"bar"}' http://localhost:8080/mymodel/save
Of course if you used url mapping properly instead of http://localhost:8080/mymodel/save you should use simple http://localhost:8080/mymodel
Sure that this is a bug, I open an issue on github. Closed like not a bug.
I forgot to add on UrlMappings.groovy the following line:
"/foos"(resources:"foo")
https://github.com/grails/grails-core/issues/10067

Resources