;; lib/dream/cors.sx — Dream-on-SX CORS middleware.
;; Decorates responses with Access-Control-Allow-* headers and short-circuits
;; preflight OPTIONS requests with a 204. Depends on types.sx.

(define dream-cors-defaults {:methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" :headers "Content-Type" :max-age 86400 :credentials false :origin "*"})

(define
  dr/cors-origin-headers
  (fn
    (opts resp)
    (let
      ((r1 (dream-add-header resp "access-control-allow-origin" (get opts :origin))))
      (if
        (get opts :credentials)
        (dream-add-header r1 "access-control-allow-credentials" "true")
        r1))))

(define
  dr/cors-preflight
  (fn
    (opts)
    (dr/cors-origin-headers
      opts
      (dream-add-header
        (dream-add-header
          (dream-add-header
            (dream-empty 204)
            "access-control-allow-methods"
            (get opts :methods))
          "access-control-allow-headers"
          (get opts :headers))
        "access-control-max-age"
        (str (get opts :max-age))))))

(define
  dream-cors-with
  (fn
    (opts)
    (fn
      (next)
      (fn
        (req)
        (if
          (= (dream-method req) "OPTIONS")
          (dr/cors-preflight opts)
          (dr/cors-origin-headers opts (next req)))))))

(define dream-cors (dream-cors-with dream-cors-defaults))
(define
  dream-cors-origin
  (fn (origin) (dream-cors-with (assoc dream-cors-defaults :origin origin))))
