Module: URI

Defined in:
lib/opal_patches.rb

Defined Under Namespace

Classes: Error, Generic, InvalidURIError, Parser

Constant Summary collapse

DEFAULT_PARSER =
Module.new do
  UNSAFE = Regexp.compile('[^\-_.!~*\'()a-zA-Z0-9;/?:@&=+$,\[\]]').freeze

  def self.regexp
    { UNSAFE: UNSAFE }
  end

  def self.escape(s, unsafe = UNSAFE)
    CGI.escape(s.to_s)
  end

  def self.unescape(s)
    CGI.unescape(s.to_s)
  end
end
RFC2396_PARSER =
DEFAULT_PARSER

Class Method Summary collapse

Class Method Details

.decode_www_form_component(str, _enc = nil) ⇒ Object

CRuby’s URI.decode_www_form_component / encode_www_form_component are used by Rack::Utils#unescape / Rack::Utils#escape. Opal’s ‘uri` stdlib omits them. Back them with CGI so that Rack’s query-string parser works for any request with a body / query (Sinatra’s ‘request.body.read` path eventually walks through this code).

IMPORTANT (Opal): CGI.unescape maps to JS decodeURI, which does NOT decode ‘%2F` (`/`). RFC 3986 decodeURI reserves those escapes; Rack form bodies need decodeURIComponent semantics (same as CGI.unescapeURIComponent). Without this, HTML like `</h1>` survives as literal `<%2Fh1>` in params.



277
278
279
280
281
282
# File 'lib/opal_patches.rb', line 277

def self.decode_www_form_component(str, _enc = nil)
  s = str.to_s.tr("+", " ")
  CGI.unescapeURIComponent(s)
rescue ::Exception
  str.to_s
end

.encode_www_form_component(str, _enc = nil) ⇒ Object



285
286
287
# File 'lib/opal_patches.rb', line 285

def self.encode_www_form_component(str, _enc = nil)
  CGI.escape(str.to_s)
end

.HTTP_class_for(scheme) ⇒ Object

Net::HTTP.get(URI(‘https://…’)) is the canonical entry point in CRuby Ruby code. CRuby resolves ‘URI(’…‘)` via Kernel#URI, which is defined in `uri/common.rb` as `URI.parse(arg)`. Opal’s stdlib omits that; install it here so vendored gems (and our Net::HTTP shim) can use the idiomatic short form.



389
390
391
# File 'lib/opal_patches.rb', line 389

def self.HTTP_class_for(scheme)
  HTTP if scheme == "http"
end

.parse(str) ⇒ Object



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/opal_patches.rb', line 330

def self.parse(str)
  s = str.to_s
  if s.empty?
    return(
      Generic.new(
        host: nil,
        scheme: nil,
        port: nil,
        path: "",
        query: nil,
        fragment: nil
      )
    )
  end

  js_url =
    `
    (function() {
      try { return new URL(#{s}); }
      catch (e) {
        try { return new URL(#{s}, "http://__homura.invalid/"); }
        catch (e2) { return null; }
      }
    })()
  `
  if `#{js_url} == null`
    raise ::URI::InvalidURIError, "bad URI(is not URI?): #{s}"
  end

  host = `#{js_url}.host` || ""
  host = nil if host == "" || host.include?("__homura.invalid")
  scheme = `#{js_url}.protocol` || ""
  scheme = scheme.sub(/:$/, "")
  scheme = nil if scheme == ""
  port_raw = `#{js_url}.port` || ""
  port = port_raw == "" ? nil : port_raw.to_i
  path = `#{js_url}.pathname` || ""
  query = `#{js_url}.search` || ""
  query = query.sub(/^\?/, "")
  query = nil if query == ""
  frag = `#{js_url}.hash` || ""
  frag = frag.sub(/^#/, "")
  frag = nil if frag == ""

  Generic.new(
    host: host,
    scheme: scheme,
    port: port,
    path: path,
    query: query,
    fragment: frag
  )
end