Class: Tep::Security::Cors

Inherits:
Filter
  • Object
show all
Defined in:
lib/tep/security.rb

Overview

CORS preflight + same-origin response decoration.

Configurable bits:

- origin: a single allowed origin URL ("*" allowed for
  fully open APIs; not recommended for any endpoint that
  uses cookies / Authorization headers).
- methods: comma-separated. Default "GET,POST,OPTIONS".
- headers: comma-separated. Default "Content-Type,Authorization".
- max_age: number of seconds the browser caches the
  preflight result. Default 3600.

Behaviour:

- On any request: emits `Access-Control-Allow-Origin` plus
  credential / vary headers.
- On `OPTIONS` preflight: short-circuits to a 204 with
  `Access-Control-Allow-Methods` / `-Headers` / `-Max-Age`.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Filter

#after

Constructor Details

#initializeCors

Returns a new instance of Cors.



55
56
57
58
59
60
# File 'lib/tep/security.rb', line 55

def initialize
  @origin          = "*"
  @allowed_verbs   = "GET,POST,OPTIONS"
  @allowed_headers = "Content-Type,Authorization"
  @max_age         = 3600
end

Instance Attribute Details

#allowed_headersObject

Field names are deliberately distinctive (not ‘methods` / `headers`) – spinel’s per-method type inference unifies method names across classes, and ‘Object#methods` / `Tep::Response#headers` would widen the dispatch return to poly and break res.headers writes downstream.



53
54
55
# File 'lib/tep/security.rb', line 53

def allowed_headers
  @allowed_headers
end

#allowed_verbsObject

Field names are deliberately distinctive (not ‘methods` / `headers`) – spinel’s per-method type inference unifies method names across classes, and ‘Object#methods` / `Tep::Response#headers` would widen the dispatch return to poly and break res.headers writes downstream.



53
54
55
# File 'lib/tep/security.rb', line 53

def allowed_verbs
  @allowed_verbs
end

#max_ageObject

Field names are deliberately distinctive (not ‘methods` / `headers`) – spinel’s per-method type inference unifies method names across classes, and ‘Object#methods` / `Tep::Response#headers` would widen the dispatch return to poly and break res.headers writes downstream.



53
54
55
# File 'lib/tep/security.rb', line 53

def max_age
  @max_age
end

#originObject

Field names are deliberately distinctive (not ‘methods` / `headers`) – spinel’s per-method type inference unifies method names across classes, and ‘Object#methods` / `Tep::Response#headers` would widen the dispatch return to poly and break res.headers writes downstream.



53
54
55
# File 'lib/tep/security.rb', line 53

def origin
  @origin
end

Instance Method Details

#before(req, res) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/tep/security.rb', line 67

def before(req, res)
  res.headers["Access-Control-Allow-Origin"] = @origin
  res.headers["Vary"] = "Origin"
  if req.verb == "OPTIONS"
    res.headers["Access-Control-Allow-Methods"] = @allowed_verbs
    res.headers["Access-Control-Allow-Headers"] = @allowed_headers
    res.headers["Access-Control-Max-Age"]      = @max_age.to_s
    res.set_status(204)
    res.set_body_if_empty("")
    # `res.halted = true` short-circuits the dispatch loop
    # (see App#dispatch) so the no-route fallthrough doesn't
    # overwrite our 204 with a 404.
    res.halted = true
  end
  0
end

#set_allowed_headers(h) ⇒ Object



64
# File 'lib/tep/security.rb', line 64

def set_allowed_headers(h); @allowed_headers = h; end

#set_allowed_verbs(m) ⇒ Object



63
# File 'lib/tep/security.rb', line 63

def set_allowed_verbs(m);   @allowed_verbs   = m; end

#set_max_age(n) ⇒ Object



65
# File 'lib/tep/security.rb', line 65

def set_max_age(n);         @max_age         = n; end

#set_origin(o) ⇒ Object



62
# File 'lib/tep/security.rb', line 62

def set_origin(o);          @origin          = o; end