Module: KnoxCall::Intercept::NetHTTPRequest

Defined in:
lib/knoxcall/intercept_patch.rb

Overview

The prepended seam. request is where every Net::HTTP call lands — but Net::HTTP CONNECTS in start, before request ever runs, so a request the seam is about to reroute would still open a TCP (and TLS) connection to the real upstream first, and fail outright when that host is unreachable from the process. Measured by the CI smoke (#1000): the echo lives on the runner's loopback, the container's loopback refuses, and Net::HTTP.get_response died in connect before KnoxCall was ever asked. So connect is part of the seam too: a host the decision table would reroute defers its connection, and a request that ends up direct — unlisted, route-around, the kill switch, or the unavailable: :direct fallback — connects at that moment instead.

Instance Method Summary collapse

Instance Method Details

#request(req, body = nil) {|resp| ... } ⇒ Object

Yields:

  • (resp)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/knoxcall/intercept_patch.rb', line 122

def request(req, body = nil, &block)
  handle = Intercept.installed
  if handle.nil? || !handle.active? || InterceptContext.suppressed?
    knoxcall_connect_if_deferred
    return super
  end

  url = Intercept.url_for(self, req)
  decision = handle.pipeline.decide(url, req.method)
  if decision.direct?
    direct_headers = {}
    req.each_header { |k, v| direct_headers[k] = v }
    handle.pipeline.direct_decided(decision, url, method: req.method, headers: direct_headers)
    knoxcall_connect_if_deferred
    return super
  end

  # The body is held in memory (Net::HTTP's own requirement for a resend
  # too), so a resend after a routing refusal is replayable.
  stream = req.body_stream
  payload = body || req.body || stream&.read
  headers = {}
  req.each_header { |k, v| headers[k] = v }

  resp = handle.pipeline.send(decision, url: url, method: req.method, headers: headers, body: payload)
  if resp == InterceptPipeline::DIRECT
    # Perform the ORIGINAL request ourselves — connecting now, since the
    # connection was deferred for this host. A consumed body stream is
    # replaced by its bytes so Net::HTTP can send them.
    knoxcall_connect_if_deferred
    if stream
      req.body_stream = nil
      req.body = payload
      return super(req, nil, &block)
    end
    return super(req, body, &block)
  end

  yield resp if block_given?
  resp
end