34void add_cors_headers(crow::response &res,
const rest_server_context &ctx) {
35 if (ctx.config && !ctx.config->cors_allowed_origins.empty()) {
36 res.add_header(
"Access-Control-Allow-Origin",
37 ctx.config->cors_allowed_origins);
44std::string series_to_json(
const storage::series_record &series) {
45 std::ostringstream oss;
46 oss << R
"({"pk":)" << series.pk << R"(,"study_pk":)" << series.study_pk
49 << R"(","series_number":)";
50 if (
series.series_number) {
51 oss << *
series.series_number;
58 << R"(","num_instances":)" << series.num_instances << "}";
65std::string instance_to_json(
const storage::instance_record &instance) {
66 std::ostringstream oss;
67 oss << R
"({"pk":)" << instance.pk << R"(,"series_pk":)" << instance.series_pk
68 << R"(,"sop_instance_uid":")" << json_escape(instance.sop_uid)
69 << R"(","sop_class_uid":")" << json_escape(instance.sop_class_uid)
70 << R"(","transfer_syntax":")" << json_escape(instance.transfer_syntax)
71 << R"(","instance_number":)";
72 if (instance.instance_number) {
73 oss << *instance.instance_number;
77 oss << R
"(,"file_size":)" << instance.file_size << "}";
84std::string instances_to_json(
const std::vector<storage::instance_record> &instances) {
85 std::ostringstream oss;
86 oss << R
"({"data":[)";
87 for (
size_t i = 0; i < instances.size(); ++i) {
91 oss << instance_to_json(instances[i]);
93 oss << R
"(],"count":)" << instances.size() << "}";
101 std::shared_ptr<rest_server_context> ctx) {
103 CROW_ROUTE(app,
"/api/v1/series/<string>")
104 .methods(crow::HTTPMethod::GET)(
105 [ctx](
const crow::request & ,
const std::string &series_uid) {
107 res.add_header(
"Content-Type",
"application/json");
108 add_cors_headers(res, *ctx);
110 if (!ctx->database) {
113 "Database not configured");
117 auto series = ctx->database->find_series(series_uid);
125 res.body = series_to_json(*series);
130 CROW_ROUTE(app,
"/api/v1/series/<string>/instances")
131 .methods(crow::HTTPMethod::GET)(
132 [ctx](
const crow::request & ,
const std::string &series_uid) {
134 res.add_header(
"Content-Type",
"application/json");
135 add_cors_headers(res, *ctx);
137 if (!ctx->database) {
140 "Database not configured");
145 auto series = ctx->database->find_series(series_uid);
152 auto instances_result = ctx->database->list_instances(series_uid);
153 if (!instances_result.is_ok()) {
156 instances_result.error().message);
161 res.body = instances_to_json(instances_result.value());
PACS index database for metadata storage and retrieval.
Instance record data structures for database operations.
void register_series_endpoints_impl(crow::SimpleApp &app, std::shared_ptr< rest_server_context > ctx)
std::string make_error_json(std::string_view code, std::string_view message)
Create JSON error response body with details.
std::string json_escape(std::string_view s)
Escape a string for JSON.
Configuration for REST API server.
Common types and utilities for REST API.
Series API endpoints for REST server.
Series record data structures for database operations.
System API endpoints for REST server.