perform a HTTP/HTTPS request * Perform a HTTP/HTTPS request. * * [icon:attention] If no timeout value is passed, the configuration value "network.http_timeout" is used. If that is not set, the timeout value is `0` (which blocks indefinitely). * * @name http.request * @param url [type:string] target url * @param method [type:string] HTTP/HTTPS method, e.g. "GET",
| 131 | * ``` |
| 132 | */ |
| 133 | static int Http_Request(lua_State* L) |
| 134 | { |
| 135 | int top = lua_gettop(L); |
| 136 | |
| 137 | dmMessage::URL sender; |
| 138 | if (dmScript::GetURL(L, &sender)) { |
| 139 | |
| 140 | const char* url = luaL_checkstring(L, 1); |
| 141 | const uint32_t max_url_len = dmURI::MAX_URI_LEN; |
| 142 | const uint32_t url_len = (uint32_t)strlen(url); |
| 143 | if (url_len > max_url_len) |
| 144 | { |
| 145 | assert(top == lua_gettop(L)); |
| 146 | return luaL_error(L, "http.request does not support URIs longer than %d characters.", max_url_len); |
| 147 | } |
| 148 | |
| 149 | const char* method = luaL_checkstring(L, 2); |
| 150 | const uint32_t max_method_len = 16; |
| 151 | const uint32_t method_len = (uint32_t)strlen(method); |
| 152 | if (method_len > max_method_len) { |
| 153 | assert(top == lua_gettop(L)); |
| 154 | return luaL_error(L, "http.request does not support request methods longer than %d characters.", max_method_len); |
| 155 | } |
| 156 | |
| 157 | // The callback is called from CompScriptOnMessage in comp_script.cpp |
| 158 | luaL_checktype(L, 3, LUA_TFUNCTION); |
| 159 | lua_pushvalue(L, 3); |
| 160 | // NOTE: By convention m_FunctionRef is offset by LUA_NOREF, in order to have 0 for "no function" |
| 161 | int callback = dmScript::RefInInstance(L) - LUA_NOREF; |
| 162 | |
| 163 | char* headers = 0; |
| 164 | int headers_length = 0; |
| 165 | if (top > 3 && !lua_isnil(L, 4)) { |
| 166 | dmArray<char> h; |
| 167 | h.SetCapacity(4 * 1024); |
| 168 | |
| 169 | luaL_checktype(L, 4, LUA_TTABLE); |
| 170 | lua_pushvalue(L, 4); |
| 171 | lua_pushnil(L); |
| 172 | while (lua_next(L, -2)) { |
| 173 | const char* attr = lua_tostring(L, -2); |
| 174 | const char* val = lua_tostring(L, -1); |
| 175 | if (attr && val) { |
| 176 | uint32_t left = h.Capacity() - h.Size(); |
| 177 | uint32_t required = strlen(attr) + strlen(val) + 2; |
| 178 | if (left < required) { |
| 179 | h.OffsetCapacity(dmMath::Max(required, 1024U)); |
| 180 | } |
| 181 | h.PushArray(attr, strlen(attr)); |
| 182 | h.Push(':'); |
| 183 | h.PushArray(val, strlen(val)); |
| 184 | h.Push('\n'); |
| 185 | } else { |
| 186 | // luaL_error would be nice but that would evade call to 'h' destructor |
| 187 | dmLogWarning("Ignoring non-string data passed as http request header data"); |
| 188 | } |
| 189 | lua_pop(L, 1); |
| 190 | } |
nothing calls this directly
no test coverage detected