I have a large number of JSON files and would like to automate POSTing them all via my form. I tried via curl:
curl -d "startup[name]='test startup'" -d "startup[url]='http://startup.com'" -d "startup[category]=['','Analytics']" -d "startup[founded(1i)]='2013'" -d "startup[founded(2i)]='5'" -d "startup[founded(3i)]='1'" -d "startup[description]='blah'" http://localhost:5000/startups
But I get an HTML response with a trace that says ActionController::InvalidAuthenticityToken
How can I easily automate my POSTs. If I can do this easier in Ruby I would love to hear how.
You can disable csrf protection on controller-by-controller basis:
skip_before_filter :verify_authenticity_token
Add the above line to StartupsController, now the form will submit
I think you should do a get request to the new action first, say
http://localhost:5000/startups/new
Then parse html to find out the authenticity token, use this as one of the parameters of your POST request
Related
I've written a controller function that runs a curl command to send a message to a 3rd party service. I'd like to test this function to confirm my message was sent. However, when I use Webmock, it does not block the command. What can I do to validate that the message was sent in an rspec test?
I ended up using Typhoeus which allows me to send custom, curl style web requests in ruby. I can also stub calls with it. The rspec test content looks like:
it 'correctly prepares a new Typhoeus request and runs it' do
Typhoeus::Request.should_receive(:new).with(<request>).and_call_original
Typhoeus::Request.any_instance.should_receive(:run).and_call_original
object.method
end
You could either use ruby to make the HTTP call, or you could wrap the curl command in a module on which you could set an expectation:
module Curl
def self.perform(url)
`curl -s "#{url}"`
end
end
Curl.stub(perform: 'http response')
perform_some_action
expect(Curl).to have_received(:perform).with(the_url)
I have created nested form and want to test it from terminal. How can I Make POST request that creates 2 records - one for parent and one for child - at once?
Pry can help. This is not "testing" but more "debugging" in terminal.
gem 'pry'
bundle install
and in the beginning of your action accepting post request, let's say create;
def create
binding.pry
...
end
Browser will not respond but you will get what you want in your terminal.
See this railscast for more info.
HTTP-wise, nested forms are no different than regular forms. Rails uses the naming of the fields to separate parent data from child data. Use your browser's inspector to inspect the HTTP request sent when you fill out the form manually. From there, you can see the name of all the fields used. Then, in terminal, you can typically do something like this:
curl --data "parent[foo]=1&child[bar]=2" http://myapp.dev/parent/create
Just replace the parent[foo] and similar with what you find in the inspector, and it should all work. Tail the dev log if you want to see potential errors in the request.
How about to use rspec testing framework?
If I create a brand new Rails application (using Rails 3.0.9) and knock up a quick bit of scaffolding as follows:
$ rails new testing
$ rails g scaffold thing name:string
Then app/controllers/application_controller.rb contains a "protect_from_forgery" by default, so it should check the authenticity_token during a POST create. At least, that's my understanding.
Why then, does this line successfully create a new Thing, without supplying the token.
$ curl -F "thing[name]=abc123" http://localhost:3000/things
The log entry says:
Started POST "/things" for 127.0.0.1 at 2011-07-05 08:29:18 +0100
Processing by ThingsController#create as
Parameters: {"thing"=>{"name"=>"abc123"}}
AREL (0.3ms) INSERT INTO "things" ("name", "created_at", "updated_at") VALUES ('abc123', '2011-07-05 07:29:18.484457', '2011-07-05 07:29:18.484457')
Redirected to http://localhost:3000/things/18
Completed 302 Found in 89ms
I can also do this to delete records:
$ curl -X DELETE http://localhost:3000/things/18
The same thing happens in production mode. Doesn't this leave my application open to CSRF?
If you pass invalid CSRF token or send request without it, Rails will nullify session, so protect_form_forgery is useless if your application could be accessed by everyone.
But it will save your application from CSRF attack if you have session-based authentication system.
More info: How does Rails CSRF protection work?
I'm trying to simulate a POST to my simple Rails scaffold web service. The files created by the scaffold have not been changed. When I POST data from the website form, a record is created correctly.
When I attempt to POST with curl, a record is created in the database, but it has NULL values in the fields, except for 'updated_at' and 'created_at'. I'm new to command line curl so I may not be doing it correctly.
curl -d "name=Gazoo&friend=Rubble" localhost:3000/flintstones
I get back this from WEBrick:
Started POST "/flintstones" for 127.0.0.1 at Thu Apr 28 18:04:47 -0600 2011 Processing by FlintstonesController#create as Parameters: {"name"=>"Gazoo", "friend"=>"Rubble"} AREL (0.3ms) INSERT INTO "flintstones" ("name", "friend", "created_at", "updated_at") VALUES (NULL, NULL, '2011-04-29 00:04:47.779902', '2011-04-29 00:04:47.779902') Redirected to http://localhost:3000/flintstones/4
After a GET for the json
curl localhost:3000/flintstones.json
I receive:
[{"flintstone:{"name":null,"created_at":"2011-04-29T00:09:58Z","updated_at":"2011-04-29T00:09:58Z","id":4,"friend":null}}]
Why do I get null in my fields?
Thanks in advance.
I've googled a bit and every example of using curl with a rails web service shows the parameters passed in the format
object[paramName]=paramValue
as well as one -d set for each parameter which would make your CURL statement look like
curl -d "flintstone[name]=Gazoo" -d "flintstone[friend]=Rubble" localhost:3000/flintstones
Here are the sources I'm referencing:
How to Use cURL to Test RESTful
Rails
Using cURL to test RESTful
Rails Web Services
Rails (by default) doesn't look for a post body in the way provided, "name=Gazoo&friend=Rubble". It looks for this scheme - given your model is Flintstones and your fields are name and friend - "Flintstone[name]=Gazoo&Flintstone[friend]=Rubble". This is rail's DSL for post body from a form post.
there is a scaffold created Story... and in the create action, there is
#story = Story.new(params[:story])
i was curious as to what is in params... so i want to dump out params... but there is no view associated with the create action... is there a way to dump out its content? is there a way to dump out the POST variables in of my code too? (to see what's going on in the lower level)
The easiest thing to do is just dump params out to the log:
Rails.logger.info("PARAMS: #{params.inspect}")
If you're in development mode, just look in your development.log and that line will be there.
The params scope is a combination of URL/FORM (GET/POST) fields, and it will be printed out in the log as part of the normal output processing, so you might not need your own dumping of it - any development or production log contains the params dump at the top of the log line, e.g.
Processing Clients::ClientsController#show (for x.x.x. at 2009-05-24 00:34:26) [GET]
Parameters: {"id"=>"303", "user_id"=>"2"}
Now I know Rails more, you can also simply use a
p params
in your code and look at the console's output (the log shown on the console)
If you're on a Mac, Spike is a great little app the analyses log files and will let you inspect params for requests, amongst other things.
Using Fiddler on Windows, it is shown
the HTTP line #1 is:
POST /stories HTTP/1.1
this is the POST content:
authenticity_token=62iw%2BrsxlCFsbnxsS7FXKRn6CcvJfjottrsBPlM5lZo%3D&story%5Bname%5D=Google+Main+Site&story%5Blink%5D=www.google.com&commit=Create
listed in a table:
authenticity_token 62iw+rsxlCFsbnxsS7FXKRn6CcvJfjottrsBPlM5lZo=
story[name] Google Main Site
story[link] www.google.com
commit Create
and the server log is:
Parameters: {"commit"=>"Create", "story"=>{"name"=>"Google Main Site", "link"=>"www.google.com"}, "authenticity_token"=>"62iw+rsxlCFsbnxsS7FXKRn6CcvJfjottrsBPlM5lZo="}
You don't need to anything except look in your logs (they live in /log). Unless you're fiddling with something, the logging of parameters is turned on by default in all logs.
Processing PostsController#create (for 127.0.0.1 at 2009-05-24 13:03:24) [POST]
Parameters: {"commit"=>"Create", "authenticity_token"=>"2G6BKOs8xNAaXiToVf4r1ko8QZzP9QAomi2PHVQC5Oc=", "story"=>{"something"=>"asdfafd"}}
Parameters lists all parameters, and the hash following "story" is the equivalent of params[:story] (everything comes to the server as strings, and Rails turns it into a HashWithIndifferentAccess so that you can access it with a symbol).
If you're on a *NIX system (including OS X) open a new terminal window/tab and type the following command:
tail -f log/development.log
You'll get a constant stream of requests coming in -- including params -- and the resulting DB actions. Invaluable for development/debugging, IMO.