### Handle HTTP Verbs with Lapis respond_to (MoonScript) Source: https://leafo.net/lapis/reference/quick_reference Provides an example of handling HTTP GET and POST requests using the `respond_to` decorator within a Lapis application written in MoonScript. It shows common setup logic in `before` and specific actions for GET and POST requests. ```moonscript lapis = require "lapis" import respond_to from require "lapis.application" class App extends lapis.Application "/login": respond_to { before: -- do common setup if @session.current_user @write redirect_to: "/" GET: -- render the view render: true POST: -- handle the form submission @session.current_user = try_to_login(@params.username, @params.password) redirect_to: "/" } ``` -------------------------------- ### Basic Lapis Application Setup (Lua) Source: https://leafo.net/lapis/index This snippet demonstrates the fundamental setup of a Lapis web application in Lua. It initializes a Lapis application and defines a simple route that returns 'Hello world!'. This is the starting point for most Lapis applications. ```lua local lapis = require "lapis" local app = lapis.Application() app:match("/", function(self) return "Hello world!" end) return app ``` -------------------------------- ### Handle HTTP Verbs with Lapis respond_to (Lua) Source: https://leafo.net/lapis/reference/quick_reference Demonstrates using the `respond_to` action decorator in Lapis to define different handlers for HTTP GET and POST requests. It includes a `before` function for common setup and specific handlers for GET (rendering) and POST (login processing). ```lua local lapis = require("lapis") local app = lapis.Application() local respond_to = require("lapis.application").respond_to app:match("/", respond_to({ -- do common setup before = function(self) if self.session.current_user then self:write({ redirect_to = "/" }) end end, -- render the view GET = function(self) return { render = true } end, -- handle the form submission POST = function(self) self.session.current_user = try_to_login(self.params.username, self.params.password) return { redirect_to = "/" } end })) ``` -------------------------------- ### Start Lapis Server Source: https://leafo.net/lapis/reference/moon_getting_started Command to start the Lapis development server. Assumes that MoonScript files have been compiled. ```bash lapis server ``` -------------------------------- ### Lua Lapis Configuration Example Source: https://leafo.net/lapis/reference/lua_creating_configurations Demonstrates how to define and merge configurations using the `lapis.config` module in Lua. It shows how to set base values and then override them for specific environments like 'production'. The output shows the resulting merged configurations for 'development' and 'production'. ```lua -- config.lua local config = require("lapis.config") config({"development", "production"}, { host = "example.com", email_enabled = false, postgres = { host = "localhost", port = "5432", database = "my_app" } }) config("production", { email_enabled = true, postgres = { database = "my_app_prod" } }) ``` ```lua -- "development" { host = "example.com", email_enabled = false, postgres = { host = "localhost", port = "5432", database = "my_app", }, _name = "development" } ``` ```lua -- "production" { host = "example.com", email_enabled = true, postgres = { host = "localhost", port = "5432", database = "my_app_prod" }, _name = "production" } ``` -------------------------------- ### Basic Lapis Application Setup (MoonScript) Source: https://leafo.net/lapis/index This snippet shows the equivalent basic setup of a Lapis web application using MoonScript, a language that compiles to Lua. It defines a simple route returning 'Hello world!' in a more concise syntax. ```moonscript lapis = require "lapis" class extends lapis.Application "/": => "Hello world!" ``` -------------------------------- ### Example cURL command for JSON request Source: https://leafo.net/lapis/reference/quick_reference An example of using `curl` to send a JSON-encoded request body to a Lapis application endpoint. It includes setting the `Content-Type` header and providing the JSON data. ```bash $ curl \ -H "Content-type: application/json" \ -d '{"value": "hello"}' \ 'https://localhost:8080/json' ``` -------------------------------- ### Accessing Configuration in Lapis (Lua - alternative syntax) Source: https://leafo.net/lapis/reference/configuration An alternative syntax for accessing Lapis configuration in Lua. It achieves the same result as the previous example by calling `lapis.config.get()` and accessing the `port` property. ```lua config = require "lapis.config".get! print config.port -- shows the current port ``` -------------------------------- ### Write HTTP Header Source: https://leafo.net/lapis/reference/quick_reference Illustrates two methods for setting HTTP headers in Lapis responses. ```APIDOC ## How do I write a HTTP header? There are two ways to write headers. In these examples we set the `Access-Control-Allow-Origin` header to `*` You can return a headers field (or pass it to `write`) from an action: ### Lua Example ```lua local lapis = require("lapis") local app = lapis.Application() app:match("/", function(self) return { "OK", headers = { ["Access-Control-Allow-Origin"] = "*" } } end) ``` ### MoonScript Example ```moonscript lapis = require "lapis" class App extends lapis.Application "/": => "ok", { headers: { "Access-Control-Allow-Origin": "*" } } ``` Alternatively, the `res` field of the `self` has a `headers` field that lets you set headers. ### Lua Example ```lua local lapis = require("lapis") local app = lapis.Application() app:match("/", function(self) self.res.headers["Access-Control-Allow-Origin"] = "*" return "ok" end) ``` ### MoonScript Example ```moonscript lapis = require "lapis" class App extends lapis.Application "/": => @res.headers["Access-Control-Allow-Origin"] = "*" "ok" ``` If you need to change the content type see below. ``` -------------------------------- ### OpenResty Installation Paths Searched by Lapis Source: https://leafo.net/lapis/reference/getting_started Lapis searches for the OpenResty Nginx binary in these directories. It prioritizes specific OpenResty installation locations and checks the system's PATH as a fallback. Lapis requires OpenResty, not a standard Nginx installation. ```text "/usr/local/openresty/nginx/sbin/" "/usr/local/opt/openresty/bin/" "/usr/sbin/" "" ``` -------------------------------- ### ETLua Template Example Source: https://leafo.net/lapis/index An example of an etlua template file demonstrating basic HTML structure, variable interpolation, and conditional logic. Etlua is a templating language for Lapis that allows embedding Lua code. ```etlua

<%= "Hello" %>

<% if current_user then %>
Welcome back <%= current_user.name %>
<% end %>
Welcome to my site
``` -------------------------------- ### Lapis HTTP Module - Basic Usage Source: https://leafo.net/lapis/reference/utilities Demonstrates making simple GET and POST requests using the `lapis.http` module, which abstracts the underlying HTTP client. ```APIDOC ## Making HTTP Requests with lapis.http ### Description The `lapis.http` module provides a unified interface for making HTTP requests, automatically selecting an appropriate client based on the environment (Nginx, Cqueues, or default LuaSocket). ### Methods - `lapis.http.request(url)`: Performs a GET request. - `lapis.http.request(options)`: Performs a request with custom options (method, headers, body, etc.). ### Parameters for `lapis.http.request(options)` #### Request Body (for POST/PUT) - **url** (string) - The URL to request. - **method** (string) - The HTTP method (e.g., "POST", "GET"). Defaults to "GET". - **headers** (table) - A table of request headers. - **source** (LTN12 stream) - The request body source (for POST/PUT). - **sink** (LTN12 stream) - The response body sink. ### Request Example (Lua) ```lua local http = require("lapis.http") local ltn12 = require("ltn12") -- Simple GET request local body, status_code, headers = http.request("http://leafo.net") -- Simple POST request local out = {} local _, status_code, headers = http.request({ url = "http://leafo.net", method = "POST", headers = { ["Content-type"] = "application/x-www-form-urlencoded" }, source = ltn12.source.string("param1=value1¶m2=value2"), sink = ltn12.sink.table(out) }) local body = table.concat(out) ``` ### Request Example (MoonScript) ```moonscript http = require "lapis.http" ltn12 = require "ltn12" -- Simple GET request body, status_code, headers = http.request "http://leafo.net" -- Simple POST request out = {} _, status_code, headers = http.request { url: "http://leafo.net", method: "POST", headers: { ["Content-type"] = "application/x-www-form-urlencoded" } source: ltn12.source.string "param1=value1¶m2=value2" sink: ltn12.sink.table(out) } body = table.concat out ``` ### Response - **body** (string) - The response body. - **status_code** (number) - The HTTP status code. - **headers** (table) - A table of response headers. ``` -------------------------------- ### Database Migrations Source: https://leafo.net/lapis/reference/database Guide to managing database schema changes using Lapis migrations. ```APIDOC ## Database Migrations Lapis provides a module for managing database schema changes (Migrations). * Running Migrations * Generating Migration Stubs * Manually Running Migrations (Further details on migration commands and usage would be provided here.) ``` -------------------------------- ### Basic Lapis Application Structure (Lua) Source: https://leafo.net/lapis/reference/lua_getting_started Defines a fundamental Lapis application in Lua. It sets up a GET route for the root path that returns a welcome message including the Lapis version. ```lua -- app.lua local lapis = require("lapis") local app = lapis.Application() app:get("/", function() return "Welcome to Lapis " .. require("lapis.version") end) return app ``` -------------------------------- ### Install Lapis Console with LuaRocks Source: https://leafo.net/lapis/reference/lapis_console Installs the Lapis Console package using LuaRocks, the Lua package manager. This command is executed in the terminal. ```bash $ luarocks install lapis-console ``` -------------------------------- ### Read HTTP Header Source: https://leafo.net/lapis/reference/quick_reference Demonstrates how to read HTTP headers from an incoming request in Lapis. ```APIDOC ## How do I read a HTTP header? The `req` field of the `self` passed to actions has a headers fields with all the request headers. They are normalized so you don’t have to be concerned about capitalization. ### Lua Example ```lua local lapis = require("lapis") local app = lapis.Application() app:match("/", function(self) return self.req.headers["referrer"] end) ``` ### MoonScript Example ```moonscript lapis = require "lapis" class App extends lapis.Application "/": => @req.headers["referrer"] ``` ``` -------------------------------- ### Set Content Type Source: https://leafo.net/lapis/reference/quick_reference Explains how to set the `Content-Type` header for responses in Lapis. ```APIDOC ## How do I set the content type? Either manually set the header as described above, or use the `content_type` option of the `write` method, or action return value: ### Lua Example ```lua local lapis = require("lapis") local app = lapis.Application() app:match("/", function(self) return { content_type = "text/rss", [[]] } end) ``` ### MoonScript Example ```moonscript lapis = require "lapis" class App extends lapis.Application "/": => [[]], content_type: "text/rss" ``` ``` -------------------------------- ### Lapis Server Startup and Termination Commands Source: https://leafo.net/lapis/reference/getting_started Commands for managing the Lapis server. 'lapis server' starts the application by finding and configuring OpenResty. 'lapis term' is used to stop a server that is running in the background by sending a TERM signal to its PID. ```shell $ lapis server ``` ```shell lapis term ``` -------------------------------- ### Database Migrations with Schema Functions (Lua) Source: https://leafo.net/lapis/reference/database Provides examples of database migrations in Lua using `lapis.db.schema` functions. It shows how to define migrations as a table of functions, keyed by timestamps, to add columns and create indexes. ```lua local schema = require("lapis.db.schema") return { [1368686109] = function() schema.add_column("my_table", "hello", schema.types.integer) end, [1368686843] = function() schema.create_index("my_table", "hello") end } ``` -------------------------------- ### Create Database Tables with Lapis Schema Source: https://leafo.net/lapis/reference/database Provides examples of using `lapis.db.schema.create_table` to define and create database tables. It covers specifying columns, data types, and primary keys for both Lua and MoonScript. ```Lua local schema = require("lapis.db.schema") local types = schema.types schema.create_table("users", { {"id", types.serial}, {"username", types.varchar}, "PRIMARY KEY (id)" }) ``` ```MoonScript schema = require "lapis.db.schema" import create_table, types from schema create_table "users", { {"id", types.serial} {"username", types.varchar} "PRIMARY KEY (id)" } ``` ```SQL CREATE TABLE IF NOT EXISTS "users" ( "id" serial NOT NULL, "username" character varying(255) NOT NULL, PRIMARY KEY (id) ); ``` -------------------------------- ### HTTP Verb Route Shortcuts Source: https://leafo.net/lapis/reference/actions Provides shortcut methods (`get`, `post`, `delete`, etc.) for adding routes specific to HTTP verbs, utilizing the `match` method internally. ```APIDOC ## HTTP Verb Route Shortcuts ### Description These are shortcut methods for `application:match` that specifically handle requests for a given HTTP verb. They use `respond_to` internally to match the verb. ### Methods - `application:get(...)` - `application:post(...)` - `application:delete(...)` - (And other HTTP verbs) ### Endpoint N/A (These are methods for defining routes within the application) ### Parameters Same arguments as `application:match`. ### Request Example ```lua -- Lua MoonScript app:get("/users", function(self) return User.all() end) app:post("/users", function(self) return User.create(self.params) end) ``` ```moonscript -- MoonScript app:get "/users", => User.all() app:post "/users", => User.create(@params) ``` ### Response N/A (These methods configure routes; the response is determined by the action function executed when the route is matched.) ``` -------------------------------- ### Create New Lapis Project Source: https://leafo.net/lapis/reference/command_line Initializes a new Lapis project with starter files. Supports generating configurations for Nginx or cqueues, and templates in Lua or MoonScript. Optionally includes .gitignore, Tupfile, and rockspec files. Use --force to bypass environment checks. ```bash Usage: lapis new ([--nginx] | [--cqueues]) ([--lua] | [--moonscript]) [-h] [--etlua-config] [--git] [--tup] [--rockspec] [--force] Create a new Lapis project in the current directory Options: -h, --help Show this help message and exit. --nginx Generate config for nginx server (default) --cqueues Generate config for cqueues server --lua Generate app template file in Lua (default) --moonscript, --moon Generate app template file in MoonScript --etlua-config Use etlua for templated configuration files (eg. nginx.conf) --git Generate default .gitignore file --tup Generate default Tupfile --rockspec Generate a rockspec file for managing dependencies --force Bypass errors when detecting functional server environment ``` -------------------------------- ### Basic Route and Action in MoonScript Source: https://leafo.net/lapis/reference/moon_getting_started A simple Lapis application demonstrating a route '/hello' mapped to an action that returns 'Hello World!'. It illustrates the basic structure of a route and its corresponding action function. ```moonscript lapis = require "lapis" class App extends lapis.Application "/hello": => "Hello World!" ``` -------------------------------- ### Complex has_many relation with custom options Source: https://leafo.net/lapis/reference/models Provides an example of a more complex 'has_many' relation setup. It utilizes custom 'where', 'order', and 'key' options to define the relationship and fetching behavior for 'authored_posts'. ```lua local Model = require("lapis.db.model").Model local Users = Model:extend("users", { relations = { {"authored_posts", has_many = "Posts", where = {deleted = false}, order = "id desc", key = "poster_id"} } }) ``` ```moonscript import Model from require "lapis.db.model" class Users extends Model @relations: {"authored_posts" has_many: "Posts" where: {deleted = false} order: "id desc" key: "poster_id"} ``` ```lua local posts = user:get_authored_posts() ``` ```moonscript posts = user\get_authored_posts! ``` ```sql SELECT * from "posts" where "poster_id" = 123 and deleted = FALSE order by id desc ``` -------------------------------- ### Nginx Configuration Interpolation Example Source: https://leafo.net/lapis/reference/configuration This snippet demonstrates how Lapis configuration values can be interpolated into an Nginx configuration file. The `${{VARIABLE_NAME}}` syntax is used for variable substitution, often sourced from environment variables. ```nginx events { worker_connections ${{WORKER_CONNECTIONS}}; } ``` -------------------------------- ### Establishing A Connection Source: https://leafo.net/lapis/reference/database Details on how to establish database connections for PostgreSQL, MySQL, and SQLite. ```APIDOC ## Establishing A Connection Lapis supports connections to PostgreSQL, MySQL, and SQLite. The specific library used depends on the environment and configuration. ### PostgreSQL * Uses `pgmoon`. Supports OpenResty’s cosocket API, LuaSocket, and cqueues. ### MySQL * In OpenResty environments: `lua-resty-mysql`. * Otherwise: `LuaSQL-MySQL`. ### SQLite * Uses `LuaSQLite3`. * Note: SQLite queries are blocking and do not use connection pooling as it's embedded into the application. ``` -------------------------------- ### Set Content Type in Lapis (MoonScript) Source: https://leafo.net/lapis/reference/quick_reference Demonstrates setting the response `content_type` in Lapis using MoonScript. The example shows utilizing the `content_type` option directly in the action's return value for efficiency. ```moonscript lapis = require "lapis" class App extends lapis.Application "/": => [[]], content_type: "text/rss" ``` -------------------------------- ### Get Model Table Name (Lua, MoonScript) Source: https://leafo.net/lapis/reference/models The `table_name()` method returns the name of the database table associated with the model. This method can be overridden in a model class to specify a custom table name. Examples are shown for both Lua and MoonScript syntax. ```lua Model:extend("users"):table_name() --> "users" Model:extend("user_posts"):table_name() --> "user_posts" class Users extends Model @table_name: => "active_users" ``` ```moonscript (class Users extends Model)\table_name! --> "users" (class UserPosts extends Model)\table_name! --> "user_posts" (class Users extends Model) @table_name: => "active_users" ``` -------------------------------- ### Create a New Lapis Project with MoonScript Source: https://leafo.net/lapis/reference/moon_getting_started Command to initialize a new Lapis project with MoonScript support. It generates a default Nginx configuration and a skeleton MoonScript application file. ```bash $ lapis new --moonscript ``` -------------------------------- ### Render JSON Response in Lapis (Lua) Source: https://leafo.net/lapis/reference/quick_reference Provides a Lua example for rendering a JSON response in Lapis. It utilizes the `json` option within the action's return value to automatically serialize a Lua table into a JSON string. ```lua local lapis = require("lapis") local app = lapis.Application() app:match("/", function(self) return { json = { success = true, message = "hello world" } } end) ``` -------------------------------- ### Basic Lapis Application Structure in MoonScript Source: https://leafo.net/lapis/reference/moon_getting_started A minimal Lapis application written in MoonScript. It defines a single route '/' that responds with a welcome message including the Lapis version. ```moonscript lapis = require "lapis" class extends lapis.Application "/": => "Welcome to Lapis #{require "lapis.version"}!" ``` -------------------------------- ### Generate New Lapis Project Source: https://leafo.net/lapis/reference/lua_getting_started Command to create a new Lapis project skeleton. Assumes OpenResty and Nginx configurations are pre-existing. Initializes an 'app.lua' file for the application. ```bash $ lapis new ``` -------------------------------- ### Overriding Configuration with Environment Variables Source: https://leafo.net/lapis/reference/configuration This example shows how to override Lapis configuration values using environment variables. By prefixing the configuration name with 'LAPIS_' and making it uppercase, the environment variable takes precedence. Note that values are read as strings and may require type coercion. ```bash $ LAPIS_WORKER_CONNECTIONS=5 lapis server ``` -------------------------------- ### Get Model Singular Name (Lua, MoonScript) Source: https://leafo.net/lapis/reference/models The `singular_name()` method returns the singular form of the model's name, typically derived from the table name. This is used internally by Lapis for features like `include_in` and determining foreign key names in relations (`has_one`, `has_many`). Examples are provided for Lua and MoonScript. ```lua Model:extend("users"):singular_name() --> "user" Model:extend("user_posts"):singular_name() --> "user_post" ``` ```moonscript (class Users extends Model)\singular_name! --> "user" (class UserPosts extends Model)\singular_name! --> "user_post" ``` -------------------------------- ### Handling HTTP Verbs with respond_to Source: https://leafo.net/lapis/reference/actions Demonstrates how to handle different HTTP verbs (like GET and POST) within a single route using the `respond_to` helper. It also shows how to define a `before` filter. ```APIDOC ## Handling HTTP Verbs with `respond_to` ### Description The `respond_to` helper allows a single route handler to respond differently based on the incoming HTTP verb. It accepts a table where keys are HTTP verbs and values are the corresponding handler functions. A `before` filter can also be specified to run before any verb-specific handler. ### Method `respond_to(options)` where `options` is a table containing HTTP verb keys (e.g., `GET`, `POST`) and their associated functions, and an optional `before` function. ### Endpoint Examples - `/create-account` - `/edit-user/:id` ### Parameters - **HTTP Verb** (e.g., `GET`, `POST`) - A function to execute for the specified HTTP verb. - **before** (function, optional) - A function to execute before the verb-specific handler. If this function calls `self:write()`, subsequent handlers will not be executed. ### Request Example (Lua MoonScript) ```moonscript app:match("create_account", "/create-account", respond_to({ GET = function(self) return { render = true } end, POST = function(self) do_something(self.params) return { redirect_to = self:url_for("index") } end })) app:match("edit_user", "/edit-user/:id", respond_to({ before = function(self) self.user = Users:find(self.params.id) if not self.user then self:write({"Not Found", status = 404}) end end, GET = function(self) return "Edit account " .. self.user.name end, POST = function(self) self.user:update(self.params.user) return { redirect_to = self:url_for("index") } end })) ``` ### Request Body - When `Content-Type` is `application/x-www-form-urlencoded` on `POST` requests, parameters are parsed into `self.params`. ### Response Example (Success) - Depends on the handler function; can return rendered content, redirects, or other Lapis responses. ### Error Handling - If the `before` filter calls `self:write({..., status = 404})`, a 404 Not Found response is returned. ``` -------------------------------- ### lapis new Source: https://leafo.net/lapis/reference/command_line Creates a new Lapis project in the current directory. It generates starter files for configuration and application logic. Options allow customization of server type (Nginx or Cqueues), language (Lua or MoonScript), and additional files like .gitignore, Tupfile, and rockspec. ```APIDOC ## `lapis new` ### Description Creates a new Lapis project in the current directory by generating starter files. This command can be helpful for getting started quickly, but it's not mandatory to use it. ### Method CLI Command ### Endpoint N/A (CLI Command) ### Parameters #### CLI Arguments - **`[--nginx | --cqueues]`**: Server type. `--nginx` for Nginx (default), `--cqueues` for Cqueues. - **`[--lua | --moonscript]`**: Language for app template. `--lua` (default), `--moonscript` for MoonScript. #### Options - **`-h, --help`**: Show help message and exit. - **`--etlua-config`**: Use etlua for templated configuration files. - **`--git`**: Generate a default `.gitignore` file. - **`--tup`**: Generate a default `Tupfile`. - **`--rockspec`**: Generate a rockspec file for dependency management. - **`--force`**: Bypass errors when detecting a functional server environment. ### Request Example ```bash lapis new --moonscript --rockspec ``` ### Response #### Success Response Generates project files in the current directory. #### Response Example ``` (Project files created: nginx.conf, mime.types, app.lua, config.lua, etc.) ``` ``` -------------------------------- ### Lapis Request Write Method Example Source: https://leafo.net/lapis/reference/actions Illustrates the usage of the `request:write()` method in Lapis. It shows how strings, callable functions, and tables are handled when appended to the output buffer or options table. ```lapis request:write(string_argument) request:write(function_argument) request:write(table_argument) ``` -------------------------------- ### Example JSON Error Response from Lapis Source: https://leafo.net/lapis/reference/exception_handling This is an example of the JSON output generated by `capture_errors_json` when an error occurs. The response includes an `errors` key containing an array of error messages. ```json { errors: ["something bad happened"] } ``` -------------------------------- ### Set Up User Session with Before Filter (Lua) Source: https://leafo.net/lapis/reference/actions This example shows how to set up a user session before each action is processed. It checks for a user in the session and loads the user object if found. This filter runs before the root path '/' action. ```lua local app = lapis.Application() app:before_filter(function(self) if self.session.user then self.current_user = load_user(self.session.user) end end) app:match("/", function(self) return "current user is: " .. tostring(self.current_user) end) ``` ```moonscript lapis = require "lapis" class App extends lapis.Application @before_filter => if @session.user @current_user = load_user @session.user "/": => "current user is: #{@current_user}" ``` -------------------------------- ### Lapis Application with Database and CSRF (Lua) Source: https://leafo.net/lapis/index A comprehensive Lapis application example written in pure Lua. It demonstrates setting up routes for listing users, viewing a user profile, and creating a new user with CSRF protection and database interactions using Lapis models. ```lua local lapis = require "lapis" local Model = require("lapis.db.model").Model local capture_errors = require("lapis.application").capture_errors local csrf = require "lapis.csrf" local Users = Model:extend("users") local app = lapis.Application() app:before_filter(function(self) self.csrf_token = csrf.generate_token(self) end) app:get("list_users", "/users", function(self) self.users = Users:select() -- `select` all users return { render = true } end) app:get("user", "/profile/:id", function(self) local user = Users:find({ id = self.params.id }) if not user then return { status = 404 } end return { render = true } end) app:post("new_user", "/user/new", capture_errors(function(self) csrf.assert_token(self) Users:create({ name = assert_error(self.params.username, "Missing username") }) return { redirect_to = self:url_for("list_users") } end)) app:get("new_user", "/user/new", function(self) return { render = true } end) return app ``` -------------------------------- ### Install Tableshape Validation Library Source: https://leafo.net/lapis/reference/input_validation This command installs the Tableshape library, which is required for using Lapis's new validation system. Tableshape provides powerful tools for validating and transforming data structures. ```bash $ luarocks install tableshape ``` -------------------------------- ### Define Polymorphic Belongs To Relation (MoonScript) Source: https://leafo.net/lapis/reference/models Example of defining a polymorphic_belongs_to relation in Lapis ORM using MoonScript. This demonstrates the equivalent syntax to the Lua example for creating a relation where a model can belong to multiple other types. ```moonscript import Model from require "lapis.db.model" class Posts extends Model @relations: { {"object", polymorphic_belongs_to: { [1]: "VideoGames" [2]: "Books" }} } ``` -------------------------------- ### Convenience HTTP Verb Wrappers Source: https://leafo.net/lapis/reference/actions Introduces the convenience methods like `app:get()`, `app:post()`, `app:delete()`, and `app:put()` as shortcuts for defining actions that handle specific HTTP verbs. ```APIDOC ## Convenience HTTP Verb Wrappers ### Description Lapis provides shortcut methods for the most common HTTP verbs (`get`, `post`, `delete`, `put`) that act as wrappers around `respond_to`. These simplify the definition of routes that only need to handle a single HTTP verb. ### Method - `app:get(pattern, handler)` - `app:post(pattern, handler)` - `app:delete(pattern, handler)` - `app:put(pattern, handler)` ### Endpoint Examples - `/test` (for GET requests) - `/delete-account` (for DELETE requests) ### Parameters - **pattern** (string) - The URL pattern for the route. - **handler** (function) - The function to execute when a request with the corresponding HTTP verb matches the pattern. ### Request Example (Lua) ```lua app:get("/test", function(self) return "I only render for GET requests" end) app:delete("/delete-account", function(self) -- do something destructive end) ``` ### Response Example (Success) - Returns the value returned by the handler function. ``` -------------------------------- ### Lapis HTTP GET and POST Requests (MoonScript) Source: https://leafo.net/lapis/reference/utilities Illustrates making GET and POST HTTP requests with `lapis.http` in MoonScript. This version uses MoonScript's syntax for defining tables and function calls. Requires `lapis.http` and `ltn12`. ```moonscript http = require "lapis.http" ltn12 = require "ltn12" -- a simple GET request body, status_code, headers = http.request "http://leafo.net" out = {} _, status_code, headers = http.request { url: "http://leafo.net", method: "POST", headers: { ["Content-type"] = "application/x-www-form-urlencoded" } source: ltn12.source.string "param1=value1¶m2=value2" sink ltn12.sink.table(out) } body = table.concat out ``` -------------------------------- ### Lapis Application with Multiple Routes in MoonScript Source: https://leafo.net/lapis/reference/moon_getting_started An example of a Lapis application in MoonScript with three routes: a homepage, a list of favorite foods, and a detail page for each food. It demonstrates inline HTML generation and URL for route generation. ```moonscript lapis = require "lapis" favorite_foods = { "pizza": "Wow pizza is the best! Definitely my favorite" "egg": "A classic breakfast, never leave home without" "ice cream": "Can't have a food list without a dessert" } class App extends lapis.Application [index: "/"]: => -- Render HTML inline for simplicity @html -> h1 "My homepage" a href: @url_for("list_foods"), "Check out my favorite foods" [list_foods: "/foods"]: @html -> ul -> for food in pairs favorite_foods li -> a href: @url_for("food", name: food), food [food: "/food/:name"]: food_description = favorite_foods[@params.name] unless food_description return "Not found", status: 404 @html -> h1 @params.name h2 "My thoughts on this food" p food_description ``` -------------------------------- ### Lapis HTTP GET and POST Requests (Lua) Source: https://leafo.net/lapis/reference/utilities Demonstrates how to perform simple GET and POST HTTP requests using the `lapis.http` module in Lua. It utilizes LTN12 for handling request bodies and sinks. Requires `lapis.http` and `ltn12`. ```lua local http = require("lapis.http") local ltn12 = require("ltn12") -- a simple GET request local body, status_code, headers = http.request("http://leafo.net") -- a simple POST request local out = {} local _, status_code, headers = http.request({ url = "http://leafo.net", method = "POST", headers = { ["Content-type"] = "application/x-www-form-urlencoded" }, source = ltn12.source.string("param1=value1¶m2=value2"), sink = ltn12.sink.table(out) }) local body = table.concat(out) ``` -------------------------------- ### MoonScript Configuration Builder Example Source: https://leafo.net/lapis/reference/moon_creating_configurations Demonstrates the MoonScript configuration builder syntax using function calls to define variables and structure configurations. It includes conditional logic, nested table definitions, merging behavior for duplicate keys, and inclusion of external functions. The output shows the generated Lua table. ```moonscript some_function = -> steak "medium_well" config "development", -> hello "world" if 20 > 4 color "blue" else color "green" custom_settings -> age 10 enabled true -- tables are merged extra -> name "leaf" mood "happy" extra -> name "beef" shoe_size 12 include some_function include some_function -- a normal table can be passed instead of a function some_list { 1,2,3,4 } -- use set to assign names that are unavailable set "include", "hello" ``` ```lua { hello: "world" color: "blue" custom_settings: { age: 10 enabled: true } extra: { name: "beef" mood: "happy" shoe_size: 12 steak: "medium_well" } steak: "medium_well" some_list: { 1,2,3,4 } include: "hello" } ``` -------------------------------- ### Optional Validation Example Source: https://leafo.net/lapis/reference/input_validation Demonstrates how to use optional validations in Lapis. The 'optional = true' flag allows a validation to be skipped if the parameter's value is nil. This example validates a 'color' parameter, ensuring it exists and meets length constraints only if provided. ```moonscript validate.assert_valid(self.params, { { "color", exists = true, min_length = 2, max_length = 25, optional = true }, }) ``` ```moonscript assert_valid @params, { { "color", exists: true, min_length: 2, max_length: 25, optional: true }, } ``` -------------------------------- ### Basic etlua Tags and Usage in Lapis Source: https://leafo.net/lapis/reference/lua_getting_started Demonstrates the fundamental etlua tags for embedding Lua code and expressions within HTML. Includes an example of assigning data in a Lapis application action and rendering it in an etlua view, showing verbatim code execution and HTML-escaped output. ```lua -- app.lua local lapis = require("lapis") local app = lapis.Application() app:enable("etlua") app:get("/", function(self) self.my_favorite_things = { "Cats", "Horses", "Skateboards" } return { render = "list" } end) return app ``` ```html

Here are my favorite things

    <% for i, thing in pairs(my_favorite_things) do %>
  1. <%= thing %>
  2. <% end %>
``` -------------------------------- ### Curl Request Example for JSON Parameters Source: https://leafo.net/lapis/reference/utilities This example demonstrates how to send a JSON payload to a Lapis application endpoint configured to use `json_params`. It uses `curl` to send a POST request with the `Content-type` header set to `application/json` and a JSON string in the request body. ```shell $ curl \ -H "Content-type: application/json" \ -d '{"value": "hello"}' \ 'https://localhost:8080/json' ``` -------------------------------- ### Define a simple '/hello' route in Lapis Source: https://leafo.net/lapis/reference/actions This snippet demonstrates how to define a basic route that responds with a JSON object. It shows the implementation in both Lua and MoonScript, highlighting their distinct syntax for defining routes and JSON responses. ```lua app:match("/hello", function(self) return { json = { hello = "world" } } end) ``` ```moonscript class App extends lapis.Application "/hello": => json: { hello: "world!" } ``` -------------------------------- ### Application Methods for Routing Source: https://leafo.net/lapis/reference/actions Provides an overview of the methods available on the `lapis.Application` object for defining routes and actions. ```APIDOC ## Application Methods for Routing These methods are used to define routes and associate them with action functions or module names. ### `application:match([route_name], route_patch, action_fn)` - **Purpose**: Defines a route that matches a given `route_patch` and executes the `action_fn`. - **Parameters**: - `route_name` (string, optional): A name for the route, used for URL generation. - `route_patch` (string): The URL path pattern to match. - `action_fn` (function or string): The function to execute or the module name to load the action from. ### `application:get(route_patch, action_fn)` - **Purpose**: Defines a route that specifically handles GET requests. ### `application:post(route_patch, action_fn)` - **Purpose**: Defines a route that specifically handles POST requests. ### `application:delete(route_patch, action_fn)` - **Purpose**: Defines a route that specifically handles DELETE requests. ### `application:put(route_patch, action_fn)` - **Purpose**: Defines a route that specifically handles PUT requests. ``` -------------------------------- ### POST /user/:id Source: https://leafo.net/lapis/reference/input_validation Example of using `with_params` to validate and extract parameters for a user action. ```APIDOC ## POST /user/:id ### Description This endpoint uses `with_params` to validate the `id` and `action` parameters from the request. If validation succeeds, it proceeds to execute the action function, passing the validated parameters. ### Method POST ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (db_id) - Required - The ID of the user. #### Query Parameters None #### Request Body None (parameters are expected to be validated from path and potentially other sources like query or form data, depending on Lapis configuration). ### Request Example ```json { "action": "update" } ``` ### Response #### Success Response (200) - **Output**: The result of the executed action function. In the example, it prints to the server console. #### Response Example ``` Perform update on user 123 ``` #### Error Response (e.g., 400) - **error** (string) - A JSON object detailing the validation errors if the parameters do not match the expected schema. ``` -------------------------------- ### lapis server Source: https://leafo.net/lapis/reference/command_line Starts the configured web server for the Lapis application in a specified environment. It reads the configuration to determine the server type and then launches the application. Supports OpenResty and Cqueues servers, with options for specifying the OpenResty binary path. ```APIDOC ## `lapis server` ### Description Starts the configured webserver for your Lapis application under the specified environment. It reads the configuration file to determine the server type and then attempts to start the application. ### Method CLI Command ### Endpoint N/A (CLI Command) ### Parameters #### Arguments - **`[environment]`**: The environment to run the server in (e.g., `development`, `production`). #### Environment Variables - **`LAPIS_OPENRESTY`**: Manually specify the path to the OpenResty binary if it's not found in standard locations. ### Request Example ```bash lapis server development LAPIS_OPENRESTY=/usr/local/openresty/nginx/sbin/nginx lapis server production ``` ### Response #### Success Response Starts the web server and listens for requests. #### Response Example ``` (Server started successfully. Listening on port X...) ``` ``` -------------------------------- ### Complex `has_many` Example Source: https://leafo.net/lapis/reference/models Demonstrates a more complex `has_many` relation configuration with custom keys, filtering, and ordering. ```APIDOC ## Complex `has_many` Example Here’s a more complex example utilizing some of the options for `has_many`: ### Lua Example ```lua local Model = require("lapis.db.model").Model local Users = Model:extend("users", { relations = { {"authored_posts", has_many = "Posts", where = {deleted = false}, order = "id desc", key = "poster_id"} } }) ``` ### MoonScript Example ```moonscript import Model from require "lapis.db.model" class Users extends Model @relations: {"authored_posts" has_many: "Posts" where: {deleted = false} order: "id desc" key: "poster_id"} ``` ### Fetching Related Objects #### Lua Example ```lua local posts = user:get_authored_posts() ``` #### MoonScript Example ```moonscript posts = user\get_authored_posts! ``` #### SQL Example ```sql SELECT * from "posts" where "poster_id" = 123 and deleted = FALSE order by id desc ``` ``` -------------------------------- ### Configure 'test' Environment Database (MoonScript) Source: https://leafo.net/lapis/reference/testing This MoonScript snippet shows the equivalent configuration for the 'test' environment's PostgreSQL database as the Lua example. It uses MoonScript syntax to define the database settings for testing. Add this to your 'config.moon' file. ```moonscript config = require "lapis.config" -- other configuration ... config "test", -> postgres { backend: "pgmoon" database: "myapp_test" } ``` -------------------------------- ### Lapis Routing and HTML Generation (MoonScript) Source: https://leafo.net/lapis/index This MoonScript snippet demonstrates advanced Lapis routing, mirroring the Lua example. It shows named routes with parameters and the use of HTML builder syntax for generating markup, defining a root and a profile route. ```moonscript lapis = require "lapis" class extends lapis.Application -- Define a basic pattern that matches / "/": => profile_url = @url_for "profile", name: "leafo" -- Use HTML builder syntax helper to quickly and safely write markup @html -> h2 "Welcome!" text "Go to my " a href: profile_url, "profile" -- Define a named route pattern with a variable called name [profile: "/:name"]: @html -> div class: "profile", -> text "Welcome to the profile of ", @params.name ``` -------------------------------- ### Render JSON Response Source: https://leafo.net/lapis/reference/quick_reference Details how to send JSON data as an HTTP response using Lapis. ```APIDOC ## How to do I render JSON? Use the `json` option of the `write` method, or the action’s return value: ### Lua Example ```lua local lapis = require("lapis") local app = lapis.Application() app:match("/", function(self) return { json = { success = true, message = "hello world" } } end) ``` ### MoonScript Example ```moonscript lapis = require "lapis" class App extends lapis.Application "/": => { json: { success: true message: "hello world" } } ``` ``` -------------------------------- ### Handle HTTP Verbs with Lapis respond_to (Lua & MoonScript) Source: https://leafo.net/lapis/reference/actions Shows how to use the `respond_to` helper to define different actions for GET and POST requests on the same route. Includes basic rendering and redirection logic. Supports Lua and MoonScript. ```lua local lapis = require("lapis") local respond_to = require("lapis.application").respond_to local app = lapis.Application() app:match("create_account", "/create-account", respond_to({ GET = function(self) return { render = true } end, POST = function(self) do_something(self.params) return { redirect_to = self:url_for("index") } end })) ``` ```moonscript lapis = require "lapis" import respond_to from require "lapis.application" class App extends lapis.Application [create_account: "/create-account"]: respond_to { GET: => render: true POST: => do_something @params redirect_to: @url_for "index" } ``` -------------------------------- ### Run Lapis Server Source: https://leafo.net/lapis/reference/command_line Starts the Lapis web server for a specified environment. It configures and launches either an OpenResty server or a cqueues-based server. The OpenResty server path can be specified using the LAPIS_OPENRESTY environment variable. ```bash $ lapis server [environment] ``` ```bash LAPIS_OPENRESTY=/home/leafo/bin/openresty lapis server ``` ```bash $ nginx -p "$(pwd)" -c "nginx.conf.compiled" ```