mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-19 21:34:40 +00:00
Improve redbean fetch() (#460)
* Updated Fetch to return `nil,error` on errors * Fix localhost connect when only IP address is specified
This commit is contained in:
parent
853b6c3864
commit
059fe22ea3
2 changed files with 35 additions and 42 deletions
|
@ -722,7 +722,8 @@ FUNCTIONS
|
||||||
This function is not available in unsecure mode.
|
This function is not available in unsecure mode.
|
||||||
|
|
||||||
Fetch(url:str[,body:str|{method=value:str,body=value:str,headers=table,...}])
|
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
|
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
|
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
|
are specified, then a POST request is sent. If any other method needs
|
||||||
|
|
|
@ -3641,17 +3641,6 @@ static void ReseedRng(mbedtls_ctr_drbg_context *r, const char *s) {
|
||||||
#endif
|
#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) {
|
static void LogMessage(const char *d, const char *s, size_t n) {
|
||||||
size_t n2, n3;
|
size_t n2, n3;
|
||||||
char *s2, *s3;
|
char *s2, *s3;
|
||||||
|
@ -3681,6 +3670,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) {
|
static int LuaFetch(lua_State *L) {
|
||||||
#define ssl nope // TODO(jart): make this file less huge
|
#define ssl nope // TODO(jart): make this file less huge
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -3738,11 +3742,11 @@ static int LuaFetch(lua_State *L) {
|
||||||
if (lua_type(L, -2) == LUA_TSTRING) { // skip any non-string keys
|
if (lua_type(L, -2) == LUA_TSTRING) { // skip any non-string keys
|
||||||
key = lua_tolstring(L, -2, &keylen);
|
key = lua_tolstring(L, -2, &keylen);
|
||||||
if (!IsValidHttpToken(key, 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);
|
val = lua_tolstring(L, -1, &vallen);
|
||||||
if (!(hdr = gc(EncodeHttpHeaderValue(val, vallen, 0))))
|
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;
|
// Content-Length and Connection will be overwritten;
|
||||||
// skip them to avoid duplicates;
|
// skip them to avoid duplicates;
|
||||||
|
@ -3795,8 +3799,7 @@ static int LuaFetch(lua_State *L) {
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (!(url.scheme.n == 4 && !memcasecmp(url.scheme.p, "http", 4))) {
|
if (!(url.scheme.n == 4 && !memcasecmp(url.scheme.p, "http", 4))) {
|
||||||
luaL_argerror(L, 1, "bad scheme");
|
return LuaNilError(L, "bad scheme");
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3815,16 +3818,14 @@ static int LuaFetch(lua_State *L) {
|
||||||
} else {
|
} else {
|
||||||
port = "80";
|
port = "80";
|
||||||
}
|
}
|
||||||
|
} else if ((ip = ParseIp(urlarg, -1)) != -1) {
|
||||||
|
host = urlarg;
|
||||||
|
port = "80";
|
||||||
} else {
|
} else {
|
||||||
ip = servers.n ? ntohl(servers.p[0].addr.sin_addr.s_addr) : INADDR_LOOPBACK;
|
return LuaNilError(L, "invalid host");
|
||||||
host =
|
|
||||||
gc(xasprintf("%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16, ip >> 8, ip));
|
|
||||||
port =
|
|
||||||
gc(xasprintf("%d", servers.n ? ntohs(servers.p[0].addr.sin_port) : 80));
|
|
||||||
}
|
}
|
||||||
if (!IsAcceptableHost(host, -1)) {
|
if (!IsAcceptableHost(host, -1)) {
|
||||||
luaL_argerror(L, 1, "invalid host");
|
return LuaNilError(L, "invalid host");
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
if (!hosthdr) hosthdr = gc(xasprintf("%s:%s", host, port));
|
if (!hosthdr) hosthdr = gc(xasprintf("%s:%s", host, port));
|
||||||
|
|
||||||
|
@ -3859,9 +3860,8 @@ static int LuaFetch(lua_State *L) {
|
||||||
*/
|
*/
|
||||||
DEBUGF("(ftch) client resolving %s", host);
|
DEBUGF("(ftch) client resolving %s", host);
|
||||||
if ((rc = getaddrinfo(host, port, &hints, &addr)) != EAI_SUCCESS) {
|
if ((rc = getaddrinfo(host, port, &hints, &addr)) != EAI_SUCCESS) {
|
||||||
luaL_error(L, "getaddrinfo(%s:%s) error: EAI_%s %s", host, port,
|
return LuaNilError(L, "getaddrinfo(%s:%s) error: EAI_%s %s", host, port,
|
||||||
gai_strerror(rc), strerror(errno));
|
gai_strerror(rc), strerror(errno));
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3876,8 +3876,7 @@ static int LuaFetch(lua_State *L) {
|
||||||
freeaddrinfo(addr), addr = 0;
|
freeaddrinfo(addr), addr = 0;
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
close(sock);
|
close(sock);
|
||||||
luaL_error(L, "connect(%s:%s) error: %s", host, port, strerror(errno));
|
return LuaNilError(L, "connect(%s:%s) error: %s", host, port, strerror(errno));
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef UNSECURE
|
#ifndef UNSECURE
|
||||||
|
@ -3906,8 +3905,7 @@ static int LuaFetch(lua_State *L) {
|
||||||
goto VerifyFailed;
|
goto VerifyFailed;
|
||||||
default:
|
default:
|
||||||
close(sock);
|
close(sock);
|
||||||
LuaThrowTlsError(L, "handshake", ret);
|
return LuaNilTlsError(L, "handshake", ret);
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LockInc(&shared->c.sslhandshakes);
|
LockInc(&shared->c.sslhandshakes);
|
||||||
|
@ -3927,15 +3925,13 @@ static int LuaFetch(lua_State *L) {
|
||||||
if (ret != requestlen) {
|
if (ret != requestlen) {
|
||||||
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) goto VerifyFailed;
|
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) goto VerifyFailed;
|
||||||
close(sock);
|
close(sock);
|
||||||
LuaThrowTlsError(L, "write", ret);
|
return LuaNilTlsError(L, "write", ret);
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (WRITE(sock, request, requestlen) != requestlen) {
|
if (WRITE(sock, request, requestlen) != requestlen) {
|
||||||
close(sock);
|
close(sock);
|
||||||
luaL_error(L, "write error: %s", strerror(errno));
|
return LuaNilError(L, "write error: %s", strerror(errno));
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
if (logmessages) {
|
if (logmessages) {
|
||||||
LogMessage("sent", request, requestlen);
|
LogMessage("sent", request, requestlen);
|
||||||
|
@ -3963,8 +3959,7 @@ static int LuaFetch(lua_State *L) {
|
||||||
close(sock);
|
close(sock);
|
||||||
free(inbuf.p);
|
free(inbuf.p);
|
||||||
DestroyHttpMessage(&msg);
|
DestroyHttpMessage(&msg);
|
||||||
LuaThrowTlsError(L, "read", rc);
|
return LuaNilTlsError(L, "read", rc);
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -3973,8 +3968,7 @@ static int LuaFetch(lua_State *L) {
|
||||||
close(sock);
|
close(sock);
|
||||||
free(inbuf.p);
|
free(inbuf.p);
|
||||||
DestroyHttpMessage(&msg);
|
DestroyHttpMessage(&msg);
|
||||||
luaL_error(L, "read error: %s", strerror(errno));
|
return LuaNilError(L, "read error: %s", strerror(errno));
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
g = rc;
|
g = rc;
|
||||||
inbuf.n += g;
|
inbuf.n += g;
|
||||||
|
@ -4117,16 +4111,14 @@ TransportError:
|
||||||
DestroyHttpMessage(&msg);
|
DestroyHttpMessage(&msg);
|
||||||
free(inbuf.p);
|
free(inbuf.p);
|
||||||
close(sock);
|
close(sock);
|
||||||
luaL_error(L, "transport error");
|
return LuaNilError(L, "transport error");
|
||||||
unreachable;
|
|
||||||
#ifndef UNSECURE
|
#ifndef UNSECURE
|
||||||
VerifyFailed:
|
VerifyFailed:
|
||||||
LockInc(&shared->c.sslverifyfailed);
|
LockInc(&shared->c.sslverifyfailed);
|
||||||
close(sock);
|
close(sock);
|
||||||
LuaThrowTlsError(
|
return LuaNilTlsError(
|
||||||
L, gc(DescribeSslVerifyFailure(sslcli.session_negotiate->verify_result)),
|
L, gc(DescribeSslVerifyFailure(sslcli.session_negotiate->verify_result)),
|
||||||
ret);
|
ret);
|
||||||
unreachable;
|
|
||||||
#endif
|
#endif
|
||||||
#undef ssl
|
#undef ssl
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue