Class: Cloudflare::DurableObjectStub

Inherits:
Object
  • Object
show all
Defined in:
lib/cloudflare_workers/durable_object.rb

Overview

Wraps a stub (the object returned by ‘namespace.get(id)`). Its only callable method is `fetch(request)`, which submits an HTTP request to the DO instance and returns a `Response`. We return the same `Cloudflare::HTTPResponse` shape as Phase 6 so routes don’t need to learn a second API.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(js) ⇒ DurableObjectStub

Returns a new instance of DurableObjectStub.



129
130
131
# File 'lib/cloudflare_workers/durable_object.rb', line 129

def initialize(js)
  @js = js
end

Instance Attribute Details

#jsObject (readonly)

Returns the value of attribute js.



127
128
129
# File 'lib/cloudflare_workers/durable_object.rb', line 127

def js
  @js
end

Instance Method Details

#fetch(url_or_request, method: 'GET', headers: nil, body: nil) ⇒ Object

Call the DO with a plain URL (String) and optional init-Hash. The DO’s fetch handler sees the URL as-is (no routing layer strips the prefix), so user code can use any pathname it wants as its internal DO command channel. Returns a JS Promise the caller ‘__await__`s to get a `Cloudflare::HTTPResponse`.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/cloudflare_workers/durable_object.rb', line 155

def fetch(url_or_request, method: 'GET', headers: nil, body: nil)
  js_stub = @js
  hdrs = headers || {}
  method_str = method.to_s.upcase
  js_headers = Cloudflare::HTTP.ruby_headers_to_js(hdrs)
  js_body = body.nil? ? nil : body.to_s
  url_str = url_or_request.to_s
  err_klass = Cloudflare::DurableObjectError
  response_klass = Cloudflare::HTTPResponse
  do_class_label = 'DurableObjectStub'

  # Single-line IIFE — see `lib/cloudflare_workers/cache.rb#put`
  # for why Opal can silently drop a multi-line x-string Promise.
  js_promise = `(async function(stub, url_str, method_str, js_headers, js_body, Kernel, err_klass, do_class_label) { var init = { method: method_str, headers: js_headers }; if (js_body !== null && js_body !== undefined && js_body !== Opal.nil) { init.body = js_body; } var resp; try { resp = await stub.fetch(url_str, init); } catch (e) { Kernel.$raise(err_klass.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'stub.fetch', do_class: do_class_label }))); } var text = ''; try { text = await resp.text(); } catch (_) { text = ''; } var hk = []; var hv = []; if (resp.headers && typeof resp.headers.forEach === 'function') { resp.headers.forEach(function(v, k) { hk.push(String(k).toLowerCase()); hv.push(String(v)); }); } return { status: resp.status|0, text: text, hkeys: hk, hvals: hv }; })(#{js_stub}, #{url_str}, #{method_str}, #{js_headers}, #{js_body}, #{Kernel}, #{err_klass}, #{do_class_label})`

  js_result = js_promise.__await__
  hkeys = `#{js_result}.hkeys`
  hvals = `#{js_result}.hvals`
  h = {}
  i = 0
  len = `#{hkeys}.length`
  while i < len
    h[`#{hkeys}[#{i}]`] = `#{hvals}[#{i}]`
    i += 1
  end

  response_klass.new(
    status:  `#{js_result}.status`,
    headers: h,
    body:    `#{js_result}.text`,
    url:     url_str
  )
end

#fetch_raw(url_or_request, method: 'GET', headers: nil, body: nil) ⇒ Object

Same as ‘fetch` but returns the raw JS Response (a JS Promise resolving to it) instead of wrapping it in a `Cloudflare::HTTPResponse`. Needed for WebSocket-upgrade responses — the 101 Response carries its WebSocket in a `.webSocket` property that disappears if we reconstruct the Response via the HTTPResponse wrapper.



139
140
141
142
143
144
145
146
147
148
# File 'lib/cloudflare_workers/durable_object.rb', line 139

def fetch_raw(url_or_request, method: 'GET', headers: nil, body: nil)
  hdrs = headers || {}
  method_str = method.to_s.upcase
  js_headers = Cloudflare::HTTP.ruby_headers_to_js(hdrs)
  js_body = body.nil? ? nil : body.to_s
  url_str = url_or_request.to_s
  js_stub = @js
  err_klass = Cloudflare::DurableObjectError
  `(async function(stub, url_str, method_str, js_headers, js_body, Kernel, err_klass) { var init = { method: method_str, headers: js_headers }; if (js_body !== null && js_body !== undefined && js_body !== Opal.nil) { init.body = js_body; } try { return await stub.fetch(url_str, init); } catch (e) { Kernel.$raise(err_klass.$new(e && e.message ? e.message : String(e), Opal.hash({ operation: 'stub.fetch_raw' }))); } })(#{js_stub}, #{url_str}, #{method_str}, #{js_headers}, #{js_body}, #{Kernel}, #{err_klass})`
end