Skip to content

Commit 2c28902

Browse files
committed
refactor(routes): remove inner try-catch blocks and improve error handling
- Remove inner try-catch blocks in data/[id].dart to allow exceptions to propagate - Move ID validation inside switch blocks after type casting - Add block scope in switch cases for better variable management - Catch TypeError in POST /data deserialization and return 400 response - Add comments about middleware responsibility for error handling
1 parent 877b929 commit 2c28902

File tree

2 files changed

+88
-76
lines changed

2 files changed

+88
-76
lines changed

routes/api/v1/data/[id].dart

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ Future<Response> onRequest(RequestContext context, String id) async {
2424
// --- GET Request ---
2525
if (context.request.method == HttpMethod.get) {
2626
Map<String, dynamic> itemJson;
27-
try {
28-
switch (modelName) {
29-
case 'headline':
30-
final repo = context.read<HtDataRepository<Headline>>();
27+
// Removed inner try-catch block to allow exceptions to propagate
28+
switch (modelName) {
29+
case 'headline':
30+
final repo = context.read<HtDataRepository<Headline>>();
3131
final item = await repo.read(id);
3232
// Serialize using the specific model's toJson method
3333
itemJson = item.toJson();
@@ -44,23 +44,13 @@ Future<Response> onRequest(RequestContext context, String id) async {
4444
final item = await repo.read(id);
4545
itemJson = item.toJson();
4646
default:
47+
// This case should ideally be caught by middleware, but added for safety
4748
return Response(
4849
statusCode: HttpStatus.internalServerError,
4950
body:
5051
'Internal Server Error: Unsupported model type "$modelName" reached handler.',
5152
);
5253
}
53-
} catch (e) {
54-
// Catch potential provider errors during context.read
55-
print(
56-
'Error reading repository provider for model "$modelName" in GET [id]: $e',
57-
);
58-
return Response(
59-
statusCode: HttpStatus.internalServerError,
60-
body:
61-
'Internal Server Error: Could not resolve repository for model "$modelName".',
62-
);
63-
}
6454
// Return the serialized item
6555
return Response.json(body: itemJson);
6656
}
@@ -78,65 +68,89 @@ Future<Response> onRequest(RequestContext context, String id) async {
7868
// Deserialize using ModelConfig's fromJson
7969
final itemToUpdate = modelConfig.fromJson(requestBody);
8070

81-
// Validate ID consistency using ModelConfig's getId
82-
final incomingId = modelConfig.getId(itemToUpdate);
83-
if (incomingId != id) {
84-
return Response(
85-
statusCode: HttpStatus.badRequest,
86-
body:
87-
'Bad Request: ID in request body ("$incomingId") does not match ID in path ("$id").',
88-
);
89-
}
71+
// ID validation moved inside the switch block after type casting
9072

9173
Map<String, dynamic> updatedJson;
92-
try {
93-
switch (modelName) {
94-
case 'headline':
74+
// Removed inner try-catch block to allow exceptions to propagate
75+
switch (modelName) {
76+
case 'headline':
77+
{ // Added block scope
9578
final repo = context.read<HtDataRepository<Headline>>();
96-
// Cast itemToUpdate to the specific type expected by the repository's update method
97-
final updatedItem = await repo.update(id, itemToUpdate as Headline);
98-
// Serialize using the specific model's toJson method
79+
final typedItem = itemToUpdate as Headline; // Cast to specific type
80+
// Validate ID consistency
81+
if (typedItem.id != id) {
82+
return Response(
83+
statusCode: HttpStatus.badRequest,
84+
body:
85+
'Bad Request: ID in request body ("${typedItem.id}") does not match ID in path ("$id").',
86+
);
87+
}
88+
final updatedItem = await repo.update(id, typedItem);
9989
updatedJson = updatedItem.toJson();
90+
} // End block scope
10091
case 'category':
92+
{ // Added block scope
10193
final repo = context.read<HtDataRepository<Category>>();
102-
final updatedItem = await repo.update(id, itemToUpdate as Category);
94+
final typedItem = itemToUpdate as Category; // Cast to specific type
95+
// Validate ID consistency
96+
if (typedItem.id != id) {
97+
return Response(
98+
statusCode: HttpStatus.badRequest,
99+
body:
100+
'Bad Request: ID in request body ("${typedItem.id}") does not match ID in path ("$id").',
101+
);
102+
}
103+
final updatedItem = await repo.update(id, typedItem);
103104
updatedJson = updatedItem.toJson();
105+
} // End block scope
104106
case 'source':
107+
{ // Added block scope
105108
final repo = context.read<HtDataRepository<Source>>();
106-
final updatedItem = await repo.update(id, itemToUpdate as Source);
109+
final typedItem = itemToUpdate as Source; // Cast to specific type
110+
// Validate ID consistency
111+
if (typedItem.id != id) {
112+
return Response(
113+
statusCode: HttpStatus.badRequest,
114+
body:
115+
'Bad Request: ID in request body ("${typedItem.id}") does not match ID in path ("$id").',
116+
);
117+
}
118+
final updatedItem = await repo.update(id, typedItem);
107119
updatedJson = updatedItem.toJson();
120+
} // End block scope
108121
case 'country':
122+
{ // Added block scope
109123
final repo = context.read<HtDataRepository<Country>>();
110-
final updatedItem = await repo.update(id, itemToUpdate as Country);
124+
final typedItem = itemToUpdate as Country; // Cast to specific type
125+
// Validate ID consistency
126+
if (typedItem.id != id) {
127+
return Response(
128+
statusCode: HttpStatus.badRequest,
129+
body:
130+
'Bad Request: ID in request body ("${typedItem.id}") does not match ID in path ("$id").',
131+
);
132+
}
133+
final updatedItem = await repo.update(id, typedItem);
111134
updatedJson = updatedItem.toJson();
135+
} // End block scope
112136
default:
137+
// This case should ideally be caught by middleware, but added for safety
113138
return Response(
114139
statusCode: HttpStatus.internalServerError,
115140
body:
116141
'Internal Server Error: Unsupported model type "$modelName" reached handler.',
117142
);
118143
}
119-
} catch (e) {
120-
// Catch potential provider errors during context.read
121-
print(
122-
'Error reading repository provider for model "$modelName" in PUT [id]: $e',
123-
);
124-
return Response(
125-
statusCode: HttpStatus.internalServerError,
126-
body:
127-
'Internal Server Error: Could not resolve repository for model "$modelName".',
128-
);
129-
}
130144
// Return the serialized updated item
131145
return Response.json(body: updatedJson);
132146
}
133147

134148
// --- DELETE Request ---
135149
if (context.request.method == HttpMethod.delete) {
136-
try {
137-
// No serialization needed, just call delete based on type
138-
switch (modelName) {
139-
case 'headline':
150+
// Removed inner try-catch block to allow exceptions to propagate
151+
// No serialization needed, just call delete based on type
152+
switch (modelName) {
153+
case 'headline':
140154
await context.read<HtDataRepository<Headline>>().delete(id);
141155
case 'category':
142156
await context.read<HtDataRepository<Category>>().delete(id);
@@ -145,23 +159,13 @@ Future<Response> onRequest(RequestContext context, String id) async {
145159
case 'country':
146160
await context.read<HtDataRepository<Country>>().delete(id);
147161
default:
162+
// This case should ideally be caught by middleware, but added for safety
148163
return Response(
149164
statusCode: HttpStatus.internalServerError,
150165
body:
151166
'Internal Server Error: Unsupported model type "$modelName" reached handler.',
152167
);
153168
}
154-
} catch (e) {
155-
// Catch potential provider errors during context.read
156-
print(
157-
'Error reading repository provider for model "$modelName" in DELETE [id]: $e',
158-
);
159-
return Response(
160-
statusCode: HttpStatus.internalServerError,
161-
body:
162-
'Internal Server Error: Could not resolve repository for model "$modelName".',
163-
);
164-
}
165169
// Return 204 No Content for successful deletion
166170
return Response(statusCode: HttpStatus.noContent);
167171
}

routes/api/v1/data/index.dart

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,33 @@ Future<Response> onRequest(RequestContext context) async {
113113
);
114114
}
115115

116-
// Deserialize using ModelConfig's fromJson
117-
final newItem = modelConfig.fromJson(requestBody);
116+
// Deserialize using ModelConfig's fromJson, catching TypeErrors
117+
dynamic newItem; // Use dynamic initially
118+
try {
119+
newItem = modelConfig.fromJson(requestBody);
120+
} on TypeError catch (e) {
121+
// Catch errors during deserialization (e.g., missing required fields)
122+
print('Deserialization TypeError in POST /data: $e');
123+
return Response.json(
124+
statusCode: HttpStatus.badRequest, // 400
125+
body: {
126+
'error': {
127+
'code': 'INVALID_REQUEST_BODY',
128+
'message':
129+
'Invalid request body: Missing or invalid required field(s).',
130+
// 'details': e.toString(), // Optional: Include details in dev
131+
},
132+
},
133+
);
134+
}
118135

119136
// Process based on model type
120137
Map<String, dynamic> createdJson;
121-
try {
122-
switch (modelName) {
123-
case 'headline':
124-
final repo = context.read<HtDataRepository<Headline>>();
138+
// Removed inner try-catch block to allow exceptions like BadRequestException
139+
// from repo.create() to propagate to the outer handlers.
140+
switch (modelName) {
141+
case 'headline':
142+
final repo = context.read<HtDataRepository<Headline>>();
125143
// Cast newItem to the specific type expected by the repository's create method
126144
final createdItem = await repo.create(newItem as Headline);
127145
// Serialize using the specific model's toJson method
@@ -139,23 +157,13 @@ Future<Response> onRequest(RequestContext context) async {
139157
final createdItem = await repo.create(newItem as Country);
140158
createdJson = createdItem.toJson();
141159
default:
160+
// This case should ideally be caught by middleware, but added for safety
142161
return Response(
143162
statusCode: HttpStatus.internalServerError,
144163
body:
145164
'Internal Server Error: Unsupported model type "$modelName" reached handler.',
146165
);
147166
}
148-
} catch (e) {
149-
// Catch potential provider errors during context.read
150-
print(
151-
'Error reading repository provider for model "$modelName" in POST: $e',
152-
);
153-
return Response(
154-
statusCode: HttpStatus.internalServerError,
155-
body:
156-
'Internal Server Error: Could not resolve repository for model "$modelName".',
157-
);
158-
}
159167
// Return the serialized created item
160168
return Response.json(statusCode: HttpStatus.created, body: createdJson);
161169
}

0 commit comments

Comments
 (0)