diff --git a/src/views/api/_index.yaml b/src/views/api/_index.yaml index 0f13ec9..8cae94e 100644 --- a/src/views/api/_index.yaml +++ b/src/views/api/_index.yaml @@ -1,6 +1,13 @@ version: "1.0" namespace: wippy.views.api entries: + - name: api_error + kind: library.lua + meta: + comment: Sanitized API error responses with server-side logging + source: file://api_error.lua + modules: + - logger - name: list_pages kind: function.lua meta: @@ -9,6 +16,7 @@ entries: router: api_router source: file://list_pages.lua imports: + api_error: wippy.views.api:api_error page_registry: wippy.views:page_registry method: handler modules: @@ -38,6 +46,7 @@ entries: router: api_router source: file://list_components.lua imports: + api_error: wippy.views.api:api_error component_registry: wippy.views:component_registry bundled_meta: wippy.views:bundled_meta method: handler @@ -72,6 +81,7 @@ entries: router: api_router source: file://find_by_tag.lua imports: + api_error: wippy.views.api:api_error component_registry: wippy.views:component_registry bundled_meta: wippy.views:bundled_meta method: handler @@ -106,6 +116,7 @@ entries: router: api_router source: file://render.lua imports: + api_error: wippy.views.api:api_error page_registry: wippy.views:page_registry renderer: wippy.views:renderer resource_registry: wippy.views:resource_registry @@ -167,6 +178,7 @@ entries: router: api_router source: file://list_routes.lua imports: + api_error: wippy.views.api:api_error page_registry: wippy.views:page_registry method: handler modules: diff --git a/src/views/api/api_error.lua b/src/views/api/api_error.lua new file mode 100644 index 0000000..f0b8ec5 --- /dev/null +++ b/src/views/api/api_error.lua @@ -0,0 +1,17 @@ +local log = require("logger"):named("wippy.views.api") + +local api_error = {} + +function api_error.fail(res, status, message, err) + if err ~= nil then + log:error(message, { error = tostring(err) }) + end + + res:set_status(status) + res:write_json({ + success = false, + error = message + }) +end + +return api_error diff --git a/src/views/api/find_by_tag.lua b/src/views/api/find_by_tag.lua index 6271613..17a2921 100644 --- a/src/views/api/find_by_tag.lua +++ b/src/views/api/find_by_tag.lua @@ -1,4 +1,5 @@ local http = require("http") +local api_error = require("api_error") local component_registry = require("component_registry") local bundled_meta = require("bundled_meta") @@ -41,11 +42,7 @@ local function handler() local tag, param_err = req:param("tag") if param_err or not tag or tag == "" then - res:set_status(http.STATUS.BAD_REQUEST) - res:write_json({ - success = false, - error = "Tag name is required" .. (param_err and (": " .. tostring(param_err)) or ""), - }) + api_error.fail(res, http.STATUS.BAD_REQUEST, "Tag name is required", param_err) return end @@ -77,11 +74,7 @@ local function handler() end if err or not component then - res:set_status(http.STATUS.NOT_FOUND) - res:write_json({ - success = false, - error = err or ("No view.component registered for tag: " .. tag), - }) + api_error.fail(res, http.STATUS.NOT_FOUND, "No view.component registered for tag: " .. tag, err) return end diff --git a/src/views/api/list_components.lua b/src/views/api/list_components.lua index 42d08ab..08f8fbf 100644 --- a/src/views/api/list_components.lua +++ b/src/views/api/list_components.lua @@ -1,4 +1,5 @@ local http = require("http") +local api_error = require("api_error") local component_registry = require("component_registry") local bundled_meta = require("bundled_meta") @@ -37,11 +38,7 @@ local function handler() local all_components, err = component_registry.find_all() if err then - res:set_status(http.STATUS.INTERNAL_ERROR) - res:write_json({ - success = false, - error = err - }) + api_error.fail(res, http.STATUS.INTERNAL_ERROR, "Failed to list components", err) return end diff --git a/src/views/api/list_pages.lua b/src/views/api/list_pages.lua index 8bca50c..a6704c9 100644 --- a/src/views/api/list_pages.lua +++ b/src/views/api/list_pages.lua @@ -1,4 +1,5 @@ local http = require("http") +local api_error = require("api_error") local page_registry = require("page_registry") type PageResponse = { @@ -30,11 +31,7 @@ local function handler() local all_pages, err = page_registry.find_all() if err then - res:set_status(http.STATUS.INTERNAL_ERROR) - res:write_json({ - success = false, - error = err - }) + api_error.fail(res, http.STATUS.INTERNAL_ERROR, "Failed to list pages", err) return end diff --git a/src/views/api/list_routes.lua b/src/views/api/list_routes.lua index de1ef86..a3e320b 100644 --- a/src/views/api/list_routes.lua +++ b/src/views/api/list_routes.lua @@ -1,4 +1,5 @@ local http = require("http") +local api_error = require("api_error") local page_registry = require("page_registry") -- GET /pages/routes @@ -22,11 +23,7 @@ local function handler() -- Single fetch + validation pass — avoids the two-call race. local all_pages, list_err = page_registry.find_all() if list_err then - res:set_status(http.STATUS.INTERNAL_ERROR) - res:write_json({ - success = false, - error = list_err, - }) + api_error.fail(res, http.STATUS.INTERNAL_ERROR, "Failed to list mount routes", list_err) return end diff --git a/src/views/api/render.lua b/src/views/api/render.lua index 859013d..712b557 100644 --- a/src/views/api/render.lua +++ b/src/views/api/render.lua @@ -1,4 +1,5 @@ local http = require("http") +local api_error = require("api_error") local page_registry = require("page_registry") local resource_registry = require("resource_registry") local renderer = require("renderer") @@ -52,12 +53,7 @@ local function handler() local page_id, err = req:param("id") if err then - res:set_status(http.STATUS.INTERNAL_ERROR) - res:write_json({ - success = false, - error = "Parameter extraction error", - details = err - }) + api_error.fail(res, http.STATUS.INTERNAL_ERROR, "Parameter extraction error", err) return end @@ -74,12 +70,7 @@ local function handler() local page, page_err = page_registry.get(page_id) if page_err then - res:set_status(http.STATUS.NOT_FOUND) - res:write_json({ - success = false, - error = "Page not found", - details = page_err - }) + api_error.fail(res, http.STATUS.NOT_FOUND, "Page not found", page_err) return end @@ -149,12 +140,7 @@ local function handler() details = "You do not have permission to view this page" }) else - res:set_status(http.STATUS.INTERNAL_ERROR) - res:write_json({ - success = false, - error = "Failed to render page", - details = render_err - }) + api_error.fail(res, http.STATUS.INTERNAL_ERROR, "Failed to render page", render_err) end return end