1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
# frozen_string_literal: true
require "flipper/cloud/message_verifier"
module Flipper
module Cloud
class Middleware
# Internal: The path to match for webhook requests.
WEBHOOK_PATH = %r{\A/webhooks\/?\Z}
# Internal: The root path to match for requests.
ROOT_PATH = %r{\A/\Z}
def initialize(app, options = {})
@app = app
@env_key = options.fetch(:env_key, 'flipper')
end
def call(env)
dup.call!(env)
end
def call!(env)
request = Rack::Request.new(env)
if request.post? && (request.path_info.match(ROOT_PATH) || request.path_info.match(WEBHOOK_PATH))
status = 200
headers = {
"Content-Type" => "application/json",
}
body = "{}"
payload = request.body.read
signature = request.env["HTTP_FLIPPER_CLOUD_SIGNATURE"]
flipper = env.fetch(@env_key)
begin
message_verifier = MessageVerifier.new(secret: flipper.sync_secret)
if message_verifier.verify(payload, signature)
begin
flipper.sync
body = JSON.generate({
groups: Flipper.group_names.map { |name| {name: name}}
})
rescue Flipper::Adapters::Http::Error => error
status = error.response.code.to_i == 402 ? 402 : 500
headers["Flipper-Cloud-Response-Error-Class"] = error.class.name
headers["Flipper-Cloud-Response-Error-Message"] = error.message
rescue => error
status = 500
headers["Flipper-Cloud-Response-Error-Class"] = error.class.name
headers["Flipper-Cloud-Response-Error-Message"] = error.message
end
end
rescue MessageVerifier::InvalidSignature
status = 400
end
[status, headers, [body]]
else
@app.call(env)
end
end
end
end
end
|