@@ -18,13 +18,14 @@ import 'package:gcp/gcp.dart';
1818import 'package:http_parser/http_parser.dart' ;
1919import 'package:shelf/shelf.dart' ;
2020
21- MediaType mediaTypeFromRequest (Request request) {
21+ MediaType mediaTypeFromRequest (Request request, { String ? requiredMimeType} ) {
2222 final contentType = request.headers[contentTypeHeader];
2323 if (contentType == null ) {
2424 throw BadRequestException (400 , '$contentTypeHeader header is required.' );
2525 }
26+ final MediaType value;
2627 try {
27- return MediaType .parse (contentType);
28+ value = MediaType .parse (contentType);
2829 } catch (e, stack) {
2930 throw BadRequestException (
3031 400 ,
@@ -33,23 +34,23 @@ MediaType mediaTypeFromRequest(Request request) {
3334 innerStack: stack,
3435 );
3536 }
36- }
3737
38- void mustBeJson (MediaType type) {
39- if (type.mimeType != jsonContentType) {
40- // https://github.com/GoogleCloudPlatform/functions-framework#http-status-codes
41- throw BadRequestException (
42- 400 ,
43- 'Unsupported encoding "${type .toString ()}". '
44- 'Only "$jsonContentType " is supported.' ,
45- );
38+ if (requiredMimeType != null ) {
39+ if (value.mimeType != requiredMimeType) {
40+ // https://github.com/GoogleCloudPlatform/functions-framework#http-status-codes
41+ throw BadRequestException (
42+ 400 ,
43+ 'Unsupported encoding "${value .mimeType .toString ()}". '
44+ 'Only "$requiredMimeType " is supported.' ,
45+ );
46+ }
4647 }
48+ return value;
4749}
4850
49- Future <Object ?> decodeJson (Request request) async {
50- final content = await request.readAsString ();
51+ Future <Object ?> decodeJson (Stream <List <int >> data) async {
5152 try {
52- final value = jsonDecode (content) ;
53+ final value = await utf8.decoder. bind (data). transform (json.decoder).single ;
5354 return value;
5455 } on FormatException catch (e, stackTrace) {
5556 // https://github.com/GoogleCloudPlatform/functions-framework#http-status-codes
@@ -64,4 +65,44 @@ Future<Object?> decodeJson(Request request) async {
6465
6566const jsonContentType = 'application/json' ;
6667
68+ enum SupportedContentTypes {
69+ json (jsonContentType),
70+ protobuf ('application/protobuf' );
71+
72+ const SupportedContentTypes (this .value);
73+
74+ final String value;
75+
76+ static Future <({MediaType mimeType, Object ? data})> decode (
77+ Request request,
78+ ) async {
79+ final type = mediaTypeFromRequest (request);
80+ final supportedType = SupportedContentTypes .values.singleWhere (
81+ (element) => element.value == type.mimeType,
82+ orElse: () => throw BadRequestException (
83+ 400 ,
84+ 'Unsupported encoding "$type ". '
85+ 'Supported types: '
86+ '${SupportedContentTypes .values .map ((e ) => '"${e .value }"' ).join (', ' )}' ,
87+ ),
88+ );
89+
90+ return (
91+ mimeType: type,
92+ data: await supportedType._decode (request.read ()),
93+ );
94+ }
95+
96+ Future <Object ?> _decode (
97+ Stream <List <int >> data,
98+ ) async =>
99+ switch (this ) {
100+ json => await decodeJson (data),
101+ protobuf => await data.fold <List <int >>(
102+ < int > [],
103+ (previous, element) => previous..addAll (element),
104+ ),
105+ };
106+ }
107+
67108const contentTypeHeader = 'Content-Type' ;
0 commit comments