|
| 1 | +---@diagnostic disable: duplicate-doc-field |
| 2 | + |
| 3 | +if not _G.log then _G.log = require("loglua") end |
| 4 | +local utils = require("PudimServer.utils") |
| 5 | + |
| 6 | + |
| 7 | +--- interfaces |
| 8 | + |
| 9 | +---@class CorsConfig |
| 10 | +---@field AllowOrigins string|string[]? Origins permitidas (default: "*") |
| 11 | +---@field AllowMethods string|string[]? Métodos permitidos (default: "GET, POST, PUT, DELETE, PATCH, OPTIONS") |
| 12 | +---@field AllowHeaders string|string[]? Headers permitidos (default: "Content-Type, Authorization") |
| 13 | +---@field ExposeHeaders string|string[]? Headers expostos ao browser |
| 14 | +---@field AllowCredentials boolean? Permitir credentials (default: false) |
| 15 | +---@field MaxAge number? Tempo em segundos do cache preflight (default: 86400) |
| 16 | + |
| 17 | +local CorsConfigInter = utils:createInterface{ |
| 18 | + AllowOrigins = {"string", "table", "nil"}, |
| 19 | + AllowMethods = {"string", "table", "nil"}, |
| 20 | + AllowHeaders = {"string", "table", "nil"}, |
| 21 | + ExposeHeaders = {"string", "table", "nil"}, |
| 22 | + AllowCredentials = {"boolean", "nil"}, |
| 23 | + MaxAge = {"number", "nil"}, |
| 24 | +} |
| 25 | + |
| 26 | + |
| 27 | +--------- |
| 28 | +--- main |
| 29 | + |
| 30 | +---@type table |
| 31 | +local cors = {} |
| 32 | + |
| 33 | + |
| 34 | +---@param value string|string[]|nil |
| 35 | +---@param default string |
| 36 | +---@return string |
| 37 | +local function toHeaderValue(value, default) |
| 38 | + if not value then return default end |
| 39 | + if type(value) == "table" then |
| 40 | + return table.concat(value, ", ") |
| 41 | + end |
| 42 | + return value |
| 43 | +end |
| 44 | + |
| 45 | + |
| 46 | +---@param config? CorsConfig |
| 47 | +---@return table corsHeaders Headers CORS resolvidos |
| 48 | +---@return CorsConfig resolvedConfig Config com defaults aplicados |
| 49 | +function cors.createConfig(config) |
| 50 | + local CL = log.inSection("CORS") |
| 51 | + |
| 52 | + config = config or {} |
| 53 | + utils:verifyTypes(config, CorsConfigInter, CL.error, true) |
| 54 | + |
| 55 | + local resolved = { |
| 56 | + AllowOrigins = toHeaderValue(config.AllowOrigins, "*"), |
| 57 | + AllowMethods = toHeaderValue(config.AllowMethods, "GET, POST, PUT, DELETE, PATCH, OPTIONS"), |
| 58 | + AllowHeaders = toHeaderValue(config.AllowHeaders, "Content-Type, Authorization"), |
| 59 | + ExposeHeaders = toHeaderValue(config.ExposeHeaders, ""), |
| 60 | + AllowCredentials = config.AllowCredentials or false, |
| 61 | + MaxAge = config.MaxAge or 86400, |
| 62 | + } |
| 63 | + |
| 64 | + return resolved |
| 65 | +end |
| 66 | + |
| 67 | + |
| 68 | +---@param config table Config resolvida do CORS |
| 69 | +---@param requestOrigin string? Origin do request |
| 70 | +---@return table headers Headers CORS para adicionar na resposta |
| 71 | +function cors.buildHeaders(config, requestOrigin) |
| 72 | + local headers = {} |
| 73 | + |
| 74 | + headers["Access-Control-Allow-Origin"] = config.AllowOrigins |
| 75 | + headers["Access-Control-Allow-Methods"] = config.AllowMethods |
| 76 | + headers["Access-Control-Allow-Headers"] = config.AllowHeaders |
| 77 | + |
| 78 | + if config.ExposeHeaders ~= "" then |
| 79 | + headers["Access-Control-Expose-Headers"] = config.ExposeHeaders |
| 80 | + end |
| 81 | + |
| 82 | + if config.AllowCredentials then |
| 83 | + headers["Access-Control-Allow-Credentials"] = "true" |
| 84 | + end |
| 85 | + |
| 86 | + headers["Access-Control-Max-Age"] = tostring(config.MaxAge) |
| 87 | + |
| 88 | + return headers |
| 89 | +end |
| 90 | + |
| 91 | + |
| 92 | +---@param config table Config resolvida do CORS |
| 93 | +---@return string Resposta HTTP para preflight |
| 94 | +function cors.preflightResponse(config) |
| 95 | + local http = require("PudimServer.http") |
| 96 | + local headers = cors.buildHeaders(config) |
| 97 | + headers["Content-Length"] = "0" |
| 98 | + return http:response(204, "", headers) |
| 99 | +end |
| 100 | + |
| 101 | + |
| 102 | +return cors |
0 commit comments