0
# Base Controller
1
2
Base controller class providing helper methods for common HTTP responses and access to HTTP context. The `BaseHttpController` class includes methods for standard status codes and content negotiation, making it easy to return structured responses.
3
4
## Capabilities
5
6
### BaseHttpController Class
7
8
Abstract base class that controllers can extend to gain access to HTTP context and response helper methods.
9
10
```typescript { .api }
11
/**
12
* Base class for HTTP controllers with helper methods for common responses
13
*/
14
class BaseHttpController {
15
/** Protected access to HTTP context for the current request */
16
protected readonly httpContext: HttpContext;
17
}
18
```
19
20
### Success Response Methods
21
22
Methods for returning successful HTTP responses with various status codes.
23
24
```typescript { .api }
25
/**
26
* Returns a 200 OK response with content
27
* @param content - Response content to return
28
*/
29
protected ok<T>(content: T): OkNegotiatedContentResult<T>;
30
31
/**
32
* Returns a 200 OK response without content
33
*/
34
protected ok(): OkResult;
35
36
/**
37
* Returns a 201 Created response with location and content
38
* @param location - Location of the created resource
39
* @param content - Created resource content
40
*/
41
protected created<T>(location: string | URL, content: T): CreatedNegotiatedContentResult<T>;
42
```
43
44
### Error Response Methods
45
46
Methods for returning error HTTP responses with appropriate status codes.
47
48
```typescript { .api }
49
/**
50
* Returns a 400 Bad Request response without message
51
*/
52
protected badRequest(): BadRequestResult;
53
54
/**
55
* Returns a 400 Bad Request response with error message
56
* @param message - Error message to include in response
57
*/
58
protected badRequest(message: string): BadRequestErrorMessageResult;
59
60
/**
61
* Returns a 404 Not Found response
62
*/
63
protected notFound(): NotFoundResult;
64
65
/**
66
* Returns a 409 Conflict response
67
*/
68
protected conflict(): ConflictResult;
69
70
/**
71
* Returns a 500 Internal Server Error response without details
72
*/
73
protected internalServerError(): InternalServerErrorResult;
74
75
/**
76
* Returns a 500 Internal Server Error response with exception details
77
* @param error - Error object to include in response
78
*/
79
protected internalServerError(error: Error): ExceptionResult;
80
```
81
82
### Specialized Response Methods
83
84
Methods for specialized HTTP responses and content types.
85
86
```typescript { .api }
87
/**
88
* Returns a redirect response
89
* @param uri - URI to redirect to
90
*/
91
protected redirect(uri: string | URL): RedirectResult;
92
93
/**
94
* Returns a response with custom status code
95
* @param statusCode - HTTP status code to return
96
*/
97
protected statusCode(statusCode: number): StatusCodeResult;
98
99
/**
100
* Returns a JSON response with custom status code
101
* @param content - Content to serialize as JSON
102
* @param statusCode - HTTP status code (defaults to 200)
103
*/
104
protected json(content: unknown, statusCode?: number): JsonResult;
105
106
/**
107
* Returns a streaming response
108
* @param readableStream - Readable stream to pipe to response
109
* @param contentType - MIME type of the stream content
110
* @param statusCode - HTTP status code (defaults to 200)
111
*/
112
protected stream(
113
readableStream: Readable,
114
contentType: string,
115
statusCode?: number
116
): StreamResult;
117
118
/**
119
* Returns a custom HTTP response message
120
* @param message - HttpResponseMessage to return
121
*/
122
protected responseMessage(message: HttpResponseMessage): ResponseMessageResult;
123
```
124
125
**Usage Examples:**
126
127
```typescript
128
import { controller, httpGet, httpPost, BaseHttpController, requestParam, requestBody } from "inversify-express-utils";
129
130
@controller("/users")
131
class UserController extends BaseHttpController {
132
@httpGet("/:id")
133
async getUser(@requestParam("id") id: string) {
134
const user = await this.userService.findById(id);
135
136
if (!user) {
137
return this.notFound();
138
}
139
140
return this.ok(user);
141
}
142
143
@httpPost("/")
144
async createUser(@requestBody() userData: CreateUserDto) {
145
try {
146
const existingUser = await this.userService.findByEmail(userData.email);
147
if (existingUser) {
148
return this.conflict();
149
}
150
151
const newUser = await this.userService.create(userData);
152
return this.created(`/users/${newUser.id}`, newUser);
153
} catch (error) {
154
return this.internalServerError(error);
155
}
156
}
157
158
@httpGet("/")
159
async getUsers(@queryParam("format") format: string) {
160
const users = await this.userService.findAll();
161
162
if (format === "csv") {
163
const csvStream = this.userService.getUsersCsv();
164
return this.stream(csvStream, "text/csv");
165
}
166
167
return this.json(users, 200);
168
}
169
170
@httpPost("/:id/validate")
171
async validateUser(@requestParam("id") id: string, @requestBody() data: any) {
172
if (!data.token) {
173
return this.badRequest("Validation token is required");
174
}
175
176
const isValid = await this.userService.validateToken(id, data.token);
177
if (!isValid) {
178
return this.badRequest("Invalid validation token");
179
}
180
181
return this.ok({ message: "User validated successfully" });
182
}
183
184
@httpGet("/:id/profile-image")
185
async getProfileImage(@requestParam("id") id: string) {
186
const user = await this.userService.findById(id);
187
if (!user || !user.profileImagePath) {
188
return this.notFound();
189
}
190
191
return this.redirect(`/static/images/${user.profileImagePath}`);
192
}
193
194
@httpPost("/:id/custom-response")
195
async customResponse(@requestParam("id") id: string) {
196
const response = new HttpResponseMessage(202);
197
response.headers["X-Custom-Header"] = "custom-value";
198
response.content = new JsonContent({
199
message: "Processing started",
200
userId: id
201
});
202
203
return this.responseMessage(response);
204
}
205
}
206
```
207
208
### HTTP Context Access
209
210
The base controller provides protected access to the HTTP context for advanced scenarios.
211
212
```typescript { .api }
213
/**
214
* HTTP context providing access to container, request, response, and user
215
*/
216
interface HttpContext<T = unknown> {
217
/** Child container for request-scoped dependencies */
218
container: interfaces.Container;
219
/** Express request object */
220
request: Request;
221
/** Express response object */
222
response: Response;
223
/** Authenticated user principal */
224
user: Principal<T>;
225
}
226
```
227
228
**Usage Examples:**
229
230
```typescript
231
@controller("/advanced")
232
class AdvancedController extends BaseHttpController {
233
@httpGet("/context-info")
234
getContextInfo() {
235
// Access HTTP context directly
236
const { request, user, container } = this.httpContext;
237
238
return this.ok({
239
method: request.method,
240
path: request.path,
241
userAgent: request.headers["user-agent"],
242
isAuthenticated: await user.isAuthenticated(),
243
containerHasDependency: container.isBound("SomeService")
244
});
245
}
246
247
@httpPost("/resolve-service")
248
async resolveService() {
249
// Use container from HTTP context
250
const customService = this.httpContext.container.get<CustomService>("CustomService");
251
const result = await customService.performOperation();
252
253
return this.ok(result);
254
}
255
}
256
```