Rest
libraryHTTP client for REST and other web APIs. Responses come back as a table with status, body, headers and cookies; there is no response object to close. Things to know: HTTP error statuses (4xx, 5xx) are returned, not raised, so assert on response.status. Network failures and timeouts raise an error. Redirects are followed. Settings made with bearer(), basic(), timeout(), cookie() and the certificate functions stay active for the rest of the script run and apply to all later requests. TLS certificates are verified unless disableCertificateValidation() is called. Request bodies are text sent as UTF-8; encode tables with Json.encode first. Keep credentials in secrets: secret("name"). Headers can be given as a map, {["Content-Type"] = "application/json"}, which replaces a header of the same name, or as a list of "Name:value" strings, {"X-Trace:abc", "X-Trace:def"}, which adds a header and allows duplicates. List entries without a colon are ignored. In responses, header names are available in their original casing and in lower case, and a header that occurs more than once is a list of values.
- Kind Library, a global in every script
- Category APIs & Data
- Functions 21
Example
Session login followed by an authenticated call
-- Log in, keep the session cookie, call an endpointRest.timeout(15000)local login = Rest.post( "https://app.example.com/api/login", { ["Content-Type"] = "application/json" }, Json.encode({ user = "alice", password = secret("app_password") }))Assert.equals(200, login.status)
local response = Rest.get("https://app.example.com/api/orders?status=open", { Accept = "application/json" })Assert.equals(200, response.status)print(response.headers["content-type"])local orders = Json.decode(response.body)Functions
-
getHttpResponse Sends a GET request and returns the response. -
postHttpResponse Sends a POST request with a text body and returns the response. -
putHttpResponse Sends a PUT request with a text body and returns the response. -
patchHttpResponse Sends a PATCH request with a text body and returns the response. -
deleteHttpResponse Sends a DELETE request and returns the response. -
multipartHttpResponse Sends a multipart/form-data POST request, for example a file upload. -
downloadDownloadResponse Sends a GET request and saves the response body to a file in the project. -
bearerself Sets a default "Authorization: Bearer TOKEN" header that is sent with every later request, to any host, until it is replaced by basic() or removed with clearAuth(). -
basicself Sets a default "Authorization: Basic BASE64(username:password)" header that is sent with every later request, to any host, until it is replaced by bearer() or removed with clearAuth(). -
clearAuthself Removes the default Authorization header set by bearer() or basic(). -
timeoutself Sets the connect, response and connection-request timeouts to the same value, in milliseconds, for all later requests. -
connectTimeoutself Sets how long to wait while establishing the TCP/TLS connection, in milliseconds. -
responseTimeoutself Sets how long to wait for response data once connected, in milliseconds. -
connectionRequestTimeoutself Sets how long to wait for a connection from the client's connection pool, in milliseconds. -
clearTimeoutsself Removes the timeouts set by timeout() and its variants, restoring the defaults. -
cookiesRestCookie[] Returns the cookies currently in the cookie jar: those received through Set-Cookie headers and those added with cookie(). -
cookieself Adds a cookie to the cookie jar for the host of the given URL (the URL's path is ignored). -
clearCookiesself Empties the cookie jar, for example to start a new login session. -
disableCertificateValidationself Turns off TLS certificate and host name verification for all later requests, to any host, for the rest of the run. -
clientCertificateself Registers a PKCS#12 (.p12/.pfx) client certificate for mutual TLS. -
certself Alias for clientCertificate(host, port, file, passphrase).
Rest.get(url: string)→HttpResponseRest.get(url: string, headers: table)→HttpResponse Sends a GET request and returns the response. Redirects are followed automatically. Any HTTP status, including 4xx and 5xx, comes back as a normal response; only network failures and timeouts raise an error ("Api request failed: ...").
Parameters
-
urlstring - The URL to request
-
headerstable optional - Request headers, applied on top of the defaults set by bearer() and basic(). Either a map ({Accept = "application/json"}) or a list of "Name:value" strings; see the Rest library notes
Returns
Fields of HttpResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
bodystring - response body decoded as UTF-8 text, empty when the response has no body
-
responsestring - same value as body (older scripts use this name)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name (headers["content-type"]). The value is a string, or a list of strings when the header occurred more than once (such as Set-Cookie)
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response, not only those set by this response
Example
GET with a bearer token and an Accept header
Rest.bearer(secret("api_token"))local response = Rest.get("https://api.example.com/users/1", { Accept = "application/json" })Assert.equals(200, response.status)local user = Json.decode(response.body)print(user.name)post()
Section titled “post()”Rest.post(url: string, body: string)→HttpResponseRest.post(url: string, headers: table, body: string)→HttpResponse Sends a POST request with a text body and returns the response. The body is sent as UTF-8 text and the Content-Type defaults to "text/plain; charset=UTF-8", so set the header yourself for JSON or form data. A table is not serialised: encode it first with Json.encode. Non-2xx statuses are returned, not raised.
Parameters
-
urlstring - The URL to post to
-
headerstable - Request headers, applied on top of the defaults set by bearer() and basic()
-
bodystring - The request body, sent as UTF-8 text
Returns
Fields of HttpResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
bodystring - response body decoded as UTF-8 text, empty when the response has no body
-
responsestring - same value as body (older scripts use this name)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name (headers["content-type"]). The value is a string, or a list of strings when the header occurred more than once (such as Set-Cookie)
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response, not only those set by this response
Example
local response = Rest.post( "https://api.example.com/orders", { ["Content-Type"] = "application/json", ["X-Request-Source"] = "reflex" }, Json.encode({ sku = "A-100", quantity = 2 }))Assert.equals(201, response.status)print(Json.decode(response.body).id)Rest.put(url: string, body: string)→HttpResponseRest.put(url: string, headers: table, body: string)→HttpResponse Sends a PUT request with a text body and returns the response. Body and Content-Type behave as in post().
Parameters
-
urlstring - The URL to send the request to
-
headerstable - Request headers, applied on top of the defaults set by bearer() and basic()
-
bodystring - The request body, sent as UTF-8 text
Returns
Fields of HttpResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
bodystring - response body decoded as UTF-8 text, empty when the response has no body
-
responsestring - same value as body (older scripts use this name)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name (headers["content-type"]). The value is a string, or a list of strings when the header occurred more than once (such as Set-Cookie)
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response, not only those set by this response
Example
local response = Rest.put( "https://api.example.com/users/1", { ["Content-Type"] = "application/json" }, Json.encode({ name = "Alice", active = true }))Assert.equals(200, response.status)patch()
Section titled “patch()”Rest.patch(url: string, body: string)→HttpResponseRest.patch(url: string, headers: table, body: string)→HttpResponse Sends a PATCH request with a text body and returns the response. Body and Content-Type behave as in post().
Parameters
-
urlstring - The URL to send the request to
-
headerstable - Request headers, applied on top of the defaults set by bearer() and basic()
-
bodystring - The request body, sent as UTF-8 text
Returns
Fields of HttpResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
bodystring - response body decoded as UTF-8 text, empty when the response has no body
-
responsestring - same value as body (older scripts use this name)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name (headers["content-type"]). The value is a string, or a list of strings when the header occurred more than once (such as Set-Cookie)
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response, not only those set by this response
Example
local response = Rest.patch( "https://api.example.com/users/1", { ["Content-Type"] = "application/merge-patch+json" }, '{"active": false}')Assert.equals(200, response.status)delete()
Section titled “delete()”Rest.delete(url: string, body: string)→HttpResponseRest.delete(url: string, headers: table, body: string)→HttpResponse Sends a DELETE request and returns the response. The body argument is required: pass "" when the request has no body. With two arguments the second one is always the body, so to send headers without a body call delete(url, headers, "").
Parameters
-
urlstring - The URL to send the request to
-
headerstable - Request headers, applied on top of the defaults set by bearer() and basic()
-
bodystring - The request body; use "" for none
Returns
Fields of HttpResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
bodystring - response body decoded as UTF-8 text, empty when the response has no body
-
responsestring - same value as body (older scripts use this name)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name (headers["content-type"]). The value is a string, or a list of strings when the header occurred more than once (such as Set-Cookie)
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response, not only those set by this response
Example
local response = Rest.delete("https://api.example.com/users/1", { Accept = "application/json" }, "")Assert.equals(204, response.status)multipart()
Section titled “multipart()”Rest.multipart(url: string, parts: table)→HttpResponseRest.multipart(url: string, headers: table, parts: table)→HttpResponse Sends a multipart/form-data POST request, for example a file upload. The Content-Type header (including the boundary) is set automatically; do not set it yourself. Each entry of the parts table becomes one part: - name = "text": a text part sent as UTF-8 text/plain. - {name = "meta", value = "{}", contentType = "application/json"}: a text part with its own content type. - {name = "file", file = "docs/report.pdf", filename = "r.pdf", contentType = "application/pdf"}: a file part. "file" (alias "path") is a path in the project; it is fetched from the Reflex server when it is not in the workspace yet. "filename" defaults to the file's own name; "contentType" is guessed from the extension and falls back to application/octet-stream. Map entries take their part name from the key, list entries from their "name" field. The order of map entries is not guaranteed. Raises an error when the parts are not a table, a part has no name, neither "value" nor "file" is given, or a file does not exist.
Parameters
-
urlstring - The URL to post to
-
headerstable - Request headers, applied on top of the defaults set by bearer() and basic()
-
partstable - The parts: {fieldName = "text"} entries and/or {name = ..., value or file = ..., filename = ..., contentType = ...} tables
Returns
Fields of HttpResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
bodystring - response body decoded as UTF-8 text, empty when the response has no body
-
responsestring - same value as body (older scripts use this name)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name (headers["content-type"]). The value is a string, or a list of strings when the header occurred more than once (such as Set-Cookie)
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response, not only those set by this response
Example
local response = Rest.multipart( "https://api.example.com/documents", { Authorization = "Bearer " .. secret("api_token") }, { description = "Quarterly report", { name = "file", file = "docs/report.pdf", contentType = "application/pdf" }, })Assert.equals(201, response.status)download()
Section titled “download()”Rest.download(url: string, file: string)→DownloadResponseRest.download(url: string, headers: table, file: string)→DownloadResponse Sends a GET request and saves the response body to a file in the project. Returns the response metadata plus the saved path and size; body and response are empty strings because the content is in the file. If the target ends with "/" or "\" or is an existing directory, the file name is taken from the Content-Disposition header, then from the last segment of the URL, then "download.bin". Otherwise the target is the file to write. Missing parent directories are created and an existing file is overwritten. The status is not checked: a 404 page is saved like any other body, so check status before using the file.
Parameters
-
urlstring - The URL of the file to download
-
headerstable - Request headers, applied on top of the defaults set by bearer() and basic()
-
filestring - Where to save it, relative to the project. A trailing "/" or an existing directory means "save inside this directory"; anything else is the file path to write
Returns
Fields of DownloadResponse
-
statusnumber - HTTP status code, for example 200 or 404
-
filestring - path of the saved file, relative to the project, with forward slashes
-
sizenumber - size of the saved file in bytes
-
bodystring - always an empty string (the body is in the file)
-
responsestring - always an empty string (the body is in the file)
-
headerstable - response headers by name. Each header is present under its original name and under its lower-case name. The value is a string, or a list of strings when the header occurred more than once
-
cookiesRestCookie[] - all cookies in the Rest cookie jar after this response
Example
local response = Rest.download( "https://example.com/exports/report.csv", { Authorization = "Bearer " .. secret("api_token") }, "downloads/")Assert.equals(200, response.status)print(response.file, response.size)bearer()
Section titled “bearer()”Rest.bearer(token: string)→self Sets a default "Authorization: Bearer TOKEN" header that is sent with every later request, to any host, until it is replaced by basic() or removed with clearAuth(). A header with the same name in a request's own headers wins.
Parameters
-
tokenstring - The token, without the "Bearer " prefix
Returns
Example
Rest.bearer(secret("api_token"))local response = Rest.get("https://api.example.com/me")basic()
Section titled “basic()”Rest.basic(username: string, password: string)→self Sets a default "Authorization: Basic BASE64(username:password)" header that is sent with every later request, to any host, until it is replaced by bearer() or removed with clearAuth(). A header with the same name in a request's own headers wins.
Parameters
-
usernamestring - The user name
-
passwordstring - The password
Returns
Example
Rest.basic(secret("api_user"), secret("api_password"))local response = Rest.get("https://api.example.com/reports")clearAuth()
Section titled “clearAuth()”Rest.clearAuth()→self Removes the default Authorization header set by bearer() or basic().
Returns
timeout()
Section titled “timeout()”Rest.timeout(millis: number)→self Sets the connect, response and connection-request timeouts to the same value, in milliseconds, for all later requests. The response timeout is the longest the client waits for data on the socket, not the total duration of the request. When a timeout expires the request raises an error. Without a call, connecting and leasing a connection time out after 3 minutes and a response may take forever. Use connectTimeout, responseTimeout or connectionRequestTimeout to set them separately. Raises an error when the value is smaller than 1.
Parameters
-
millisnumber - Timeout in milliseconds, at least 1
Returns
Example
Rest.timeout(10000)local response = Rest.get("https://api.example.com/slow-report")connectTimeout()
Section titled “connectTimeout()”Rest.connectTimeout(millis: number)→self Sets how long to wait while establishing the TCP/TLS connection, in milliseconds. Default: 3 minutes. Raises an error when the value is smaller than 1.
Parameters
-
millisnumber - Connect timeout in milliseconds, at least 1
Returns
responseTimeout()
Section titled “responseTimeout()”Rest.responseTimeout(millis: number)→self Sets how long to wait for response data once connected, in milliseconds. It applies to each wait for data, not to the whole transfer. Default: no limit. Raises an error when the value is smaller than 1.
Parameters
-
millisnumber - Response timeout in milliseconds, at least 1
Returns
Example
Rest.responseTimeout(30000)connectionRequestTimeout()
Section titled “connectionRequestTimeout()”Rest.connectionRequestTimeout(millis: number)→self Sets how long to wait for a connection from the client's connection pool, in milliseconds. Every request builds its own client, so this rarely matters. Default: 3 minutes. Raises an error when the value is smaller than 1.
Parameters
-
millisnumber - Connection-request timeout in milliseconds, at least 1
Returns
clearTimeouts()
Section titled “clearTimeouts()”Rest.clearTimeouts()→self Removes the timeouts set by timeout() and its variants, restoring the defaults.
Returns
cookies()
Section titled “cookies()”Rest.cookies()→RestCookie[] Returns the cookies currently in the cookie jar: those received through Set-Cookie headers and those added with cookie(). The jar lives as long as the Rest library (one script run) and is sent automatically with later requests to matching hosts.
Returns
Fields of RestCookie
-
namestring - cookie name
-
valuestring - cookie value
-
domainstring - domain the cookie applies to
-
pathstring - path the cookie applies to
-
secureboolean - only sent over HTTPS
-
httpOnlyboolean - not readable by page scripts
-
persistentboolean - the cookie has an expiry date
-
expirystring - expiry date in ISO 8601, nil for session cookies
Example
Rest.post( "https://app.example.com/login", { ["Content-Type"] = "application/x-www-form-urlencoded" }, "user=alice&password=" .. secret("app_password"))for _, c in ipairs(Rest.cookies()) do print(c.name, c.domain, c.secure)endcookie()
Section titled “cookie()”Rest.cookie(url: string, name: string, value: string)→selfRest.cookie(url: string, name: string, value: string, path: string)→self Adds a cookie to the cookie jar for the host of the given URL (the URL's path is ignored). The cookie is marked secure when the URL uses https. Raises an error when the URL has no host.
Parameters
-
urlstring - A URL on the host that should receive the cookie
-
namestring - Cookie name
-
valuestring - Cookie value
-
pathstring optional - Path the cookie applies to; "/" when left out
Returns
Example
Rest.cookie("https://app.example.com", "session", secret("session_id"))local response = Rest.get("https://app.example.com/dashboard")clearCookies()
Section titled “clearCookies()”Rest.clearCookies()→self Empties the cookie jar, for example to start a new login session.
Returns
disableCertificateValidation()
Section titled “disableCertificateValidation()”Rest.disableCertificateValidation()→self Turns off TLS certificate and host name verification for all later requests, to any host, for the rest of the run. Meant for test environments with self-signed certificates; it cannot be switched back on. Leave it out when the server has a valid certificate.
Returns
Example
Rest.disableCertificateValidation()local response = Rest.get("https://test.internal.example:8443/health")clientCertificate()
Section titled “clientCertificate()”Rest.clientCertificate(host: string, port: number, file: string, passphrase: string)→self Registers a PKCS#12 (.p12/.pfx) client certificate for mutual TLS. It is presented only on requests to the given host and port (a URL without a port means 443 for https and 80 for http); calling it again for the same host and port replaces the certificate. The file is read from the project (fetched from the Reflex server when it is not in the workspace). A copy fetched from the server is removed from the workspace after loading; a file that was already in the workspace is left alone. Raises "Failed to configure client certificate: ..." when the port is outside 1-65535, the file is missing, or the passphrase is wrong. Use secret() for the passphrase.
Parameters
-
hoststring - Host name of the HTTPS endpoint, without scheme or port
-
portnumber - Port of the endpoint, 1-65535
-
filestring - PKCS#12 file in the project
-
passphrasestring - Passphrase of the file; nil is treated as an empty one
Returns
Example
Rest.clientCertificate("api.partner.example", 443, "certs/client.p12", secret("client_cert_passphrase"))local response = Rest.get("https://api.partner.example/orders")cert()
Section titled “cert()”Rest.cert(host: string, port: number, file: string, passphrase: string)→self Alias for clientCertificate(host, port, file, passphrase).
Parameters
-
hoststring - Host name of the HTTPS endpoint, without scheme or port
-
portnumber - Port of the endpoint, 1-65535
-
filestring - PKCS#12 file in the project
-
passphrasestring - Passphrase of the file; nil is treated as an empty one
Returns