iocaine 3.0.0

The deadliest poison known to AI
Documentation
-- SPDX-FileCopyrightText: 2025 Gergely Nagy
-- SPDX-FileContributor: Gergely Nagy
--
-- SPDX-License-Identifier: MIT

function decide(request)
   local trusted_decision_header = iocaine.config["trusted-decision-header"]
   if trusted_decision_header ~= nil then
      local decision = request:header(trusted_decision_header)
      if decision ~= nil then
         return decision
      end
   end
   local user_agent = request:header("user-agent")
   local host = request:header("host")

   METRIC_REQUESTS:inc(host)

   if AI_ROBOTS_TXT:matches(user_agent) then
      METRIC_RULESET_HITS:inc("ai.robots.txt", "garbage")
      return logged_decision(request, "garbage", "ai.robots.txt")
   end

   if MAJOR_BROWSERS:matches(user_agent) and request:header("sec-fetch-mode") == nil then
      METRIC_RULESET_HITS:inc("major-browsers", "garbage")
      return logged_decision(request, "garbage", "major-browsers")
   end

   if UNWANTED_VISITORS:matches(user_agent) then
      METRIC_RULESET_HITS:inc("unwanted-visitors", "garbage")
      return logged_decision(request, "garbage", "unwanted-visitors")
   end

   METRIC_RULESET_HITS:inc("default", "default")
   return logged_decision(request, "default", "default")
end

function logged_decision(request, decision, ruleset)
   if LOGGING_ENABLED then
      local log = {
         ["_msg"] = "handling request",
         ["service"] = "qmk",
         ["decision"] = decision,
         ["ruleset"] = ruleset,
         ["header"] = request:headers(),
         ["query"] = request:queries()
      }
      iocaine.log.stdout(log)
   end
   return decision
end

return decide