Project

General

Profile

AbsoLUAtion » early-hints.lua

RFC 8297 An HTTP Status Code for Indicating Hints (103 Early Hints) - gstrauss, 2020-09-20 08:27

 
1
-- early-hints.lua
2
--
3
-- Summary: sample script to send 103 Early Hints
4
--
5
--
6
-- Copyright (c) 2020, Glenn Strauss (gstrauss () gluelogic.com), incremental
7
-- All rights reserved.
8
--
9
-- License: 3-clause BSD
10
--
11
--
12
-- lighttpd.conf
13
--   server.modules += ("mod_magnet")
14
--   $HTTP["url"] =~ "^/" {
15
--     magnet.attract-raw-url-to = ( "/path/to/early-hints.lua" )
16
--   }
17
--
18
-- Note: lighttpd.conf was never intended to be a full programming language.
19
-- lua is available in lighttpd mod_lua to perform more precise, multi-step
20
-- processing and/or chaining of conditions.
21

    
22
-- RFC 8297 An HTTP Status Code for Indicating Hints (103 Early Hints)
23
-- https://tools.ietf.org/html/rfc8297
24

    
25
-- (optional) return if not *.html
26
--   (e.g. do not send early hints for images such as *.jpg)
27
--
28
if (not string.match(lighty.env["uri.path"], '.html$')) then return 0 end
29

    
30
-- (optional) return if HTTP/1.0 (does not support 1xx intermediate responses)
31
--if (lighty.env["request.protocol"] == "HTTP/1.0") then return 0 end
32

    
33
-- (optional) return if not HTTP/2
34
-- coarse heuristic: HTTP/2 clients are more likely to handle unexpected
35
-- 1xx intermediate responses than are HTTP/1.x clients.  (YMMV) 
36
-- HTTP protocol version is a coarse heuristic which would probably be better
37
-- if replaced with a User-Agent version parse of the User-Agent header.
38
-- note: string match "HTTP/2.0" as protocol name in lighttpd; not "HTTP/2"
39
--
40
if (not (lighty.env["request.protocol"] == "HTTP/2.0")) then return 0 end
41

    
42
-- (optional) return if User-Agent is not known to handle 1xx responses
43
--
44
-- Warning: backends which send 103 Early Hints should check User-Agent
45
-- before doing so since naive clients might not handle unexpected 1xx.
46
-- Some clients may take the 1xx response as the final response, expecting
47
-- only one response.  Some clients might not properly handle 100 Continue
48
-- if the client did not send Expect: 100-continue with the request.
49
-- https://tools.ietf.org/html/rfc8297#section-3 Security Considerations
50
-- 
51
-- coarse heuristic: simple clients might omit User-Agent request header,
52
-- but popular web browsers typically provide User-Agent request header.
53
-- 
54
-- A better approach would be to parse User-Agent for versions and selectively
55
-- allow specific user agents and versions known to support 103 Early Hints.
56
-- (Such a listing is not provided or maintained in this example)
57
-- (XXX: such an approach could also be taken in a new lighttpd module in C)
58
--
59
local ua = lighty.request["User-Agent"]
60
if (ua == nil) then return 0 end
61

    
62
--
63
-- 103 Early Hints
64
--
65

    
66
local links =
67
  {
68
    '<http://server1.example.com>; rel="preconnect"',
69
    '<http://server2.example.com>; rel="preconnect"' 
70
  }
71

    
72
lighty.header["Link"] = table.concat(links, ", ")
73
return 103
(2-2/3)