NorbixError.fromBody constructor
NorbixError.fromBody({})
Build the error a gateway answer describes.
The gateway puts its message and its error code inside
responseStatus.errors[], not at the top of the block, so that list is
read first: the first entry gives message and code, and every entry
is kept in errors. Only when the body has no responseStatus are the
top-level message and errorCode read. Request failed (HTTP N) is
the last fallback, used when the body says nothing at all — a 500 page
that is not JSON, say.
Implementation
factory NorbixError.fromBody({
required int status,
Object? body,
Map<String, dynamic> extraDetails = const {},
}) {
final asMap = body is Map<String, dynamic> ? body : <String, dynamic>{};
// `source` is responseStatus when the body has one, the body itself when
// it has none — so the top-level fields are read only in the second case.
final source = _responseStatusOf(body) ?? asMap;
final rawList = source['errors'];
final items = <NorbixErrorItem>[
if (rawList is List)
for (final entry in rawList)
if (entry is Map<String, dynamic>) NorbixErrorItem.fromJson(entry),
];
NorbixErrorItem? first;
for (final item in items) {
if (item.message != null || item.errorCode != null) {
first = item;
break;
}
}
final message = first?.message ??
_text(source['message']) ??
'Request failed (HTTP $status)';
// Callers switch on `code`, so it is never left empty; the gateway's own
// code wins whenever the gateway sent one.
final code = first?.errorCode ??
_text(source['errorCode']) ??
_text(source['code']) ??
'NORBIX_HTTP_ERROR';
final details = <String, dynamic>{
...asMap,
if (body != null && body is! Map<String, dynamic>) 'body': body,
'status': status,
...extraDetails,
};
return NorbixError.fromHttp(
status: status,
message: message,
code: code,
details: details,
errors: items,
body: body,
);
}