]> Sergey Matveev's repositories - public-inbox.git/blob - examples/cgit-wwwhighlight-filter.lua
a622e9f80338f7da08c632437d73cf8cd88f3f20
[public-inbox.git] / examples / cgit-wwwhighlight-filter.lua
1 -- Copyright (C) 2019-2021 all contributors <meta@public-inbox.org>
2 -- License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
3 --
4 -- This filter accesses the PublicInbox::WwwHighlight PSGI endpoint
5 -- (see examples/highlight.psgi)
6 --
7 -- Dependencies: lua-http
8 --
9 -- disclaimer: written by someone who does not know Lua.
10 --
11 -- This requires cgit linked with Lua
12 -- Usage (in your cgitrc(5) config file):
13 --
14 --   source-filter=lua:/path/to/this/script.lua
15 --   about-filter=lua:/path/to/this/script.lua
16 --
17 local wwwhighlight_url = 'http://127.0.0.1:9090/'
18 local req_timeout = 10
19 local too_big = false
20
21 -- match $PublicInbox::HTTP::MAX_REQUEST_BUFFER
22 local max_len = 10 * 1024 * 1024
23
24 -- about-filter needs surrounding <pre> tags if all we do is
25 -- highlight and linkify
26 local pre = true
27
28 function filter_open(...)
29         req_body = ""
30
31         -- detect when we're used in an about-filter
32         local repo_url = os.getenv('CGIT_REPO_URL')
33         if repo_url then
34                 local path_info = os.getenv('PATH_INFO')
35                 rurl = path_info:match("^/(.+)/about/?$")
36                 pre = rurl == repo_url
37         end
38
39         -- hand filename off for language detection
40         local fn = select(1, ...)
41         if fn then
42                 local http_util = require 'http.util'
43                 wwwhighlight_url = wwwhighlight_url .. http_util.encodeURI(fn)
44         end
45 end
46
47 -- try to buffer the entire source in memory
48 function filter_write(str)
49         if too_big then
50                 html(str)
51         elseif (req_body:len() + str:len()) > max_len then
52                 too_big = true
53                 req_body = ""
54                 html(req_body)
55                 html(str)
56         else
57                 req_body = req_body .. str
58         end
59 end
60
61 function fail(err)
62         io.stderr:write(tostring(err), "\n")
63         if pre then
64                 html("<pre>")
65         end
66         html_txt(req_body)
67         if pre then
68                 html("</pre>")
69         end
70         return 1
71 end
72
73 function filter_close()
74         if too_big then
75                 return 0
76         end
77         local request = require 'http.request'
78         local req = request.new_from_uri(wwwhighlight_url)
79         req.headers:upsert(':method', 'PUT')
80         req:set_body(req_body)
81
82         -- don't wait for 100-Continue message from the PSGI app
83         req.headers:delete('expect')
84
85         local headers, stream = req:go(req_timeout)
86         if headers == nil then
87                 return fail(stream)
88         end
89         local status = headers:get(':status')
90         if status ~= '200' then
91                 return fail('status ' .. status)
92         end
93         local body, err = stream:get_body_as_string()
94         if not body and err then
95                 return fail(err)
96         end
97         if pre then
98                 html("<pre>")
99         end
100         html(body)
101         if pre then
102                 html("</pre>")
103         end
104         return 0
105 end