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
I'm doing HTTP wrong
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
fireteam
May 28, 2012
Technology
2.2k
10
Share
I'm doing HTTP wrong
The slides from the presentation at PyGrunn 2012.
fireteam
May 28, 2012
Other Decks in Technology
See All in Technology
【関西製造業祭り2026春】現場を変える技術はここまで来た〜世界最大の製造業見本市から持って帰ってきたもの〜
tanakaseiya
0
180
Swift Sequence の便利 API 再発見
treastrain
1
290
Claude Code で使える DuckDB Skills を試してみた / DuckDB Skills and Claude Code
masahirokawahara
1
690
みんなの考えた最強のデータ基盤アーキテクチャ'26前期〜前夜祭〜ルーキーズ_資料_遠藤な
endonanana
0
450
エムスリーテクノロジーズ株式会社 エンジニア向け紹介資料 / M3 Technologies Company Deck
m3_engineering
0
180
AI-Assisted Contributions and Maintainer Load - PyCon US 2026
pauloxnet
1
160
AI 時代の Platform Engineering
recruitengineers
PRO
1
220
AI対話分析の夢と、汚いデータの現実 Looker / Dataplex / Dataform で実現する品質ファーストな基盤設計
waiwai2111
0
640
ESP32 IoTを動かしながらメモリ使用量を観測してみた話
zozotech
PRO
0
140
Purview 勉強会報告 Microsoft Purview 入門しようとしてみた
masakichixo
1
440
業務に残された「良くない型」で考える「TypeScriptの難しさ」
sajikix
1
290
社内RAGの導入で気を付けたポイント
yakumo
1
120
Featured
See All Featured
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
140
エンジニアに許された特別な時間の終わり
watany
106
240k
Rails Girls Zürich Keynote
gr2m
96
14k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
160
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
130
Ruling the World: When Life Gets Gamed
codingconduct
0
230
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.8k
Exploring anti-patterns in Rails
aemeredith
3
360
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
150
Thoughts on Productivity
jonyablonski
76
5.2k
The Cost Of JavaScript in 2023
addyosmani
55
9.9k
Transcript
I am doing HTTP wrong — a presentation by Armin
Ronacher @mitsuhiko
The Web developer's Evolution
echo
request.send_header(…) request.end_headers() request.write(…)
return Response(…)
Why Stop there?
What do we love about HTTP?
Text Based
REST
Cacheable
Content Negotiation
Well Supported
Works where TCP doesn't
Somewhat Simple
Upgrades to custom protocols
Why does my application look like HTTP?
everybody does it
Natural Conclusion
we can do better!
we're a level too low
Streaming: one piece at the time, constant memory usage, no
seeking.
Buffering: have some data in memory, variable memory usage, seeking.
TYPICAL Request / Response Cycle User Agent Proxy Server Application
Stream “Buffered” Dispatcher View
In Python Terms def application(environ, start_response): # Step 1: acquire
data data = environ['wsgi.input'].read(...) # Step 2: process data response = process_data(data) # Step 3: respond start_response('200 OK', [('Content-Type', 'text/plain')]) return [response]
One Level Up s = socket.accept() f = s.makefile('rb') requestline
= f.readline() headers = [] while 1: headerline = f.readline() if headerline == '\r\n': break headers.append(headerline)
Weird Mixture on the app request.headers <- buffered request.form <-
buffered request.files <- buffered to disk request.body <- streamed
HTTP's Limited signalling Strict Request / Response The only communication
during request from the server to the client is closing the connection once you started accepting the body.
Bailing out early def application(request): # At this point, headers
are parsed, everything else # is not parsed yet. if request.content_length > TWO_MEGABYTES: return error_response() ...
Bailing out a little bit later def application(request): # Read
a little bit of data request.input.read(4096) # You just committed to accepting data, now you have to # read everything or the browser will be very unhappy and # Just time out. No more responding with 413 ...
Rejecting Form fields -> memory File uploads -> disk What's
your limit? 16MB in total? All could go to memory. Reject file sizes individually? Needs overall check as well!
The Consequences How much data do you accept? Limit the
overall request size? Not helpful because all of it could be in-memory
It's not just limiting Consider a layered system How many
of you write code that streams? What happens if you pass streamed data through your layers?
A new approach
Dynamic typing made us lazy
we're trying to solve both use cases in one we're
not supporting either well
How we do it Hide HTTP from the apps HTTP
is an implementation detail
Pseudocode user_pagination = make_pagination_schema(User) @export( specs=[('page', types.Int32()), ('per_page', types.Int32())], returns=user_pagination,
semantics='select', http_path='/users/' ) def list_users(page, per_page): users = User.query.paginate(page, per_page) return users.to_dict()
Types are specific user_type = types.Object([ ('username', types.String(30)), ('email', types.Optional(types.String(250))),
('password_hash', types.String(250)), ('is_active', types.Boolean()), ('registration_date', types.DateTime()) ])
Why? Support for different input/output formats keyless transport support for
non-HTTP no hash collision attacks :-) Predictable memory usage
Comes for free Easier to test Helps documenting the public
APIs Catches common errors early Handle errors without invoking code Predictable dictionary ordering
Strict vs Lenient
Rule of Thumb Be strict in what you send, but
generous in what you receive — variant of Postel's Law
Being Generous In order to be generous you need to
know what to receive. Just accepting any input is a security disaster waiting to happen.
Support unsupported types { "foo": [1, 2, 3], "bar": {"key":
"value"}, "now": "Thu, 10 May 2012 14:16:09 GMT" } foo.0=1& foo.1=2& foo.2=3& bar.key=value& now=Thu%2C%2010%20May%202012%2014:16:09%20GMT
Solves the GET issue GET has no body parameters have
to be URL encoded inconsistency with JSON post requests
Where is the streaming?
There is none
there are always two sides to an API
If the server has streaming endpoints — the client will
have to support them as well
For things that need actual streaming we have separate endpoints.
streaming is different
but we can stream until we need buffering
Discard useless stuff { "foo": [list, of, thousands, of, items,
we don't, need], "an_important_key": "we're actually interested in" }
What if I don't make an API?
modern web apps are APIs
Dumb client? Move the client to the server
Q&A
Oh hai. We're hiring http://fireteam.net/careers