Class: Blockchain0xX402::Server::RackMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/blockchain0x_x402/server.rb

Overview

Rack middleware. Build at process boot, then ‘use` in front of the application.

Instance Method Summary collapse

Constructor Details

#initialize(app, sdk:, pricing:, default_network: 'mainnet', max_age_seconds: 60) ⇒ RackMiddleware

Returns a new instance of RackMiddleware.

Parameters:

  • app (#call)

    downstream Rack app

  • sdk (#payment_requests_settle)

    backend settle bridge

  • pricing (Hash{String=>PricingEntry})

    keyed by ‘<METHOD> <PATH>’

  • default_network (String) (defaults to: 'mainnet')

    ‘mainnet’ (default) or ‘testnet’

  • max_age_seconds (Integer) (defaults to: 60)

    how long a chain confirmation may live before the payer’s wrapper re-pays



178
179
180
181
182
183
184
# File 'lib/blockchain0x_x402/server.rb', line 178

def initialize(app, sdk:, pricing:, default_network: 'mainnet', max_age_seconds: 60)
  @app = app
  @sdk = sdk
  @pricing = pricing
  @default_network = default_network
  @max_age_seconds = max_age_seconds
end

Instance Method Details

#call(env) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/blockchain0x_x402/server.rb', line 186

def call(env)
  method = env['REQUEST_METHOD'] || 'GET'
  path = env['PATH_INFO'] || env['REQUEST_PATH'] || ''
  key = "#{method.upcase} #{path}"
  entry = @pricing[key]
  return @app.call(env) if entry.nil?

  header = env['HTTP_X_PAYMENT']
  outcome = Server.verify_x_payment(sdk: @sdk, header: header, entry: entry)

  if outcome.ok?
    env[PAYMENT_ENV_KEY] = outcome.payment
    return @app.call(env)
  end

  body = Server.build_402_body(
    entry: entry,
    resource: "#{method} #{path}",
    default_network: @default_network,
    max_age_seconds: @max_age_seconds,
  )
  payload = Server.x402_response_to_hash(body)
  payload['error'] = { 'reason' => outcome.reason, 'message' => outcome.message }
  raw = JSON.generate(payload)
  [
    402,
    {
      'Content-Type' => 'application/json',
      'Content-Length' => raw.bytesize.to_s,
    },
    [raw],
  ]
end