From 14fd395f039a8e29a8e91e04444ab34e676d7643 Mon Sep 17 00:00:00 2001 From: Paul Kulchenko Date: Sun, 3 Jul 2022 12:00:48 -0700 Subject: [PATCH] Updated Fetch to return `nil,error` on errors --- tool/net/help.txt | 3 ++- tool/net/redbean.c | 65 +++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 37 deletions(-) diff --git a/tool/net/help.txt b/tool/net/help.txt index d0421d35a..a3daa5318 100644 --- a/tool/net/help.txt +++ b/tool/net/help.txt @@ -722,7 +722,8 @@ FUNCTIONS This function is not available in unsecure mode. Fetch(url:str[,body:str|{method=value:str,body=value:str,headers=table,...}]) - → status:int,{header:str=value:str,...},body:str + ├─→ status:int, {header:str=value:str,...}, body:str + └─→ nil, error:str Sends an HTTP/HTTPS request to the specified URL. If only the URL is provided, then a GET request is sent. If both URL and body parameters are specified, then a POST request is sent. If any other method needs diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 65d50997c..097b4fbbc 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -3642,17 +3642,6 @@ static void ReseedRng(mbedtls_ctr_drbg_context *r, const char *s) { #endif } -static wontreturn void LuaThrowTlsError(lua_State *L, const char *s, int r) { - const char *code; - code = gc(xasprintf("-0x%04x", -r)); - if (!IsTiny()) { - luaL_error(L, "tls %s failed (%s %s)", s, code, GetTlsError(r)); - } else { - luaL_error(L, "tls %s failed (grep %s)", s, code); - } - unreachable; -} - static void LogMessage(const char *d, const char *s, size_t n) { size_t n2, n3; char *s2, *s3; @@ -3682,6 +3671,21 @@ static void LogBody(const char *d, const char *s, size_t n) { } } +static int LuaNilError(lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + lua_pushnil(L); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + return 2; +} + +static int LuaNilTlsError(lua_State *L, const char *s, int r) { + return LuaNilError(L, "tls %s failed (%s %s)", s, + IsTiny() ? "grep" : GetTlsError(r), + gc(xasprintf("-0x%04x", -r))); +} + static int LuaFetch(lua_State *L) { #define ssl nope // TODO(jart): make this file less huge char *p; @@ -3739,11 +3743,11 @@ static int LuaFetch(lua_State *L) { if (lua_type(L, -2) == LUA_TSTRING) { // skip any non-string keys key = lua_tolstring(L, -2, &keylen); if (!IsValidHttpToken(key, keylen)) - return luaL_argerror(L, 2, "invalid header name"); + return LuaNilError(L, "invalid header name: %s", key); val = lua_tolstring(L, -1, &vallen); if (!(hdr = gc(EncodeHttpHeaderValue(val, vallen, 0)))) - return luaL_argerror(L, 2, "invalid header value encoding"); + return LuaNilError(L, "invalid header %s value encoding", key); // Content-Length and Connection will be overwritten; // skip them to avoid duplicates; @@ -3796,8 +3800,7 @@ static int LuaFetch(lua_State *L) { } else #endif if (!(url.scheme.n == 4 && !memcasecmp(url.scheme.p, "http", 4))) { - luaL_argerror(L, 1, "bad scheme"); - unreachable; + return LuaNilError(L, "bad scheme"); } } @@ -3824,8 +3827,7 @@ static int LuaFetch(lua_State *L) { gc(xasprintf("%d", servers.n ? ntohs(servers.p[0].addr.sin_port) : 80)); } if (!IsAcceptableHost(host, -1)) { - luaL_argerror(L, 1, "invalid host"); - unreachable; + return LuaNilError(L, "invalid host"); } if (!hosthdr) hosthdr = gc(xasprintf("%s:%s", host, port)); @@ -3860,9 +3862,8 @@ static int LuaFetch(lua_State *L) { */ DEBUGF("(ftch) client resolving %s", host); if ((rc = getaddrinfo(host, port, &hints, &addr)) != EAI_SUCCESS) { - luaL_error(L, "getaddrinfo(%s:%s) error: EAI_%s %s", host, port, - gai_strerror(rc), strerror(errno)); - unreachable; + return LuaNilError(L, "getaddrinfo(%s:%s) error: EAI_%s %s", host, port, + gai_strerror(rc), strerror(errno)); } /* @@ -3877,8 +3878,7 @@ static int LuaFetch(lua_State *L) { freeaddrinfo(addr), addr = 0; if (rc == -1) { close(sock); - luaL_error(L, "connect(%s:%s) error: %s", host, port, strerror(errno)); - unreachable; + return LuaNilError(L, "connect(%s:%s) error: %s", host, port, strerror(errno)); } #ifndef UNSECURE @@ -3907,8 +3907,7 @@ static int LuaFetch(lua_State *L) { goto VerifyFailed; default: close(sock); - LuaThrowTlsError(L, "handshake", ret); - unreachable; + return LuaNilTlsError(L, "handshake", ret); } } LockInc(&shared->c.sslhandshakes); @@ -3928,15 +3927,13 @@ static int LuaFetch(lua_State *L) { if (ret != requestlen) { if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) goto VerifyFailed; close(sock); - LuaThrowTlsError(L, "write", ret); - unreachable; + return LuaNilTlsError(L, "write", ret); } } else #endif if (WRITE(sock, request, requestlen) != requestlen) { close(sock); - luaL_error(L, "write error: %s", strerror(errno)); - unreachable; + return LuaNilError(L, "write error: %s", strerror(errno)); } if (logmessages) { LogMessage("sent", request, requestlen); @@ -3964,8 +3961,7 @@ static int LuaFetch(lua_State *L) { close(sock); free(inbuf.p); DestroyHttpMessage(&msg); - LuaThrowTlsError(L, "read", rc); - unreachable; + return LuaNilTlsError(L, "read", rc); } } } else @@ -3974,8 +3970,7 @@ static int LuaFetch(lua_State *L) { close(sock); free(inbuf.p); DestroyHttpMessage(&msg); - luaL_error(L, "read error: %s", strerror(errno)); - unreachable; + return LuaNilError(L, "read error: %s", strerror(errno)); } g = rc; inbuf.n += g; @@ -4118,16 +4113,14 @@ TransportError: DestroyHttpMessage(&msg); free(inbuf.p); close(sock); - luaL_error(L, "transport error"); - unreachable; + return LuaNilError(L, "transport error"); #ifndef UNSECURE VerifyFailed: LockInc(&shared->c.sslverifyfailed); close(sock); - LuaThrowTlsError( + return LuaNilTlsError( L, gc(DescribeSslVerifyFailure(sslcli.session_negotiate->verify_result)), ret); - unreachable; #endif #undef ssl }