[Redbean] Feature / OnError(status, message) hook (#1103)

This commit is contained in:
BONNAURE Olivier 2024-02-14 10:55:50 +01:00 committed by GitHub
parent 2ab9e9f7fd
commit d3ff48c63f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 114 additions and 77 deletions

View file

@ -392,22 +392,22 @@ LUA ENHANCEMENTS
- redbean supports a printf modulus operator, like Python. For
example, you can say `"hello %s" % {"world"}` instead of
`string.format("hello %s", "world")`.
--
- redbean supports a string multiply operator, like Python. For
example, you can say `"hi" * 2` instead of `string.rep("hi", 2)`.
- redbean supports octal (base 8) integer literals. For example
`0644 == 420` is the case in redbean, whereas in upstream Lua
`0644 == 644` would be the case.
- redbean supports binary (base 2) integer literals. For example
`0b1010 == 10` is the case in redbean, whereas in upstream Lua
`0b1010` would result in an error.
- redbean supports the GNU syntax for the ASCII ESC character in
string literals. For example, `"\e"` is the same as `"\x1b"`.
]]
---@class string
@ -550,6 +550,17 @@ SPECIAL PATHS
---
function OnHttpRequest() end
--- Hooks catch errors
---
--- If this functiopn is defined in the global scope by your `/.init.lua`
--- then any errors occuring in the OnHttpRequest() hook will be catched.
--- You'll be able then to do whatever you need with the error status and
--- error message.
---
---@param status uint16
---@param message string
function OnError(status, message) end
--- Hooks client connection creation.
---
--- If this function is defined it'll be called from the main process
@ -1436,9 +1447,9 @@ function Log(level, message) end
function ParseHttpDateTime(rfc1123) end
--- Parses URL.
---
---
---@return Url url An object containing the following fields is returned:
---
---
--- - `scheme` is a string, e.g. `"http"`
--- - `user` is the username string, or nil if absent
--- - `pass` is the password string, or nil if absent
@ -1448,28 +1459,28 @@ function ParseHttpDateTime(rfc1123) end
--- - `params` is the URL paramaters, e.g. `/?a=b&c` would be
--- represented as the data structure `{{"a", "b"}, {"c"}, ...}`
--- - `fragment` is the stuff after the `#` character
---
---
---@param url string
---@param flags integer? may have:
---
---
--- - `kUrlPlus` to turn `+` into space
--- - `kUrlLatin1` to transcode ISO-8859-1 input into UTF-8
---
---
--- This parser is charset agnostic. Percent encoded bytes are
--- decoded for all fields. Returned values might contain things
--- like NUL characters, spaces, control codes, and non-canonical
--- encodings. Absent can be discerned from empty by checking if
--- the pointer is set.
---
---
--- There's no failure condition for this routine. This is a
--- permissive parser. This doesn't normalize path segments like
--- `.` or `..` so use IsAcceptablePath() to check for those. No
--- `.` or `..` so use IsAcceptablePath() to check for those. No
--- restrictions are imposed beyond that which is strictly
--- necessary for parsing. All the data that is provided will be
--- consumed to the one of the fields. Strict conformance is
--- enforced on some fields more than others, like scheme, since
--- it's the most non-deterministically defined field of them all.
---
---
--- Please note this is a URL parser, not a URI parser. Which
--- means we support everything the URI spec says we should do
--- except for the things we won't do, like tokenizing path
@ -2244,7 +2255,7 @@ function ProgramTrustedIp(ip, cidr) end
--- is granted per second to all buckets. The minimum value is 1/3600
--- which means once per hour. The maximum value for this setting is
--- 1e6, which means once every microsecond.
---
---
--- `cidr` is the specificity of judgement. Since creating 2^32 buckets
--- would need 4GB of RAM, redbean defaults this value to 24 which means
--- filtering applies to class c network blocks (i.e. x.x.x.*), and your
@ -2253,38 +2264,38 @@ function ProgramTrustedIp(ip, cidr) end
--- number means you use less ram/cpu, but splash damage applies more to
--- your clients; whereas higher numbers means more ram/cpu usage, while
--- ensuring rate limiting only applies to specific compromised actors.
---
---
--- `reject` is the token count or treshold at which redbean should send
--- 429 Too Many Request warnings to the client. Permitted values can be
--- anywhere between -1 and 126 inclusively. The default value is 30 and
--- -1 means disable to disable (assuming AcquireToken() will be used).
---
---
--- `ignore` is the token count or treshold, at which redbean should try
--- simply ignoring clients and close the connection without logging any
--- kind of warning, and without sending any response. The default value
--- for this setting is `MIN(reject / 2, 15)`. This must be less than or
--- equal to the `reject` setting. Allowed values are [-1,126] where you
--- can use -1 as a means of disabling `ignore`.
---
---
--- `ban` is the token count at which redbean should report IP addresses
--- to the blackhole daemon via a unix-domain socket datagram so they'll
--- get banned in the kernel routing tables. redbean's default value for
--- this setting is `MIN(ignore / 10, 1)`. Permitted values are [-1,126]
--- where -1 may be used as a means of disabling the `ban` feature.
---
---
--- This function throws an exception if the constraints described above
--- are not the case. Warnings are logged should redbean fail to connect
--- to the blackhole daemon, assuming it hasn't been disabled. It's safe
--- to use load balancing tools when banning is enabled, since you can't
--- accidentally ban your own network interface addresses, loopback ips,
--- or ProgramTrustedIp() addresses where these rate limits don't apply.
---
---
--- It's assumed will be called from the .init.lua global scope although
--- it could be used in interpreter mode, or from a forked child process
--- in which case the only processes that'll have ability to use it will
--- be that same process, and any descendent processes. This function is
--- only able to be called once.
---
---
--- This feature is not available in unsecure mode.
---@param replenish number?
---@param cidr integer?
@ -2309,10 +2320,10 @@ function ProgramTokenBucket(replenish, cidr, reject, ignore, ban) end
function AcquireToken(ip) end
--- Counts number of tokens in bucket.
---
---
--- This function is the same as AcquireToken() except no subtraction is
--- performed, i.e. no token is taken.
---
---
--- `ip` should be an IPv4 address and this defaults to GetClientAddr(),
--- although other interpretations of its meaning are possible.
---@param ip uint32?
@ -2326,12 +2337,12 @@ function CountTokens(ip) end
--- based on the banned threshold. However if your Lua code calls
--- `AcquireToken()` manually, then you'll need this function to take
--- action on the returned values.
---
---
--- This function returns true if a datagram could be sent sucessfully.
--- Otherwise false is returned, which can happen if blackholed isn't
--- running, or if a lot of processes are sending messages to it and the
--- operation would have blocked.
---
---
--- It's assumed that the blackholed service is running locally in the
--- background.
---@param ip uint32
@ -2416,7 +2427,7 @@ lsqlite3 = {
--- An `lsqlite3.BUSY` error can occur at any point in a transaction: when
--- the transaction is first started, during any write or update operations,
--- or when the transaction commits. To avoid encountering `lsqlite3.BUSY`
--- errors in the middle of a transaction, the application can use
--- errors in the middle of a transaction, the application can use
--- `BEGIN IMMEDIATE` instead of just `BEGIN` to start a transaction. The
--- `BEGIN IMMEDIATE` command might itself return `lsqlite3.BUSY`, but if it
--- succeeds, then SQLite guarantees that no subsequent operations on the same database through the next COMMIT will return `lsqlite3.BUSY`.
@ -2472,7 +2483,7 @@ lsqlite3 = {
CORRUPT = 11,
--- The `lsqlite3.NOTFOUND` result code is exposed in three ways:
---
--- `lsqlite3.NOTFOUND` can be returned by the `sqlite3_file_control()`
--- `lsqlite3.NOTFOUND` can be returned by the `sqlite3_file_control()`
--- interface to indicate that the file control opcode passed as the third
--- argument was not recognized by the underlying VFS.
---
@ -2491,7 +2502,7 @@ lsqlite3 = {
--- complete because the disk is full. Note that this error can occur when
--- trying to write information into the main database file, or it can also
--- occur when writing into temporary disk files.
---
---
--- Sometimes applications encounter this error even though there is an
--- abundance of primary disk space because the error occurs when writing
--- into temporary disk files on a system where temporary files are stored
@ -2521,19 +2532,19 @@ lsqlite3 = {
--- the database schema was changed by some other process in between the
--- time that the statement was prepared and the time the statement was run,
--- this error can result.
---
---
--- The statement is automatically re-prepared if the schema changes, up to
--- `SQLITE_MAX_SCHEMA_RETRY` times (default: 50). The `step()` interface
--- will only return `lsqlite3.SCHEMA` back to the application if the
--- failure persists after these many retries.
SCHEMA = 17,
--- The `lsqlite3.TOOBIG` error code indicates that a string or BLOB was too
--- large. The default maximum length of a string or BLOB in SQLite is
--- large. The default maximum length of a string or BLOB in SQLite is
--- 1,000,000,000 bytes. This maximum length can be changed at compile-time
--- using the `SQLITE_MAX_LENGTH` compile-time option. The `lsqlite3.TOOBIG`
--- error results when SQLite encounters a string or BLOB that exceeds the
--- compile-time limit.
---
---
--- The `lsqlite3.TOOBIG` error code can also result when an oversized SQL
--- statement is passed into one of the `db:prepare()` interface. The
--- maximum length of an SQL statement defaults to a much smaller value of
@ -2544,7 +2555,7 @@ lsqlite3 = {
--- information about the failed constraint can be found by consulting the
--- accompanying error message (returned via `errmsg()`) or by looking at
--- the extended error code.
---
---
--- The `lsqlite3.CONSTRAINT` code can also be used as the return value from
--- the `xBestIndex()` method of a virtual table implementation. When
--- `xBestIndex()` returns `lsqlite3.CONSTRAINT`, that indicates that the
@ -2558,7 +2569,7 @@ lsqlite3 = {
--- BLOB in a column with a declared type of BOOLEAN. But in a few cases,
--- SQLite is strict about types. The `lsqlite3.MISMATCH` error is returned
--- in those few cases when the types do not match.
---
---
--- The rowid of a table must be an integer. Attempt to set the rowid to
--- anything other than an integer (or a NULL which will be automatically
--- converted into the next available integer rowid) results in an
@ -2843,7 +2854,7 @@ function Database:close_vm(temponly) end
---@param func fun(udata: Udata) a Lua function that is invoked by SQLite3 whenever a transaction is committed. This callback receives one argument:
---@param udata Udata argument used when the callback was installed.
---
--- If `func` returns `false` or `nil` the COMMIT is allowed to proceed,
--- If `func` returns `false` or `nil` the COMMIT is allowed to proceed,
--- otherwise the COMMIT is converted to a ROLLBACK.
---
--- See: `db:rollback_hook` and `db:update_hook`
@ -2898,7 +2909,7 @@ function Database:create_aggregate(name, nargs, step, final, userdata) end
--- This creates a collation callback. A collation callback is used to establish
--- a collation order, mostly for string comparisons and sorting purposes.
---@param name string the name of the collation to be created
---@param func fun(s1: string, s2: string): -1|0|1 a function that accepts two string arguments, compares them and returns `0` if both strings are identical, `-1` if the first argument is lower in the collation order than the second and `1` if the first argument is higher in the collation order than the second.
---@param func fun(s1: string, s2: string): -1|0|1 a function that accepts two string arguments, compares them and returns `0` if both strings are identical, `-1` if the first argument is lower in the collation order than the second and `1` if the first argument is higher in the collation order than the second.
--- A simple example:
---
--- local function collate(s1,s2)
@ -7263,15 +7274,15 @@ function unix.isatty(fd) end
function unix.tiocgwinsz(fd) end
--- Returns file descriptor of open anonymous file.
---
---
--- This creates a secure temporary file inside `$TMPDIR`. If it isn't
--- defined, then `/tmp` is used on UNIX and GetTempPath() is used on
--- the New Technology. This resolution of `$TMPDIR` happens once.
---
---
--- Once close() is called, the returned file is guaranteed to be
--- deleted automatically. On UNIX the file is unlink()'d before this
--- function returns. On the New Technology it happens upon close().
---
---
--- On the New Technology, temporary files created by this function
--- should have better performance, because `kNtFileAttributeTemporary`
--- asks the kernel to more aggressively cache and reduce i/o ops.
@ -7284,7 +7295,7 @@ function unix.tmpfd() end
function unix.sched_yield() end
--- Creates interprocess shared memory mapping.
---
---
--- This function allocates special memory that'll be inherited across
--- fork in a shared way. By default all memory in Redbean is "private"
--- memory that's only viewable and editable to the process that owns
@ -7294,15 +7305,15 @@ function unix.sched_yield() end
--- don't want that to happen, and you want the memory to be shared
--- similar to how it would be shared if you were using threads, then
--- you can use this function to achieve just that.
---
---
--- The memory object this function returns may be accessed using its
--- methods, which support atomics and futexes. It's very low-level.
--- For example, you can use it to implement scalable mutexes:
---
---
--- mem = unix.mapshared(8000 * 8)
---
---
--- LOCK = 0 -- pick an arbitrary word index for lock
---
---
--- -- From Futexes Are Tricky Version 1.1 § Mutex, Take 3;
--- -- Ulrich Drepper, Red Hat Incorporated, June 27, 2004.
--- function Lock()
@ -7324,7 +7335,7 @@ function unix.sched_yield() end
--- mem:wake(LOCK, 1)
--- end
--- end
---
---
--- It's possible to accomplish the same thing as unix.mapshared()
--- using files and unix.fcntl() advisory locks. However this goes
--- significantly faster. For example, that's what SQLite does and
@ -7333,7 +7344,7 @@ function unix.sched_yield() end
--- might need something lower level than file locks, to implement
--- things like throttling. Shared memory is a good way to do that
--- since there's nothing that's faster.
---
---
---@param size integer
--- The `size` parameter needs to be a multiple of 8. The returned
--- memory is zero initialized. When allocating shared memory, you
@ -7341,7 +7352,7 @@ function unix.sched_yield() end
--- overhead of allocating a single shared mapping is 500 words of
--- resident memory and 8000 words of virtual memory. It's because
--- the Cosmopolitan Libc mmap() granularity is 2**16.
---
---
--- This system call does not fail. An exception is instead thrown
--- if sufficient memory isn't available.
---
@ -7351,16 +7362,16 @@ function unix.mapshared(size) end
---@class unix.Memory: userdata
--- unix.Memory encapsulates memory that's shared across fork() and
--- this module provides the fundamental synchronization primitives
---
---
--- Redbean memory maps may be used in two ways:
---
---
--- 1. as an array of bytes a.k.a. a string
--- 2. as an array of words a.k.a. integers
---
---
--- They're aliased, union, or overlapped views of the same memory.
--- For example if you write a string to your memory region, you'll
--- be able to read it back as an integer.
---
---
--- Reads, writes, and word operations will throw an exception if a
--- memory boundary error or overflow occurs.
unix.Memory = {}
@ -7372,7 +7383,7 @@ unix.Memory = {}
--- If `bytes` is none or nil, then the nul-terminated string at
--- `offset` is returned. You may specify `bytes` to safely read
--- binary data.
---
---
--- This operation happens atomically. Each shared mapping has a
--- single lock which is used to synchronize reads and writes to
--- that specific map. To make it scale, create additional maps.
@ -7381,7 +7392,7 @@ unix.Memory = {}
function unix.Memory:read(offset, bytes) end
--- Writes bytes to memory region.
---
---
---@param data string
---@param offset integer?
--- `offset` is the starting byte index to which memory is copied,
@ -7391,7 +7402,7 @@ function unix.Memory:read(offset, bytes) end
--- If `bytes` is none or nil, then an implicit nil-terminator
--- will be included after your `data` so things like json can
--- be easily serialized to shared memory.
---
---
--- This operation happens atomically. Each shared mapping has a
--- single lock which is used to synchronize reads and writes to
--- that specific map. To make it scale, create additional maps.
@ -7399,7 +7410,7 @@ function unix.Memory:write(data, offset, bytes) end
--- Loads word from memory region.
---
---
--- This operation is atomic and has relaxed barrier semantics.
---@param word_index integer
---@return integer
@ -7407,7 +7418,7 @@ function unix.Memory:write(data, offset, bytes) end
function unix.Memory:load(word_index) end
--- Stores word from memory region.
---
---
--- This operation is atomic and has relaxed barrier semantics.
---@param word_index integer
---@param value integer
@ -7415,10 +7426,10 @@ function unix.Memory:store(word_index, value) end
--- Exchanges value.
---
---
--- This sets word at `word_index` to `value` and returns the value
--- previously held in by the word.
---
---
--- This operation is atomic and provides the same memory barrier
--- semantics as the aligned x86 LOCK XCHG instruction.
---@param word_index integer
@ -7427,12 +7438,12 @@ function unix.Memory:store(word_index, value) end
function unix.Memory:xchg(word_index, value) end
--- Compares and exchanges value.
---
---
--- This inspects the word at `word_index` and if its value is the same
--- as `old` then it'll be replaced by the value `new`, in which case
--- `true, old` shall be returned. If a different value was held at
--- word, then `false` shall be returned along with the word.
---
---
--- This operation happens atomically and provides the same memory
--- barrier semantics as the aligned x86 LOCK CMPXCHG instruction.
---@param word_index integer
@ -7442,11 +7453,11 @@ function unix.Memory:xchg(word_index, value) end
function unix.Memory:cmpxchg(word_index, old, new) end
--- Fetches then adds value.
---
---
--- This method modifies the word at `word_index` to contain the sum of
--- value and the `value` paremeter. This method then returns the value
--- as it existed before the addition was performed.
---
---
--- This operation is atomic and provides the same memory barrier
--- semantics as the aligned x86 LOCK XADD instruction.
---@param word_index integer
@ -7455,7 +7466,7 @@ function unix.Memory:cmpxchg(word_index, old, new) end
function unix.Memory:fetch_add(word_index, value) end
--- Fetches and bitwise ands value.
---
---
--- This operation happens atomically and provides the same memory
--- barrier ordering semantics as its x86 implementation.
---@param word_index integer
@ -7464,7 +7475,7 @@ function unix.Memory:fetch_add(word_index, value) end
function unix.Memory:fetch_and(word_index, value) end
--- Fetches and bitwise ors value.
---
---
--- This operation happens atomically and provides the same memory
--- barrier ordering semantics as its x86 implementation.
---@param word_index integer
@ -7473,7 +7484,7 @@ function unix.Memory:fetch_and(word_index, value) end
function unix.Memory:fetch_or(word_index, value) end
--- Fetches and bitwise xors value.
---
---
--- This operation happens atomically and provides the same memory
--- barrier ordering semantics as its x86 implementation.
---@param word_index integer
@ -7482,24 +7493,24 @@ function unix.Memory:fetch_or(word_index, value) end
function unix.Memory:fetch_xor(word_index, value) end
--- Waits for word to have a different value.
---
---
--- This method asks the kernel to suspend the process until either the
--- absolute deadline expires or we're woken up by another process that
--- calls `unix.Memory:wake()`.
---
---
--- The `expect` parameter is used only upon entry to synchronize the
--- transition to kernelspace. The kernel doesn't actually poll the
--- memory location. It uses `expect` to make sure the process doesn't
--- get added to the wait list unless it's sure that it needs to wait,
--- since the kernel can only control the ordering of wait / wake calls
--- across processes.
---
---
--- The default behavior is to wait until the heat death of the universe
--- if necessary. You may alternatively specify an absolute deadline. If
--- it's less than or equal to the value returned by clock_gettime, then
--- this routine is non-blocking. Otherwise we'll block at most until
--- the current time reaches the absolute deadline.
---
---
--- Futexes are currently supported on Linux, FreeBSD, OpenBSD. On other
--- platforms this method calls sched_yield() and will either (1) return
--- unix.EINTR if a deadline is specified, otherwise (2) 0 is returned.
@ -7512,7 +7523,7 @@ function unix.Memory:fetch_xor(word_index, value) end
--- well-supported on all supported platforms but requires using files.
--- Please test your use case though, because it's kind of an edge case
--- to have the scenario above, and chances are this op will work fine.
---
---
---@return 0
---@overload fun(self, word_index: integer, expect: integer, abs_deadline?: integer, nanos?: integer): nil, error: unix.Errno
---
@ -7520,10 +7531,10 @@ function unix.Memory:fetch_xor(word_index, value) end
--- should use futexes inside a loop that is able to cope with spurious
--- wakeups. We don't actually guarantee the value at word has in fact
--- changed when this returns.
---
---
--- `EAGAIN` is raised if, upon entry, the word at `word_index` had a
--- different value than what's specified at `expect`.
---
---
--- `ETIMEDOUT` is raised when the absolute deadline expires.
---
---@param word_index integer
@ -7533,11 +7544,11 @@ function unix.Memory:fetch_xor(word_index, value) end
function unix.Memory:wait(word_index, expect, abs_deadline, nanos) end
--- Wakes other processes waiting on word.
---
---
--- This method may be used to signal or broadcast to waiters. The
--- `count` specifies the number of processes that should be woken,
--- which defaults to `INT_MAX`.
---
---
--- The return value is the number of processes that were actually woken
--- as a result of the system call. No failure conditions are defined.
---@param index integer