File: callbacks.rb

package info (click to toggle)
ruby-ethon 0.16.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 676 kB
  • sloc: ruby: 5,403; sh: 9; makefile: 8
file content (149 lines) | stat: -rw-r--r-- 4,396 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# frozen_string_literal: true
module Ethon
  class Easy

    # This module contains all the logic around the callbacks,
    # which are needed to interact with libcurl.
    #
    # @api private
    module Callbacks

      # :nodoc:
      def self.included(base)
        base.send(:attr_accessor, *[:response_body, :response_headers, :debug_info])
      end

      # Set writefunction and headerfunction callback.
      # They are called by libcurl in order to provide the header and
      # the body from the request.
      #
      # @example Set callbacks.
      #   easy.set_callbacks
      def set_callbacks
        Curl.set_option(:writefunction, body_write_callback, handle)
        Curl.set_option(:headerfunction, header_write_callback, handle)
        Curl.set_option(:debugfunction, debug_callback, handle)
        @response_body = String.new
        @response_headers = String.new
        @headers_called = false
        @debug_info = Ethon::Easy::DebugInfo.new
      end

      # Returns the body write callback.
      #
      # @example Return the callback.
      #   easy.body_write_callback
      #
      # @return [ Proc ] The callback.
      def body_write_callback
        @body_write_callback ||= proc do |stream, size, num, object|
          headers
          result = body(chunk = stream.read_string(size * num))
          @response_body << chunk if result == :unyielded
          result != :abort ? size * num : -1
        end
      end

      # Returns the header write callback.
      #
      # @example Return the callback.
      #   easy.header_write_callback
      #
      # @return [ Proc ] The callback.
      def header_write_callback
        @header_write_callback ||= proc {|stream, size, num, object|
          result = headers
          @response_headers << stream.read_string(size * num)
          result != :abort ? size * num : -1
        }
      end

      # Returns the debug callback. This callback is currently used
      # write the raw http request headers.
      #
      # @example Return the callback.
      #   easy.debug_callback
      #
      # @return [ Proc ] The callback.
      def debug_callback
        @debug_callback ||= proc {|handle, type, data, size, udata|
          message = data.read_string(size)
          @debug_info.add type, message
          print message unless [:data_in, :data_out].include?(type)
          0
        }
      end

      def set_progress_callback
        if Curl.version_info[:version] >= "7.32.0"
          Curl.set_option(:xferinfofunction, progress_callback, handle)
        else
          Curl.set_option(:progressfunction, progress_callback, handle)
        end
      end

      # Returns the progress callback.
      #
      # @example Return the callback.
      #   easy.progress_callback
      #
      # @return [ Proc ] The callback.
      def progress_callback
        @progress_callback ||= proc { |_, dltotal, dlnow, ultotal, ulnow|
          progress(dltotal, dlnow, ultotal, ulnow)
          0
        }
      end

      # Set the read callback. This callback is used by libcurl to
      # read data when performing a PUT request.
      #
      # @example Set the callback.
      #   easy.set_read_callback("a=1")
      #
      # @param [ String ] body The body.
      def set_read_callback(body)
        @request_body_read = 0
        readfunction do |stream, size, num, object|
          size = size * num
          body_size = if body.respond_to?(:bytesize)
            body.bytesize
          elsif body.respond_to?(:size)
            body.size
          elsif body.is_a?(File)
            File.size(body.path)
          end

          left = body_size - @request_body_read
          size = left if size > left

          if size > 0
            chunk = if body.respond_to?(:byteslice)
              body.byteslice(@request_body_read, size)
            elsif body.respond_to?(:read)
              body.read(size)
            else
              body[@request_body_read, size]
            end

            stream.write_string(
              chunk, size
            )
            @request_body_read += size
          end
          size
        end
      end

      # Returns the body read callback.
      #
      # @example Return the callback.
      #   easy.read_callback
      #
      # @return [ Proc ] The callback.
      def read_callback
        @read_callback
      end
    end
  end
end