handlePostMessage method
Handles incoming HTTP POST requests containing client messages.
Parses the request body as JSON, validates it, and invokes the onmessage callback with the parsed message.
Implementation
Future<void> handlePostMessage(
HttpRequest request, {
dynamic parsedBody,
}) async {
final response = request.response;
if (_closeController.isClosed) {
response.statusCode = HttpStatus.serviceUnavailable;
response.write("SSE connection not established or closed.");
await response.close();
onerror?.call(
StateError("Received POST message but SSE connection is not active."),
);
return;
}
if (request.method != 'POST') {
response.statusCode = HttpStatus.methodNotAllowed;
response.headers.set(HttpHeaders.allowHeader, 'POST');
response.write("Method Not Allowed. Use POST.");
await response.close();
return;
}
ContentType? contentType;
try {
contentType = request.headers.contentType ?? ContentType.json;
} catch (e) {
response.statusCode = HttpStatus.badRequest;
response.write("Invalid Content-Type header: $e");
await response.close();
onerror?.call(
ArgumentError("Invalid Content-Type header in POST request."),
);
return;
}
if (contentType.mimeType != 'application/json') {
response.statusCode = HttpStatus.unsupportedMediaType;
response.write(
"Unsupported Content-Type: ${request.headers.contentType?.mimeType}. Expected 'application/json'.",
);
await response.close();
onerror?.call(
ArgumentError(
"Unsupported Content-Type in POST request: ${request.headers.contentType?.mimeType}",
),
);
return;
}
dynamic messageJson;
try {
if (parsedBody != null) {
messageJson = parsedBody;
} else {
final bodyBytes =
await request.fold<BytesBuilder>(BytesBuilder(), (builder, chunk) {
builder.add(chunk);
if (builder.length > _maximumMessageSize) {
throw HttpException(
"Message size exceeds limit of $_maximumMessageSize bytes.",
);
}
return builder;
}).then((builder) => builder.toBytes());
final encoding =
Encoding.getByName(contentType.parameters['charset']) ?? utf8;
final bodyString = encoding.decode(bodyBytes);
messageJson = jsonDecode(bodyString);
}
if (messageJson is! Map<String, dynamic>) {
throw FormatException(
"Invalid JSON message format: Expected a JSON object.",
);
}
await handleMessage(messageJson);
response.statusCode = HttpStatus.accepted;
response.write("Accepted");
await response.close();
} catch (error) {
onerror?.call(
error is Error
? error
: StateError("Error handling POST message: $error"),
);
response.statusCode = HttpStatus.internalServerError;
response.write("Error processing message: $error");
await response.close();
}
}