From 83320d4c9a9477d88298d1aee428994508e78e0d Mon Sep 17 00:00:00 2001 From: Runar Ingebrigtsen Date: Thu, 5 Feb 2026 23:52:21 +0100 Subject: [PATCH] add CORS access for sanasto.app --- config/application.rb | 3 +++ lib/middleware/sanasto_cors.rb | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 lib/middleware/sanasto_cors.rb diff --git a/config/application.rb b/config/application.rb index b2f9895..178dbd5 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,7 @@ require_relative "boot" require "rails/all" +require_relative "../lib/middleware/sanasto_cors" # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. @@ -24,5 +25,7 @@ module SanastoWiki # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") config.active_record.schema_format = :sql + + config.middleware.insert_before 0, Middleware::SanastoCors end end diff --git a/lib/middleware/sanasto_cors.rb b/lib/middleware/sanasto_cors.rb new file mode 100644 index 0000000..67f3475 --- /dev/null +++ b/lib/middleware/sanasto_cors.rb @@ -0,0 +1,49 @@ +module Middleware + class SanastoCors + ALLOWED_APP_ID = ENV.fetch("SANASTO_APP_ID", "app.sanasto").freeze + APP_ID_HEADER = "HTTP_X_SANASTO_APP" + + def initialize(app) + @app = app + end + + def call(env) + if allow_cors_for?(env) + return preflight_response(env["HTTP_ORIGIN"]) if env["REQUEST_METHOD"] == "OPTIONS" + end + + status, headers, body = @app.call(env) + if allow_cors_for?(env) + apply_cors_headers(headers, env["HTTP_ORIGIN"]) + end + [status, headers, body] + end + + private + + def allow_cors_for?(env) + origin = env["HTTP_ORIGIN"].to_s + return false if origin.empty? + + app_id = env[APP_ID_HEADER].to_s + return false if app_id.empty? + + app_id == ALLOWED_APP_ID + end + + def preflight_response(origin) + headers = {} + apply_cors_headers(headers, origin) + headers["Access-Control-Max-Age"] = "86400" + [204, headers, []] + end + + def apply_cors_headers(headers, origin) + headers["Access-Control-Allow-Origin"] = origin + headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS" + headers["Access-Control-Allow-Headers"] = + "Origin, Content-Type, Accept, Authorization, X-Sanasto-App" + headers["Vary"] = [headers["Vary"], "Origin, X-Sanasto-App"].compact.join(", ") + end + end +end