From 35b16efcf7bab320a09b60e026665184b7be5330 Mon Sep 17 00:00:00 2001 From: Wukong Sun Date: Sat, 28 Feb 2026 12:15:39 +0800 Subject: [PATCH] feat(api): add error_type field and HTTP status codes for errors - Add optional error_type parameter to respJsonError template for reliable client-side error detection - Add httpCode parameter to return proper HTTP status codes - Use HTTP 404 for not_found errors (tweet/user not found) - Use "not_found" error_type for tweet and user not found errors This allows clients to: 1. Check error_type === 'not_found' instead of parsing error messages 2. Rely on HTTP status codes for proper REST semantics Example error response: HTTP/1.1 404 Not Found { "code": -1, "error": "Tweet not found", "error_type": "not_found" } --- src/jsons/status.nim | 2 +- src/jsons/timeline.nim | 6 +++--- src/routes/router_utils.nim | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/jsons/status.nim b/src/jsons/status.nim index aa403654b..b58ad50fe 100644 --- a/src/jsons/status.nim +++ b/src/jsons/status.nim @@ -60,7 +60,7 @@ proc createJsonApiStatusRouter*(cfg: Config) = var error = "Tweet not found" if conv != nil and conv.tweet != nil and conv.tweet.tombstone.len > 0: error = conv.tweet.tombstone - respJsonError error + respJsonError(error, "not_found", Http404) respJsonSuccess formatConversationAsJson(conv) diff --git a/src/jsons/timeline.nim b/src/jsons/timeline.nim index e58deb353..73895fc83 100644 --- a/src/jsons/timeline.nim +++ b/src/jsons/timeline.nim @@ -121,7 +121,7 @@ proc createJsonApiTimelineRouter*(cfg: Config) = if username.len > 0: respJsonSuccess formatUserName(username) else: - respJsonError "User not found" + respJsonError("User not found", "not_found", Http404) get "/api/@name/profile": cond @"name" notin ["pic", "gif", "video", "search", "settings", "login", @@ -135,7 +135,7 @@ proc createJsonApiTimelineRouter*(cfg: Config) = query.fromUser = names var profile = await fetchProfile("", query, skipRail = false) - if profile.user.username.len == 0: respJsonError "User not found" + if profile.user.username.len == 0: respJsonError("User not found", "not_found", Http404) respJsonSuccess formatProfileAsJson(profile) @@ -160,6 +160,6 @@ proc createJsonApiTimelineRouter*(cfg: Config) = respJsonSuccess formatTimelineAsJson(timeline) else: var profile = await fetchProfile(after, query, skipRail = true) - if profile.tweets.content.len == 0: respJsonError "User not found" + if profile.tweets.content.len == 0: respJsonError("User not found", "not_found", Http404) profile.tweets.beginning = true respJsonSuccess formatTimelineAsJson(profile.tweets) diff --git a/src/routes/router_utils.nim b/src/routes/router_utils.nim index 3a4569b90..38a48b2a2 100644 --- a/src/routes/router_utils.nim +++ b/src/routes/router_utils.nim @@ -53,12 +53,14 @@ template respJsonSuccess*(data: JsonNode) = } resp $successResponse, "application/json" -template respJsonError*(message: string) = - let errorResponse = %*{ +template respJsonError*(message: string, errorType: string = "", httpCode: HttpCode = Http200) = + var errorResponse = %*{ "code": -1, "error": message } - resp $errorResponse, "application/json" + if errorType.len > 0: + errorResponse["error_type"] = %errorType + resp httpCode, $errorResponse, "application/json" template respJsonNull*() = let nullResponse = newJNull()