| 1674 | } |
| 1675 | |
| 1676 | void RenderingController::HandleGET_mxnWindow(const httplib::Request& req, httplib::Response& res) const |
| 1677 | { |
| 1678 | const auto id = ReadRequiredPathParam(req, "id"); |
| 1679 | |
| 1680 | // Shape-only check: malformed ids never reach the bridge dispatch. |
| 1681 | if (!IsValidMxNWindowId(id)) |
| 1682 | { |
| 1683 | const auto error = ErrorResponse::InvalidRequest( |
| 1684 | "Malformed MxN window id '" + id + "'. Expected pattern: <prefix>__<bare> with URL-segment-safe characters.", |
| 1685 | req.path); |
| 1686 | this->SendErrorResponse(res, 400, error); |
| 1687 | return; |
| 1688 | } |
| 1689 | |
| 1690 | if (m_RenderWindowBridge == nullptr || !m_RenderWindowBridge->HasMxNWindowListProvider()) |
| 1691 | { |
| 1692 | const auto error = ErrorResponse::RenderWindowNotAvailable(req.path); |
| 1693 | this->SendErrorResponse(res, 503, error); |
| 1694 | return; |
| 1695 | } |
| 1696 | |
| 1697 | std::vector<MxNWindowInfo> windows; |
| 1698 | try |
| 1699 | { |
| 1700 | windows = m_RenderWindowBridge->ListMxNWindows(); |
| 1701 | } |
| 1702 | catch (const mitk::Exception& e) |
| 1703 | { |
| 1704 | // mitk::Exception from the bridge layer signals a binding-contract |
| 1705 | // violation surfaced via mitkThrow (e.g. an unparseable v2 |
| 1706 | // view_direction). Map to 422 RENDERING_ERROR -- the request shape was |
| 1707 | // valid; the rendering backend reports an unrecoverable state. The |
| 1708 | // generic MapBridgeException below would otherwise emit 500 |
| 1709 | // INTERNAL_ERROR, which is the wrong status class for a downstream |
| 1710 | // contract failure. |
| 1711 | const auto error = ErrorResponse::RenderingError(e.what(), req.path); |
| 1712 | this->SendErrorResponse(res, 422, error); |
| 1713 | return; |
| 1714 | } |
| 1715 | catch (const std::exception& e) |
| 1716 | { |
| 1717 | const auto [status, payload] = MapBridgeException(e, req.path); |
| 1718 | this->SendErrorResponse(res, status, payload); |
| 1719 | return; |
| 1720 | } |
| 1721 | |
| 1722 | // TODO(v3): replace the O(n) scan with a per-window descriptor query once |
| 1723 | // the bridge surface exposes a GetMxNWindowDescriptor(id) callback. |
| 1724 | // Tracked alongside the v3 migration checklist in |
| 1725 | // QmitkRestApiBridgeBindings.cpp; acceptable at v1.2 scale (dozens of |
| 1726 | // cells at most). |
| 1727 | const auto it = std::find_if(windows.begin(), windows.end(), |
| 1728 | [&](const MxNWindowInfo& w) { return w.id == id; }); |
| 1729 | if (it == windows.end()) |
| 1730 | { |
| 1731 | const auto error = ErrorResponse::RenderWindowNotFound(id, req.path); |
| 1732 | this->SendErrorResponse(res, 404, error); |
| 1733 | return; |