Add HTTP/HTTPS Fetch() API to redbean

You can now say the following in your redbean Lua code:

    status,headers,payload = Fetch("https://foo.example")

The following Lua APIs have been introduced:

  - Fetch(str) → str,{str:str},str
  - GetHttpReason(int) → str
  - GetHttpReason(int) → str
  - ProgramSslFetchVerify(bool)
  - ProgramSslClientVerify(bool)

The following flags have been introduced:

  - `-j` enables client SSL verification
  - `-k` disables Fetch() SSL verification
  - `-t INT` may now be passed a negative value for keepalive

Lua exceptions now invoke Cosmopolitan's garbage collector when
unwinding the stack. So it's now safe to use _gc() w/ Lua 𝔱𝔥𝔯𝔬𝔴

See #97
This commit is contained in:
Justine Tunney 2021-07-07 21:44:27 -07:00
parent 36b2710e1a
commit c89bc56f6a
35 changed files with 1611 additions and 591 deletions

View file

@ -84,12 +84,14 @@ C(sslcantciphers)
C(sslhandshakefails)
C(sslhandshakes)
C(sslnociphers)
C(sslnoclientcert)
C(sslnoversion)
C(sslshakemacs)
C(ssltimeouts)
C(sslunknownca)
C(sslunknowncert)
C(sslupgrades)
C(sslverifyfailed)
C(statfails)
C(staticrequests)
C(stats)

74
tool/net/demo/fetch.lua Normal file
View file

@ -0,0 +1,74 @@
-- Fetch() API Demo
local function WriteForm(url)
Write('<!doctype html>\r\n')
Write(string.format([[
<title>redbean fetch demo</title>
<style>
body {
padding: 1em;
}
h1 a {
color: inherit;
text-decoration: none;
}
h1 img {
vertical-align: middle;
}
input {
margin: 1em;
padding: .5em;
}
p {
word-break: break-word;
}
p span {
display: block;
text-indent: -1em;
padding-left: 1em;
}
</style>
<h1>
<a href="/"><img src="/redbean.png"></a>
<a href="fetch.lua">redbean fetch demo</a>
</h1>
<form action="fetch.lua" method="post">
<input type="text" id="url" name="url" size="70"
value="%s" placeholder="uri" autofocus>
<input type="submit" value="fetch">
</form>
]], EscapeHtml(url)))
end
local function main()
if IsPublicIp(GetClientAddr()) then
ServeError(403)
elseif GetMethod() == 'GET' or GetMethod() == 'HEAD' then
WriteForm("https://www.cloudflare.com/robots.txt")
elseif GetMethod() == 'POST' then
status, headers, payload = Fetch(GetParam('url'))
WriteForm(GetParam('url'))
Write('<dl>\r\n')
Write('<dt>Status\r\n')
Write(string.format('<dd><p>%d %s\r\n', status, GetHttpReason(status)))
Write('<dt>Headers\r\n')
Write('<dd><p>\r\n')
for k,v in pairs(headers) do
Write('<span><strong>')
Write(EscapeHtml(k))
Write('</strong>: ')
Write(EscapeHtml(v))
Write('</span>\r\n')
end
Write('<dt>Payload\r\n')
Write('<dd><pre>')
Write(EscapeHtml(VisualizeControlCodes(payload)))
Write('</pre>\r\n')
Write('</dl>\r\n')
else
ServeError(405)
SetHeader('Allow', 'GET, HEAD, POST')
end
end
main()

View file

@ -1,2 +1,4 @@
StoreAsset('/hi', 'sup')
if not IsPublicIp(GetClientAddr()) then
StoreAsset('/hi', 'sup')
end
mymodule.hello()

View file

@ -34,8 +34,10 @@ FLAGS
-b log message bodies
-a log resource usage
-g log handler latency
-f log worker function calls
-j enable ssl client verify
-k disable ssl fetch verify
-B use stronger cryptography
-f log worker function calls
-s increase silence [repeatable]
-v increase verbosity [repeatable]
-V increase ssl verbosity [repeatable]
@ -45,8 +47,8 @@ FLAGS
-R /X=/Y rewrites X to Y [repeatable]
-K PATH tls private key path [repeatable]
-C PATH tls certificate(s) path [repeatable]
-t MS tunes read and write timeouts [def. 60000]
-M INT tunes max message payload size [def. 65536]
-t INT timeout ms or keepalive sec if <0 [def. 60000]
-p PORT listen port [def. 8080; repeatable]
-l ADDR listen addr [def. 0.0.0.0; repeatable]
-c SEC configures static cache-control

View file

@ -50,6 +50,7 @@ TOOL_NET_DIRECTDEPS = \
LIBC_X \
LIBC_ZIPOS \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LUA \
@ -130,6 +131,7 @@ o/$(MODE)/tool/net/redbean-demo.com: \
tool/net/demo/seekable.txt \
tool/net/demo/virtualbean.html \
tool/net/demo/printpayload.lua \
tool/net/demo/fetch.lua \
tool/net/redbean.c \
net/http/parsehttpmessage.c \
net/http/parseurl.c \
@ -145,10 +147,10 @@ o/$(MODE)/tool/net/redbean-demo.com: \
@(cd o/$(MODE)/tool/net && ../../host/third_party/infozip/zip.com -qr redbean-demo.com .lua)
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/hello.lua tool/net/demo/sql.lua
@echo "&lt;-- check out this lua server page" | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj $@ tool/net/demo/redbean.lua
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/demo/redbean-form.lua tool/net/demo/redbean-xhr.lua tool/net/demo/printpayload.lua
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/demo/redbean-form.lua tool/net/demo/redbean-xhr.lua tool/net/demo/printpayload.lua tool/net/demo/fetch.lua
@echo Uncompressed for HTTP Range requests | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj0 $@ tool/net/demo/seekable.txt
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -q $@ tool/net/ tool/net/demo/ tool/net/demo/index.html tool/net/demo/redbean.css tool/net/redbean.c net/http/parsehttpmessage.c net/http/parseurl.c net/http/encodeurl.c test/net/http/parsehttpmessage_test.c test/net/http/parseurl_test.c
@printf "<p>This is a live instance of <a href=https://justine.lol/redbean/>redbean</a>: a tiny multiplatform webserver that <a href=https://news.ycombinator.com/item?id=26271117>went viral</a> on hacker news a few months ago.\r\nSince then, we've added Lua dynamic serving, which also goes as fast as 1,000,000 requests per second on a core i9 (rather than a cheap virtual machine like this)\nin addition to SQLite and SSL. The text you're reading now is a PKZIP End Of Central Directory comment.\r\n<p>redbean aims to be production worthy across six operating systems, using a single executable file (this demo is hosted on FreeBSD 13). redbean has been enhanced to restore the APE header after startup.\r\nIt automatically generates this listing page based on your zip contents. If you use redbean as an application server / web development environment,\r\nthen you'll find other new and useful features like function call logging so you can get that sweet sweet microsecond scale latency." | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -z $@
@printf "<p>Thank you for using <a href=https://justine.lol/redbean/>redbean</a> the tiniest most vertically integrated actually portable web server with superior performance." | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -z $@
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/$(MODE)/tool/net/virtualbean.justine.lol/
@$(COMPILE) -ACP -T$@ cp tool/net/redbean.png o/$(MODE)/tool/net/virtualbean.justine.lol/redbean.png
@$(COMPILE) -ACP -T$@ cp tool/net/demo/virtualbean.html o/$(MODE)/tool/net/virtualbean.justine.lol/index.html

File diff suppressed because it is too large Load diff