Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
HTTP headers for the responsible developer
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
stefan judis
March 16, 2019
Technology
5.2k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
HTTP headers for the responsible developer
stefan judis
March 16, 2019
More Decks by stefan judis
See All by stefan judis
Back to boring (part 2)
stefanjudis
0
390
Playwright can do this?
stefanjudis
0
270
Things you should know about Frontend Development in 2022
stefanjudis
0
570
Throw yourself out there for fun and profit
stefanjudis
0
140
Back to Boring
stefanjudis
1
540
Wanna scale up? Make sure your CMS is ready for it!
stefanjudis
0
290
Did we(b development) lose the right direction?
stefanjudis
6
2.2k
Regular expressions – my secret love
stefanjudis
1
1.1k
Write a Function
stefanjudis
0
630
Other Decks in Technology
See All in Technology
Von-Neumann Machines, Dreams & The Futures of IT
ufried
0
120
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
4
3.7k
Deployment の 先にある AI Agent 基盤 - kagent vNext、Agent Substrate、Hermes から読み解く Agent Runtime の現在地 / k8s-matsuri-2-ai-agent-platform-amsy810
masayaaoyama
4
710
品質と信頼性を地続きにする
grimoh
2
950
バイブコーディング時代のWebアプリ開発入門~Cloud Runで学ぶセキュアなビルドとデプロイ
waiwai2111
1
140
JSONataとAWS Step Functionsで目指すRuntimelessな世界
mu7889yoon
0
440
サーバーレスをどこまで使う? WebRTC対戦ゲームで選んだVPSとの共存設計
kaidouji85
0
350
[Kiro Meetup #7] Kiro Crew Dive Deep
konippi
0
250
Why Agent Cost Needs Observability
nttcom
0
140
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
30
19k
顧客に向き合う開発組織へ。リアーキテクチャとフィーチャーチーム化で挑む組織改革
safie
0
2.4k
C#未経験の僕がAIに読めるコードを書かせるまで
maguroalternative
0
250
Featured
See All Featured
A better future with KSS
kneath
240
18k
The Curse of the Amulet
leimatthew05
3
15k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
420
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.1k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
76k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Transcript
@stefanjudis HTTP headers for the responsible developer
My journey on the web
uboot.com
1999
The web connects people
2010
The web connects people
We connect people! We enable people! We help people!
[he/him] @stefanjudis www.stefanjudis.com Heyo, I'm Stefan!
... and I want to be a responsible developer
None
1999
2019
2019
2019
2019 We should be building for everybody
"We don't have users in/that ..."
"We don't have users in/that ..."
The challenge of building a "good" website
Design Performance Content Accessibility Devices Network Frameworks
Design Performance Content Accessibility Network Frameworks Devices
Let's talk HTTP
https://the-responsible.dev/ Accept: text/html,application/xhtml+xml,application/xml Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7 ...
Connection: keep-alive Content-Type: text/html; charset=utf-8 Date: Mon, 11 Mar 2019 12:59:38 GMT ... Response Body
Accept: text/html,application/xhtml+xml,application/xml Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7 ... https://the-responsible.dev/
Connection: keep-alive Content-Type: text/html; charset=utf-8 Date: Mon, 11 Mar 2019 12:59:38 GMT ... Response Body
the-responsible.dev
How can we use headers to make this site better?
The web is a scary place
thenextweb.com/contributors/2018/03/10/protect-website-cryptojacking-attacks/
shoptalkshow.com/episodes/special-one-one-hacker/
blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident
www.twilio.com/blog/learned-about-security-from-calling-35-contact-centers
www.twilio.com/blog/learned-about-security-from-calling-35-contact-centers We always rely on others
The web has to be safe!
HTTPS
HTTP/2 ServiceWorker getUserMedia() ...
whynohttps.com
whynohttps.com
Ensure encryption
Strict-Transport-Security: max-age=1000; includeSubDomains; preload Response Header
hstspreload.org
chromium.googlesource.com/chromium/src/net/+/master/http/ transport_security_state_static.json
None
caniuse.com/#feat=stricttransportsecurity
Upgrade HTTP requests
Content-Security-Policy: upgrade-insecure-requests Response Header
www.chromestatus.com/feature/5557268741357568
Limit what's allowed
requestmap.webperf.tools
base-uri block-all-mixed-content connect-src default-src font-src form-action frame-ancestors frame-src img-src manifest-src
media-src navigate-to object-src plugin-types report-sample report-to require-sri-for sandbox script-src strict-dynamic style-src upgrade-insecure-requests worker-src developer.mozilla.org/en-US/docs/Web/HTTP/CSP prefetch-src
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*;">
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe- inline' 'unsafe-eval' just-comments.com www.google-analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Report-To: { "group": "csp-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../csp-report"
}] }
Report-To: { "group": "csp-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../csp-report"
}] }, { "group": "network-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../network-report" }] }, { "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../general-report" }] }
developers.google.com/web/updates/2018/09/reportingapi
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy: default-src 'self'; script-src 'sha256-blL...' <script> console.log('Inline script executing ...');
</script> Response Header
Content-Security-Policy: default-src 'self'; script-src 'nonce-abc...' <script nonce="abcdef"> console.log('Inline script executing
...'); </script> Response Header
caniuse.com/#feat=contentsecuritypolicy
caniuse.com/#feat=contentsecuritypolicy2 * * not complete
httparchive.org
How many pages use CSP?
USE CSP DON'T USE CSP 94% 6%
USE CSP DON'T USE CSP 94% 6% We can do
better!
Always monitor your CSP reports and "test in production" with
report-only before enforcing them! Troy Hunt
Disallow third-party cookies!
Set-Cookie: widget_session=abc123; Response Header Set-Cookie: ...
Set-Cookie: widget_session=abc123; Response Header Set-Cookie: ... This behaviour leads to
security and privacy issues
Set-Cookie: widget_session=abc123; SameSite=None; Secure Set-Cookie: widget_session=abc123; SameSite=Lax; Secure Set-Cookie: widget_session=abc123;
SameSite=Strict; Secure Response Header
caniuse.com/#feat=same-site-cookie-attribute * * somewhat ready but maybe buggy
web.dev/samesite-cookies-explained
the-responsible.dev/safe/
The web is crucial for people.
Your sh** doesn't work in Africa. William Imoh
None
You get 6MB for 2Euros but you have only 24h
to use them! Right...
whatdoesmysitecost.com
The web has to be affordable!
Don't request the same content over and over again
Cache-Control: max-age=31536000, public, immutable Response Header
immutable developer.mozilla.org/en-US/docs/Web/HTTP/ Headers/Cache-Control
csswizardry.com/2019/03/cache-control-for-civilians/
Send the right data
Accept-Encoding: gzip, deflate, br Request Header
None
None
But Brotli compression is so slow!
GZIP Brotli vs Default Mode 6 11
GZIP Brotli Default Mode vs 6 11
GZIP Brotli Optimal middle ground vs 6 4
GZIP Brotli Optimal middle ground vs 6 4 Brotli tends
to compress better with the same speed
GZIP Brotli Optimal middle ground vs 6 4 You don't
have to do it on the fly...
blogs.akamai.com/2016/02/understanding-brotlis-potential.html
caniuse.com/#feat=brotli
None
None
Serve tailored media
<picture> <!-- serve WebP to Chrome and Opera --> <source
media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.webp 200w, /image/thing-400.webp 400w, /image/thing-800.webp 800w, /image/thing-1200.webp 1200w, /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w" type="image/webp"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w, /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w, /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w" type="image/webp"> <!-- serve JPEG to others --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w, /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w, /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w"> <source sizes="(min-width: 30em) 100vw"
/image/thing-800.webp 800w, /image/thing-1200.webp 1200w, /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w" type="image/webp"> <source
sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w, /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w, /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w" type="image/webp"> <!-- serve JPEG to others --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w, /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w, /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.jpg 200w, /image/thing-crop-400.jpg 400w, /image/thing-crop-800.jpg 800w, /image/thing-crop-1200.jpg 1200w, /image/thing-crop-1600.jpg 1600w, /image/thing-crop-2000.jpg 2000w"> <!-- fallback for browsers that don't support picture --> <img src="/image/thing.jpg" width="50%"> </picture>
Accept: image/webp, image/apng, image/*,*/*;q=0.8 Request Header
caniuse.com/#feat=webp
Accept-CH: Width, Viewport-Width Accept-CH-Lifetime: 100 Request URL: https://.../header.jpg Viewport-Width: 980
Width: 980
<img src="/header.jpg" alt="" sizes="100vw" /> Accept: image/webp,image/apng,image/*,*/*;q=0.8 Request URL: https://.../header.jpg
Viewport-Width: 980 Width: 980
<img src="/header.jpg" alt="" sizes="100vw" /> Accept: image/webp,image/apng,image/*,*/*;q=0.8 Request URL: https://.../header.jpg
Viewport-Width: 980 Width: 1960
<img src="/header.jpg" alt="" sizes="100vw" /> Accept: image/webp,image/apng,image/*,*/*;q=0.8 Request URL: https://.../header.jpg
Viewport-Width: 980 Width: 1064 Serve a tailored version via server/service worker
speaking.jeremy.codes/yD4dKY/take-a-client-hint
www.zdnet.com/article/privacy-concerns-raised-about-upcoming-client-hints-web-standard/
Sec-CH-UA: "Examplary Browser"; v="73" Accept-CH: UA, Platform Sec-CH-UA: "Examplary Browser";
v="73.3R8.2H.1" Sec-CH-UA-Platform: "Windows"; v="10"
wicg.github.io/ua-client-hints/
Save data
save-data: on if ("connection" in navigator) { if (navigator.connection.saveData ===
true) { // Implement data saving operations here. } } Request Header
None
Let's use the platform and make these features more visible
https://.... Save data?
https://.... Save data? We should provide an easy way to
save data!
Save data? https://.... Prefer reduced motion? Prefer a dark interface?
Save data? https://.... Reduced Motion? Dark colour Scheme? All these
settings should be easily accessible all the time!
None
blog.chromium.org/2019/03/chrome-lite-pages-for-faster-leaner.html
blog.chromium.org/2019/03/chrome-lite-pages-for-faster-leaner.html I'm not sure how I feel about that...
Cache-Control: max-age=31536000, public, no-transform Response Header
Be aware of CDNs and proxies – use vary
None
Should browsers or developers optimise?
The browser can only optimise to a certain extend...
None
20% of requests...
https:/ /nooshu.github.io/blog/2019/09/01/speeding-up-the-web-with-save-data-header/
Less Data Doesn't Mean a Lesser Experience Tim Kadlec
the-responsible.dev/affordable/
The web is with us every day
2018.bloomca.me
It has to be respectful!
Get stuff "down" as quickly as possible
Link: </unleashed.jpg>; rel=preload; as=image; no-push <link rel="preload" href="/unleashed.jpg" as="image"> Response
Header
Link: </unleashed.jpg>; rel=preload; as=image; no-push <link rel="preload" href="/unleashed.jpg" as="image"> Response
Header This is great to speed up critical resources
caniuse.com/#feat=link-rel-preload * * behind a flag
Don't annoy the user (aka. the AMP reaction)
speakerdeck.com/stefanjudis/amp-tries-to-fix-the-web-what-can-we-learn-from-it?slide=112
Feature-Policy: vibrate 'none'; geolocation 'none' Response Header
accelerometer ambient-light-sensor autoplay camera document-domain encrypted-media fullscreen geolocation gyroscope layout-animations
legacy-image-formats magnetometer microphone midi oversized-images payment picture-in-picture speaker sync-xhr unoptimized-images unsized-media usb vibrate vr developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
accelerometer ambient-light-sensor autoplay camera document-domain encrypted-media fullscreen geolocation gyroscope layout-animations
legacy-image-formats magnetometer microphone midi oversized-images payment picture-in-picture speaker sync-xhr unoptimized-images unsized-media usb vibrate vr developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
accelerometer ambient-light-sensor autoplay camera document-domain encrypted-media fullscreen geolocation gyroscope layout-animations
legacy-image-formats magnetometer microphone midi oversized-images payment picture-in-picture speaker sync-xhr unoptimized-images unsized-media usb vibrate vr developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
tiny-helpers.dev
<img srcset="/screenshots/{{ item.slug }}@1.jpg 1x, /screenshots/{{ item.slug }}@2.jpg 2x" src="/screenshots/{{
item.slug }}@2.jpg" alt="Screenshot of {{ item.name }}" loading="lazy"> <img srcset="/screenshots/{{ item.slug }}@1.jpg 1x, /screenshots/{{ item.slug }}@2.jpg 2x" src="/screenshots/{{ item.slug }}@2.jpg" alt="Screenshot of {{ item.name }}" width="1000" height="600" loading="lazy">
tiny-helpers.dev
www.youtube.com/watch?v=4-d_SoCHeWE
www.youtube.com/watch?v=4-d_SoCHeWE Define width & height to avoid jumpy pages
None
new ReportingObserver((reports, observer) => { reports.forEach(({type, url, body}) => {
console.log(type, url); // 'feature-policy-violation', https://some-url.com/... console.log(body); // { // featureId: 'oversized-images', // sourceFile: 'https://path-to-image/... // ... // } }); }, {types: ['feature-policy-violation'], buffered: true}).observe();
Report-To: { "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../general-report" }] }
timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/
feature-policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer
'none'; microphone 'none'; payment 'none'; usb 'none' Response Header
<iframe allow="camera 'none'; microphone 'none'"> document.featurePolicy.allowedFeatures(); // → ["geolocation", "midi",
...] document.featurePolicy.allowsFeature('geolocation'); // → true document.featurePolicy.getAllowlistForFeature('geolocation'); // → ["https://example.com"]
What happened to the most annoying one?
github.com/w3c/webappsec-feature-policy/issues/243
blog.chromium.org/2020/01/introducing-quieter-permission-ui-for.html
caniuse.com/#feat=feature-policy ** support only for allow on iframes ** *
support for Feature-Policy header, allow on iframes, and JS API behind a flag * * * **
Respect privacy
None
caniuse.com/#feat=do-not-track
webkit.org/blog/8594/release-notes-for-safari-technology-preview-75/
caniuse.com/#feat=do-not-track
caniuse.com/#feat=do-not-track It was a nice try, but I don't really
see that happening...
None
None
None
None
www.xanjero.com/news/samsung-internet-beta-version-9-2-now-includes-oneui-design-smart- anti-tracking-and-more-features/
webkit.org/blog/category/privacy/
www.engadget.com/2019/11/04/chromium-edge-browser-release-date/
The next browser war is on its way...
the-responsible.dev/respectful/
Building for the web is very hard
Design Performance Content Accessibility Devices Network Frameworks
Lighthouse
webhint.io
If you want to get a more complete overview...
www.twilio.com/blog/a-http-headers-for-the-responsible-developer
securityheaders.com
schepp.github.io/HTTP-headers
youtu.be/II9m9_esNZc
The web has to be safe...
The web has to be safe, affordable...
The web has to be safe, affordable and respectful...
... so that it really is for everybody!
@stefanjudis www.stefanjudis.com Thanks. Slides: my-links.online/the-responsible-dev
@stefanjudis www.stefanjudis.com Thanks. Slides: my-links.online/the-responsible-dev I have some stickers!