docs: def cors(origins,
          methods=['HEAD', 'OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
          headers=['Accept', 'Accept-Language', 'Content-Language', 'Content-Type', 'X-Requested-With'],
          max_age=None):
      """
      Adds CORS headers to the decorated view function.
  
      :param origins: Allowed origins (see below)
      :param methods: A list of allowed HTTP methods
      :param headers: A list of allowed HTTP headers
      :param max_age: Duration in seconds for which the CORS response may be cached
  
      The :obj:`origins` parameter may be one of:
  
      1. A callable that receives the origin as a parameter.
      2. A list of origins.
      3. ``*``, indicating that this resource is accessible by any origin.
  
      Example use::
  
          from flask import Flask, Response
          from coaster.views import cors
  
          app = Flask(__name__)
  
          @app.route('/any')
          @cors('*')
          def any_origin():
              return Response()
  
          @app.route('/static', methods=['GET', 'POST'])
          @cors(['https://hasgeek.com'], methods=['GET'], headers=['Content-Type', 'X-Requested-With'],
              max_age=3600)
          def static_list():
              return Response()
  
          def check_origin(origin):
              # check if origin should be allowed
              return True
  
          @app.route('/callable')
          @cors(check_origin)
          def callable_function():
              return Response()
      """
      def inner(f):
          @wraps(f)
          def wrapper(*args, **kwargs):
              origin = request.headers.get('Origin')
              if request.method not in methods:
                  abort(405)
  
              if origins == '*':
                  pass
              elif is_collection(origins) and origin in origins:
                  pass
              elif callable(origins) and origins(origin):
                  pass
              else:
                  abort(403)
  
              if request.method == 'OPTIONS':
                  # pre-flight request
                  resp = Response()
              else:
                  result = f(*args, **kwargs)
                  resp = make_response(result) if not isinstance(result,
                      (Response, WerkzeugResponse, current_app.response_class)) else result
  
              resp.headers['Access-Control-Allow-Origin'] = origin if origin else ''
              resp.headers['Access-Control-Allow-Methods'] = ', '.join(methods)
              resp.headers['Access-Control-Allow-Headers'] = ', '.join(headers)
              if max_age:
                  resp.headers['Access-Control-Max-Age'] = str(max_age)
              # Add 'Origin' to the Vary header since response will vary by origin
              if 'Vary' in resp.headers:
                  vary_values = [item.strip() for item in resp.headers['Vary'].split(',')]
                  if 'Origin' not in vary_values:
                      vary_values.append('Origin')
                  resp.headers['Vary'] = ', '.join(vary_values)
              else:
                  resp.headers['Vary'] = 'Origin'
  
              return resp
          return wrapper
      return inner