Class: PatientHttp::SynchronousExecutor
- Inherits:
-
Object
- Object
- PatientHttp::SynchronousExecutor
- Includes:
- RedirectHelper
- Defined in:
- lib/patient_http/synchronous_executor.rb
Overview
Handles synchronous/inline execution of HTTP requests.
Used for testing or when synchronous execution is needed. Accepts configuration and optional callback hooks so it has no dependency on any module-level singleton state.
Instance Method Summary collapse
-
#call ⇒ void
Execute the request synchronously.
-
#initialize(task, config:, on_complete: nil, on_error: nil) ⇒ SynchronousExecutor
constructor
A new instance of SynchronousExecutor.
Constructor Details
#initialize(task, config:, on_complete: nil, on_error: nil) ⇒ SynchronousExecutor
Returns a new instance of SynchronousExecutor.
16 17 18 19 20 21 22 23 |
# File 'lib/patient_http/synchronous_executor.rb', line 16 def initialize(task, config:, on_complete: nil, on_error: nil) @task = task @config = config @on_complete = on_complete @on_error = on_error @proxy_client = nil @request_preparer = RequestPreparer.new(config) end |
Instance Method Details
#call ⇒ void
This method returns an undefined value.
Execute the request synchronously.
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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/patient_http/synchronous_executor.rb', line 27 def call Async do start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) begin http_client = nil response_data = nil redirect_error = nil loop do http_client&.close @proxy_client&.close @proxy_client = nil outgoing = @request_preparer.prepare(@task.request, @task.id) http_client = create_http_client(outgoing.url) timeout = @task.request.timeout || @config.request_timeout response_data = Async::Task.current.with_timeout(timeout) do headers = outgoing.headers.to_h body = Protocol::HTTP::Body::Buffered.wrap([@task.request.body.to_s]) if @task.request.body endpoint = Async::HTTP::Endpoint.parse(outgoing.url) endpoint = configure_endpoint(endpoint) if @config.connection_timeout verb = @task.request.http_method.to_s.upcase = { headers: headers, body: body, scheme: endpoint.scheme, authority: endpoint. } request = Protocol::HTTP::Request[verb, endpoint.path, **] async_response = http_client.call(request) # Note: headers that appear multiple times (e.g. set-cookie) are # flattened to a single joined string value. headers_hash = async_response.headers.to_h.transform_values(&:to_s) body_content = read_response_body(async_response, headers_hash) { status: async_response.status, headers: headers_hash, body: body_content } end # Check for redirect break unless should_follow_redirect?(@task, response_data) # Note: a `return` here would raise LocalJumpError since this block # runs on a reactor fiber, so break out and handle the error below. redirect_error = check_redirect_error(@task, response_data) break if redirect_error location = response_data[:headers]["location"] @task = @task.redirect_task(location: location, status: response_data[:status]) end if redirect_error invoke_callback(redirect_error, :error) else end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) duration = end_time - start_time response = Response.new( status: response_data[:status], headers: response_data[:headers], body: response_data[:body], duration: duration, request_id: @task.original_id, url: @task.request.url, http_method: @task.request.http_method, callback_args: @task.callback_args, redirects: @task.redirects ) if @task.raise_error_responses && !response.success? http_error = HttpError.new(response) invoke_callback(http_error, :error) else invoke_callback(response, :response) end end rescue => e end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) duration = end_time - start_time error = RequestError.from_exception( e, request_id: @task.id, duration: duration, url: @task.request.url, http_method: @task.request.http_method, callback_args: @task.callback_args ) invoke_callback(error, :error) ensure http_client&.close @proxy_client&.close @proxy_client = nil end end end |