module Curl

expose shortcut methods

Constants

CURB_VERSION
CURLAUTH_ANY
CURLAUTH_ANYSAFE
CURLAUTH_BASIC
CURLAUTH_DIGEST
CURLAUTH_GSSNEGOTIATE
CURLAUTH_NTLM
CURLINFO_DATA_IN

Passed to on_debug handler to indicate that the data is protocol data received from the peer.

CURLINFO_DATA_OUT

Passed to on_debug handler to indicate that the data is protocol data sent to the peer.

CURLINFO_HEADER_IN

Passed to on_debug handler to indicate that the data is header (or header-like) data received from the peer.

CURLINFO_HEADER_OUT

Passed to on_debug handler to indicate that the data is header (or header-like) data sent to the peer.

CURLINFO_TEXT

Passed to on_debug handler to indicate that the data is informational text.

CURLPROXY_HTTP
CURLPROXY_SOCKS4
CURLPROXY_SOCKS4A
CURLPROXY_SOCKS5
CURLPROXY_SOCKS5_HOSTNAME
CURL_LONG_VERSION
CURL_MULTICWD
CURL_NOCWD
CURL_SINGLECWD
CURL_SSLVERSION_DEFAULT
CURL_SSLVERSION_MAX_DEFAULT
CURL_SSLVERSION_MAX_TLSv1_0
CURL_SSLVERSION_MAX_TLSv1_1
CURL_SSLVERSION_MAX_TLSv1_2
CURL_SSLVERSION_MAX_TLSv1_3
CURL_SSLVERSION_SSLv2
CURL_SSLVERSION_SSLv3
CURL_SSLVERSION_TLSv1
CURL_SSLVERSION_TLSv1_0
CURL_SSLVERSION_TLSv1_1
CURL_SSLVERSION_TLSv1_2
CURL_SSLVERSION_TLSv1_3
CURL_USESSL_ALL
CURL_USESSL_CONTROL
CURL_USESSL_NONE
CURL_USESSL_TRY
CURL_VERNUM
CURL_VERSION
HTTP_1_0
HTTP_1_1
HTTP_2TLS
HTTP_2_0
HTTP_2_PRIOR_KNOWLEDGE
HTTP_NONE
LONG_VERSION
PIPE_HTTP1
PIPE_MULTIPLEX
PIPE_NOTHING
VERNUM
VERSION

Public Class Methods

asyncdns? → true or false click to toggle source

Returns true if the installed libcurl was built with support for asynchronous name lookups, which allows more exact timeouts (even on Windows) and less blocking when using the multi interface. For libcurl versions < 7.10.7, always returns false.

static VALUE ruby_curl_asyncdns_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_ASYNCHDNS
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_ASYNCHDNS) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
block_scheduler_waiter(waiter) click to toggle source
# File lib/curl.rb, line 57
def self.block_scheduler_waiter(waiter)
  unless scheduler_waiter_blocking_supported?
    sleep 0
    return
  end

  waiter[:fiber] = Fiber.current
  waiter[:scheduler] ||= Fiber.scheduler
  return if waiter[:done] || waiter[:error]

  waiter[:scheduler].block(waiter, nil)
ensure
  waiter[:fiber] = nil if waiter[:fiber].equal?(Fiber.current)
end
complete_scheduler_waiter(waiter) click to toggle source
# File lib/curl.rb, line 32
def self.complete_scheduler_waiter(waiter)
  return if waiter[:done]

  waiter[:done] = true
  wake_scheduler_waiter(waiter)
end
conv? → true or false click to toggle source

Returns true if the installed libcurl was built with support for character conversions. For libcurl versions < 7.15.4, always returns false.

static VALUE ruby_curl_conv_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_CONV
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_CONV) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
debug? → true or false click to toggle source

Returns true if the installed libcurl was built with extra debug capabilities built-in. For libcurl versions < 7.10.6, always returns false.

static VALUE ruby_curl_debug_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_DEBUG
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_DEBUG) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
deferred_exception_source_id(state) click to toggle source
# File lib/curl.rb, line 13
def self.deferred_exception_source_id(state)
  return unless state[:multi].instance_variable_defined?(:@__curb_deferred_exception_source_id)

  state[:multi].instance_variable_get(:@__curb_deferred_exception_source_id)
end
delete(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 234
def self.delete(url, params={}, &block)
  http :DELETE, url, postalize(params), nil, &block
end
drain_scheduler_pending(state) click to toggle source
# File lib/curl.rb, line 189
def self.drain_scheduler_pending(state)
  pending = state[:pending]
  until pending.empty?
    easy = pending.first

    break if state[:multi].instance_variable_defined?(:@__curb_deferred_exception)

    state[:multi].add(easy)
    break unless state[:multi].requests.key?(easy.object_id)

    pending.shift
  end
end
ensure_scheduler_driver(state) click to toggle source
# File lib/curl.rb, line 141
def self.ensure_scheduler_driver(state)
  return if state[:driver_running]

  state[:driver_running] = true
  state[:error] = nil

  runner = proc do
    begin
      # Give sibling fibers a chance to enqueue work so the shared multi can
      # batch scheduler-driven Easy#perform calls together.
      pending_count = -1
      until pending_count == state[:pending].size
        pending_count = state[:pending].size
        scheduler_yield
      end

      loop do
        drain_scheduler_pending(state)
        break if state[:multi].idle?

        begin
          state[:multi].perform do
            drain_scheduler_pending(state)
            release_scheduler_waiters(state)
            scheduler_yield
          end
        ensure
          # Release any siblings that completed just before a deferred
          # callback exception is re-raised.
          release_scheduler_waiters(state)
        end
      end
    rescue => e
      release_scheduler_waiters(state)
      release_scheduler_error(state, e)
    ensure
      state[:driver_running] = false
      ensure_scheduler_driver(state) if state[:error].nil? && !state[:pending].empty?
    end
  end

  if Fiber.respond_to?(:schedule)
    Fiber.schedule(&runner)
  else
    Fiber.new(blocking: false, &runner).resume
  end
end
fail_scheduler_waiter(waiter, error) click to toggle source
# File lib/curl.rb, line 39
def self.fail_scheduler_waiter(waiter, error)
  return if waiter[:error]

  waiter[:error] = error
  wake_scheduler_waiter(waiter)
end
get(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 222
def self.get(url, params={}, &block)
  http :GET, urlalize(url, params), nil, nil, &block
end
gssnegotiate? → true or false click to toggle source

Returns true if the installed libcurl supports HTTP GSS-Negotiate. For libcurl versions < 7.10.6, always returns false.

static VALUE ruby_curl_gssnegotiate_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_GSSNEGOTIATE
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_GSSNEGOTIATE) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
head(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 242
def self.head(url, params={}, &block)
  http :HEAD, urlalize(url, params), nil, nil, &block
end
http(verb, url, post_body=nil, put_data=nil) { |handle| ... } click to toggle source
# File lib/curl.rb, line 203
def self.http(verb, url, post_body=nil, put_data=nil, &block)
  if Thread.current[:curb_curl_yielding]
    handle = Curl::Easy.new # we can't reuse this
  else
    handle = Thread.current[:curb_curl] ||= Curl::Easy.new
    handle.reset
  end
  handle.url = url
  handle.post_body = post_body if post_body
  handle.put_data = put_data if put_data
  if block_given?
    Thread.current[:curb_curl_yielding] = true
    yield handle
    Thread.current[:curb_curl_yielding] = false
  end
  handle.http(verb)
  handle
end
http2? → true or false click to toggle source

Returns true if the installed libcurl was built with support for HTTP2. For libcurl versions < 7.33.0, always returns false.

static VALUE ruby_curl_http2_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_HTTP2
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_HTTP2) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
idn? → true or false click to toggle source

Returns true if the installed libcurl was built with support for IDNA, domain names with international letters. For libcurl versions < 7.12.0, always returns false.

static VALUE ruby_curl_idn_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_IDN
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_IDN) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
ipv6? → true or false click to toggle source

Returns true if the installed libcurl supports IPv6.

static VALUE ruby_curl_ipv6_q(VALUE mod) {
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_IPV6) ? Qtrue : Qfalse);
}
kerberos4? → true or false click to toggle source

Returns true if the installed libcurl supports Kerberos4 authentication with FTP connections.

static VALUE ruby_curl_kerberos4_q(VALUE mod) {
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_KERBEROS4) ? Qtrue : Qfalse);
}
largefile? → true or false click to toggle source

Returns true if the installed libcurl was built with support for large files. For libcurl versions < 7.11.1, always returns false.

static VALUE ruby_curl_largefile_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_LARGEFILE
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_LARGEFILE) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
libz? → true or false click to toggle source

Returns true if the installed libcurl supports HTTP deflate using libz. For libcurl versions < 7.10, always returns false.

static VALUE ruby_curl_libz_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_LIBZ
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_LIBZ) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
ntlm? → true or false click to toggle source

Returns true if the installed libcurl supports HTTP NTLM. For libcurl versions < 7.10.6, always returns false.

static VALUE ruby_curl_ntlm_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_NTLM
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_NTLM) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
options(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 246
def self.options(url, params={}, &block)
  http :OPTIONS, urlalize(url, params), nil, nil, &block
end
patch(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 238
def self.patch(url, params={}, &block)
  http :PATCH, url, postalize(params), nil, &block
end
perform_with_scheduler(easy) click to toggle source
# File lib/curl.rb, line 92
def self.perform_with_scheduler(easy)
  state = scheduler_state
  waiter = {completed: false, done: false, error: nil, fiber: nil, scheduler: Fiber.scheduler}
  state[:waiters][easy.object_id] = waiter
  previous_complete = easy.on_complete do |completed_easy|
    previous_complete.call(completed_easy) if previous_complete
    waiter[:completed] = true
  end

  state[:pending] << easy
  ensure_scheduler_driver(state)

  until waiter[:done]
    raise waiter[:error] if waiter[:error]
    raise state[:error] if state[:error]
    block_scheduler_waiter(waiter)
  end

  while state[:driver_running] && state[:pending].empty? &&
        state[:waiters].length == 1 && state[:waiters].key?(easy.object_id)
    scheduler_yield
  end

  true
ensure
  state[:waiters].delete(easy.object_id) if defined?(state) && state[:waiters]
  if defined?(previous_complete)
    if previous_complete
      easy.on_complete(&previous_complete)
    else
      easy.on_complete
    end
  end
end
post(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 226
def self.post(url, params={}, &block)
  http :POST, url, postalize(params), nil, &block
end
postalize(params={}) click to toggle source
# File lib/curl.rb, line 260
def self.postalize(params={})
  params.respond_to?(:map) ? URI.encode_www_form(params) : (params.respond_to?(:to_s) ? params.to_s : params)
end
put(url, params={}, &block) click to toggle source
# File lib/curl.rb, line 230
def self.put(url, params={}, &block)
  http :PUT, url, nil, postalize(params), &block
end
release_scheduler_error(state, error) click to toggle source
# File lib/curl.rb, line 46
def self.release_scheduler_error(state, error)
  source_waiter = state[:waiters][deferred_exception_source_id(state)]

  if source_waiter
    fail_scheduler_waiter(source_waiter, error)
  else
    state[:error] = error
    state[:waiters].each_value { |waiter| wake_scheduler_waiter(waiter) }
  end
end
release_scheduler_waiters(state) click to toggle source
# File lib/curl.rb, line 82
def self.release_scheduler_waiters(state)
  source_id = deferred_exception_source_id(state)

  state[:waiters].each do |easy_id, waiter|
    next if source_id == easy_id

    complete_scheduler_waiter(waiter) if waiter[:completed]
  end
end
reset() click to toggle source
# File lib/curl.rb, line 264
def self.reset
  Thread.current[:curb_curl] = Curl::Easy.new
end
scheduler_active?() click to toggle source
# File lib/curl.rb, line 9
def self.scheduler_active?
  Fiber.respond_to?(:scheduler) && !Fiber.scheduler.nil?
end
scheduler_state() click to toggle source
# File lib/curl.rb, line 127
def self.scheduler_state
  Thread.current.thread_variable_get(:curb_scheduler_state) || begin
    state = {
      multi: Curl::Multi.new,
      pending: [],
      driver_running: false,
      error: nil,
      waiters: {},
    }
    Thread.current.thread_variable_set(:curb_scheduler_state, state)
    state
  end
end
scheduler_waiter_blocking_supported?() click to toggle source
# File lib/curl.rb, line 19
def self.scheduler_waiter_blocking_supported?
  scheduler = Fiber.scheduler
  scheduler && scheduler.respond_to?(:block) && scheduler.respond_to?(:unblock)
end
scheduler_yield() click to toggle source
# File lib/curl.rb, line 72
def self.scheduler_yield
  scheduler = Fiber.scheduler

  if scheduler&.respond_to?(:kernel_sleep)
    scheduler.kernel_sleep(0)
  else
    sleep 0
  end
end
spnego? → true or false click to toggle source

Returns true if the installed libcurl was built with support for SPNEGO authentication (Simple and Protected GSS-API Negotiation Mechanism, defined in RFC 2478). For libcurl versions < 7.10.8, always returns false.

static VALUE ruby_curl_spnego_q(VALUE mod) {
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
#ifdef HAVE_CURL_VERSION_SPNEGO
  if (ver->features & CURL_VERSION_SPNEGO) return Qtrue;
#endif
#ifdef HAVE_CURL_VERSION_GSSNEGOTIATE
  if (ver->features & CURL_VERSION_GSSNEGOTIATE) return Qtrue;
#endif
  return Qfalse;
}
ssl? → true or false click to toggle source

Returns true if the installed libcurl supports SSL connections. For libcurl versions < 7.10, always returns false.

static VALUE ruby_curl_ssl_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_SSL
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_SSL) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
sspi? → true or false click to toggle source

Returns true if the installed libcurl was built with support for SSPI. This is only available on Windows and makes libcurl use Windows-provided functions for NTLM authentication. It also allows libcurl to use the current user and the current user’s password without the app having to pass them on. For libcurl versions < 7.13.2, always returns false.

static VALUE ruby_curl_sspi_q(VALUE mod) {
#ifdef HAVE_CURL_VERSION_SSPI
  curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
  return((ver->features & CURL_VERSION_SSPI) ? Qtrue : Qfalse);
#else
  return Qfalse;
#endif
}
urlalize(url, params={}) click to toggle source
# File lib/curl.rb, line 250
def self.urlalize(url, params={})
  uri = URI(url)
  # early return if we didn't specify any extra params
  return uri.to_s if (params || {}).empty?

  params_query = URI.encode_www_form(params || {})
  uri.query = [uri.query.to_s, params_query].reject(&:empty?).join('&')
  uri.to_s
end
wake_scheduler_waiter(waiter) click to toggle source
# File lib/curl.rb, line 24
def self.wake_scheduler_waiter(waiter)
  fiber = waiter[:fiber]
  scheduler = waiter[:scheduler]
  return unless fiber&.alive? && scheduler&.respond_to?(:unblock)

  scheduler.unblock(waiter, fiber)
end