Class: Basecamp::Webhooks::RackMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/basecamp/webhooks/rack_middleware.rb

Overview

Rack middleware that intercepts POST requests to a configurable path and dispatches them to a WebhookReceiver for processing.

Constant Summary collapse

DEFAULT_PATH =
"/webhooks/basecamp"

Instance Method Summary collapse

Constructor Details

#initialize(app, receiver:, path: DEFAULT_PATH) ⇒ RackMiddleware

Returns a new instance of RackMiddleware.



10
11
12
13
14
# File 'lib/basecamp/webhooks/rack_middleware.rb', line 10

def initialize(app, receiver:, path: DEFAULT_PATH)
  @app = app
  @receiver = receiver
  @path = path
end

Instance Method Details

#call(env) ⇒ Object



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
# File 'lib/basecamp/webhooks/rack_middleware.rb', line 16

def call(env)
  unless env["PATH_INFO"] == @path
    return @app.call(env)
  end

  unless env["REQUEST_METHOD"] == "POST"
    return [ 405, { "Content-Type" => "text/plain" }, [ "Method Not Allowed" ] ]
  end

  body = env["rack.input"].read
  env["rack.input"].rewind

  headers = lambda { |name|
    # Rack normalizes headers to HTTP_UPPER_CASE format
    rack_key = "HTTP_#{name.upcase.tr('-', '_')}"
    env[rack_key]
  }

  begin
    @receiver.handle_request(raw_body: body, headers: headers)
    [ 200, { "Content-Type" => "text/plain" }, [ "OK" ] ]
  rescue VerificationError
    [ 401, { "Content-Type" => "text/plain" }, [ "Unauthorized" ] ]
  rescue JSON::ParserError
    [ 400, { "Content-Type" => "text/plain" }, [ "Bad Request" ] ]
  rescue StandardError
    [ 500, { "Content-Type" => "text/plain" }, [ "Internal Server Error" ] ]
  end
end