mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 04:08:32 +00:00
Add /statusz page to redbean plus other enhancements
redbean improvements: - Explicitly disable corking - Simulate Python regex API for Lua - Send warmup requests in main process on startup - Add Class-A granular IPv4 network classification - Add /statusz page so you can monitor your redbean's health - Fix regressions on OpenBSD/NetBSD caused by recent changes - Plug Authorization header into Lua GetUser and GetPass APIs - Recognize X-Forwarded-{For,Host} from local reverse proxies - Add many additional functions to redbean Lua server page API - Report resource usage of child processes on `/` listing page - Introduce `-a` flag for logging child process resource usage - Introduce `-t MILLIS` flag and `ProgramTimeout(ms)` init API - Introduce `-H "Header: value"` flag and `ProgramHeader(k,v)` API Cosmopolitan Libc improvements: - Make strerror() simpler - Make inet_pton() not depend on sscanf() - Fix OpenExecutable() which broke .data section earlier - Fix stdio in cases where it overflows kernel tty buffer - Fix bugs in crash reporting w/o .com.dbg binary present - Add polyfills for SO_LINGER, SO_RCVTIMEO, and SO_SNDTIMEO - Polyfill TCP_CORK on BSD and XNU using TCP_NOPUSH magnums New netcat clone in examples/nc.c: While testing some of the failure conditions for redbean, I noticed that BusyBox's `nc` command is pretty busted, if you use it as an interactive tool, rather than having it be part of a pipeline. Unfortunately this'll only work on UNIX since Windows doesn't let us poll on stdio and sockets at the same time because I don't think they want tools like this running on their platform. So if you want forbidden fruit, it's here so enjoy it
This commit is contained in:
parent
4effa23528
commit
b107d2709f
163 changed files with 4425 additions and 2104 deletions
|
@ -71,6 +71,7 @@ o/$(MODE)/tool/net/redbean.com.dbg: \
|
|||
|
||||
o/$(MODE)/tool/net/redbean.com: \
|
||||
o/$(MODE)/tool/net/redbean.com.dbg \
|
||||
tool/net/net.mk \
|
||||
tool/net/favicon.ico \
|
||||
tool/net/redbean.png \
|
||||
tool/net/.init.lua \
|
||||
|
@ -80,9 +81,13 @@ o/$(MODE)/tool/net/redbean.com: \
|
|||
@$(COMPILE) -AZIP -T$@ zip -qj $@ o/$(MODE)/tool/net/.ape tool/net/.init.lua tool/net/.reload.lua tool/net/favicon.ico tool/net/redbean.png
|
||||
|
||||
o/$(MODE)/tool/net/redbean-demo.com: \
|
||||
o/$(MODE)/tool/net/redbean.com \
|
||||
o/$(MODE)/tool/net/redbean.com.dbg \
|
||||
tool/net/net.mk \
|
||||
tool/net/.init.lua \
|
||||
tool/net/.reload.lua \
|
||||
tool/net/404.html \
|
||||
tool/net/favicon.ico \
|
||||
tool/net/redbean.png \
|
||||
tool/net/index.html \
|
||||
tool/net/redbean.css \
|
||||
tool/net/redbean.lua \
|
||||
|
@ -95,9 +100,9 @@ o/$(MODE)/tool/net/redbean-demo.com: \
|
|||
net/http/encodeurl.c \
|
||||
test/net/http/parsehttprequest_test.c \
|
||||
test/net/http/parseurl_test.c
|
||||
@$(COMPILE) -ACP -T$@ cp $< $@
|
||||
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||
@$(COMPILE) -ADD -T$@ dd if=$@ of=o/$(MODE)/tool/net/.ape bs=64 count=11 conv=notrunc 2>/dev/null
|
||||
@$(COMPILE) -AZIP -T$@ zip -qj $@ o/$(MODE)/tool/net/.ape tool/net/404.html tool/net/redbean.lua tool/net/redbean-form.lua tool/net/redbean-xhr.lua
|
||||
@$(COMPILE) -AZIP -T$@ zip -qj $@ o/$(MODE)/tool/net/.ape tool/net/.init.lua tool/net/.reload.lua tool/net/redbean.lua tool/net/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/redbean-form.lua tool/net/redbean-xhr.lua
|
||||
@$(COMPILE) -AZIP -T$@ zip -qj0 $@ tool/net/seekable.txt
|
||||
@$(COMPILE) -AZIP -T$@ zip -q $@ tool/net tool/net/index.html tool/net/redbean.css tool/net/redbean.c net/http/parsehttprequest.c net/http/parseurl.c net/http/encodeurl.c test/net/http/parsehttprequest_test.c test/net/http/parseurl_test.c
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ local function main()
|
|||
lastname = GetParam('lastname')
|
||||
if firstname and lastname then
|
||||
Write('Hello ')
|
||||
Write(EscapeHtml(firstname))
|
||||
Write(EscapeHtml(VisualizeControlCodes(firstname)))
|
||||
Write(' ')
|
||||
Write(EscapeHtml(lastname))
|
||||
Write(EscapeHtml(VisualizeControlCodes(lastname)))
|
||||
Write('!<br>')
|
||||
Write('Thank you for using redbean.')
|
||||
end
|
||||
|
@ -32,11 +32,11 @@ local function main()
|
|||
params = GetParams()
|
||||
for i = 1,#params do
|
||||
Write('<dt>')
|
||||
Write(EscapeHtml(params[i][1]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(params[i][1])))
|
||||
Write('\r\n')
|
||||
if params[i][2] then
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(params[i][2]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(params[i][2])))
|
||||
Write('\r\n')
|
||||
end
|
||||
end
|
||||
|
@ -57,7 +57,7 @@ local function main()
|
|||
|
||||
Write('<dt>Payload\r\n')
|
||||
Write('<dd><p>')
|
||||
Write(EscapeHtml(GetPayload()))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetPayload())))
|
||||
Write('\r\n')
|
||||
|
||||
Write('</dl>\r\n')
|
||||
|
|
2506
tool/net/redbean.c
2506
tool/net/redbean.c
File diff suppressed because it is too large
Load diff
|
@ -1,19 +1,5 @@
|
|||
-- redbean lua server page demo
|
||||
|
||||
local function DescribeIp(ip)
|
||||
Write(' <small>[')
|
||||
if IsPrivateIp(ip) then
|
||||
Write('PRIVATE')
|
||||
elseif IsTestIp(ip) then
|
||||
Write('TESTNET')
|
||||
elseif IsLocalIp(ip) then
|
||||
Write('LOCALNET')
|
||||
else
|
||||
Write('PUBLIC')
|
||||
end
|
||||
Write(']</small>')
|
||||
end
|
||||
|
||||
local function main()
|
||||
-- This is the best way to print data to the console or log file.
|
||||
Log(kLogWarn, "hello from \e[1mlua\e[0m!")
|
||||
|
@ -34,7 +20,12 @@ local function main()
|
|||
-- Compression is applied automatically, based on your headers.
|
||||
Write('<!doctype html>\r\n')
|
||||
Write('<title>redbean</title>\r\n')
|
||||
Write('<h1>redbean lua server page demo</h1>\r\n')
|
||||
Write('<h1>\r\n')
|
||||
Write('<img style="vertical-align:middle" src="data:image/png;base64,\r\n')
|
||||
Write(EncodeBase64(LoadAsset('/redbean.png')))
|
||||
Write('">\r\n')
|
||||
Write('redbean lua server page demo\r\n')
|
||||
Write('</h1>\r\n')
|
||||
|
||||
-- Prevent caching.
|
||||
-- We need this because we're doing things like putting the client's
|
||||
|
@ -55,11 +46,11 @@ local function main()
|
|||
Write('<dl>\r\n')
|
||||
for i = 1,#params do
|
||||
Write('<dt>')
|
||||
Write(EscapeHtml(params[i][1]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(params[i][1])))
|
||||
Write('\r\n')
|
||||
if params[i][2] then
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(params[i][2]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(params[i][2])))
|
||||
Write('\r\n')
|
||||
end
|
||||
end
|
||||
|
@ -68,7 +59,7 @@ local function main()
|
|||
Write('<p>\r\n')
|
||||
Write('<em>none</em><br>\r\n')
|
||||
Write('ProTip: Try <a href="')
|
||||
Write(EscapeHtml(EscapePath(GetPath()) .. '?x=hi%20there&y&z&z=' .. EscapeParam('&')))
|
||||
Write(EscapeHtml(EscapePath(GetPath()) .. '?x=hi%20there%00%C0%80&y&z&z=' .. EscapeParam('&')))
|
||||
Write('">clicking here</a>!\r\n')
|
||||
end
|
||||
|
||||
|
@ -79,7 +70,7 @@ local function main()
|
|||
Write('<ul>\r\n')
|
||||
for i = 1,#argv do
|
||||
Write('<li>')
|
||||
Write(EscapeHtml(argv[i]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(argv[i])))
|
||||
Write('\r\n')
|
||||
end
|
||||
Write('</ul>\r\n')
|
||||
|
@ -120,22 +111,6 @@ local function main()
|
|||
</script>
|
||||
]])
|
||||
|
||||
Write('<h3>statistics</h3>\r\n')
|
||||
Write('<dl>\r\n')
|
||||
Write('<dt>GetStatistics().workers\r\n')
|
||||
Write('<dd>')
|
||||
Write(tostring(GetStatistics().workers))
|
||||
Write('\r\n')
|
||||
Write('<dt>GetStatistics().requestshandled\r\n')
|
||||
Write('<dd>')
|
||||
Write(tostring(GetStatistics().requestshandled))
|
||||
Write('\r\n')
|
||||
Write('<dt>GetStatistics().uptime\r\n')
|
||||
Write('<dd>')
|
||||
Write(tostring(GetStatistics().uptime))
|
||||
Write(' seconds\r\n')
|
||||
Write('</dl>\r\n')
|
||||
|
||||
-- fast redbean apis for accessing already parsed request data
|
||||
Write('<h3>extra information</h3>\r\n')
|
||||
Write('<dl>\r\n')
|
||||
|
@ -146,7 +121,7 @@ local function main()
|
|||
if GetUser() then
|
||||
Write('<dt>GetUser()\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(GetUser()))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetUser())))
|
||||
Write('\r\n')
|
||||
end
|
||||
if GetScheme() then
|
||||
|
@ -158,44 +133,57 @@ local function main()
|
|||
if GetPass() then
|
||||
Write('<dt>GetPass()\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(GetPass()))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetPass())))
|
||||
Write('\r\n')
|
||||
end
|
||||
Write('<dt>GetHost() <small>(from HTTP Request-URL or Host header)</small>\r\n')
|
||||
Write('<dt>GetHost() <small>(from HTTP Request-URI or Host header or X-Forwarded-Host header or Berkeley Sockets)</small>\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(GetHost()))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetHost())))
|
||||
Write('\r\n')
|
||||
Write('<dt>GetPort() <small>(from HTTP Request-URL or Host header)</small>\r\n')
|
||||
Write('<dt>GetPort() <small>(from HTTP Request-URI or Host header or X-Forwarded-Host header or Berkeley Sockets)</small>\r\n')
|
||||
Write('<dd>')
|
||||
Write(tostring(GetPort()))
|
||||
Write('\r\n')
|
||||
Write('<dt>GetPath()\r\n')
|
||||
Write('<dt>GetPath() <small>(from HTTP Request-URI)</small>\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(GetPath()))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetPath())))
|
||||
Write('\r\n')
|
||||
Write('<dt>GetEffectivePath() <small>(actual path used internally to load the lua asset: routed depending on host, request path, and rewrites)</small>\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetEffectivePath())))
|
||||
Write('\r\n')
|
||||
if GetFragment() then
|
||||
Write('<dt>GetFragment()\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(GetFragment()))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetFragment())))
|
||||
Write('\r\n')
|
||||
end
|
||||
Write('<dt>GetClientIp()\r\n')
|
||||
Write('<dt>GetRemoteAddr() <small>(from Bekeley Sockets or X-Forwarded-For header)</small>\r\n')
|
||||
Write('<dd>')
|
||||
Write(FormatIp(GetClientIp()))
|
||||
DescribeIp(GetClientIp())
|
||||
ip, port = GetRemoteAddr()
|
||||
Write(string.format('%s, %d', FormatIp(ip), port))
|
||||
if CategorizeIp(ip) then
|
||||
Write('<br>\r\n')
|
||||
Write(CategorizeIp(ip))
|
||||
end
|
||||
Write('\r\n')
|
||||
Write('<dt>GetClientPort()\r\n')
|
||||
Write('<dt>GetClientAddr()\r\n')
|
||||
Write('<dd>')
|
||||
Write(tostring(GetClientPort()))
|
||||
ip, port = GetClientAddr()
|
||||
Write(string.format('%s, %d', FormatIp(ip), port))
|
||||
if CategorizeIp(ip) then
|
||||
Write('<br>\r\n')
|
||||
Write(CategorizeIp(ip))
|
||||
end
|
||||
Write('\r\n')
|
||||
Write('<dt>GetServerIp()\r\n')
|
||||
Write('<dd>')
|
||||
Write(FormatIp(GetServerIp()))
|
||||
DescribeIp(GetServerIp())
|
||||
Write('\r\n')
|
||||
Write('<dt>GetServerPort()\r\n')
|
||||
Write('<dd>')
|
||||
Write(tostring(GetServerPort()))
|
||||
ip, port = GetServerAddr()
|
||||
Write(string.format('%s, %d', FormatIp(ip), port))
|
||||
if CategorizeIp(ip) then
|
||||
Write('<br>\r\n')
|
||||
Write(CategorizeIp(ip))
|
||||
end
|
||||
Write('\r\n')
|
||||
Write('</dl>\r\n')
|
||||
|
||||
|
@ -213,32 +201,32 @@ local function main()
|
|||
if url.scheme then
|
||||
Write('<dt>scheme\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.scheme))
|
||||
Write(url.scheme)
|
||||
end
|
||||
if url.user then
|
||||
Write('<dt>user\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.user))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.user)))
|
||||
end
|
||||
if url.pass then
|
||||
Write('<dt>pass\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.pass))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.pass)))
|
||||
end
|
||||
if url.host then
|
||||
Write('<dt>host\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.host))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.host)))
|
||||
end
|
||||
if url.port then
|
||||
Write('<dt>port\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.port))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.port)))
|
||||
end
|
||||
if url.path then
|
||||
Write('<dt>path\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.path))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.path)))
|
||||
end
|
||||
if url.params then
|
||||
Write('<dt>params\r\n')
|
||||
|
@ -246,11 +234,11 @@ local function main()
|
|||
Write('<dl>\r\n')
|
||||
for i = 1,#url.params do
|
||||
Write('<dt>')
|
||||
Write(EscapeHtml(url.params[i][1]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.params[i][1])))
|
||||
Write('\r\n')
|
||||
if url.params[i][2] then
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(url.params[i][2]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.params[i][2])))
|
||||
Write('\r\n')
|
||||
end
|
||||
end
|
||||
|
@ -259,42 +247,52 @@ local function main()
|
|||
if url.fragment then
|
||||
Write('<dt>fragment\r\n')
|
||||
Write('<dd>\r\n')
|
||||
Write(EscapeHtml(url.fragment))
|
||||
Write(EscapeHtml(VisualizeControlCodes(url.fragment)))
|
||||
end
|
||||
Write('</dl>\r\n')
|
||||
end
|
||||
|
||||
Write('<h3>posix extended regular expressions</h3>\r\n')
|
||||
s = 'my ' .. FormatIp(GetClientIp()) .. ' ip'
|
||||
r = CompileRegex('([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})', 'e')
|
||||
m,a,b,c,d = ExecuteRegex(r, s)
|
||||
s = 'my ' .. FormatIp(GetRemoteAddr()) .. ' ip'
|
||||
-- traditional regular expressions
|
||||
m,a,b,c,d = re.search([[\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)]], s, re.BASIC)
|
||||
-- easy api (~10x slower because compile is O(2ⁿ) and search is O(n))
|
||||
m,a,b,c,d = re.search([[([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})]], s)
|
||||
-- proper api (especially if you put the re.compile() line in /.init.lua)
|
||||
pat = re.compile([[([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})]])
|
||||
m,a,b,c,d = pat:search(s) -- m and rest are nil if match not found
|
||||
Write('<pre>\r\n')
|
||||
Write(string.format([[m,a,b,c,d = ExecuteRegex(CompileRegex('([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})', 'e'), %q)]], s))
|
||||
Write([[pat = re.compile('([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})', re.EXTENDED)]])
|
||||
Write(string.format('\r\nm,a,b,c,d = pat:search(%q)\r\n', s))
|
||||
Write('</pre>\r\n')
|
||||
ReleaseRegex(r)
|
||||
Write('<dl>\r\n')
|
||||
Write('<dt>m\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(tostring(m)))
|
||||
Write(tostring(m))
|
||||
Write('\r\n')
|
||||
Write('<dt>a\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(tostring(a)))
|
||||
Write(tostring(a))
|
||||
Write('\r\n')
|
||||
Write('<dt>b\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(tostring(b)))
|
||||
Write(tostring(b))
|
||||
Write('\r\n')
|
||||
Write('<dt>c\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(tostring(c)))
|
||||
Write(tostring(c))
|
||||
Write('\r\n')
|
||||
Write('<dt>d\r\n')
|
||||
Write('<dd>')
|
||||
Write(EscapeHtml(tostring(d)))
|
||||
Write(tostring(d))
|
||||
Write('\r\n')
|
||||
Write('</dl>\r\n')
|
||||
|
||||
Write('<h3>source code to this page</h3>\r\n')
|
||||
Write('<pre>\r\n')
|
||||
Write(EscapeHtml(LoadAsset(GetEffectivePath())))
|
||||
Write('</pre>\r\n')
|
||||
|
||||
-- redbean zip assets
|
||||
Write('<h3>zip assets</h3>\r\n')
|
||||
paths = GetZipPaths()
|
||||
|
@ -305,7 +303,7 @@ local function main()
|
|||
Write('<a href="')
|
||||
Write(EscapeHtml(EscapePath(paths[i])))
|
||||
Write('">')
|
||||
Write(EscapeHtml(paths[i]))
|
||||
Write(EscapeHtml(VisualizeControlCodes(paths[i])))
|
||||
Write('</a>')
|
||||
if IsHiddenPath(paths[i]) then
|
||||
Write(' <small>[HIDDEN]</small>')
|
||||
|
@ -331,7 +329,7 @@ local function main()
|
|||
Write('<br>\r\n')
|
||||
if GetComment(paths[i]) then
|
||||
Write('Comment: ')
|
||||
Write(EscapeHtml(GetComment(paths[i])))
|
||||
Write(EscapeHtml(VisualizeControlCodes(GetComment(paths[i]))))
|
||||
Write('<br>\r\n')
|
||||
end
|
||||
Write('\r\n')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue