http
Встроенный модуль http отправляет HTTP- и HTTPS-запросы из скрипта. Запросы асинхронные: ответ приходит в колбэк, игра не ждёт сеть.
Модуль подключается через require и, как ffi, должен быть указан в зависимостях скрипта на сайте. Иначе require вернёт ошибку module 'http' needs to be stated in the 'requirements' section of the script. Модуль из зависимостей также сразу доступен как глобальная переменная http.
-- В зависимостях скрипта на сайте указан http
local http = require("http")
print(type(http.get)) --> function
- Поддерживаются только адреса
http://иhttps://. - Синхронного варианта нет: результат приходит только в колбэк.
- Колбэк вызывается в игровом потоке, не больше одного HTTP-колбэка за кадр. Несколько запросов можно отправить сразу, их ответы придут по одному в следующих кадрах.
- Ошибка внутри колбэка выводится в консоль, скрипт продолжает работать.
- При выключении скрипта его незавершённые запросы отменяются, колбэк не придёт. Игра при этом не зависает.
- Системный прокси Windows используется автоматически.
- Заголовки ответа скрипту не передаются: доступны только код ответа и тело.
http.get(url: string, options: table | nil, callback: function)#
Отправляет запрос GET.
| Параметр | Тип | Описание |
|---|---|---|
url |
string |
адрес запроса |
options |
table или nil |
опции запроса (см. «Опции запроса»). Любое значение, кроме таблицы, игнорируется |
callback |
function |
функция function(response), получает таблицу ответа (см. «Ответ») |
- Колбэк — всегда третий аргумент. Без опций передавайте
nil:http.get(url, nil, cb). Вызовhttp.get(url, cb)даёт ошибкуbad argument #3 ... (function expected, got nil). urlне строка — ошибкаbad argument #1 ... (string expected, got ...).
Возвращает: ничего.
local http = require("http")
http.get("https://httpbin.org/get", nil, function(r)
if r.error then
print("сетевая ошибка: ", r.error)
return
end
print("код ", r.status, ", длина ", #r.body)
end)
Другие методы#
http.head, http.post, http.put, http.delete, http.patch принимают те же аргументы, что http.get, и отправляют запрос с соответствующим методом.
| Функция | Метод | Куда идут params |
|---|---|---|
http.get(url, options, callback) |
GET |
в строку запроса |
http.head(url, options, callback) |
HEAD |
в строку запроса; тело ответа всегда пустое |
http.delete(url, options, callback) |
DELETE |
в строку запроса |
http.post(url, options, callback) |
POST |
в тело запроса |
http.put(url, options, callback) |
PUT |
в тело запроса |
http.patch(url, options, callback) |
PATCH |
в тело запроса |
post, put и patch без json и params отправляют пустое тело с Content-Type: application/x-www-form-urlencoded.
Возвращает: ничего.
local http = require("http")
http.put("https://httpbin.org/put", { json = '{"p":1}' }, function(r) print("PUT ", r.status) end)
http.patch("https://httpbin.org/patch", { params = { q = "w" } }, function(r) print("PATCH ", r.status) end)
http.delete("https://httpbin.org/delete", { params = { id = "1" } }, function(r) print("DELETE ", r.status) end)
http.head("https://httpbin.org/get", nil, function(r) print("HEAD ", r.status, " ", #r.body) end) --> HEAD 200 0
Опции запроса#
Таблица options. Все ключи необязательны, неизвестные ключи пропускаются. Ключ должен быть строкой, значение — указанного типа, иначе ошибка bad argument ... (<тип> expected, got ...).
| Ключ | Тип | Описание |
|---|---|---|
timeout |
number |
предел на весь запрос, секунды (включая все редиректы). По умолчанию 30. 0 или отрицательное значение — без предела. Дробная часть отбрасывается |
headers |
table |
заголовки запроса { ["Имя"] = "значение" }. Ключи и значения — только строки |
params |
table или string |
параметры. Таблица склеивается в k=v&k2=v2 (порядок — как у pairs), строка берётся как есть. У post/put/patch это тело запроса (Content-Type: application/x-www-form-urlencoded, если свой не задан в headers), у get/head/delete — строка запроса: к адресу дописывается ? или &, если ? уже есть |
json |
string |
тело запроса в виде готовой строки JSON и заголовок Content-Type: application/json. Если строка не пустая, params не используется. Работает с любым методом |
cookie |
cookies |
объект из http.cookies(): его cookies отправляются, а cookies из ответа записываются в него. Другое значение — ошибка cookies expected |
authorization |
table |
Basic-авторизация: { username = "...", password = "..." }. Оба поля обязательны и должны быть строками |
paramsне кодируются: пробелы,&,=, кириллицу и другие особые символы в значениях кодируйте сами в виде%XX. Пробел или управляющий символ в адресе даёт ошибкуinvalid_url. Кириллицу в адресе тоже лучше кодировать самим.
local http = require("http")
http.get("https://httpbin.org/get", {
timeout = 10,
headers = { ["X-Key"] = "secret" },
params = { page = "2", sort = "name" }, -- уйдёт как ?page=2&sort=name (порядок не гарантирован)
}, function(r)
print(r.status)
end)
http.get("https://httpbin.org/basic-auth/user1/pass1", {
authorization = { username = "user1", password = "pass1" },
}, function(r)
print(r.status) --> 200; с неверным паролем — 401
end)
Ответ#
Колбэк получает одну таблицу:
| Поле | Тип | Описание |
|---|---|---|
status |
number |
HTTP-код ответа. 0 — сетевая ошибка, ответа нет |
body |
string |
тело ответа; при сетевой ошибке и у head — пустая строка |
error |
string или nil |
причина сетевой ошибки. Если ошибки нет, поля нет (nil) |
- Коды 4xx и 5xx — обычный ответ:
statusиbodyзаполнены,errorнет. - Редиректы выполняются автоматически, до 50 переходов.
statusиbody— последнего ответа. На301,302,303запросPOSTповторяется какGETбез тела. - Тело приходит целиком, в том числе двоичное: это строка Lua с любыми байтами, включая нулевые.
local http = require("http")
http.get("https://httpbin.org/status/404", nil, function(r)
if r.error then
print("сеть: ", r.error)
elseif r.status ~= 200 then
print("сервер ответил ", r.status) --> сервер ответил 404
else
print(r.body)
end
end)
Ошибки сети#
При сетевой ошибке status = 0, body = "", а error — строка вида <вид> или <вид> (<код>), где код — системный код ошибки Windows. Проверяйте вид по началу строки, например r.error:find("^dns").
| Вид | Когда |
|---|---|
timeout |
истёк timeout запроса |
dns |
имя сервера не найдено |
connect |
не удалось соединиться или соединение оборвалось |
tls |
ошибка защищённого соединения или сертификата |
invalid_url |
неверный адрес (в том числе пробел в адресе) |
unsupported_scheme |
схема не http/https (например, ftp://) |
invalid_response |
сервер ответил не по протоколу HTTP |
proxy |
ошибка автонастройки системного прокси |
too_many_redirects |
больше 50 редиректов |
cancelled |
запрос отменён |
out_of_memory |
не хватило памяти под тело ответа |
response_too_large |
тело ответа больше наибольшей строки Lua |
winhttp |
прочие системные ошибки сети |
local http = require("http")
http.get("https://httpbin.org/delay/5", { timeout = 2 }, function(r)
if r.error == "timeout" then
print("сервер не ответил за 2 секунды")
elseif r.error then
print("сеть: ", r.error)
else
print(r.status)
end
end)
http.cookies()#
Создаёт пустой объект cookies. Передайте его в опцию cookie, чтобы запросы отправляли и сохраняли cookies, как браузер.
- Объект накапливает cookies из ответов (в том числе из промежуточных ответов при редиректах). Cookie с тем же именем, доменом и путём заменяет прежнюю, дублей нет. Cookie, удалённые сервером, убираются.
- Cookies записываются в объект перед вызовом колбэка и только если запрос завершился без сетевой ошибки.
- Прочитать содержимое объекта из скрипта нельзя: он только переносит cookies между запросами.
tostring(obj)возвращает"cookies". - Без опции
cookieзапрос не отправляет cookies.
Возвращает: cookies — новый объект.
local http = require("http")
local jar = http.cookies()
-- Сервер ставит cookie srv=abc и перенаправляет на /cookies
http.get("https://httpbin.org/cookies/set?srv=abc", { cookie = jar }, function(r)
-- Следующий запрос с тем же объектом отправит srv=abc
http.get("https://httpbin.org/cookies", { cookie = jar }, function(r2)
print(r2.body) --> { "cookies": { "srv": "abc" } }
end)
end)
cookies:set(fields: table)#
Добавляет cookie в объект вручную. Повторный вызов с тем же name, host и path заменяет значение.
| Поле | Тип | Описание |
|---|---|---|
host |
string |
домен, например "httpbin.org". По умолчанию "" |
name |
string |
имя. По умолчанию "" |
value |
string |
значение. По умолчанию "" |
path |
string |
путь, для которого действует cookie. По умолчанию "/" |
subdomains |
boolean |
действует и на поддоменах host. По умолчанию false |
secure |
boolean |
отправляется только по https://. По умолчанию false |
expire |
number |
срок действия, unix-время в секундах. По умолчанию 0 — до конца работы объекта |
Все поля необязательны, неизвестные пропускаются. Поле не того типа — ошибка bad argument ... (<тип> expected, got ...). Если аргумент не таблица — table expected.
Возвращает: ничего.
local http = require("http")
local jar = http.cookies()
jar:set({ host = "httpbin.org", name = "session", value = "1" })
jar:set({ host = "httpbin.org", name = "session", value = "2" }) -- заменит предыдущую
http.get("https://httpbin.org/cookies", { cookie = jar }, function(r)
print(r.body) --> { "cookies": { "session": "2" } }
end)
Пример: POST с JSON#
local http = require("http")
local body = json.encode({ name = "player", score = 10 })
http.post("https://httpbin.org/post", { json = body, timeout = 10 }, function(r)
if r.error then
print("сеть: ", r.error)
return
end
if r.status ~= 200 then
print("сервер ответил ", r.status)
return
end
local answer = json.decode(r.body)
print(answer.json.name) --> player
end)