SlideShare a Scribd company logo
BUILDINg BETTER
WITH railS
Devils Tower, WY
web APIS
@caikeCarlos Souza
Code School
codeschool.com
tryruby.org
railsforzombies.org
Building Better Web APIs with Rails
perfect
rails web app
Deadline
Budget
Features
Tests
“We need a snappier
experience”
“We’ve detected the majority
of our visitors come from
mobile devices. 



We need to launch a native app

as soon as possible!”
“Does our web app
expose an API ?”
• Routes
• CONNEG
• AUTH
• VERSION
• Tests
endpoints, resources and
url-to-controller mappings
ROUTES
URLs are very important
/gists
/gists/public
/gists/starred
Building Better Web APIs with Rails
resources :projects
GET

POST

PATCH (PUT) 

DELETE
!
!
...
Projects#index
Projects#create
Projects#show
Projects#update
Projects#destroy
...
paths methods actions
/projects
/projects/:id
resources :projects
paths
/projects/archived

/projects/:id/archive

/projects
/projects/:id
?????
resources :projects
end
end
end
member do	
post 'archive'


collection do	
get 'archived'
do


!
get 'active'	
get 'suspended'	
!
!
!
post 'activate'	
post 'suspend'	
!
!
resources :projects
end
end
end
do
member do	
post 'archive'


collection do	
get 'archived'
post 'create_review'


!
get 'active'	
get 'suspended'	
!
!
!
post 'activate'	
post 'suspend'	
!
!
resources :projects
end
end
end
do
member do	
post 'archive'


collection do	
get 'archived', to: 'archived_projects#index'
, to: 'active_projects#index'
, to: 'suspended_projects#index'
, to: 'archived_projects#create'
, to: 'active_projects#create'
, to: 'suspended_projects#create'
post 'create_review'


!
get 'active'	
get 'suspended'	
!
!
!
post 'activate'	
post 'suspend'	
!
!
resources :projects
end
end
end
do
member do	
post 'archive'


collection do	
get 'archived'
resources :reviews, only: :create
, to: 'archived_projects#index'
, to: 'active_projects#index'
, to: 'suspended_projects#index'
, to: 'archived_projects#create'
, to: 'active_projects#create'
, to: 'suspended_projects#create'
app/controllers/api/projects_controller.rb
module Api	
class ProjectsController < ApplicationController	
def index	
...	
end	
end	
end
ActiveSupport::Inflector.inflections(:en) do |inflect|	
inflect.acronym 'API'	
end
config/initializers/inflections.rb
module API	
class ProjectsController < ApplicationController	
def index	
...	
end	
end	
end
connegcontent negotiation
Client A
API
I’m a Rich Java$cript Application 

and I want JSON!
Hey, I’m an Enterprise Java Application
and I want XML! (Ha Ha, Business!)
¯_(ツ)_/¯
Oi, soy un browser e quiero HTML!
response in JSON
respuesta en HTML
response in XML
Client B
Client C
content negotiation
The process in which client and server
determine the best representation for a response

when many are available.
/projects.json
GET /projects

Accept: application/json
vs.
Rails nicety
Part of the HTTP spec
client requests
responders
extracted out to 

responders gem
in Rails 4.2
module API	
class ProjectsController < ApplicationController	
respond_to :json, :xml	
!
def index	
@projects = Project.all	
!
respond_with(@projects)	
end	
end	
end
calls #to_json
calls #to_xml
respond_to
module API	
class ProjectsController < ApplicationController	
def index	
@projects = Project.recent	
!
respond_to do |format|	
format.json { render json: @projects, status: 200 }	
format.xml { render xml: @projects, status: 200 }	
end	
end	
end	
end
JBuilder
json.content format_content(@message.content)	
json.(@message, :created_at, :updated_at)	
!
json.author do	
json.name @message.creator.name.familiar	
json.url url_for(@message.creator, format: :json)	
end
https://github.com/rails/jbuilder
class ProjectSerializer < ActiveModel::Serializer	
attributes :id, :title, :amount	
!
embed :ids, include: true	
has_many :products	
end
defaults to JSON-API
https://github.com/rails-api/active_model_serializers
ActiveModel::Serializers
module SongsRepresenter	
include Roar::JSON::JsonApi	
name :songs	
!
property :id	
property :title	
end
class SongRepresenter < Roar::Decorator	
include Roar::JSON::JsonApi	
name :songs	
!
property :id	
property :title	
end
https://github.com/apotonick/roar
using Mixins using Decorators
Roar
AUTHenticationpreventing unauthorized access
to protected resources
• Quick and Simple
• Reutilizes existing credentials
• HTTP spec (RFC 2617)
http basic AUTH
http basic AUTH
module API	
class ProjectsController < ApplicationController	
before_action :authenticate_or_request	
!
protected	
!
def authenticate_or_request	
authenticate_or_request_with_http_basic do |user, pwd|	
User.authenticate(user, pwd)	
end	
end	
end	
end
use the -u option
$ curl -I http://carlos:secret@localhost:3000/projects	
!
HTTP/1.1 200 OK	
Content-Type: application/json; charset=utf-8
$ curl -Iu 'carlos:secret' http://localhost:3000/projects	
!
HTTP/1.1 200 OK	
Content-Type: application/json; charset=utf-8
http basic AUTH with curl
• Can easily expire or regenerate tokens.
• Any vulnerability is limited to API access.
• Multiple tokens for each user.
• Different access rules can be implemented.
API
Projects
Forum
Admin
Client A
token based auth
token for the Backpack API
providing the token
Typically available out-of-band
on a user settings page
token for the Digital Ocean API
For security purposes, 

some services will only display
the access token once.
providing the token
token based auth
module API	
class ProjectsController < ApplicationController	
before_action :authenticate_or_request	
!
protected	
!
def authenticate_or_request	
authenticate_or_request_with_http_token do |token, opt|	
User.find_by(auth_token: token)	
end	
end	
end	
end
UUID - Universally Unique Identifier
GENERATING TOKENS
RFC 4122
We can use the Ruby standard library
SecureRandom.uuid
f4ea855f-d303-43e6-bee3-94581c0ecb21
90ab3255-ce33-4022-8349-b7979655b07c
371c760d-2539-41b9-b665-98c255d4c323
...
GENERATING TOKENS
end
def generate_auth_token
.gsub(/-/,'')
end
omits the hyphensSecureRandom.uuid
class User < ActiveRecord::Base	
before_create :set_auth_token	
!
private	
!
def set_auth_token	
return if auth_token.present?

self.auth_token = generate_auth_token	
end	
!
a47a8e54b11c4de5a4a351734c80a14a
9fa8a147b10c4efca3e8592b3a1c2729
823c1c984d504f66a2e6cbb2eb69e842
...
GENERATING TOKENS
$ curl -IH "Authorization: Token token=16d7d6089b8fe0c5e19bfe10bb156832" 	
http://localhost:3000/episodes	
!
HTTP/1.1 200 OK	
Content-Type: application/json; charset=utf-8
use the -H option
token based auth com curl
versioning resources
Version
MAJOR

incompatible changes


MINOR

backwards-compatible changes


PATCH

backwards-compatible bug fixes
http://semver.org/Semantic versioning
Works great for software libraries
V1/V1
feature X, feature Y
/V2
feature X, feature Y,
feature Z
Compatible changes:
• addition of a new format (i.e. JSON, XML )
• addition of a new property on a resource
• renaming of an end-point (use 3xx status code!)
• Only use major version.
• Changes cannot break existing clients.
• No need to bump version on compatible changes.
versioning services
410 Gone
https://www.mnot.net/blog/2012/12/04/api-evolution
“The biggest way to avoid new 

major versions is to make as many 

of your changes backwards-compatible 

as possible”
TESTSautomated verification
API
Unit Tests
testing apis
Not the time nor place to test business logic
API
• Status Code
• Mime Types
• Authentication
WHAT SHOULD WE TEST ?
API
HOW SHOULD WE TEST ?
Requesting endpoints and verifying responses
$ rails g integration_test <doing-something>
testing status code
require 'test_helper'	
!
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	
!
test 'returns list of projects' do	
get '/projects'	
assert_equal 200, response.status	
refute_empty response.body	
end	
end
testing status code
require 'test_helper'	
!
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	
!
test 'returns list of projects' do	
get '/projects'	
assert_equal 200, response.status	
refute_empty response.body	
end	
end
testing mime types
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	


test 'returns projects in JSON' do	
get '/projects', {}, { 'Accept' => Mime::JSON }	
assert_equal Mime::JSON, response.content_type	
end	
test 'returns projects in XML' do	
get '/projects', {}, { 'Accept' => Mime::XML }	
assert_equal Mime::XML, response.content_type	
end	
end
testing mime types
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	


test 'returns projects in JSON' do	
get '/projects', {}, { 'Accept' => Mime::JSON }	
assert_equal Mime::JSON, response.content_type	
end	
test 'returns projects in XML' do	
get '/projects', {}, { 'Accept' => Mime::XML }	
assert_equal Mime::XML, response.content_type	
end	
end
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { @user = User.create! }	
setup { host! 'api.example.com' }	
!
test 'valid authentication with token' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"}	
assert_equal 200, response.status	
assert_equal Mime::JSON, response.content_type	
end	
!
test 'invalid authentication' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" }	
assert_equal 401, response.status	
end	
end
testing access rules
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { @user = User.create! }	
setup { host! 'api.example.com' }	
!
test 'valid authentication with token' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"}	
assert_equal 200, response.status	
assert_equal Mime::JSON, response.content_type	
end	
!
test 'invalid authentication' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" }	
assert_equal 401, response.status	
end	
end
testing access rules
railsapis.codeschool.com
Thank you
BUILDINg BETTER
WITH railS@caikeCarlos Souza
Code School
web APIS
Devils Tower, WY
Ad

Recommended

PPTX
Ruby On Grape
Andrii Furmanets
 
PPTX
Building RESTful APIs w/ Grape
Daniel Doubrovkine
 
PDF
Get cfml Into the Box 2018
Ortus Solutions, Corp
 
PDF
Effectively Testing Services - Burlington Ruby Conf
neal_kemp
 
PDF
Do you want a SDK with that API? (Nordic APIS April 2014)
Nordic APIs
 
PDF
Serverless in production, an experience report (linuxing in london)
Yan Cui
 
PPTX
RESTful API Design Best Practices Using ASP.NET Web API
💻 Spencer Schneidenbach
 
PDF
Serverless in Production, an experience report (cloudXchange)
Yan Cui
 
PDF
Behavior Driven Development with Cucumber
Brandon Keepers
 
PPTX
The REST And Then Some
Nordic APIs
 
PDF
Introduction to plugin development
Caldera Labs
 
PDF
Scaling your Android App With Modularization
Ben Schwab
 
PPTX
Test automation with Cucumber-JVM
Alan Parkinson
 
PDF
Finding Restfulness - Madrid.rb April 2014
samlown
 
PPTX
django Forms in a Web API World
Tareque Hossain
 
PPTX
REST API Best Practices & Implementing in Codeigniter
Sachin G Kulkarni
 
PDF
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
崇之 清水
 
PDF
Enter the app era with ruby on rails
Matteo Collina
 
PDF
Rails 4.0
Robert Gogolok
 
PDF
Refactoring @ Mindvalley: Smells, Techniques and Patterns
Tristan Gomez
 
PPTX
Calabash for iPhone apps
Chathura palihakkara
 
KEY
Motion Django Meetup
Mike Malone
 
PDF
Observability and Troubleshooting in Forge
Atlassian
 
PPTX
Workshop Laravel 5.2
Wahyu Rismawan
 
PDF
Building Beautiful REST APIs with ASP.NET Core
Stormpath
 
PDF
Browser-level testing
Martin Kleppmann
 
PDF
Serverless observability - a hero's perspective
Yan Cui
 
PDF
REST full API Design
Christian Guenther
 
PPT
Scalability for Startups (Frank Mashraqi, Startonomics SF 2008)
Dealmaker Media
 
PPTX
A Local SEO Case Study
Will Fleiss
 

More Related Content

What's hot (20)

PDF
Behavior Driven Development with Cucumber
Brandon Keepers
 
PPTX
The REST And Then Some
Nordic APIs
 
PDF
Introduction to plugin development
Caldera Labs
 
PDF
Scaling your Android App With Modularization
Ben Schwab
 
PPTX
Test automation with Cucumber-JVM
Alan Parkinson
 
PDF
Finding Restfulness - Madrid.rb April 2014
samlown
 
PPTX
django Forms in a Web API World
Tareque Hossain
 
PPTX
REST API Best Practices & Implementing in Codeigniter
Sachin G Kulkarni
 
PDF
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
崇之 清水
 
PDF
Enter the app era with ruby on rails
Matteo Collina
 
PDF
Rails 4.0
Robert Gogolok
 
PDF
Refactoring @ Mindvalley: Smells, Techniques and Patterns
Tristan Gomez
 
PPTX
Calabash for iPhone apps
Chathura palihakkara
 
KEY
Motion Django Meetup
Mike Malone
 
PDF
Observability and Troubleshooting in Forge
Atlassian
 
PPTX
Workshop Laravel 5.2
Wahyu Rismawan
 
PDF
Building Beautiful REST APIs with ASP.NET Core
Stormpath
 
PDF
Browser-level testing
Martin Kleppmann
 
PDF
Serverless observability - a hero's perspective
Yan Cui
 
PDF
REST full API Design
Christian Guenther
 
Behavior Driven Development with Cucumber
Brandon Keepers
 
The REST And Then Some
Nordic APIs
 
Introduction to plugin development
Caldera Labs
 
Scaling your Android App With Modularization
Ben Schwab
 
Test automation with Cucumber-JVM
Alan Parkinson
 
Finding Restfulness - Madrid.rb April 2014
samlown
 
django Forms in a Web API World
Tareque Hossain
 
REST API Best Practices & Implementing in Codeigniter
Sachin G Kulkarni
 
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
崇之 清水
 
Enter the app era with ruby on rails
Matteo Collina
 
Rails 4.0
Robert Gogolok
 
Refactoring @ Mindvalley: Smells, Techniques and Patterns
Tristan Gomez
 
Calabash for iPhone apps
Chathura palihakkara
 
Motion Django Meetup
Mike Malone
 
Observability and Troubleshooting in Forge
Atlassian
 
Workshop Laravel 5.2
Wahyu Rismawan
 
Building Beautiful REST APIs with ASP.NET Core
Stormpath
 
Browser-level testing
Martin Kleppmann
 
Serverless observability - a hero's perspective
Yan Cui
 
REST full API Design
Christian Guenther
 

Viewers also liked (20)

PPT
Scalability for Startups (Frank Mashraqi, Startonomics SF 2008)
Dealmaker Media
 
PPTX
A Local SEO Case Study
Will Fleiss
 
PDF
Building an API in Rails without Realizing It
Mark
 
PDF
SEO Case Study: Self Storage Industry
farhan "Frank"​ mashraqi
 
PDF
What Academia Can Learn from Open Source
All Things Open
 
PDF
Open Source Systems Administration
All Things Open
 
PDF
What Does Big Data Really Mean for Your Business?
All Things Open
 
PDF
The PHP Renaissance
All Things Open
 
PDF
Lessons Learned with Distributed Systems at Bitly
All Things Open
 
PPTX
Considerations for Operating an OpenStack Cloud
All Things Open
 
PPTX
All Things Open Opening Keynote
All Things Open
 
PDF
Building the iRODS Consortium
All Things Open
 
PDF
The Gurubox Project: Open Source Troubleshooting Tools
All Things Open
 
PDF
Open Source in Healthcare
All Things Open
 
PDF
Open Source & The Internet of Things
All Things Open
 
PDF
The Ember.js Framework - Everything You Need To Know
All Things Open
 
PDF
Stop Worrying & Love the SQL - A Case Study
All Things Open
 
PDF
Trademarks and Your Free and Open Source Software Project
All Things Open
 
PPTX
I Know It Was MEAN, But I Cut the Cord to LAMP Anyway
All Things Open
 
Scalability for Startups (Frank Mashraqi, Startonomics SF 2008)
Dealmaker Media
 
A Local SEO Case Study
Will Fleiss
 
Building an API in Rails without Realizing It
Mark
 
SEO Case Study: Self Storage Industry
farhan "Frank"​ mashraqi
 
What Academia Can Learn from Open Source
All Things Open
 
Open Source Systems Administration
All Things Open
 
What Does Big Data Really Mean for Your Business?
All Things Open
 
The PHP Renaissance
All Things Open
 
Lessons Learned with Distributed Systems at Bitly
All Things Open
 
Considerations for Operating an OpenStack Cloud
All Things Open
 
All Things Open Opening Keynote
All Things Open
 
Building the iRODS Consortium
All Things Open
 
The Gurubox Project: Open Source Troubleshooting Tools
All Things Open
 
Open Source in Healthcare
All Things Open
 
Open Source & The Internet of Things
All Things Open
 
The Ember.js Framework - Everything You Need To Know
All Things Open
 
Stop Worrying & Love the SQL - A Case Study
All Things Open
 
Trademarks and Your Free and Open Source Software Project
All Things Open
 
I Know It Was MEAN, But I Cut the Cord to LAMP Anyway
All Things Open
 
Ad

Similar to Building Better Web APIs with Rails (20)

PDF
Building Mobile Friendly APIs in Rails
Jim Jeffers
 
PPTX
Women Who Code - RSpec JSON API Workshop
Eddie Lau
 
KEY
Rails web api 开发
shaokun
 
PDF
Api FUNdamentals #MHA2017
JoEllen Carter
 
PDF
Security Goodness with Ruby on Rails
Source Conference
 
PDF
Intro to Rack
Rubyc Slides
 
PDF
Design Web Api
Tailor Fontela
 
PPT
Rails 101
The Active Network
 
PDF
Example Mobile Push Notification Service in Rails
Mo Omer
 
PDF
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
Mike Desjardins
 
PDF
Api Testing.pdf
JitendraYadav351971
 
PDF
API testing Notes and features, difference.pdf
kunjukunjuzz904
 
PDF
Using Sinatra to Build REST APIs in Ruby
LaunchAny
 
PDF
APIs for mobile
Andrei Navarro
 
PDF
Api fundamentals
AgileDenver
 
PPT
Rails Rookies Bootcamp - Blogger
Nathanial McConnell
 
PDF
Rack
shen liu
 
PDF
Basic Rails Training
Arthit Hongchintakul
 
PDF
Rails - getting started
True North
 
KEY
Wider than rails
Alexey Nayden
 
Building Mobile Friendly APIs in Rails
Jim Jeffers
 
Women Who Code - RSpec JSON API Workshop
Eddie Lau
 
Rails web api 开发
shaokun
 
Api FUNdamentals #MHA2017
JoEllen Carter
 
Security Goodness with Ruby on Rails
Source Conference
 
Intro to Rack
Rubyc Slides
 
Design Web Api
Tailor Fontela
 
Example Mobile Push Notification Service in Rails
Mo Omer
 
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
Mike Desjardins
 
Api Testing.pdf
JitendraYadav351971
 
API testing Notes and features, difference.pdf
kunjukunjuzz904
 
Using Sinatra to Build REST APIs in Ruby
LaunchAny
 
APIs for mobile
Andrei Navarro
 
Api fundamentals
AgileDenver
 
Rails Rookies Bootcamp - Blogger
Nathanial McConnell
 
Rack
shen liu
 
Basic Rails Training
Arthit Hongchintakul
 
Rails - getting started
True North
 
Wider than rails
Alexey Nayden
 
Ad

More from All Things Open (20)

PDF
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
All Things Open
 
PPTX
Big Data on a Small Budget: Scalable Data Visualization for the Rest of Us - ...
All Things Open
 
PDF
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
All Things Open
 
PDF
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
All Things Open
 
PDF
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
All Things Open
 
PDF
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
All Things Open
 
PDF
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
All Things Open
 
PPTX
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
All Things Open
 
PDF
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
All Things Open
 
PDF
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
All Things Open
 
PPTX
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
All Things Open
 
PDF
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
All Things Open
 
PPTX
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
All Things Open
 
PDF
The Death of the Browser - Rachel-Lee Nabors, AgentQL
All Things Open
 
PDF
Making Operating System updates fast, easy, and safe
All Things Open
 
PDF
Reshaping the landscape of belonging to transform community
All Things Open
 
PDF
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
All Things Open
 
PDF
Integrating Diversity, Equity, and Inclusion into Product Design
All Things Open
 
PDF
The Open Source Ecosystem for eBPF in Kubernetes
All Things Open
 
PDF
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
All Things Open
 
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
All Things Open
 
Big Data on a Small Budget: Scalable Data Visualization for the Rest of Us - ...
All Things Open
 
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
All Things Open
 
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
All Things Open
 
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
All Things Open
 
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
All Things Open
 
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
All Things Open
 
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
All Things Open
 
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
All Things Open
 
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
All Things Open
 
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
All Things Open
 
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
All Things Open
 
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
All Things Open
 
The Death of the Browser - Rachel-Lee Nabors, AgentQL
All Things Open
 
Making Operating System updates fast, easy, and safe
All Things Open
 
Reshaping the landscape of belonging to transform community
All Things Open
 
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
All Things Open
 
Integrating Diversity, Equity, and Inclusion into Product Design
All Things Open
 
The Open Source Ecosystem for eBPF in Kubernetes
All Things Open
 
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
All Things Open
 

Recently uploaded (20)

PDF
Tech-ASan: Two-stage check for Address Sanitizer - Yixuan Cao.pdf
caoyixuan2019
 
PDF
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
PDF
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
PDF
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
PPTX
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
PDF
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
DOCX
Daily Lesson Log MATATAG ICT TEchnology 8
LOIDAALMAZAN3
 
PDF
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
Edge AI and Vision Alliance
 
PDF
2025_06_18 - OpenMetadata Community Meeting.pdf
OpenMetadata
 
PDF
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
PDF
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
PPTX
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
Fwdays
 
PDF
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
PDF
Lessons Learned from Developing Secure AI Workflows.pdf
Priyanka Aash
 
PDF
The Growing Value and Application of FME & GenAI
Safe Software
 
PDF
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
yosra Saidani
 
PDF
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
PDF
Securing AI - There Is No Try, Only Do!.pdf
Priyanka Aash
 
PDF
From Manual to Auto Searching- FME in the Driver's Seat
Safe Software
 
PDF
A Constitutional Quagmire - Ethical Minefields of AI, Cyber, and Privacy.pdf
Priyanka Aash
 
Tech-ASan: Two-stage check for Address Sanitizer - Yixuan Cao.pdf
caoyixuan2019
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
Daily Lesson Log MATATAG ICT TEchnology 8
LOIDAALMAZAN3
 
“MPU+: A Transformative Solution for Next-Gen AI at the Edge,” a Presentation...
Edge AI and Vision Alliance
 
2025_06_18 - OpenMetadata Community Meeting.pdf
OpenMetadata
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
Fwdays
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
Lessons Learned from Developing Secure AI Workflows.pdf
Priyanka Aash
 
The Growing Value and Application of FME & GenAI
Safe Software
 
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
yosra Saidani
 
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
Securing AI - There Is No Try, Only Do!.pdf
Priyanka Aash
 
From Manual to Auto Searching- FME in the Driver's Seat
Safe Software
 
A Constitutional Quagmire - Ethical Minefields of AI, Cyber, and Privacy.pdf
Priyanka Aash
 

Building Better Web APIs with Rails

  • 1. BUILDINg BETTER WITH railS Devils Tower, WY web APIS @caikeCarlos Souza Code School
  • 7. “We need a snappier experience”
  • 8. “We’ve detected the majority of our visitors come from mobile devices. 
 
 We need to launch a native app
 as soon as possible!”
  • 9. “Does our web app expose an API ?”
  • 10. • Routes • CONNEG • AUTH • VERSION • Tests
  • 12. URLs are very important /gists /gists/public /gists/starred
  • 14. resources :projects GET
 POST
 PATCH (PUT) 
 DELETE ! ! ... Projects#index Projects#create Projects#show Projects#update Projects#destroy ... paths methods actions /projects /projects/:id
  • 16. resources :projects end end end member do post 'archive' 
 collection do get 'archived' do
  • 17. 
 ! get 'active' get 'suspended' ! ! ! post 'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' 
 collection do get 'archived' post 'create_review'
  • 18. 
 ! get 'active' get 'suspended' ! ! ! post 'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' 
 collection do get 'archived', to: 'archived_projects#index' , to: 'active_projects#index' , to: 'suspended_projects#index' , to: 'archived_projects#create' , to: 'active_projects#create' , to: 'suspended_projects#create' post 'create_review'
  • 19. 
 ! get 'active' get 'suspended' ! ! ! post 'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' 
 collection do get 'archived' resources :reviews, only: :create , to: 'archived_projects#index' , to: 'active_projects#index' , to: 'suspended_projects#index' , to: 'archived_projects#create' , to: 'active_projects#create' , to: 'suspended_projects#create'
  • 20. app/controllers/api/projects_controller.rb module Api class ProjectsController < ApplicationController def index ... end end end
  • 21. ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'API' end config/initializers/inflections.rb module API class ProjectsController < ApplicationController def index ... end end end
  • 23. Client A API I’m a Rich Java$cript Application 
 and I want JSON! Hey, I’m an Enterprise Java Application and I want XML! (Ha Ha, Business!) ¯_(ツ)_/¯ Oi, soy un browser e quiero HTML! response in JSON respuesta en HTML response in XML Client B Client C content negotiation The process in which client and server determine the best representation for a response
 when many are available.
  • 24. /projects.json GET /projects
 Accept: application/json vs. Rails nicety Part of the HTTP spec client requests
  • 25. responders extracted out to 
 responders gem in Rails 4.2 module API class ProjectsController < ApplicationController respond_to :json, :xml ! def index @projects = Project.all ! respond_with(@projects) end end end
  • 26. calls #to_json calls #to_xml respond_to module API class ProjectsController < ApplicationController def index @projects = Project.recent ! respond_to do |format| format.json { render json: @projects, status: 200 } format.xml { render xml: @projects, status: 200 } end end end end
  • 27. JBuilder json.content format_content(@message.content) json.(@message, :created_at, :updated_at) ! json.author do json.name @message.creator.name.familiar json.url url_for(@message.creator, format: :json) end https://github.com/rails/jbuilder
  • 28. class ProjectSerializer < ActiveModel::Serializer attributes :id, :title, :amount ! embed :ids, include: true has_many :products end defaults to JSON-API https://github.com/rails-api/active_model_serializers ActiveModel::Serializers
  • 29. module SongsRepresenter include Roar::JSON::JsonApi name :songs ! property :id property :title end class SongRepresenter < Roar::Decorator include Roar::JSON::JsonApi name :songs ! property :id property :title end https://github.com/apotonick/roar using Mixins using Decorators Roar
  • 31. • Quick and Simple • Reutilizes existing credentials • HTTP spec (RFC 2617) http basic AUTH
  • 32. http basic AUTH module API class ProjectsController < ApplicationController before_action :authenticate_or_request ! protected ! def authenticate_or_request authenticate_or_request_with_http_basic do |user, pwd| User.authenticate(user, pwd) end end end end
  • 33. use the -u option $ curl -I http://carlos:secret@localhost:3000/projects ! HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 $ curl -Iu 'carlos:secret' http://localhost:3000/projects ! HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 http basic AUTH with curl
  • 34. • Can easily expire or regenerate tokens. • Any vulnerability is limited to API access. • Multiple tokens for each user. • Different access rules can be implemented. API Projects Forum Admin Client A token based auth
  • 35. token for the Backpack API providing the token Typically available out-of-band on a user settings page
  • 36. token for the Digital Ocean API For security purposes, 
 some services will only display the access token once. providing the token
  • 37. token based auth module API class ProjectsController < ApplicationController before_action :authenticate_or_request ! protected ! def authenticate_or_request authenticate_or_request_with_http_token do |token, opt| User.find_by(auth_token: token) end end end end
  • 38. UUID - Universally Unique Identifier GENERATING TOKENS RFC 4122
  • 39. We can use the Ruby standard library SecureRandom.uuid f4ea855f-d303-43e6-bee3-94581c0ecb21 90ab3255-ce33-4022-8349-b7979655b07c 371c760d-2539-41b9-b665-98c255d4c323 ... GENERATING TOKENS
  • 40. end def generate_auth_token .gsub(/-/,'') end omits the hyphensSecureRandom.uuid class User < ActiveRecord::Base before_create :set_auth_token ! private ! def set_auth_token return if auth_token.present?
 self.auth_token = generate_auth_token end ! a47a8e54b11c4de5a4a351734c80a14a 9fa8a147b10c4efca3e8592b3a1c2729 823c1c984d504f66a2e6cbb2eb69e842 ... GENERATING TOKENS
  • 41. $ curl -IH "Authorization: Token token=16d7d6089b8fe0c5e19bfe10bb156832" http://localhost:3000/episodes ! HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 use the -H option token based auth com curl
  • 43. MAJOR
 incompatible changes 
 MINOR
 backwards-compatible changes 
 PATCH
 backwards-compatible bug fixes http://semver.org/Semantic versioning Works great for software libraries
  • 44. V1/V1 feature X, feature Y /V2 feature X, feature Y, feature Z Compatible changes: • addition of a new format (i.e. JSON, XML ) • addition of a new property on a resource • renaming of an end-point (use 3xx status code!) • Only use major version. • Changes cannot break existing clients. • No need to bump version on compatible changes. versioning services
  • 46. https://www.mnot.net/blog/2012/12/04/api-evolution “The biggest way to avoid new 
 major versions is to make as many 
 of your changes backwards-compatible 
 as possible”
  • 48. API Unit Tests testing apis Not the time nor place to test business logic
  • 49. API • Status Code • Mime Types • Authentication WHAT SHOULD WE TEST ?
  • 50. API HOW SHOULD WE TEST ? Requesting endpoints and verifying responses $ rails g integration_test <doing-something>
  • 51. testing status code require 'test_helper' ! class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } ! test 'returns list of projects' do get '/projects' assert_equal 200, response.status refute_empty response.body end end
  • 52. testing status code require 'test_helper' ! class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } ! test 'returns list of projects' do get '/projects' assert_equal 200, response.status refute_empty response.body end end
  • 53. testing mime types class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } 
 test 'returns projects in JSON' do get '/projects', {}, { 'Accept' => Mime::JSON } assert_equal Mime::JSON, response.content_type end test 'returns projects in XML' do get '/projects', {}, { 'Accept' => Mime::XML } assert_equal Mime::XML, response.content_type end end
  • 54. testing mime types class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } 
 test 'returns projects in JSON' do get '/projects', {}, { 'Accept' => Mime::JSON } assert_equal Mime::JSON, response.content_type end test 'returns projects in XML' do get '/projects', {}, { 'Accept' => Mime::XML } assert_equal Mime::XML, response.content_type end end
  • 55. class ListingProjectsTest < ActionDispatch::IntegrationTest setup { @user = User.create! } setup { host! 'api.example.com' } ! test 'valid authentication with token' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"} assert_equal 200, response.status assert_equal Mime::JSON, response.content_type end ! test 'invalid authentication' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" } assert_equal 401, response.status end end testing access rules
  • 56. class ListingProjectsTest < ActionDispatch::IntegrationTest setup { @user = User.create! } setup { host! 'api.example.com' } ! test 'valid authentication with token' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"} assert_equal 200, response.status assert_equal Mime::JSON, response.content_type end ! test 'invalid authentication' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" } assert_equal 401, response.status end end testing access rules
  • 58. Thank you BUILDINg BETTER WITH railS@caikeCarlos Souza Code School web APIS Devils Tower, WY