+ All Categories
Home > Software > Conditional get

Conditional get

Date post: 13-Apr-2017
Category:
Upload: brad-johnson
View: 52 times
Download: 0 times
Share this document with a friend
17
Fast APIs with Conditional GET
Transcript

Fast APIs with Conditional GET

Brad Johnson

Coshx Labs

http://www.coshx.com/

https://www.railsschool.org/

Agenda1.Why do we need to do this? 2.What is a Conditional GET request? 3.How do we do it? 4.How does it work?

The Problem:We build apps quickly. Apps consume a lot

of data (JSON in this example). Often, a lot of the data doesn’t change very often, but it’s easier to just fetch all the things all the time,

because cache invalidation is hard.

Then, one day we need to scale. And one of the

strategies we decide to use is to cache some responses.

Problems• Page and action cacheing have been

moved from Rails 4 into gems • Fragment cacheing requires memory,

and often things like Redis or memcached.

• Buggy

Solution

Conditional requestsPart of the HTTP standard that

allows browsers to ask servers if anything has changed, or not.

Request headers can be used by both the client and the server to determine if any new data is present. If no new data is

present, the server can return a 304. If new data is available, it can render the new data.

Time-Basedclass PokemonsController < ApplicationController

def index pokemons = Pokemon.all.includes(:pokemon_type) expires_in 1.minute render json: pokemons endend

Etagsclass PokemonsController < ApplicationController

def index pokemons = Pokemon.all.includes(:pokemon_type) if stale? etag: pokemons render json: pokemons end endend

Last Modifiedclass PokemonsController < ApplicationController

def index pokemons = Pokemon.all.includes(:pokemon_type) if stale? last_modified: pokemons.maximum(:updated_at) render json: pokemons end endend

Last Modified + Etagclass PokemonsController < ApplicationController

def index pokemons = Pokemon.all.includes(:pokemon_type) if stale? pokemons render json: pokemons end endend

#stale?# rails/actionpack/lib/action_controller/metal/conditional_get.rb

def stale?(object = nil, **freshness_kwargs) fresh_when(object, **freshness_kwargs) !request.fresh?(response)end

#fresh_when?# rails/actionpack/lib/action_controller/metal/conditional_get.rb

def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, template: nil)

weak_etag ||= etag || object unless strong_etag last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)

if strong_etag response.strong_etag = combine_etags strong_etag, last_modified: last_modified, public: public, template: template elsif weak_etag || template response.weak_etag = combine_etags weak_etag, last_modified: last_modified, public: public, template: template end

response.last_modified = last_modified if last_modified response.cache_control[:public] = true if public

head :not_modified if request.fresh?(response)end

#request_fresh?# rails/actionpack/lib/action_dispatch/http/cache.rb

def fresh?(response) last_modified = if_modified_since etag = if_none_match

return false unless last_modified || etag

success = true success &&= not_modified?(response.last_modified) if last_modified success &&= etag_matches?(response.etag) if etag successend

@johnsonbradleym

[email protected]

https://github.com/cdale77/pokelist


Recommended