Skip to content

Commit 7791b11

Browse files
committed
wip
1 parent 42ec8d4 commit 7791b11

File tree

7 files changed

+82
-40
lines changed

7 files changed

+82
-40
lines changed

functions_framework/lib/src/cloud_event.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,19 @@
1313
// limitations under the License.
1414

1515
import 'package:json_annotation/json_annotation.dart';
16+
import 'package:meta/meta.dart';
1617

1718
part 'cloud_event.g.dart';
1819

19-
@JsonSerializable(includeIfNull: false, checked: true)
20-
class CloudEvent {
20+
@internal
21+
typedef FromJson<T> = T Function(Map<String, dynamic> json);
22+
23+
@JsonSerializable(
24+
includeIfNull: false,
25+
checked: true,
26+
genericArgumentFactories: true,
27+
)
28+
class CloudEvent<T> {
2129
@JsonKey(required: true)
2230
final String id;
2331
@JsonKey(required: true)
@@ -30,7 +38,7 @@ class CloudEvent {
3038

3139
@JsonKey(name: 'datacontenttype')
3240
final String? dataContentType;
33-
final Object? data;
41+
final T? data;
3442

3543
@JsonKey(name: 'dataschema')
3644
final Uri? dataSchema;
@@ -49,8 +57,12 @@ class CloudEvent {
4957
this.time,
5058
});
5159

52-
factory CloudEvent.fromJson(Map<String, dynamic> json) =>
53-
_$CloudEventFromJson(json);
60+
factory CloudEvent.fromJson(
61+
Map<String, dynamic> json,
62+
FromJson<T> fromJsonT,
63+
) =>
64+
_$CloudEventFromJson(
65+
json, (value) => fromJsonT(value as Map<String, dynamic>));
5466

55-
Map<String, dynamic> toJson() => _$CloudEventToJson(this);
67+
Map<String, dynamic> toJson() => _$CloudEventToJson(this, (val) => val);
5668
}

functions_framework/lib/src/cloud_event.g.dart

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

functions_framework/lib/src/function_target.dart

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ abstract class FunctionTarget {
3434
HandlerWithLogger function,
3535
) = HttpWithLoggerFunctionTarget;
3636

37-
factory FunctionTarget.cloudEvent(
38-
CloudEventHandler function,
39-
) = CloudEventFunctionTarget;
40-
41-
factory FunctionTarget.cloudEventWithContext(
42-
CloudEventWithContextHandler function,
43-
) = CloudEventWithContextFunctionTarget;
37+
static FunctionTarget cloudEvent<T>(
38+
CloudEventHandler<T> function,
39+
) =>
40+
CloudEventFunctionTarget<T>(function);
41+
42+
static FunctionTarget cloudEventWithContext<T>(
43+
CloudEventWithContextHandler<T> function,
44+
) =>
45+
CloudEventWithContextFunctionTarget<T>(function);
4446

4547
FutureOr<Response> handler(Request request);
4648
}

functions_framework/lib/src/targets/cloud_event_targets.dart

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,49 +24,55 @@ import '../json_request_utils.dart';
2424
import '../request_context.dart';
2525
import '../typedefs.dart';
2626

27-
class CloudEventFunctionTarget extends FunctionTarget {
28-
final CloudEventHandler function;
27+
abstract class _CloudEventFunctionTarget<T> extends FunctionTarget {
28+
_CloudEventFunctionTarget();
29+
30+
Future<CloudEvent<T>> _eventFromRequest(Request request) async =>
31+
_requiredBinaryHeader.every(request.headers.containsKey)
32+
? await _decodeBinary(request, _decode)
33+
: await _decodeStructured(request, _decode);
34+
35+
T _decode(Map<String, dynamic> json) => json as T;
36+
}
37+
38+
class CloudEventFunctionTarget<T> extends _CloudEventFunctionTarget<T> {
39+
final CloudEventHandler<T> function;
2940

3041
@override
3142
FunctionType get type => FunctionType.cloudevent;
3243

3344
@override
3445
FutureOr<Response> handler(Request request) async {
3546
final event = await _eventFromRequest(request);
36-
3747
await function(event);
38-
3948
return Response.ok('');
4049
}
4150

4251
CloudEventFunctionTarget(this.function);
4352
}
4453

45-
class CloudEventWithContextFunctionTarget extends FunctionTarget {
46-
final CloudEventWithContextHandler function;
54+
class CloudEventWithContextFunctionTarget<T>
55+
extends _CloudEventFunctionTarget<T> {
56+
final CloudEventWithContextHandler<T> function;
4757

4858
@override
4959
FunctionType get type => FunctionType.cloudevent;
5060

5161
@override
5262
Future<Response> handler(Request request) async {
5363
final event = await _eventFromRequest(request);
54-
5564
final context = contextForRequest(request);
5665
await function(event, context);
57-
5866
return Response.ok('', headers: context.responseHeaders);
5967
}
6068

6169
CloudEventWithContextFunctionTarget(this.function);
6270
}
6371

64-
Future<CloudEvent> _eventFromRequest(Request request) =>
65-
_requiredBinaryHeader.every(request.headers.containsKey)
66-
? _decodeBinary(request)
67-
: _decodeStructured(request);
68-
69-
Future<CloudEvent> _decodeStructured(Request request) async {
72+
Future<CloudEvent<T>> _decodeStructured<T>(
73+
Request request,
74+
FromJson<T> fromJson,
75+
) async {
7076
final type = mediaTypeFromRequest(request);
7177

7278
mustBeJson(type);
@@ -79,13 +85,20 @@ Future<CloudEvent> _decodeStructured(Request request) async {
7985
};
8086
}
8187

82-
return _decodeValidCloudEvent(jsonObject, 'structured-mode message');
88+
return _decodeValidCloudEvent(
89+
jsonObject,
90+
'structured-mode message',
91+
fromJson,
92+
);
8393
}
8494

8595
const _cloudEventPrefix = 'ce-';
8696
const _clientEventPrefixLength = _cloudEventPrefix.length;
8797

88-
Future<CloudEvent> _decodeBinary(Request request) async {
98+
Future<CloudEvent<T>> _decodeBinary<T>(
99+
Request request,
100+
FromJson<T> fromJson,
101+
) async {
89102
final type = mediaTypeFromRequest(request);
90103
mustBeJson(type);
91104

@@ -97,15 +110,16 @@ Future<CloudEvent> _decodeBinary(Request request) async {
97110
'data': await decodeJson(request),
98111
};
99112

100-
return _decodeValidCloudEvent(map, 'binary-mode message');
113+
return _decodeValidCloudEvent(map, 'binary-mode message', fromJson);
101114
}
102115

103-
CloudEvent _decodeValidCloudEvent(
116+
CloudEvent<T> _decodeValidCloudEvent<T>(
104117
Map<String, dynamic> map,
105118
String messageType,
119+
FromJson<T> fromJson,
106120
) {
107121
try {
108-
return CloudEvent.fromJson(map);
122+
return CloudEvent.fromJson(map, fromJson);
109123
} catch (e, stackTrace) {
110124
throw BadRequestException(
111125
400,

functions_framework/lib/src/typedefs.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ import 'cloud_event.dart';
2020
import 'log_severity.dart';
2121
import 'request_context.dart';
2222

23-
typedef CloudEventHandler = FutureOr<void> Function(CloudEvent request);
23+
typedef CloudEventHandler<T> = FutureOr<void> Function(CloudEvent<T> request);
2424

25-
typedef CloudEventWithContextHandler = FutureOr<void> Function(
26-
CloudEvent request,
25+
typedef CloudEventWithContextHandler<T> = FutureOr<void> Function(
26+
CloudEvent<T> request,
2727
RequestContext context,
2828
);
2929

test/hello/bin/server.dart

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/hello/lib/src/pub_sub_types.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import 'dart:convert';
1616
import 'dart:typed_data';
1717

18+
import 'package:functions_framework/functions_framework.dart';
1819
import 'package:json_annotation/json_annotation.dart';
1920

2021
part 'pub_sub_types.g.dart';
@@ -47,3 +48,6 @@ class PubSubMessage {
4748

4849
Map<String, dynamic> toJson() => _$PubSubMessageToJson(this);
4950
}
51+
52+
@CloudFunction()
53+
void customTypeHandler(CloudEvent bob, RequestContext context) {}

0 commit comments

Comments
 (0)