Class: Dinie::Internal::Multipart
- Inherits:
-
Object
- Object
- Dinie::Internal::Multipart
- Defined in:
- lib/dinie/runtime/multipart.rb,
sig/dinie/runtime/multipart.rbs
Overview
Transport wrapper for a multipart/form-data request body (architecture §10/§14, story 009).
The runtime serializes a normal request body to a JSON String (the JSON-only path in
HttpClient#serialize_body). The KYC attachment upload — the project's only multipart
endpoint (POST /customers/{id}/kyc-attachments) — needs multipart/form-data instead, so
this is the seam Ruby adds that the V0.2 TS runtime deferred (the tracked RUNTIME GAP).
An instance holds the deterministic scalar field-map (fields) plus the optional binary
file part. HttpClient recognizes it in serialize_body, hands #to_faraday_body to
Faraday with a bare multipart/form-data content type, and Faraday's :multipart request
middleware (mounted on the shared connection) appends the boundary and encodes every entry
— scalars become plain form-data parts, the file becomes a binary part. Setting the
content type explicitly forces multipart encoding even for the email variant, which carries
no file part (only a scalar value).
── runtime ↔ generated boundary (architecture §4) ──
Lives in runtime/ (CODEOWNER humans). It is transport-aware (Faraday multipart parts) so
the generated KYC layer stays transport-agnostic: Dinie::Kyc.serialize_upload produces a
plain Kyc::UploadForm (the conformance unit — fields + opaque file), and the
customers resource wraps it here at the boundary.
Constant Summary collapse
- CONTENT_TYPE =
Content type Faraday's multipart middleware matches on; it appends
; boundary=…itself. "multipart/form-data"- DEFAULT_FILE_CONTENT_TYPE =
Fallback MIME type for a wrapped file part when the caller passes a bare IO/String. The API validates the real format from the bytes; the SDK does not sniff it.
"application/octet-stream"- DEFAULT_FILE_FILENAME =
Fallback filename for a wrapped file part with no
#path. "upload"
Instance Attribute Summary collapse
-
#fields ⇒ Hash{Symbol => String}
readonly
The scalar form fields (alphabetical — R-ORDER).
-
#file ⇒ Object?
readonly
The file part (a
Faraday::Multipart::FilePart, an IO, or raw bytes).
Instance Method Summary collapse
-
#initialize(fields:, file: nil) ⇒ Multipart
constructor
A new instance of Multipart.
- #multipart_part?(file) ⇒ Boolean
-
#to_faraday_body ⇒ Hash[Symbol, untyped]
The Faraday multipart body: scalar fields plus the wrapped
filepart when present. -
#wrap_file(file) ⇒ Object
Wrap a caller-supplied file into a Faraday multipart part.
Constructor Details
#initialize(fields:, file: nil) ⇒ Multipart
Returns a new instance of Multipart.
45 46 47 48 |
# File 'lib/dinie/runtime/multipart.rb', line 45 def initialize(fields:, file: nil) @fields = fields @file = file end |
Instance Attribute Details
#fields ⇒ Hash{Symbol => String} (readonly)
Returns the scalar form fields (alphabetical — R-ORDER).
38 39 40 |
# File 'lib/dinie/runtime/multipart.rb', line 38 def fields @fields end |
#file ⇒ Object? (readonly)
Returns the file part (a Faraday::Multipart::FilePart, an IO, or raw bytes).
40 41 42 |
# File 'lib/dinie/runtime/multipart.rb', line 40 def file @file end |
Instance Method Details
#multipart_part?(file) ⇒ Boolean
72 73 74 |
# File 'lib/dinie/runtime/multipart.rb', line 72 def multipart_part?(file) file.is_a?(Faraday::Multipart::FilePart) || file.is_a?(Faraday::Multipart::ParamPart) end |
#to_faraday_body ⇒ Hash[Symbol, untyped]
The Faraday multipart body: scalar fields plus the wrapped file part when present.
54 55 56 57 58 |
# File 'lib/dinie/runtime/multipart.rb', line 54 def to_faraday_body body = @fields.dup body[:file] = wrap_file(@file) unless @file.nil? body end |
#wrap_file(file) ⇒ Object
Wrap a caller-supplied file into a Faraday multipart part. An already-wrapped part passes through; an IO is wrapped directly; a String is treated as raw bytes via a StringIO.
64 65 66 67 68 69 70 |
# File 'lib/dinie/runtime/multipart.rb', line 64 def wrap_file(file) return file if multipart_part?(file) io = file.respond_to?(:read) ? file : StringIO.new(file.to_s) filename = file.respond_to?(:path) && file.path ? File.basename(file.path) : DEFAULT_FILE_FILENAME Faraday::Multipart::FilePart.new(io, DEFAULT_FILE_CONTENT_TYPE, filename) end |