Class: Rubino::API::Operations::Files::UploadOperation::CappedInput

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/api/operations/files/upload_operation.rb

Overview

Wraps a Rack input stream and raises PayloadTooLargeError once the cumulative bytes read pass limit. Rack::Multipart drives the read loop, so raising here unwinds straight out of parse_multipart and the partially-written tempfile is collected by the ensure block in #call.

Instance Method Summary collapse

Constructor Details

#initialize(io, limit) ⇒ CappedInput

Returns a new instance of CappedInput.



31
32
33
34
35
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 31

def initialize(io, limit)
  @io = io
  @limit = limit
  @read = 0
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object



82
83
84
85
86
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 82

def method_missing(name, *, &)
  return @io.send(name, *, &) if @io.respond_to?(name)

  super
end

Instance Method Details

#eof?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 59

def eof?
  @io.eof?
end

#getsObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 63

def gets(*)
  line = @io.gets(*)
  return line if line.nil?

  @read += line.bytesize
  if @read > @limit
    raise Rubino::PayloadTooLargeError.new(
      "multipart upload exceeds #{@limit} bytes",
      details: { limit_bytes: @limit }
    )
  end

  line
end

#read(length = nil, buffer = nil) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 37

def read(length = nil, buffer = nil)
  chunk = buffer ? @io.read(length, buffer) : @io.read(length)
  return chunk if chunk.nil?

  @read += chunk.bytesize
  if @read > @limit
    raise Rubino::PayloadTooLargeError.new(
      "multipart upload exceeds #{@limit} bytes",
      details: { limit_bytes: @limit }
    )
  end

  chunk
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 78

def respond_to_missing?(name, include_private = false)
  @io.respond_to?(name, include_private) || super
end

#rewindObject

Rack::Multipart::Parser interrogates rewind/eof?/gets on the input; delegate so the parser is unaware it’s wrapped.



54
55
56
57
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 54

def rewind
  @read = 0
  @io.rewind
end