HTTP headers for the responsible developer

HTTP headers for the responsible developer

22725c2d3eb331146549bf0d5d3c050c?s=128

stefan judis

March 16, 2019
Tweet

Transcript

  1. @stefanjudis HTTP headers for the responsible developer

  2. My journey on the web

  3. uboot.com

  4. 1999

  5. The web connects people

  6. 2010

  7. The web connects people

  8. We connect people! We enable people! We help people!

  9. [he/him] @stefanjudis www.stefanjudis.com Heyo, I'm Stefan!

  10. ... and I want to be a responsible developer

  11. None
  12. 1999

  13. 2019

  14. 2019

  15. 2019

  16. 2019 We should be building for everybody

  17. "We don't have users in/that ..."

  18. "We don't have users in/that ..."

  19. The challenge of building a "good" website

  20. Design Performance Content Accessibility Devices Network Frameworks

  21. Design Performance Content Accessibility Network Frameworks Devices

  22. Let's talk HTTP

  23. 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
  24. 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
  25. the-responsible.dev

  26. How can we use headers to make this site better?

  27. The web is a scary place

  28. thenextweb.com/contributors/2018/03/10/protect-website-cryptojacking-attacks/

  29. shoptalkshow.com/episodes/special-one-one-hacker/

  30. blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident

  31. www.twilio.com/blog/learned-about-security-from-calling-35-contact-centers

  32. www.twilio.com/blog/learned-about-security-from-calling-35-contact-centers We always rely on others

  33. The web has to be safe!

  34. HTTPS

  35. HTTP/2 ServiceWorker getUserMedia() ...

  36. whynohttps.com

  37. whynohttps.com

  38. Ensure encryption

  39. Strict-Transport-Security: max-age=1000; includeSubDomains; preload Response Header

  40. hstspreload.org

  41. chromium.googlesource.com/chromium/src/net/+/master/http/ transport_security_state_static.json

  42. None
  43. caniuse.com/#feat=stricttransportsecurity

  44. Upgrade HTTP requests

  45. Content-Security-Policy: upgrade-insecure-requests Response Header

  46. www.chromestatus.com/feature/5557268741357568

  47. Limit what's allowed

  48. requestmap.webperf.tools

  49. 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
  50. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*;">

  51. 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
  52. 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
  53. 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
  54. Report-To: { "group": "csp-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../csp-report"

    }] }
  55. 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" }] }
  56. developers.google.com/web/updates/2018/09/reportingapi

  57. 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
  58. 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
  59. Content-Security-Policy: default-src 'self'; script-src 'sha256-blL...' <script> console.log('Inline script executing ...');

    </script> Response Header
  60. Content-Security-Policy: default-src 'self'; script-src 'nonce-abc...' <script nonce="abcdef"> console.log('Inline script executing

    ...'); </script> Response Header
  61. caniuse.com/#feat=contentsecuritypolicy

  62. caniuse.com/#feat=contentsecuritypolicy2 * * not complete

  63. httparchive.org

  64. How many pages use CSP?

  65. USE CSP DON'T USE CSP 94% 6%

  66. USE CSP DON'T USE CSP 94% 6% We can do

    better!
  67. Always monitor your CSP reports and "test in production" with

    report-only before enforcing them! Troy Hunt
  68. Disallow third-party cookies!

  69. Set-Cookie: widget_session=abc123; Response Header Set-Cookie: ...

  70. Set-Cookie: widget_session=abc123; Response Header Set-Cookie: ... This behaviour leads to

    security and privacy issues
  71. 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
  72. caniuse.com/#feat=same-site-cookie-attribute * * somewhat ready but maybe buggy

  73. web.dev/samesite-cookies-explained

  74. the-responsible.dev/safe/

  75. The web is crucial for people.

  76. Your sh** doesn't work in Africa. William Imoh

  77. None
  78. You get 6MB for 2Euros but you have only 24h

    to use them! Right...
  79. whatdoesmysitecost.com

  80. The web has to be affordable!

  81. Don't request the same content over and over again

  82. Cache-Control: max-age=31536000, public, immutable Response Header

  83. immutable developer.mozilla.org/en-US/docs/Web/HTTP/ Headers/Cache-Control

  84. csswizardry.com/2019/03/cache-control-for-civilians/

  85. Send the right data

  86. Accept-Encoding: gzip, deflate, br Request Header

  87. None
  88. None
  89. But Brotli compression is so slow!

  90. GZIP Brotli vs Default Mode 6 11

  91. GZIP Brotli Default Mode vs 6 11

  92. GZIP Brotli Optimal middle ground vs 6 4

  93. GZIP Brotli Optimal middle ground vs 6 4 Brotli tends

    to compress better with the same speed
  94. GZIP Brotli Optimal middle ground vs 6 4 You don't

    have to do it on the fly...
  95. blogs.akamai.com/2016/02/understanding-brotlis-potential.html

  96. caniuse.com/#feat=brotli

  97. None
  98. None
  99. Serve tailored media

  100. <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"
  101. /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>
  102. Accept: image/webp, image/apng, image/*,*/*;q=0.8 Request Header

  103. caniuse.com/#feat=webp

  104. Accept-CH: Width, Viewport-Width Accept-CH-Lifetime: 100 Request URL: https://.../header.jpg
 Viewport-Width: 980

    Width: 980
  105. <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
  106. <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
  107. <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
  108. speaking.jeremy.codes/yD4dKY/take-a-client-hint

  109. www.zdnet.com/article/privacy-concerns-raised-about-upcoming-client-hints-web-standard/

  110. 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"
  111. wicg.github.io/ua-client-hints/

  112. Save data

  113. save-data: on if ("connection" in navigator) { if (navigator.connection.saveData ===

    true) { // Implement data saving operations here. } } Request Header
  114. None
  115. Let's use the platform and make these features more visible

  116. https://.... Save data?

  117. https://.... Save data? We should provide an easy way to

    save data!
  118. Save data? https://.... Prefer reduced motion? Prefer a dark interface?

  119. Save data? https://.... Reduced Motion? Dark colour Scheme? All these

    settings should be easily accessible all the time!
  120. None
  121. blog.chromium.org/2019/03/chrome-lite-pages-for-faster-leaner.html

  122. blog.chromium.org/2019/03/chrome-lite-pages-for-faster-leaner.html I'm not sure how I feel about that...

  123. Cache-Control: max-age=31536000, public, no-transform Response Header

  124. Be aware of CDNs and proxies – use vary

  125. None
  126. Should browsers or developers optimise?

  127. The browser can only optimise to a certain extend...

  128. None
  129. 20% of requests...

  130. https:/ /nooshu.github.io/blog/2019/09/01/speeding-up-the-web-with-save-data-header/

  131. Less Data Doesn't Mean a Lesser Experience Tim Kadlec

  132. the-responsible.dev/affordable/

  133. The web is with us every day

  134. 2018.bloomca.me

  135. It has to be respectful!

  136. Get stuff "down" as quickly as possible

  137. Link: </unleashed.jpg>; rel=preload; as=image; no-push <link rel="preload" href="/unleashed.jpg" as="image"> Response

    Header
  138. 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
  139. caniuse.com/#feat=link-rel-preload * * behind a flag

  140. Don't annoy the user (aka. the AMP reaction)

  141. speakerdeck.com/stefanjudis/amp-tries-to-fix-the-web-what-can-we-learn-from-it?slide=112

  142. Feature-Policy: vibrate 'none'; geolocation 'none' Response Header

  143. 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
  144. 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
  145. 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
  146. tiny-helpers.dev

  147. <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">
  148. tiny-helpers.dev

  149. www.youtube.com/watch?v=4-d_SoCHeWE

  150. www.youtube.com/watch?v=4-d_SoCHeWE Define width & height to avoid jumpy pages

  151. None
  152. 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();
  153. Report-To: { "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../general-report" }] }

  154. timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/

  155. feature-policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer

    'none'; microphone 'none'; payment 'none'; usb 'none' Response Header
  156. <iframe allow="camera 'none'; microphone 'none'"> document.featurePolicy.allowedFeatures(); // → ["geolocation", "midi",

    ...] document.featurePolicy.allowsFeature('geolocation'); // → true document.featurePolicy.getAllowlistForFeature('geolocation'); // → ["https://example.com"]
  157. What happened to the most annoying one?

  158. github.com/w3c/webappsec-feature-policy/issues/243

  159. blog.chromium.org/2020/01/introducing-quieter-permission-ui-for.html

  160. 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 * * * **
  161. Respect privacy

  162. None
  163. caniuse.com/#feat=do-not-track

  164. webkit.org/blog/8594/release-notes-for-safari-technology-preview-75/

  165. caniuse.com/#feat=do-not-track

  166. caniuse.com/#feat=do-not-track It was a nice try, but I don't really

    see that happening...
  167. None
  168. None
  169. None
  170. None
  171. www.xanjero.com/news/samsung-internet-beta-version-9-2-now-includes-oneui-design-smart- anti-tracking-and-more-features/

  172. webkit.org/blog/category/privacy/

  173. www.engadget.com/2019/11/04/chromium-edge-browser-release-date/

  174. The next browser war is on its way...

  175. the-responsible.dev/respectful/

  176. Building for the web is very hard

  177. Design Performance Content Accessibility Devices Network Frameworks

  178. Lighthouse

  179. webhint.io

  180. If you want to get a more complete overview...

  181. www.twilio.com/blog/a-http-headers-for-the-responsible-developer

  182. securityheaders.com

  183. schepp.github.io/HTTP-headers

  184. youtu.be/II9m9_esNZc

  185. The web has to be safe...

  186. The web has to be safe, affordable...

  187. The web has to be safe, affordable and respectful...

  188. ... so that it really is
 for everybody!

  189. @stefanjudis www.stefanjudis.com Thanks. Slides:
 my-links.online/the-responsible-dev

  190. @stefanjudis www.stefanjudis.com Thanks. Slides:
 my-links.online/the-responsible-dev I have some stickers!