Class: AtlasRb::Middleware::RaiseOnResourceError
- Inherits:
-
Faraday::Middleware
- Object
- Faraday::Middleware
- AtlasRb::Middleware::RaiseOnResourceError
- Defined in:
- lib/atlas_rb/middleware/raise_on_resource_error.rb
Overview
Translates Atlas's structured re-parent / linked-member rejections into typed Ruby exceptions, so the resource bindings don't silently swallow the error envelope.
The re-parent and linked-member bindings unwrap their success payload by
a fixed key (["collection"] / ["work"] / ["community"], or the
bare linked-member array). On a 4xx that key is absent, so the binding
would return nil and discard Atlas's machine-readable error /
message. This middleware keys on the request path + status and
raises a typed error carrying the envelope through, parallel to
RaiseOnStaleResource.
It is intentionally narrow — it only fires on the re-parent
(.../parent) and linked-member (.../linked_members...) write paths,
the Compilation surface (/compilations...), and binary uploads
(/files..., /file_sets...), and only on 403 / 422 bodies carrying
an error discriminator. The upload branch is further gated on a fixity
discriminator (FIXITY_CODES), so a 422 on those paths with any other
error (or 403s on uploads, which stay raw) passes through untouched.
Everything else (other paths, other statuses, a 422 whose body uses a
different discriminator such as tombstone's code: "has_live_children")
passes through untouched, so atlas_rb stays a thin Faraday binding that
translates only the wire signals callers genuinely need to discriminate.
Mapping:
403on a re-parent/linked/Compilation path → ForbiddenError422on.../parent→ ReparentError (error/resource_id)422on.../linked_members...→ LinkedMemberError422on/compilations...→ CompilationError422+ a fixity discriminator on/files...//file_sets...→ FixityMismatchError
Constant Summary collapse
- FIXITY_CODES =
Upload-path
422discriminators this middleware translates; any othererroron those paths passes through (Atlas owns these as a wire contract). %w[fixity_mismatch unsupported_digest_algorithm].freeze
Instance Method Summary collapse
Instance Method Details
#on_complete(env) ⇒ void
This method returns an undefined value.
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 |
# File 'lib/atlas_rb/middleware/raise_on_resource_error.rb', line 48 def on_complete(env) return unless [403, 422].include?(env.status) path = env.url&.path.to_s reparent = path.end_with?("/parent") linked = path.include?("/linked_members") compilation = path.start_with?("/compilations") upload = path.start_with?("/files") || path.start_with?("/file_sets") return unless reparent || linked || compilation || upload body = parse_json(env.body) return unless body.is_a?(Hash) && body["error"] if env.status == 403 # 403s on upload paths stay raw — acting-as/authz isn't an upload concern here. return unless reparent || linked || compilation raise AtlasRb::ForbiddenError.new( body["message"] || "Atlas refused the request", code: body["error"], action: body["action"], subject: body["subject"] ) elsif reparent raise AtlasRb::ReparentError.new( body["message"] || "Atlas rejected the re-parent", code: body["error"], resource_id: body["resource_id"] ) elsif linked raise AtlasRb::LinkedMemberError.new( body["message"] || "Atlas rejected the linked-member write", code: body["error"], resource_id: body["resource_id"] ) elsif compilation raise AtlasRb::CompilationError.new( body["message"] || "Atlas rejected the compilation write", code: body["error"], resource_id: body["resource_id"] ) elsif FIXITY_CODES.include?(body["error"]) raise AtlasRb::FixityMismatchError.new( body["message"] || "Atlas rejected the upload (fixity)", code: body["error"], resource_id: body["resource_id"] ) end end |