Skip to content

Conversation

dhh
Copy link
Member

@dhh dhh commented Apr 20, 2015

[Description extracted from http://wyeworks.com/blog/2015/4/20/rails-api-is-going-to-be-included-in-rails-5/]

A decision was made to incorporate Rails API into Rails core 🎉 🎉 🎉.

What Is Rails API?

The original idea behind Rails API was to serve as a starting point for a version of Rails better suited for JS-heavy apps. As of today, Rails API provides: trimmed down controllers and middleware stack together with a matching set of generators, all specifically tailored for API type applications.

Next steps

We still need to discuss the “Rails way” for API applications, how API apps should be built and, what features we’d like included from our original list of ideas. In particular:

  • Do we want to avoid asset generation in Rails by having a back-end and a front-end apps?
  • Do we prefer to have a single application and keep asset generation in Rails instead?
  • Do we like Active Model Serializers better than Jbuilder?
  • If not, can we make Rails API play nicely with Jbuilder?


def one
if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123])
render :text => "Hi!"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use new hash syntax on code we are adding?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please.

On Mon, Apr 20, 2015 at 10:58 PM, Arthur Nogueira Neves <
notifications@github.com> wrote:

In actionpack/test/controller/api/conditional_get_test.rb
#19832 (comment):

@@ -0,0 +1,57 @@
+require 'abstract_unit'
+require 'active_support/core_ext/integer/time'
+require 'active_support/core_ext/numeric/time'
+
+class ConditionalGetApiController < ActionController::API

  • before_action :handle_last_modified_and_etags, :only => :two
  • def one
  • if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123])
  •  render :text => "Hi!"
    

should we use new hash syntax on code we are adding?


Reply to this email directly or view it on GitHub
https://github.com/rails/rails/pull/19832/files#r28728425.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@ZhangHanDong
Copy link

Good job, although I have been using Rails Metal for my Api.

@spastorino
Copy link
Contributor

Hey @dhh, thanks for opening the PR.
We need to discuss a lot of stuff about this, I've written a short blog post that also has links for a previous article I've written in the past http://wyeworks.com/blog/2015/4/20/rails-api-is-going-to-be-included-in-rails-5/

Some of the things that needs discussions are ...

  • Would we like to have a backend app and a frontend app and then avoid assets generation in Rails?
  • Would we prefer to have just one app and keep assets generation in Rails?
  • Would we like to include Active Model Serializers by default or jbuilder?
  • How this will play nicely when used with jbuilder?

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
<%- end -%>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about that advice:

# For APIs, you may want to use :null_session instead.

Don't we want to do that for APIs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null_session should be an explicit choice, I think. If you have a API endpoint that doesn't have any parameters to validate, the null_session will still execute the endpoint. Exception is safer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem to make sense for a controller in an API-only app to have cross-site request forgery protection. Also, from the docs, API controllers do not have session handling:

An API Controller is different from a normal controller in the sense that by default it doesn't include a number of features that are usually required by browser access only: layouts and templates rendering, cookies, sessions, flash, assets, and so on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many APIs would want CSRF protection. This includes single page javascript applications.

null_session isn't the same thing as a browser session, but is instead more like an 'empty' request. It's more like passing a NullObject to a controller instead of raising an exception. The benefit of doing so is that you have more explicit control over the actions regarding that request on a per action basis. With exceptions, you're handling the exception in a more generic location (controller level instead of action level).

Not all of this is 100% verified, just off of my memory. Apologies if I got something wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I misunderstood! Was thinking in the context of a public API. Thanks for correcting me. 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if there's a consensus on this, or what that consensus is if it exists, but I think it still makes sense to use a cookie for authentication when serving an API to a client using AJAX through a browser, because you can use an HttpOnly cookie, which javascript can't access, rather than local storage, which it can. If you're doing that, then CSRF protection is still important.

Having said that, it doesn't look (based on your quote) like API controllers will be using cookie-based sessions by default, so maybe they don't need CSRF protection by default either.

Edit: Wrote this before seeing @hammerdr's comment – I'll leave it here anyway, but it might be irrelevant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't need CSRF protection, we are not adding session stuff on this configuration.
The comment is still valid for regular Rails applications where you can build APIs, for those APIs maybe null_session is a good idea. For Rails API's apis you don't need this kind of stuff.

@rafaelfranca rafaelfranca added this to the 5.0.0 milestone Apr 21, 2015
# end
#
# class PostsController < ApplicationController
# respond_to :json, :xml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature was removed from core.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I maybe I should just remove all that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chancancode
Copy link
Member

@rwz you might have opinions on some of the open questions?

@dhh
Copy link
Member Author

dhh commented Apr 21, 2015

Agree on keeping assets out of the app. Need to take another (long over
due) look at AMS. But regardless of whether we go with AMS or jbuilder as
default, both should be totally equal and trivial to swap between.

On Tue, Apr 21, 2015 at 5:08 PM, Santiago Pastorino <
notifications@github.com> wrote:

BTW, because I left some open questions without answers, my take on those
is ...

Would we like to have a backend app and a frontend app and then avoid
assets generation in Rails?
Yes. So Rails should only generate the API and completely skip assets
generation.

Would we prefer to have just one app and keep assets generation in
Rails?
No.

Would we like to include Active Model Serializers by default or
jbuilder?
AMS.

How this will play nicely when used with jbuilder?
It should work.

But given that the questions could be a bit controversial I left it there
to be able to discuss.


Reply to this email directly or view it on GitHub
#19832 (comment).

internal_asset = Rails.application.config.respond_to?(:assets) &&
path =~ %r{\a#{Rails.application.config.assets.prefix}\z}

internal_controller || internal_asset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original is using the || short-circuit in a much nicer way then here.
You do all the work for internal_asset even though you don't need it.

A nicer solution might be to split it into two private methods and call them with the same short-circuiting logic:

def internal?
  internal_controller? || internal_asset?
end

...

private

def internal_controller?
  controller.to_s =~ %r{\arails/(info|mailers|welcome)}
end

def internal_asset?
  Rails.application.config.respond_to?(:assets) &&
    path =~ %r{\a#{Rails.application.config.assets.prefix}\z}
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed and fixed.

spastorino added a commit that referenced this pull request Jun 11, 2015
@spastorino spastorino merged commit 21f7bcb into rails:master Jun 11, 2015
@bf4
Copy link
Contributor

bf4 commented Jun 11, 2015

@spastorino Awesome! Would you be interested in me writing a PR along the lines of https://groups.google.com/d/topic/rubyonrails-core/K8t4-DZ_DkQ/discussion (as discussed above)?

@joaomdmoura
Copy link

Amazing! Really happy you made it! Let's keep up the good work!

@claudiob
Copy link
Member

👏 👏 👏 👏 👏 👏

@ajoy39
Copy link

ajoy39 commented Jun 12, 2015

Great work! 


Sent from Mailbox

On Thu, Jun 11, 2015 at 4:04 PM, Claudio B. notifications@github.com
wrote:

👏 👏 👏 👏 👏 👏

Reply to this email directly or view it on GitHub:
#19832 (comment)

@dhh
Copy link
Member Author

dhh commented Jun 12, 2015

🤘

@gfvcastro
Copy link

Excellent. 👏 🎉

@vestimir
Copy link

🖖

@robin850
Copy link
Member

(ping #20612)

@yosriady
Copy link

Brilliant! 🎊

@Justin-lu
Copy link

🤘

@spuyet
Copy link
Contributor

spuyet commented Jun 29, 2015

👍

@ai-agent-coder
Copy link

Good job 👍

@Theminijohn
Copy link

👍

@hapiben
Copy link

hapiben commented Jun 30, 2015

Sweet!

@seemsindie
Copy link

Ok, i have to ask, how i can use this now?

@bf4
Copy link
Contributor

bf4 commented Jul 1, 2015

@dhh @spastorino lock comments, please?

@robin850
Copy link
Member

robin850 commented Jul 1, 2015

@seemsindie : You have to use Rails' master ; this is not yet released.

@bf4 : Yes, you're right!

@rails rails locked and limited conversation to collaborators Jul 1, 2015
@rails rails unlocked this conversation Jul 2, 2015
@spastorino
Copy link
Contributor

@rails rails locked and limited conversation to collaborators Jul 2, 2015
require 'test_helper'

<% module_namespacing do -%>
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should replace this with an ActionDispatch::IntegrationTest generator instead. ActionController::TestCase is legacy ware.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 will take a look at it

@rafaelfranca rafaelfranca modified the milestones: 5.0.0 [temp], 5.0.0 Dec 30, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.