GET /api/index-status — returns status of all index jobs */
| 1122 | |
| 1123 | /* GET /api/index-status — returns status of all index jobs */ |
| 1124 | static void handle_index_status(cbm_http_server_t *server, cbm_http_conn_t *c) { |
| 1125 | char buf[2048] = "["; |
| 1126 | int pos = 1; |
| 1127 | for (int i = 0; i < MAX_INDEX_JOBS; i++) { |
| 1128 | int st = atomic_load(&server->index_jobs[i].status); |
| 1129 | if (st == 0) |
| 1130 | continue; |
| 1131 | if (pos > 1) |
| 1132 | http_appendf(buf, sizeof(buf), &pos, ","); |
| 1133 | const char *ss = st == 1 ? "indexing" : st == 2 ? "done" : "error"; |
| 1134 | /* root_path comes from POST /api/index and is up to 1023 bytes, so four |
| 1135 | * occupied slots exceed this buffer. http_appendf pins pos to |
| 1136 | * sizeof(buf) on truncation, so the separator and the close have to go |
| 1137 | * through it as well rather than indexing raw. Both fields are free-form, |
| 1138 | * so escape them — a quote in a path would otherwise end its JSON string |
| 1139 | * early. */ |
| 1140 | /* Escaping can double each byte: root_path is 1024, error_msg 256. */ |
| 1141 | char esc_path[2048]; |
| 1142 | char esc_error[512]; |
| 1143 | cbm_json_escape(esc_path, (int)sizeof(esc_path), server->index_jobs[i].root_path); |
| 1144 | cbm_json_escape(esc_error, (int)sizeof(esc_error), |
| 1145 | st == 3 ? server->index_jobs[i].error_msg : ""); |
| 1146 | http_appendf(buf, sizeof(buf), &pos, |
| 1147 | "{\"slot\":%d,\"status\":\"%s\",\"path\":\"%s\",\"error\":\"%s\"}", i, ss, |
| 1148 | esc_path, esc_error); |
| 1149 | } |
| 1150 | http_appendf(buf, sizeof(buf), &pos, "]"); |
| 1151 | if ((size_t)pos >= sizeof(buf)) { |
| 1152 | pos = (int)sizeof(buf) - 1; |
| 1153 | } |
| 1154 | buf[pos] = '\0'; |
| 1155 | cbm_http_replyf(c, 200, g_cors_json, "%s", buf); |
| 1156 | } |
| 1157 | |
| 1158 | static void unwatch_project(cbm_http_server_t *srv, const char *name) { |
| 1159 | if (srv && srv->watcher) { |
no test coverage detected