@@ -18,13 +18,14 @@ import 'package:gcp/gcp.dart';
18
18
import 'package:http_parser/http_parser.dart' ;
19
19
import 'package:shelf/shelf.dart' ;
20
20
21
- MediaType mediaTypeFromRequest (Request request) {
21
+ MediaType mediaTypeFromRequest (Request request, { String ? requiredMimeType} ) {
22
22
final contentType = request.headers[contentTypeHeader];
23
23
if (contentType == null ) {
24
24
throw BadRequestException (400 , '$contentTypeHeader header is required.' );
25
25
}
26
+ final MediaType value;
26
27
try {
27
- return MediaType .parse (contentType);
28
+ value = MediaType .parse (contentType);
28
29
} catch (e, stack) {
29
30
throw BadRequestException (
30
31
400 ,
@@ -33,23 +34,23 @@ MediaType mediaTypeFromRequest(Request request) {
33
34
innerStack: stack,
34
35
);
35
36
}
36
- }
37
37
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
+ }
46
47
}
48
+ return value;
47
49
}
48
50
49
- Future <Object ?> decodeJson (Request request) async {
50
- final content = await request.readAsString ();
51
+ Future <Object ?> decodeJson (Stream <List <int >> data) async {
51
52
try {
52
- final value = jsonDecode (content) ;
53
+ final value = await utf8.decoder. bind (data). transform (json.decoder).single ;
53
54
return value;
54
55
} on FormatException catch (e, stackTrace) {
55
56
// https://github.com/GoogleCloudPlatform/functions-framework#http-status-codes
@@ -64,4 +65,44 @@ Future<Object?> decodeJson(Request request) async {
64
65
65
66
const jsonContentType = 'application/json' ;
66
67
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
+
67
108
const contentTypeHeader = 'Content-Type' ;
0 commit comments