my presentation at houston.rb on Grape, the API builder for rack based systems using a friendly ruby/sinatra like interface. It makes separating out your API from you web app logic really easy.
“Lagom”
• Swedish for “just the right amount”
• “Small things, loosely joined, written fast”
- Justin Gehtland
“Lagom”
• Swedish for “just the right amount”
• “Small things, loosely joined, written fast”
- Justin Gehtland
• Separation of concerns
“Lagom”
• Swedish for “just the right amount”
• “Small things, loosely joined, written fast”
- Justin Gehtland
• Separation of concerns
• Testability, Scalability
Prefixing
require 'grape'
module TestApp
class Bar < Grape::API
prefix "api"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
end
Prefixing
require 'grape'
module TestApp
class Bar < Grape::API
prefix "api"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
end
>GET /api/widgets/1
Prefixing
require 'grape'
module TestApp
class Bar < Grape::API
prefix "api"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
end
>GET /api/widgets/1
{“name”:”widget1”}
Prefixing
require 'grape'
module TestApp
class Bar < Grape::API
prefix "api"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
end
>GET /api/widgets >GET /api/widgets/1
{“name”:”widget1”}
Prefixing
require 'grape'
module TestApp
class Bar < Grape::API
prefix "api"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
end
>GET /api/widgets >GET /api/widgets/1
[{“name”:”widget1”}] {“name”:”widget1”}
Versioning
require 'grape'
module TestApp
class Bar < Grape::API
resource, namespace,
prefix “api” group all synonyms here
version "v2"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
Versioning
require 'grape'
module TestApp
class Bar < Grape::API
resource, namespace,
prefix “api” group all synonyms here
version "v2"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
>GET /api/v2/widgets
Versioning
require 'grape'
module TestApp
class Bar < Grape::API
resource, namespace,
prefix “api” group all synonyms here
version "v2"
resource "widgets" do
get do
Widget.all
end
get ":id" do
Widget.find(params[:id])
end
end
end
>GET /api/v2/widgets
[{“name”:”widget1”}]
Basic Authentication
require 'grape'
module TestApp
class Bar < Grape::API
prefix “api”
version "v2"
resource "widgets" do
get do
Widget.all
end
end
namespace :admin do
http_basic do |u,p|
u == 'admin' && p == YOURPASSWORD
end
namespace 'metrics' do get do
{:clicks => Click.count} end
end
end
end
end
OAuth soon...
Basic Authentication
require 'grape'
module TestApp
class Bar < Grape::API
prefix “api”
version "v2"
resource "widgets" do
get do
Widget.all
end
end
namespace :admin do
http_basic do |u,p|
u == 'admin' && p == YOURPASSWORD
end
namespace 'metrics' do get do
{:clicks => Click.count} end
end
end
end
end
OAuth soon...
admin:<password>
Basic Authentication
require 'grape'
module TestApp
class Bar < Grape::API
prefix “api”
version "v2"
resource "widgets" do
get do
Widget.all
end
end
namespace :admin do
http_basic do |u,p|
u == 'admin' && p == YOURPASSWORD
end
namespace 'metrics' do get do
{:clicks => Click.count} end
end
end
end
end
OAuth soon...
admin:<password>
>GET /api/v2/admin
Basic Authentication
require 'grape'
module TestApp
class Bar < Grape::API
prefix “api”
version "v2"
resource "widgets" do
get do
Widget.all
end
end
namespace :admin do
http_basic do |u,p|
u == 'admin' && p == YOURPASSWORD
end
namespace 'metrics' do get do
{:clicks => Click.count} end
end
end
end
end
OAuth soon...
admin:<password>
>GET /api/v2/admin
{“clicks”:1234}
Basic Authentication
require 'grape'
module TestApp
class Bar < Grape::API
prefix “api”
version "v2"
resource "widgets" do
get do
Widget.all
end
end
namespace :admin do
http_basic do |u,p|
u == 'admin' && p == YOURPASSWORD
end
namespace 'metrics' do get do
{:clicks => Click.count} end
end
end
end
end
OAuth soon...
admin:<password>
>GET /api/v2/admin
>GET /api/v2/admin
{“clicks”:1234}
Basic Authentication
require 'grape'
module TestApp
class Bar < Grape::API
prefix “api”
version "v2"
resource "widgets" do
get do
Widget.all
end
end
namespace :admin do
http_basic do |u,p|
u == 'admin' && p == YOURPASSWORD
end
namespace 'metrics' do get do
{:clicks => Click.count} end
end
end
end
end
OAuth soon...
admin:<password>
>GET /api/v2/admin
>GET /api/v2/admin
401 Unauthorized
{“clicks”:1234}
Status/Error Codes
class MyAPI < Grape::API
helpers do
def current_user
@current_user ||= User.find_by_single_use_token(params[:auth_token])
end
end
get '/self' do
error!("401 Unauthorized", 401) unless current_user
current_user
end
end
Status/Error Codes
class MyAPI < Grape::API
helpers do
def current_user
@current_user ||= User.find_by_single_use_token(params[:auth_token])
end
end
get '/self' do
error!("401 Unauthorized", 401) unless current_user
current_user
end
end
>GET /self?auth_token=BAD
Status/Error Codes
class MyAPI < Grape::API
helpers do
def current_user
@current_user ||= User.find_by_single_use_token(params[:auth_token])
end
end
get '/self' do
error!("401 Unauthorized", 401) unless current_user
current_user
end
end
>GET /self?auth_token=BAD
401 Unauthorized