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
HTTP headers for the responsible developer
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
stefan judis
March 16, 2019
Technology
5.1k
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
360
Playwright can do this?
stefanjudis
0
240
Things you should know about Frontend Development in 2022
stefanjudis
0
550
Throw yourself out there for fun and profit
stefanjudis
0
140
Back to Boring
stefanjudis
1
530
Wanna scale up? Make sure your CMS is ready for it!
stefanjudis
0
280
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
620
Other Decks in Technology
See All in Technology
手塩にかけりゃいいってもんじゃない
ming_ayami
0
590
スキルと MCP ツール、責務をどう分けるか? AI が迷わないインターフェース設計の戦略
cdataj
1
1.1k
Agent Skills設計で柔軟性と硬さのバランスが難しい話
nassy20
0
130
アジャイルな経理と Claude Code と経営の未来
kawaguti
PRO
3
120
ルールやカスタム機能、どう活かす?ハンズオンで体感するIBM Bobの出力コントロール
muehara
1
170
AmazonRoute 53ではじめてのドメイン取得!HTTPS化までの道のりを整理してみた
usanchuu
3
140
AIエージェントが名古屋の猛暑からあなたを守る
happysamurai294
0
130
いまさら聞けない「仕様駆動開発入門」 〜AI活用時代の開発プロセスを考える〜
findy_eventslides
2
130
AIのReact習熟度を測る
uhyo
2
600
自律型AIエージェントは何を破壊するのか
kojira
0
160
やさしいA2A入門
minorun365
PRO
12
1.9k
中期計画、2回作ってみた ~業務委託と正社員、両方の視点から~
demaecan
1
890
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
610
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
Accessibility Awareness
sabderemane
1
140
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
For a Future-Friendly Web
brad_frost
183
10k
Making the Leap to Tech Lead
cromwellryan
135
9.9k
Chasing Engaging Ingredients in Design
codingconduct
0
220
WCS-LA-2024
lcolladotor
0
630
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
140
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.3k
KATA
mclloyd
PRO
35
15k
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!