Example
Inventory System
A full CRUD inventory using all four HTTP methods. GET fetches with Deflate compression, POST adds items, PUT updates slots, DELETE removes items.
Route map
| Method | Route | Description |
|---|---|---|
| GET | inventory | Fetch all items (compressed) |
| GET | inventory/:slot=int | Fetch single slot |
| POST | inventory | Add item to first free slot |
| PUT | inventory/:slot=int | Swap/update a slot |
| DELETE | inventory/:slot=int | Remove item from slot |
Server: InventoryServer.luau
local RoExpress = require(game.ReplicatedStorage.RoExpress)
local app = RoExpress.GetApp()
local DS = game:GetService("DataStoreService"):GetDataStore("Inventory")
local cache = {} -- { [userId] = { [slot] = item } }
local function getInv(player)
return cache[player.UserId] or {}
end
game.Players.PlayerAdded:Connect(function(p)
local ok, data = pcall(DS.GetAsync, DS, tostring(p.UserId))
cache[p.UserId] = (ok and data) or {}
end)
game.Players.PlayerRemoving:Connect(function(p)
pcall(DS.SetAsync, DS, tostring(p.UserId), cache[p.UserId])
cache[p.UserId] = nil
end)
-- GET all items (large table | compress it)
app:Get("inventory", function(req, res)
res:Send(getInv(req.player))
end, { compress = true })
-- GET single slot
app:Get("inventory/:slot=int[1,40]", function(req, res)
local inv = getInv(req.player)
res:Send(inv[req.params.slot])
end)
-- POST add item to first free slot
app:Post("inventory", function(req, res)
local inv = getInv(req.player)
local item = req.data
for slot = 1, 40 do
if not inv[slot] then
inv[slot] = item
res:Send({ slot = slot })
return
end
end
res:Status(409):Error("Inventory full")
end)
-- PUT update/swap slot
app:Put("inventory/:slot=int[1,40]", function(req, res)
getInv(req.player)[req.params.slot] = req.data.item
res:Send()
end)
-- DELETE remove item
app:Delete("inventory/:slot=int[1,40]", function(req, res)
getInv(req.player)[req.params.slot] = nil
res:Send()
end)
Client: InventoryClient.luau
local network = RoExpress.GetNetwork()
-- Load full inventory on spawn (auto-decompressed)
network:GetAsync("inventory")
:Then(function(res)
buildInventoryUI(res.data)
end)
-- Add item to server
local function addItem(itemData)
network:Post("inventory", itemData, function(res)
if res.type == "success" then
setUISlot(res.data.slot, itemData)
end
end)
end
-- Remove item
local function removeItem(slot)
network:Delete("inventory/" .. slot, nil, function(res)
if res.type == "success" then
clearUISlot(slot)
end
end)
end
See also
App | routing API · Network | client requests · Codec | compression · Router | typed params & range constraints