Api Class
The Api class lets you define HTTP endpoints and handle requests based on method and path. The matching API is selected based on the URL (the path) and the type of operation (method). If both match, the process function is executed and the result is returned to the client.
The Api class is the most important element that defines an endpoint. It hides the bloody internals and gives you handy static or instance methods for common tasks.
Different endpoints can use the same path with a different method, or use the same method with a different path.
If different endpoints use the same method and path, then one is selected without particular order guarantee (in other words, don't do this).
Members
atomic() | Protects an operation to make sure only one request can execute at the same time. |
chain() | Calls another endpoint. |
database() | Gets a database instance. |
debug() | Sends variables to the debug stream. |
defer() | Executes some operations later in the background. |
env() | Fetches the value of an environment variable. |
error() | Throws a proper exception. |
log() | Sends a message to the log stream. |
metrics() | Captures personalized metrics. |
storage() | Gets a storage instance. |
allow*() | Protects access to your endpoint. |
concurrency() | Sets the maximum number of simultaenous requests. |
deny*() | Protects access to your endpoint. |
description() | Documents your endpoint. |
parameter() | Declares a parameter that your endpoint needs. |
process() | Sets the core execution function of your endpoint. |
returns() | Documents your endpoint. |
summary() | Documents your endpoint. |
Constructor
public Api(String path, String method)
- path: this is the last part of the URL to call this endpoint. It will be prefixed with the global path prefix of your instance and the workspace prefix.
It is case sensitive and should only include ASCII characters.
The path will be normalized so that it may contain a leading '/' character, or not. And it may include the workspace prefix or the global prefix too. However, the correct way to declare the path is to include the leading '/' character and to omit the prefixes, so that if those change, it will not mess around.
You can use
{name}
placeholders to capture values as parameters for your endpoint. - method: this is the http method to contact this endpoint.
It must be one uppercase ASCII word without any special characters.
It can be any word (not restricted to classic
GET
,POST
,...) but it must match exactly what the client request will send, otherwise it will not match.
Api.atomic() function
The atomic
function has two variants: one that returns a value, and one that doesn't. Either way, it allows to make sure
an operation can only be executed by one request at a time. This is good for sensitive operations but can also become a bottleneck,
as other requests will wait until it finishes.
public static void atomic(Runnable operation) throws Exception
- operation: This is not a standard
Runnable
but a Functions.Runnable (which allows throwing exceptions).It is recommended to use a lambda-expression here.
public static <T> T atomic(Supplier<T> operation) throws Exception
- operation: Same here, but using Functions.Supplier so the operation returns a value.
A lambda expression works perfectly here too.
Api.chain() function
Use the chain
function to call another endpoint and get its result. It can be overloaded with
multiple optional parameters.
public static Data chain(String url, [String method], [Data data], [User.Type user]) throws Exception
- url: Full path to the other endpoint, including the global and workspace prefix.
- method (optional): HTTP method expected by the other endpoint. Defaults to
GET
if not specified. - data (optional): Parameters to pass to the other endpoint as a JSON object. Defaults to none.
- user (optional): User to act as. Defaults to the internal
SYSTEM
user.
The function returns the response from the called endpoint, including any errors. If no matching endpoint is found (based on URL and method), a 404 error is thrown.
Api.database() function
Use the database
function to fetch an instance of a Database you declared in the User Panel.
public static Database.Type database(String name)
- name: The name of the database as defined in the User Panel. (Obvious, no?)
If no database with the given name is found, the function returns null
.
Api.debug() function
Use the debug
function to inspect the value of a variable at runtime.
public static void debug(String tag, [Object...data])
- tag: A label to categorize and filter debug points in your code.
- data (optional): The variables or values you want to inspect.
Api.defer() function
Use the defer
function to execute some operations in the background. This allows your endpoint to return early.
public static void defer(Runnable operation)
- operation: This is not a standard
Runnable
but a Functions.Runnable (which allows throwing exceptions).It is recommended to use a lambda-expression here.
If the operation throws an exception, it will be caught in the log rather than being exposed to the user.
Api.env() function
Use the env
function to get the runtime value of an environment variable defined in the User Panel.
public static Data env(String name)
- name: The name of the environment parameter as defined in the User Panel. (Obvious, no?)
The value is returned as a Data object so that you can quickly coerce it to any other type if needed.
If the parameter is not defined or has no value, an empty data object is returned (use data.isEmpty()
to check).
Api.error() function
You don't want users to see nasty errors, right! So use the error
function to generate a user-friendly HTTP error response instead.
public static void error(int code, String message) public static void error(int code, Data data) public static void error(int code, Exception error)
- code: The http status code. For user's fault, use the
400
range, for internal errors, use the500
range. - message: A simple textual description of the error.
- data: A JSON object that will be included in the response.
- error: The root cause of the error. (The
exception.getMessage()
will be used as the response message.)
Api.log() function
Live stream troubleshooting information using the log
function.
public static void log(int level, String message, [Object...data]) public static void log(int level, Exception error)
- level: The log level (0 - 1000). A higher level means it is more important. The level is used in the User Panel to filter relevant logs to watch in real time.
- message: Text to display.
If a log message contains
{}
placeholders, they will be replaced by the corresponding arguments. Extra arguments are ignored. - data (optional): A list of values to inject into the message placeholders.
- error: An exception to log. Equivalent to using the first variant with the exception as a data argument.
Api.metrics() function
Use the metrics
function to keep a custom custom cumulative count and sum over one hour.
public static void metrics(String name, [long value])
- name: Label for the custom metrics.
- value (optional): Value to accumulate over time. This could be the execution time, the amount of flowers in a field - you name it.
If the value is not provided, 0
is assumed. The count and sum are reset every hour, so you can aggregate those to build trends.
Api.storage() function
Use the storage
function to fetch an instance of an object Storage you declared in the User Panel.
public static Storage.Type storage(String name)
- name: The name of the object storage as defined in the User Panel. (Obvious, no?)
If no object storage with the given name is found, the function returns null
.
Api.allow*() functions
Use the allow functions to define who can access your endpoint. The users, groups and roles are defined in the User Panel.
public Api allowGroup(String ...group)
- group: List of group names to grant access to your endpoint. If a user is not a member of any of these groups, access will be denied.
public Api allowRole(String ...role)
- role: List of role names to grant access to your endpoint. If a user does not have any of these roles, access will be denied.
public Api allowUser(String ...user)
- user: List of explicit user names that are granted access to your endpoint. All other users will be denied.
You can combine the different allow*
rules. After evaluating all of them, if at least one rule matches, access is granted. Otherwise, access is denied.
If you do not specify any allow*
or deny*
rules, the endpoint is public and everyone can use it (are you sure you want this?).
Returns the same Api
instance, so you can chain this with other setup calls.
Api.concurrency() function
Use the concurrency
function to limit how many requests can be processed in parallel by this endpoint.
This ensures controlled execution and prevents excessive resource usage.
By default, there is no concurrency limit, endpoints can handle unlimited parallel requests, subject to system capacity.
Setting a hard concurrency limit can help prevent race conditions by ensuring the endpoint is accessed by only one or a few requests at a time. Alternatively, you can use it to throttle access and prevent excessive use of system resources.
public Api concurrency(int level)
- level: The maximum number of concurrent requests allowed. For unmetered access, omit this setting or use a value
<= 0
.
Returns the same Api
instance, so you can chain this with other setup calls.
Api.deny*() functions
Use the deny*
functions to define who cannot access your endpoint. The users, groups, and roles are defined in the User Panel.
public Api denyGroup(String ...group)
- group: List of group names to deny access to your endpoint. If a user is a member of any of these groups, access will be denied.
public Api denyRole(String ...role)
- role: List of role names to deny access to your endpoint. If a user has any of these roles, access will be denied.
public Api denyUser(String ...user)
- user: List of explicit user names to deny access to your endpoint. All other users will be allowed.
If any deny*
rule matches, access is denied immediately. If none match, access is granted (unless restricted by other allow*
rules).
If you do not specify any allow*
or deny*
rules, the endpoint is public and everyone can use it (are you sure you want this?).
Returns the same Api
instance, so you can chain this with other setup calls.
Api.description() function
Users can't see your code, so help them out by writing a proper description of your endpoint. AI Agents will also be able to discover your endpoint using MCP (Model Context Protocol) thanks to your valuable input.
public Api description(String value)
- value: Your best prose.
Returns the same Api
instance, so you can chain this with other setup calls.
Api.parameter() function
Use the parameter
function to declare which parameters your endpoint expects.
If provided in the request, these parameters will be passed to your process function.
Although the description is optional, it is highly recommended as it helps users understand how to use your API, and ensures compatibility with AI Agents using MCP (Model Context Protocol).
public Api parameter(String name)
- name: Parameter name.
public Api parameter(String name, String description)
- name: Parameter name.
- description: Parameter description.
public Api parameter(String name, Predicate<Data> validator)
- name: Parameter name.
- validator: Input validation function. It is recommended to use a lambda expression or use one of the pre-built Input functions.
public Api parameter(String name, String description, Predicate<Data> validator)
- name: Parameter name.
- description: Parameter description.
- validator: Input validation function. It is recommended to use a lambda expression or use one of the pre-built Input functions.
If a {name}
placeholder was used in the URL of your endpoint declaration, you must also declare it as a parameter.
Returns the same Api
instance, so you can chain this with other setup calls.
Api.process() function
Use the process
function to set the actual behavior of your endpoint.
public Api process(Supplier<Object> handler) public Api process(Function<Data, Object> handler) public Api process(BiFunction<Data, User.Type, Object> handler)
- handler: A function that returns the response of your endpoint. It can:
Have no input parameters (just return a value).
Accept a Data object with all declared request parameters.
Also accept the authenticated User (in addition to the data).
These are not standard Java functional interfaces, but a Functions.Supplier, Functions.Function, or Functions.BiFunction, all of which support throwing exceptions.
Using a lambda expression is recommended.
The return value is automatically converted to a JSON response. If you care about edge cases or want to get fancy... check the whole doc.
Api.returns() function
Describe what your endpoint returns in the response body. This helps users understand what to expect, and allows AI agents to discover your endpoint using MCP (Model Context Protocol).
public Api returns(String value)
- value: An amazing explanation.
Returns the same Api
instance, so you can chain this with other setup calls.
Api.summary() function
The friendly display name of your endpoint. We could have called this name()
, but decided to mimic OpenAPI instead.
public Api summary(String value)
- value: It is your creature, name it!
Returns the same Api
instance, so you can chain this with other setup calls.
Data Class
The Data class is your all-purpose container for anything structured, typed, or messy. It handles values, lists, and key-value maps without forcing you to write schemas, DTOs, or converters.
A Data instance can represent a single value, a key-value object, or a list, and it figures that out based on how you build it.
Once the general shape is set (value, map, or list), it stays fixed, but you can still mutate the content. Yes, it’s mutable and schemaless by design. That’s what lets you skip the traditional boilerplate.
Plenty of coercion methods are available to turn values into numbers, booleans, strings, or other Data instances, plus helpers to loop, merge, filter, extract... you get the idea.
Members
empty() | Creates an empty value data object. |
list() | Creates a list data object. |
map() | Creates a key-value data object. |
of() | Wraps and best-guesses the value as a data object. |
add() | Appends values to a list-type data object. |
as*() | Converts the value to a Java primitive or standard type. |
clear() | Clears this data object. |
clone*() | Returns a deep copy of this data object including nested values. |
containsKey*() | Checks if the key exists. |
entrySet() | Returns a set to iterate over all entries. |
equals() | Checks for equality. |
find() | Search for a value. |
get*() | Get a value. |
is*() | Checks if a value is of a certain type. |
iterator() | Iterates over all values. |
put*() | Adds or replaces entries in a map-type data object. |
remove*() | Removes a value. |
set() | Sets or updates a value. |
size() | Returns the size of this data object. |
toString() | Converts to a JSON string. |
Data.empty() function
Returns a new instance of an empty value data object. The wrapped value is null
.
public static Data empty()
Data.list() function
Returns a new instance of a list data object.
public static Data list([Object ...elements])
- elements (optional): Initial elements present in the list. Elements may be of different type and each will be wrapped in a data object too.
Data.map() function
Returns a new instance of an empty key-value data object.
public static Data map()
Data.of() function
Wraps an object into a data object.
public static Data of(Object item)
- item: The object to wrap.
If the value is already a data object, it is returned as-is (not a copy).
If the value is a java
Map<>
, it leads to a key-value data object. All keys are transformed to string and all values are also wrapped in a data object recursively, meaning nested maps and lists are fully converted.If the value is a java
Collection<>
,Set<>
,Enumeration<>
,Iterable<>
,Iterator<>
, or a primitive array, it leads to a list data object where all values are also wrapped in a data object recursively, meaning nested maps and lists are fully converted.In all other cases, it leads to a value data object.
Caution: Sometimes the data wrapping process can lead to an infinite loop! This happens with circular references,
or with object types that are iterable of the same type. (i.e. the java.nio.Path
is also Iterable<Path>
)
Data.add() function
Use the add
function to append values to a list or entries to a map.
public Data add(Object ...value)
- value: One or more values to add.
If this data object is a list, all values are appended.
If it's a map, values are interpreted as alternating key/value pairs like in
Map.of()
. This works like calling put() repeatedly: existing keys will be overwritten.If this data object is a simple value it will throw an exception.
Returns the same Data
instance, so you can chain this with other calls.
Data.as*() function
Use the as*
functions to convert the value to a Java primitive type or standard type.
public boolean asBool([int index | String key]) public double asDouble([int index | String key]) public int asInt([int index | String key]) public long asLong([int index | String key]) public Number asNumber([int index | String key]) public String asString([int index | String key])
These methods can optionally take either:
- index: to access and convert an item in a data list (equivalent to
get(index).as*()
) - key: to access and convert an item in a data map (equivalent to
get(key).as*()
) - no parameter to apply it to the object itself.
Coercion rules:
- boolean: A numeric value is true if greater than zero. A string value is true if it is "yes" or "true" (case-insensitive). A data list or map is true if it is not empty.
- double, int, long, Number: A boolean becomes 1 or 0. A string is parsed as a number; if parsing fails, 0 is returned. A data list or map returns its size.
- String: A data list or map returns its JSON representation. Other values are their
toString()
form.
Data.clear() function
Use the clear
function to remove all content from a data object.
public void clear()
If this data object is a list or map, all its elements are removed.
If it's a single value, the value is reset to null
.
Data.clone*() function
Use the clone
functions to duplicate the content of a data object.
public Data clone() public void cloneTo(Data other)
The parameterless clone()
method returns a deep copy of the data structure (map, list, or value type).
However, the underlying Java objects inside are not duplicated. If any value is mutable, it will be shared with the original.
The cloneTo()
method copies the current content into another Data
instance,
overwriting its existing value or structure. If the receiving data object has a different type (e.g. list vs. map),
an exception is thrown.
Data.containsKey*() function
Checks whether this data object contains a given key or index.
public boolean containsKey(String key) public default boolean containsKeyNested(String key)
- key: The key or index to look for.
For a plain value, this always returns
false
.For a map, the key is checked directly.
For a list, the key is interpreted as a numeric index. Returns
true
if the index is valid (i.e. in bounds).
The containsKeyNested
variant supports deep key paths using .
or /
as separators.
This allows checking for nested keys inside maps or lists.
Data.entrySet() function
Returns all key-value pairs in this data object. This is useful for for-each
loops.
public Iterable<Map.Entry<String, Data>> entrySet()
Only map-type data objects return entries. For value or list types, the result is an empty collection.
Data.equals() function
This function checks for value equality, not in the strict Java sense, but in the intentional, developer-friendly way.
public boolean equals(Object other) public default boolean equals(String key, Object other) public default boolean equals(int index, Object other)
- other: The value to compare against.
- key: For map-type data. Equivalent to
get(key).equals(other)
. - index: For list-type data. Equivalent to
get(index).equals(other)
.
For lists, returns true
if the list has the same size and each element matches (using original equals()
logic).
For maps, returns true
if all keys match and all values match (again using their underlying equals()
logic).
For simple values, the value is coerced to match the type of other
(if it’s a boolean, string, or number), then compared.
Note: This does not follow the Java convention for equals()
symmetry.
data.equals("true")
may return true
, but "true".equals(data)
will not.
This method is designed to match developer intent, not Java's object model.
Data.find() function
Searches for the first matching value.
public Data find(Predicate<Data> predicate)
- predicate: A test that returns
true
for the data you're looking for.
If this data object is a list or map, it iterates through all values. If it's a single value, the predicate is applied to it directly.
Returns the first value for which the predicate returns true
, or null
if nothing matches.
Data.get() function
Fetches or unwraps a value from this data object.
public <T> T get() public Data get(int index) public Data get(String key) public Data getNested(String key)
get(int index)
: Fetches an item from a list. ReturnsData.empty()
if the index is out of bounds.get(String key)
: Fetches a value from a map. ReturnsData.empty()
if the key doesn't exist.get()
: On a simple value, returns the unwrapped Java object (e.g.String
,Integer
, etc.).
getNested(String key)
supports deep key paths using .
or /
as separators.
This allows fetching deeply nested values in map or list structures.
If yo uuse the index variant on a map, or the key variant on a list, the argument is converted to match.
Data.is*() function
Use the is*
functions to check the type of a data object or one of its elements.
public boolean is([int index | String key], Class<?> type) public boolean isBool([int index | String key]) public boolean isEmpty([int index | String key]) public boolean isList([int index | String key]) public boolean isMap([int index | String key]) public boolean isNull([int index | String key]) public boolean isNumber([int index | String key]) public boolean isString([int index | String key])
These methods can optionally take either:
- no parameter to check the current value.
- index: to access and convert an item in a data list (equivalent to
get(index).is*()
) - key: to access and convert an item in a data map (equivalent to
get(key).is*()
)
is(Class<?> type)
checks if the value is an instanceof
the selected class.
All other is*
methods test for a specific type.
isList
and isMap
apply only to list and map data objects, respectively.
isEmpty
checks whether a map or list is empty. For value objects, it returns true if the value is
null
or a blank string.
Data.iterator() function
Returns an iterator over the elements in this data object. This is useful for for-each
loops.
public Iterator<Data> iterator()
For a list, the iterator returns each element.
For a map, it returns the map values (not the keys).
For a plain value, it returns a single-element iterator containing itself.
Data.put*() function
Use the put
function to add or update a key in a map or list data object.
public Data put(String key, Object value) public default Data putNested(String key, Object value)
- key: The key to insert or update.
- value: The value to associate with the key. It will be wrapped as a data object.
For a list, it will try to convert the key to an integer and set() it instead.
For a simple value, it will throw an exception.
The putNested
variant supports deep key paths using .
or /
as separators.
This allows setting the value for nested keys inside maps or lists.
Returns the same Data
instance, so you can chain this with other calls.
Data.remove*() function
Use the remove
functions to delete a value from a list or map and get it back.
public Data remove(Data item) public Data remove(int index) public Data remove(String key) public void removeIf(Predicate<Data> check) public Data removeNested(String key)
The remove method can optionally take either:
- item: Removes that exact value from the list or map, if present.
- index: Removes the item at that index in a list.
- key: Removes the entry for that key in a map.
removeIf()
removes all list elements that match the given condition.
These methods return the removed element (except removeIf()
). If called on a plain value, they will throw an exception.
The removeNested
variant supports deep key paths using .
or /
as separators.
This allows removing the value for nested keys inside maps or lists.
Data.set() function
Use the set
function to update the content of this data object.
public Data set(Object value) public Data set(int index, Object value)
- Without index: behaves like add() for lists and maps, or replaces the content for a plain value data object.
- With index: updates the value at the given index (for lists) or key (for maps). This fails for value data objects.
Returns the same Data
instance, so you can chain this with other calls.
Data.size() function
Returns the size of this data object or one of its children.
public int size([int index | String key])
This method can optionally take either:
- no parameter: checks the size of this data object itself.
- index: returns the size of the item at the given index in a data list (same as
get(index).size()
). - key: returns the size of the item associated with the key in a data map (same as
get(key).size()
).
If this object is a list or map, it returns the number of elements.
If it's a plain value: returns 1
for most types, or the string length if it's a String
.
Data.toString() function
Returns the JSON representation of this data object.
public String toString()
Database Class
The Database class is a simple SQL query pass-through. Instances are created in the User Panel.
In practice, the real class is Database.Type
because of encapsulation.
Members
columns() | Lists columns of a table. |
query() | Execute a query. |
schema() | Gets the database schema as json. |
tables() | Lists all tables. |
Database.columns() function
Use the columns
function to list all columns in the specified table.
public Data columns(String table) throws SQLException, InterruptedException
- table: Table name.
The returned value is a list of column descriptions:
[ { "name": the column name, "size": the column data type size, "auto": whether or not the column has a default value or is auto-incremented, "null": whether or not the column accepts null values, "type": the JDBC data type as a string, "primary": whether or not the column is part of a primary key, },... ]
Database.query() function
Use the query
function to... well, run a SQL query.
public Data query(String sql, Object ... params) throws SQLException public Data query(String sql, Collection<Object> params) throws SQLException public Data query(long timeout, String sql, Object ... params) throws SQLException
- sql: Anything the database supports as a query.
Avoid hardcoding values in the query, use parameters with '?'.
- params: Query parameters to safely replace '?' in the query.
- timeout: The maximum time to wait for a connection to be avaiable (in milliseconds). This is not a timeout on the duration of the query itself.
The returned value depends on the query. For SELECT
queries, it returns a list of rows, each as a key-value map of
column names to values.
Database.schema() function
Returns a full description of all tables and their columns.
public Data schema() throws SQLException, InterruptedException
The returned value is the list of tables with all columns:
[ { "name": the table name, "schema": the table schema, "database": the table database (or catalog in JDBC terms), "columns": [ { "name": the column name, "size": the column data type size, "auto": whether or not the column has a default or auto-increment value, "null": whether or not the column accepts null values, "type": the JDBC data type as a string, "primary": whether or not the column is part of a primary key, },... ] },... ]
Database.tables() function
Use the tables
function to list all tables in the database.
public Data tables() throws SQLException, InterruptedException
The returned value is a list of table descriptions:
[ { "name": the table name, "schema": the table schema, "database": the table database (or catalog in JDBC terms), },... ]
Functions Class
The Functions class offers classic java.util.function.*
variants up to 4 parameters, and that can throw an exception.
Members
*Consumer<> | Accepts (1 to 4) inputs and returns nothing. |
*Function<> | Accepts (1 to 4) inputs and returns something. |
*Predicate<> | Accepts (1 to 4) inputs and returns a boolean. |
Runnable | Accepts nothing and returns nothing. |
Supplier<> | Accepts nothing and returns something. |
Functions.*Consumer<> interfaces
Represents an operation that accepts up to four input arguments and returns no result. It may throw an exception.
public static interface Consumer<A> public static interface BiConsumer<A, B> public static interface TriConsumer<A, B, C> public static interface QuadriConsumer<A, B, C, D>
public void accept(A a, [B b], [C c], [D d]) throws Exception
- a: the first parameter.
- b (optional): the second parameter.
- c (optional): the third parameter.
- d (optional): the fourth parameter.
Does not return anything.
Functions.*Function<> interfaces
Represents an operation that accepts up to four arguments and produces a result. It may throw an exception.
public static interface Function<A, R> public static interface BiFunction<A, B, R> public static interface TriFunction<A, B, C, R> public static interface QuadriFunction<A, B, C, D, R>
public R apply(A a, [B b], [C c], [D d]) throws Exception
- a: the first parameter.
- b (optional): the second parameter.
- c (optional): the third parameter.
- d (optional): the fourth parameter.
Returns a result of type R
.
Functions.*Predicate<> interfaces
Represents a predicate that accepts up to four arguments and returns a boolean. It may throw an exception.
public static interface Predicate<A> public static interface BiPredicate<A, B> public static interface TriPredicate<A, B, C> public static interface QuadriPredicate<A, B, C, D>
public boolean test(A a, [B b], [C c], [D d]) throws Exception
- a: the first parameter.
- b (optional): the second parameter.
- c (optional): the third parameter.
- d (optional): the fourth parameter.
Returns a boolean.
Functions.Runnable interface
Represents an operation with no input and no output. It may throw an exception.
public static interface Runnable
public void run() throws Exception
Does not return anything.
Functions.Supplier<> interface
Produces a result with no input. It may throw an exception.
public static interface Supplier<R>
public R get() throws Exception
Returns a result of type R
.
Http Class
The Http class provides simple methods to perform HTTP requests and get the result as a Data object.
The Http class will folow any redirects issued by the server, but will not hold a session nor save cookies.
Members
Error | Represents an http exception. |
get() | Performs a request without body. |
mTLS() | Configures mutual TLS authentication. |
post() | Performs a request with a body. |
Http.Error class
Represents an HTTP response error. It contains the following properties:
- body: The string content of the response.
- code: The HTTP status code.
Http.get() function
Use the get
function to perform an http request without a body.
public static Data get(String url, [Data queryString], [Data headers], [String method], [int timeout], [SSLContext context])
- url: The full URL to fetch.
- queryString (optional): A data object with key-value pairs of parameters to send as query string. Defaults to an empty map.
- headers (optional): A data object with key-value pairs of http headers. Defaults to an empty map.
- method (optional): The HTTP method to use. Defaults to
GET
. - timeout (optional): Enforce a timeout on the request. If
<= 0
, no timeout is enforced. Defaults to 0. - context (optional): SSL context to use for mutual TLS. See mTLS(). Defaults to null (i.e., no custom SSL configuration).
If the response is JSON (application/json
), it is decoded and returned as a data object. Otherwise, it is returned as a plain string inside a Data wrapper.
In case of errors, an Http.Error is thrown.
Http.mTLS() function
Use the mTLS
function to build a SSL context to use in get()
or post()
.
public static SSLContext mTLS(String clientCertificate, String clientKey, String serverCertificate) throws Exception
- clientCertificate: The certificate used to authenticate yourself against the server. It should be encoded in PEM format.
- clientKey: The matching private key. It should be encoded in PKCS-8 PEM format.
- serverCertificate: The server certificate or any intermediate signing authority to check the identity of the server. It should be encoded in PEM format.
This function returns a new SSLContext
to use in other requests.
Http.post() function
Use the post
function to perform an http request with a body.
public static Data post(String url, [Data body], [Data headers], [String method], [int timeout], [SSLContext context])
- url: The full URL to fetch.
- body (optional): A data object with key-value pairs of parameters to send in the body. Defaults to an empty map.
- headers (optional): A data object with key-value pairs of http headers. Defaults to an empty map.
- method (optional): The HTTP method to use. Defaults to
POST
. - timeout (optional): Enforce a timeout on the request. If
<= 0
, no timeout is enforced. Defaults to 0. - context (optional): SSL context to use for mutual TLS. See mTLS(). Defaults to null (i.e., no custom SSL configuration).
The default body encoding is application/x-www-form-urlencoded
unless the headers specify another encoding. If the Content-Type
header is multipart/form-data
, the content is encoded accordingly. Otherwise, the body is sent as a plain string.
If the response is JSON (application/json
), it is decoded and returned as a data object. Otherwise, it is returned as a plain string inside a Data wrapper.
In case of errors, an Http.Error is thrown.
Input Class
The Input class contains utility methods and predicates to validate input parameters for your endpoint.
Members
isAlphaNumeric | Returns true if input is alpha-numeric. |
isBoolean | Returns true if input is a boolean-like. |
isEmail | Returns true if input is an email address. |
isEmpty | Returns true if input is empty. |
isFile | Returns true if input is a file. |
isFloatingPoint | Returns true if input is a floating point number. |
isInteger | Returns true if input is an integer. |
isNagative | Returns true if input is a negative number. |
isNotEmpty | Returns true if input is not empty. |
isPositive | Returns true if input is a positive number. |
hasFileExtension() | Returns true if input is a file with the specified extension. |
hasMimeType() | Returns true if input is a file with the specified mime type. |
maxSize() | Returns true if input size is below the threshold. |
minSize() | Returns true if input size is above the threshold. |
Input.isAlphaNumeric constant
A predicate that returns true if the input is composed only of alphanumeric characters (a-z A-Z 0-9).
Input.isBoolean constant
A predicate that returns true if the input is a boolean (case invariant true/false 1/0).
Input.isEmail constant
A predicate that returns true if the input seems to be an email address.It does not imply that the input is a valid email address.
Input.isEmpty constant
A predicate that returns true if the input is null or has a length of 0.
Input.isFile constant
A predicate that returns true if the input is a data object with a file-upload structure.
Input.isFloatingPoint constant
A predicate that returns true if the input is composed only of digits (0-9) eventually preceded by the minus sign and may contain one decimal point separator.
Input.isInteger constant
A predicate that returns true if the input is composed only of digits (0-9) eventually preceded by the minus sign.
Input.isNagative constant
A predicate that returns true if the input is an integer or floating point number starting with the minus sign (-).
Input.isNotEmpty constant
A predicate that returns true if the input is not null and has a length greater than 0.
Input.isPositive constant
A predicate that returns true if the input is an integer or floating point number not starting with the minus sign (-).
Input.hasFileExtension() function
A function that returns a predicate to check if the input is a file-upload data structure and the file name ends with the specified extension.
public static final Predicate<Data> hasFileExtension(final String value)
- value: The file name ending.
Input.hasMimeType() function
A function that returns a predicate to check if the input is a file-upload data structure and has the specified mime type.
public static final Predicate<Data> hasFileExtension(final String value)
- value: The file mime type.
Input.maxSize() function
A function that returns a predicate to check if the input length is less or equal to the specified threshold.
public static final Predicate<Data> maxSize(final int value)
- value: The length threshold.
Input.minSize() function
A function that returns a predicate to check if the input length is greater or equal to the specified threshold.
public static final Predicate<Data> minSize(final int value)
- value: The length threshold.
JSON Class
The JSON class is a simple explicit wrapper to create Data class instances. It might be more intuitive for developers used to Javascript.
Members
array() | Returns an empty data list. |
object() | Returns an empty data map. |
parse() | Parses the input json string into a data object. |
stringify() | Converts values to a json string. |
JSON.array() function
Returns an empty Data object behaving like a list (array).
public static Data array()
JSON.object() function
Returns an empty Data object behaving like a map (object).
public static Data object()
JSON.parse() function
Parses the input json string into a Data object.
public static Data parse(String value)
- value: The input json to parse.
The parser is lenient, it can handle minor formatting issues. If the input is too malformed, an exception is thrown.
JSON.stringify() function
Converts values to a json string.
public static String stringify(Object value)
- value: The object to convert.
Output is always valid JSON, with strings properly escaped.
State Class
The State class can be used to manage temporary in-memory variables (i.e. session) from your endpoints.
The local state is bound to an endpoint while the global state is shared by all endpoints. State variables can also be bound to a User, or not.
Members
global() | Stores a value in, or retrieves a value from, the global state. |
local() | Stores a value in, or retrieves a value from, the local state. |
State.global() function
Stores a value in, or retrieves a value from, the global state.
public static <T> T global(String key, [User.Type user])
- key: The state variable name.
- user (optional): The user bound to that variable.
Returns the object that was previously set for that state variable name. If the value is not set, null
is returned.
If a value was stored with a user, it must be retrieved with the same user reference, global values are not shared across users unless explicitly stored without a user.
Returns the value previously stored, automatically cast to the expected type if possible.
If the cast fails, a ClassCastException
may occur.
public static <T> T global(String key, Object value, [long ttl]) public static <T> T global(String key, User.Type user, Object value, [long ttl])
- key: The state variable name.
- value: The value to store.
- user: The user to bind the value to.
- ttl (optional): Time to live (TTL), in milliseconds, after which the value is automatically removed.
Returns the previous value if one existed before, null
otherwise.
State.local() function
Stores a value in, or retrieves a value from, the local state.
public static <T> T local(String key, [User.Type user])
- key: The state variable name.
- user (optional): The user bound to that variable.
Returns the object that was previously set for that state variable name. If the value is not set, null
is returned.
If a value was stored with a user, it must be retrieved with the same user reference, local values are not shared across users unless explicitly stored without a user.
Returns the value previously stored, automatically cast to the expected type if possible.
If the cast fails, a ClassCastException
may occur.
public static <T> T local(String key, Object value, [long ttl]) public static <T> T local(String key, User.Type user, Object value, [long ttl])
- key: The state variable name.
- value: The value to store.
- user: The user to bind the value to.
- ttl (optional): Time to live (TTL), in milliseconds, after which the value is automatically removed.
Returns the previous value if one existed before, null
otherwise.
Storage Class
The Storage class is a simple object store wrapper. Instances are created in the User Panel.
In practice, the real class is Storage.Type
because of encapsulation.
Members
contains*() | Checks for existence of an item. |
get*() | Fetches an item. |
list() | Lists all items recursively. |
put() | Stores an item. |
remove() | Removes an item. |
tree() | Returns the tree-view (list of direct children). |
Storage.contains*() function
Checks for existence of an item.
public boolean containsEntry(String path)
- path: The full path to an item.
Returns whether the specified path exists and is an item you can fetch.
public boolean containsPath(String path)
- path: An intermediate path.
Returns whether the specified path exists and is not a final item (i.e. is a directory).
Storage.get*() function
Fetches an item.
public byte[] get(String path) public String getString(String path) public Data getData(String path)
- path: The full path to an item.
Returns the item content. Either the raw byte[]
, parsed as an UTF-8 String
, or parsed as a Data
object.
Storage.list() function
Lists all final entries (files only) that start with the provided path. If the path targets a final entry, that entry is returned. If the path targets a parent entry (a directory), all final entries are returned recursively.
public Collection<String> list(String path)
- path: The path to list.
The returned entries are full absolute paths.
Storage.put() function
Stores an item. If the item already exists, it is overwritten.
public void put(String path, byte[] content) public void put(String path, String content) public void put(String path, Data content)
- path: The full path of the item to store.
- content: The content either as a raw
byte[]
, aString
(will be encoded in UTF-8), or aData
object (will be encoded in JSON).
Storage.remove() function
Removes all entries that match the provided path. If the path targets a parent entry (a directory), all sub-entries are removed recursively.
public void remove(String path)
- path: The path to remove.
Storage.tree() function
Lists all direct sub-entries of the provided path. If the provided path is a final entry (a file), an empty list is returned. Directory entries are suffixed with a '/' character.
public Collection<String> tree(String path)
- path: The path to list.
The returned entries are relative to the provided path. For example, if the path is /foo/bar
and a direct child
is /foo/bar/beef
, the returned value will be beef
.
User Class
The User class represents the current authentication context to use in your endpoints.
In practice, the real class is User.Type
because of encapsulation.
Members
ANONYMOUS | Fixed user that represents the absence of authentication. |
SYSTEM | Fixed user that represents the internal system. |
hasRole() | Checks if the user has a specific role. |
isMemberOf() | Checks if the user is member of a specific group. |
name() | Returns the user name. |
User.ANONYMOUS constant
This constant represents the absence of authentication. The anonymous user has no privileges, is not member of any groups and does not have any roles.
User.SYSTEM constant
This constant represents the internal system. The system user has all privileges, and passes all security checks. However, it is not a member of any groups and does not have any specific roles.
User.hasRole() function
Returns whether the user has the specified role. Roles are defined in the User Panel.
public boolean hasRole(String role)
- role: The role name.
User.isMemberOf() function
Returns whether the user is a member of the specified group. Groups are defined in the User Panel.
public boolean isMemberOf(String group)
- group: The group name.
User.name() function
Returns the user name. Users are defined in the User Panel.
public String name()