27
RESTful APIs w/ Grape Tuesday, November 8 th 2011 Daniel Doubrovkine / Art.sy [email protected] @dblockdotorg

Building RESTful APIs w/ Grape

Embed Size (px)

DESCRIPTION

NYC.rb talk on building

Citation preview

Page 1: Building RESTful APIs w/ Grape

RESTful APIs w/ GrapeTuesday, November 8th 2011

Daniel Doubrovkine / [email protected] @dblockdotorg

Page 2: Building RESTful APIs w/ Grape

Solid API or Else …

http://www.youtube.com/watch?v=l9vYE7B1_PU

Page 3: Building RESTful APIs w/ Grape

The Rails Way: M(V)C

config/routes.rb

resources :artists

app/controllers/artists_controller.rb

class ArtistsController < ApplicationController   def index @artists = … # all kinds of stuff that serves views respond_to do |format| format.html { @artists } format.json { render json: @artists.as_json } end end End

Page 4: Building RESTful APIs w/ Grape

The Rails Way: MVC

app/views/artists/index.json.erb

[email protected] do |artist| {    'first_name': '<%= @artist.first_name.to_json %>',    'last_name': '<%= @artist.last_name.to_json %>' }

Page 5: Building RESTful APIs w/ Grape

» Where does the API start and end?

» How are we going to build API v2 on top of v1?

» Is API testing the same as controller testing?

» How much discipline are we going to need to keep sanity?

» How will deal with more difficult problems?Caching, authentication, authorization …

Occupy Rails?

Page 6: Building RESTful APIs w/ Grape

Modern Web Applications: NoRails

» MVC UI

» RESTful API

» Storage

Page 7: Building RESTful APIs w/ Grape

» API DSLrack-based / middlewarehttp://github.com/intridea/grape

Grape

class API < Grape::API version ‘1'

namespace :artist get “:id” do Artist.find(params[:id]).as_json end end

namespace :artists do get “/” do Artist.all.as_json end endend

Page 8: Building RESTful APIs w/ Grape

Documentation

» Developers Have the Attention Span of a Fish ** when reading documentation

» Written in Markdownhttp://code.dblock.org/rendering-markdown-documents-in-rails

» Reference will be Generated

» API Sandboxeshttps://github.com/mmcnierney14/API-Sandbox

» API Explorerhttps://github.com/mmcnierney14/API-Sandbox

Page 9: Building RESTful APIs w/ Grape

# spec/spec_helper.rb

RSpec.configure do |config|

config.include RSpec::Rails::RequestExampleGroup, :type => :request, :example_group => {

:file_path => /spec\/api/ }

end

Testing an API

See “Writing Tests” @ https://github.com/intridea/grape

Page 10: Building RESTful APIs w/ Grape

describe "artworks" do

before(:each) do

login_as Fabricate(:admin)

end

describe "GET /api/v1/artwork/:slug" do

it "returns an unpublished artwork" do

artwork = Fabricate(:artwork, published: false)

get "/api/v1/artwork/#{artwork.slug}"

response.status.should == 200

response.body.at_json_path(“id”).should == artwork.slug # Pathy!

end

end

end

end

Mocking is for Java Programmers

Page 11: Building RESTful APIs w/ Grape

Version 1 Births Version 2

» Include Api_v1» Folder-Driven Development (FDD)

api/api_v1/…

module Api_v1 version 'v1‘ module Api_v1_Me

module Api_v1_Artworks # ...end

module Api_v2 version 'v2‘ module Api_v1_Me

module Api_v2_Artworks # ...end

See “Modularizing Grape API” @ http://code.dblock.org/modularizing-a-ror-grape-api-multiple-versions

Page 12: Building RESTful APIs w/ Grape

Exceptions Abort Flow

» Don’t question yourself, raise a hand.

rescue_from :all, :backtrace => true

error_format :json

rescue_from Mongoid::Errors::Validations do |e| rack_response({ :message => e.message, :detail => e.document.errors, :backtrace => e.backtrace }.to_json) end end

See “Grape: trapping all exceptions within the API” @ http://code.dblock.org/grape-trapping-all-exceptions-within-the-api

Page 13: Building RESTful APIs w/ Grape

Authentication Methods

» XApp: Exchange client ID for an XApp tokenapi/v1/api_xapp_auth.rb

» OAuth 2.0: Browser-Based Redirectscontrollers/oauth_controller.rb

» XAuth: Exchange credentials for an OAuth tokencontrollers/oauth_controller.rb

» Forms Login to Websitedevise/warden via user.rb

See “Grape: API Authentication w/ Devise” @ http://code.dblock.org/grape-api-authentication-w-devise

Page 14: Building RESTful APIs w/ Grape

Authenticated Users

» Unauthenticated Calls

» Authorized Apps

» Logged In Users, RBAC

def authenticated_user authenticated error!('Unauthorized', 401) unless current_user end

Page 15: Building RESTful APIs w/ Grape

Object Identity

» Everything has an ID

» Internal ID: BSON ObjectId

» External ID: humanly-readable ID

» ID is the same for all API consumers

» API consumers know of a single ID

» When do I use a Slug?

» When do I use BSON ObjectId?

Page 16: Building RESTful APIs w/ Grape

JSON Formats

» ActiveRecord as_json passes options recursively

:all – all fields visible to the object’s owner

:public – all fields visible to a user with :read permissions

:short – enough fields visible to a user with :read permissions, used within a collection

» JSON data can be grown incrementally

Page 17: Building RESTful APIs w/ Grape

POST and PUT

» Validate Input Parameters in Models

save(hashie)

valid_hash_fields :first, :last

Page 18: Building RESTful APIs w/ Grape

Authorization

» Admins have :create, :read, :update, :delete on everything, also known as :manage

» Partners have :manage on their partner dataeg. partner location, get :all JSON

» Users have :manage on their personal dataeg. my collection, get :all JSON

» Everyone has :read on public dataeg. a published artwork, get :public JSON

Page 19: Building RESTful APIs w/ Grape

Authorization Usage

cannot :read, Artworkcan :read, Artwork do |artwork| artwork.publishedend

error!(‘Unauthorized', 403) unless current_user.has_authorization_to?(:delete, artist)

» Implemented w/ CanCan

Page 20: Building RESTful APIs w/ Grape

Pagination

» paginate(collection)» :offset or :page» :size

Pagination Helper for Grape @ https://gist.github.com/1335242

Page 21: Building RESTful APIs w/ Grape

Logging

» Implemented as Rack Middleware

» Logs API Calls

Page 22: Building RESTful APIs w/ Grape

Caching

» Implemented w/Rails Cache / Memcached

» Key based on Class and Identity

» Cache Locally

» Invalidate Aggressively

Page 23: Building RESTful APIs w/ Grape

Cache Busting

» IE9

See “IE9: Cache-Busting with Grape Middleware” @ http://code.dblock.org/ie9-cache-busting-with-grape-middleware

Page 24: Building RESTful APIs w/ Grape

Instrumentation

» See API Stats in New Relicconfig/initializers/new_relic_agent_instrumentation_api.rb

See “New Relic: Performance Instrumentaiton w/ Grape” @ http://code.dblock.org/new-relic-performance-instrumentation-with-grape-api

Page 25: Building RESTful APIs w/ Grape

Performance

» Trends

Page 26: Building RESTful APIs w/ Grape

Next

» Deep Data

» Caching in JSON

» Generated Documentation

Page 27: Building RESTful APIs w/ Grape

Thank you.

How to design a good API and why it matters (Joshua Bloch)http://www.youtube.com/watch?v=aAb7hSCtvGw

1. Do one thing well

2. API is a Language, names matter

3. Documentation matters

4. Minimize mutability

5. Don’t make the client do anything the API could do