Class: Rubino::API::Operations::Files::UploadOperation
- Inherits:
-
Object
- Object
- Rubino::API::Operations::Files::UploadOperation
- Defined in:
- lib/rubino/api/operations/files/upload_operation.rb
Overview
POST /v1/files (multipart/form-data, field “file”) Persists a single uploaded file into the sandboxed workspace and returns its descriptor (id, filename, size).
Multipart payload is capped at api.max_upload_bytes (default 50 MiB). The cap is enforced twice: first against the declared Content-Length (cheap reject before any IO), then by wrapping rack.input so a body that lies about its size — or omits Content-Length entirely — still aborts mid-stream before Rack::Multipart can fully buffer it to disk.
Defined Under Namespace
Classes: CappedInput
Constant Summary collapse
- DEFAULT_MAX_UPLOAD_BYTES =
50 * 1024 * 1024
Class Method Summary collapse
Instance Method Summary collapse
- #call(request) ⇒ Object
-
#initialize(workspace: nil) ⇒ UploadOperation
constructor
Accepts an alternate workspace for tests.
Constructor Details
#initialize(workspace: nil) ⇒ UploadOperation
Accepts an alternate workspace for tests.
Roots at the tool workspace (terminal.cwd || Dir.pwd), the same root tools and attach_file use, so uploaded files land where the agent can read them back. See ReadOperation for the rationale.
98 99 100 |
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 98 def initialize(workspace: nil) @workspace = workspace || ::Rubino::Files::Workspace.new(root: ::Rubino::Tools::Base.workspace_root) end |
Class Method Details
.call(request) ⇒ Object
89 90 91 |
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 89 def self.call(request) new.call(request) end |
Instance Method Details
#call(request) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rubino/api/operations/files/upload_operation.rb', line 102 def call(request) content_type = request.env["CONTENT_TYPE"].to_s unless content_type.start_with?("multipart/form-data") raise ValidationError, "content-type must be multipart/form-data" end limit = max_upload_bytes declared = request.env["CONTENT_LENGTH"].to_s if !declared.empty? && declared.to_i > limit raise PayloadTooLargeError.new( "multipart upload exceeds #{limit} bytes", details: { limit_bytes: limit } ) end params = parse_with_cap(request.env, limit) upload = params["file"] raise ValidationError, "missing 'file' field" if upload.nil? || !upload.is_a?(Hash) descriptor = @workspace.upload(filename: upload[:filename], io: upload[:tempfile]) [201, { id: descriptor[:id], filename: descriptor[:filename], size: descriptor[:size] }] end |