Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Libsaas: one API to rule them all
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Aitor Guevara
May 29, 2014
Technology
210
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Libsaas: one API to rule them all
APIdays Mediterranea May 2014, Barcelona
Aitor Guevara
May 29, 2014
More Decks by Aitor Guevara
See All by Aitor Guevara
Concurrent IO & Python
aitorciki
8
1k
From pull to push: towards a real-time web
aitorciki
4
340
Ducksboard's architecture, a real-time online dashboard
aitorciki
12
2.7k
Ducksboard - Betabeers BCN
aitorciki
1
210
Other Decks in Technology
See All in Technology
AI Driven AI Governance
pict3
0
310
Keeping applications secure by evolving OAuth 2.0 and OpenID Connect
ahus1
PRO
1
150
なぜ人は自分のプロジェクトを 「なんちゃってアジャイル」と 自嘲するのか
kozotaira
0
270
最近評価が難しくなった
maroon8021
0
260
Oracle Exadata Database Service on Cloud@Customer X11M (ExaDB-C@C) サービス概要
oracle4engineer
PRO
2
8.4k
そのタスクオンスケですか?
poropinai1966
0
150
グローバルチームと挑むプロダクト開発
sansantech
PRO
1
170
Claude Code 珍プレー好プレー
shinyasaita
0
300
AI時代のエンジニアキャリアについて今一度考える
sakamoto_582
2
1.4k
AI時代における最適なQA組織の作り方
ymty
3
500
ゼロをイチにする仕事が終わったあと
smasato
0
330
Claude Codeとハーネスについて考えてみる
oikon48
18
9k
Featured
See All Featured
We Are The Robots
honzajavorek
0
270
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
760
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
560
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
260
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
340
Six Lessons from altMBA
skipperchong
29
4.3k
A Tale of Four Properties
chriscoyier
163
24k
Mobile First: as difficult as doing things right
swwweet
225
10k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
180
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Transcript
libsaas one API to rule them all Aitor Guevara •
@aitorciki
Context
business data spread across cloud services
Ducksboard consumes SaaS APIs to collect and visualize data
None
None
REST APIs
heterogeneous implementations headers, query params, auth, mime types, versioning, error
handling…
ad-hoc vendor libraries data structures, HTTP handling, sync/async IO, Python
versions
Enter libsaas
abstraction layer on top of heterogeneous SaaS APIs URLs generation,
parameters serialization, authentication, …
uniform interface Python methods and objects supports Python 2.x, Python
3.x, PyPy
extensible implement services as modules base classes, decorators, helpers, documentation
auto-generation
agnostic isolates modelling from networking
Architecture
service / resources hierarchy of Python classes
filters reusable requests modifiers e.g. pre-built authentication mechanisms
executors pluggable HTTP handlers urllib2, Requests, Twisted
parsers know how to deserialize responses JSON, XML
Example: service definition
1 import json 2 from libsaas import http 3 from
libsaas.filters import auth 4 from libsaas.services import base 5 from . import repos 6 7 class GitHub(base.Resource): 8 9 def __init__(self, token_or_username, password=None): 10 self.apiroot = 'https://api.github.com' 11 12 self.add_filter(self.use_json) 13 14 if password is None: 15 self.oauth_token = token_or_username 16 self.add_filter(self.add_authorization) 17 else: 18 self.add_filter(auth.BasicAuth(token_or_username, password)) 19 20 def add_authorization(self, request): 21 request.headers['Authorization'] = 'token {0}'.format(self.oauth_token) 22 23 def use_json(self, request): 24 if request.method.upper() not in http.URLENCODE_METHODS: 25 request.params = json.dumps(request.params) 26 27 def get_url(self): 28 return self.apiroot 29 30 @base.resource(repos.Repo) 31 def repo(self, user, repo): 32 return repos.Repo(self, user, repo) filters definition child resource
1 from libsaas import http 2 from libsaas.services import base
3 from . import resource, repocommits 4 5 class Repo(resource.GitHubResource): 6 7 def __init__(self, parent, user, repo): 8 self.parent = parent 9 self.user = http.quote_any(user) 10 self.repo = http.quote_any(repo) 11 12 def get_url(self): 13 return '{0}/repos/{1}/{2}'.format(self.parent.get_url(), 14 self.user, self.repo) 15 16 def require_collection(self): 17 return False 18 19 def require_item(self): 20 return True 21 22 @base.resource(repocommits.RepoCommits) 23 def commits(self): 24 return repocommits.RepoCommits(self) child resource resource URL
1 from libsaas import http, parsers 2 from libsaas.services import
base 3 4 class GitHubResource(base.RESTResource): 5 6 @base.apimethod 7 def get(self, page=None, per_page=None): 8 params = base.get_params(('page', 'per_page'), locals()) 9 request = http.Request('GET', self.get_url(), params) 10 11 return request, parsers.parse_json 12 13 @base.apimethod 14 def update(self, obj): 15 self.require_item() 16 # GitHub uses PATCH for updates 17 request = http.Request('PATCH', self.get_url(), self.wrap_object(obj)) 18 19 return request, parsers.parse_json parse response as JSON
1 from __future__ import print_function 2 from libsaas.services import github
3 4 gh = github.GitHub('my_token') 5 6 repo = gh.repo('aitorciki', 'apidays-demo') 7 8 for commit in repo.commits().get(): 9 msg = commit['commit']['message'] 10 author = commit['commit']['author']['name'] 11 date = commit['commit']['author']['date'] 12 13 print('{0} by {1} on {2}'.format(msg, author, date)) resources tree Python dict HTTP method
Questions? Thanks! Aitor Guevara • @aitorciki http://libsaas.net/