Class: Rubino::API::Operations::Files::ReadOperation

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

Overview

GET /v1/files?path=relative/path Streams raw bytes from a path inside the sandboxed workspace as application/octet-stream. Path traversal is enforced by the workspace.

Returns:

  • ([Integer, Hash, Array<String>])

    200 + octet-stream Rack triple.

Raises:

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(workspace: nil) ⇒ ReadOperation

Accepts an alternate workspace for tests.

Roots the workspace at the SAME directory the tools sandbox to (terminal.cwd || Dir.pwd), not config.paths_home. Tools and attach_file emit absolute paths under that root, so a produced artifact lives there — rooting at paths_home would make every such path look like a traversal escape and 422 the download.



25
26
27
# File 'lib/rubino/api/operations/files/read_operation.rb', line 25

def initialize(workspace: nil)
  @workspace = workspace || ::Rubino::Files::Workspace.new(root: ::Rubino::Tools::Base.workspace_root)
end

Class Method Details

.call(request) ⇒ Object



14
15
16
# File 'lib/rubino/api/operations/files/read_operation.rb', line 14

def self.call(request)
  new.call(request)
end

Instance Method Details

#call(request) ⇒ Object

Raises:



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

def call(request)
  path = request.query["path"]
  raise ValidationError, "path query parameter is required" if path.nil? || path.empty?

  content = @workspace.read(path)
  [200, { "content-type" => "application/octet-stream" }, [content]]
end