Skip to content

Commit

Permalink
fix(dynamite)!: propperly serialize headers in requests
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolas Rimikis <[email protected]>
  • Loading branch information
Leptopoda committed Dec 19, 2023
1 parent 728f8df commit b2728f0
Show file tree
Hide file tree
Showing 14 changed files with 502 additions and 113 deletions.
2 changes: 1 addition & 1 deletion packages/dynamite/dynamite/lib/src/builder/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ String buildParameterSerialization(

if (parameter.$in == openapi.ParameterType.header) {
final assignment =
"_headers['${parameter.pctEncodedName}'] = ${result.encode(serializedName, onlyChildren: true)};";
"_headers['${parameter.pctEncodedName}'] = const dynamite_utils.HeaderEncoder(explode: ${parameter.explode}).convert($serializedName);";

if ($default == null) {
buffer
Expand Down
16 changes: 0 additions & 16 deletions packages/dynamite/dynamite/lib/src/models/type_result/enum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,6 @@ class TypeResultEnum extends TypeResult {
@override
String? get _builderFactory => null;

@override
String encode(
final String object, {
final bool onlyChildren = false,
final String? mimeType,
}) {
if (subType.name == 'String') {
return '$object.name';
}

return super.encode(object, mimeType: mimeType);
}

@override
String decode(final String object) => subType.decode(object);

@override
bool operator ==(final Object other) =>
other is TypeResultEnum && other.className == className && other.generics == generics && other.subType == subType;
Expand Down
13 changes: 0 additions & 13 deletions packages/dynamite/dynamite/lib/src/models/type_result/list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,6 @@ class TypeResultList extends TypeResult {
@override
String? get _serializer => null;

@override
String encode(
final String object, {
final bool onlyChildren = false,
final String? mimeType,
}) {
if (onlyChildren) {
return '($object as List).map<String>((final e) => ${subType.encode('e', mimeType: mimeType)}).join()';
}

return super.encode(object, mimeType: mimeType);
}

@override
TypeResultList get dartType => TypeResultList('List', subType, nullable: nullable);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ class TypeResultObject extends TypeResult {
@override
String encode(
final String object, {
final bool onlyChildren = false,
final String? mimeType,
required final String mimeType,
}) {
if (className == _contentString) {
assert(mimeType == 'application/json', '$_contentString should have a mimeType of application/json');
return serialize(object);
if (className == _contentString && mimeType != 'application/json') {
throw StateError('$_contentString should have a mimeType of application/json');
}

return super.encode(object, onlyChildren: onlyChildren, mimeType: mimeType);
return super.encode(object, mimeType: mimeType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ sealed class TypeResult {
/// Encodes the variable named [object].
String encode(
final String object, {
final bool onlyChildren = false,
final String? mimeType,
required final String mimeType,
}) {
final serialized = serialize(object);

Expand Down
150 changes: 136 additions & 14 deletions packages/dynamite/dynamite_end_to_end_test/lib/parameters.openapi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Client extends DynamiteClient {
/// * [contentString]
/// * [contentParameter]
/// * [array]
/// * [arrayString]
/// * [$bool]
/// * [string]
/// * [stringBinary]
Expand All @@ -64,7 +65,8 @@ class Client extends DynamiteClient {
Future<DynamiteResponse<JsonObject, void>> $get({
final ContentString<BuiltMap<String, JsonObject>>? contentString,
final ContentString<BuiltMap<String, JsonObject>>? contentParameter,
final BuiltList<String>? array,
final BuiltList<JsonObject>? array,
final BuiltList<String>? arrayString,
final bool? $bool,
final String? string,
final Uint8List? stringBinary,
Expand All @@ -80,6 +82,7 @@ class Client extends DynamiteClient {
contentString: contentString,
contentParameter: contentParameter,
array: array,
arrayString: arrayString,
$bool: $bool,
string: string,
stringBinary: stringBinary,
Expand All @@ -104,6 +107,7 @@ class Client extends DynamiteClient {
/// * [contentString]
/// * [contentParameter]
/// * [array]
/// * [arrayString]
/// * [$bool]
/// * [string]
/// * [stringBinary]
Expand All @@ -124,7 +128,8 @@ class Client extends DynamiteClient {
DynamiteRawResponse<JsonObject, void> $getRaw({
final ContentString<BuiltMap<String, JsonObject>>? contentString,
final ContentString<BuiltMap<String, JsonObject>>? contentParameter,
final BuiltList<String>? array,
final BuiltList<JsonObject>? array,
final BuiltList<String>? arrayString,
final bool? $bool,
final String? string,
final Uint8List? stringBinary,
Expand Down Expand Up @@ -158,9 +163,13 @@ class Client extends DynamiteClient {
);
parameters['content_parameter'] = $contentParameter;

final $array = jsonSerializers.serialize(array, specifiedType: const FullType(BuiltList, [FullType(String)]));
final $array = jsonSerializers.serialize(array, specifiedType: const FullType(BuiltList, [FullType(JsonObject)]));
parameters['array'] = $array;

final $arrayString =
jsonSerializers.serialize(arrayString, specifiedType: const FullType(BuiltList, [FullType(String)]));
parameters['array_string'] = $arrayString;

final $$bool = jsonSerializers.serialize($bool, specifiedType: const FullType(bool));
parameters['bool'] = $$bool;

Expand Down Expand Up @@ -194,7 +203,7 @@ class Client extends DynamiteClient {

final uri = Uri.parse(
UriTemplate(
'/{?content_string*,content_parameter*,array*,bool*,string*,string_binary*,int*,double*,num*,object*,oneOf*,anyOf*,enum_pattern*}',
'/{?content_string*,content_parameter*,array*,array_string*,bool*,string*,string_binary*,int*,double*,num*,object*,oneOf*,anyOf*,enum_pattern*}',
).expand(parameters),
);
return DynamiteRawResponse<JsonObject, void>(
Expand All @@ -215,33 +224,57 @@ class Client extends DynamiteClient {
/// Throws a [DynamiteApiException] if the API call does not return an expected status code.
///
/// Parameters:
/// * [contentString]
/// * [contentParameter]
/// * [array]
/// * [arrayString]
/// * [$bool]
/// * [string]
/// * [stringBinary]
/// * [$int]
/// * [$double]
/// * [$num]
/// * [object]
/// * [oneOf]
/// * [anyOf]
/// * [enumPattern]
///
/// Status codes:
/// * 200
///
/// See:
/// * [getHeadersRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized.
Future<DynamiteResponse<JsonObject, void>> getHeaders({
final BuiltList<String>? array,
final ContentString<BuiltMap<String, JsonObject>>? contentString,
final ContentString<BuiltMap<String, JsonObject>>? contentParameter,
final BuiltList<JsonObject>? array,
final BuiltList<String>? arrayString,
final bool? $bool,
final String? string,
final Uint8List? stringBinary,
final int? $int,
final double? $double,
final num? $num,
final JsonObject? object,
final GetHeadersOneOf? oneOf,
final GetHeadersAnyOf? anyOf,
final GetHeadersEnumPattern? enumPattern,
}) async {
final rawResponse = getHeadersRaw(
contentString: contentString,
contentParameter: contentParameter,
array: array,
arrayString: arrayString,
$bool: $bool,
string: string,
stringBinary: stringBinary,
$int: $int,
$double: $double,
$num: $num,
object: object,
oneOf: oneOf,
anyOf: anyOf,
enumPattern: enumPattern,
);

return rawResponse.future;
Expand All @@ -253,12 +286,20 @@ class Client extends DynamiteClient {
/// Throws a [DynamiteApiException] if the API call does not return an expected status code.
///
/// Parameters:
/// * [contentString]
/// * [contentParameter]
/// * [array]
/// * [arrayString]
/// * [$bool]
/// * [string]
/// * [stringBinary]
/// * [$int]
/// * [$double]
/// * [$num]
/// * [object]
/// * [oneOf]
/// * [anyOf]
/// * [enumPattern]
///
/// Status codes:
/// * 200
Expand All @@ -267,47 +308,107 @@ class Client extends DynamiteClient {
/// * [getHeaders] for an operation that returns a [DynamiteResponse] with a stable API.
@experimental
DynamiteRawResponse<JsonObject, void> getHeadersRaw({
final BuiltList<String>? array,
final ContentString<BuiltMap<String, JsonObject>>? contentString,
final ContentString<BuiltMap<String, JsonObject>>? contentParameter,
final BuiltList<JsonObject>? array,
final BuiltList<String>? arrayString,
final bool? $bool,
final String? string,
final Uint8List? stringBinary,
final int? $int,
final double? $double,
final num? $num,
final JsonObject? object,
final GetHeadersOneOf? oneOf,
final GetHeadersAnyOf? anyOf,
final GetHeadersEnumPattern? enumPattern,
}) {
final parameters = <String, dynamic>{};
final headers = <String, String>{
'Accept': 'application/json',
};
Uint8List? body;

final $array = jsonSerializers.serialize(array, specifiedType: const FullType(BuiltList, [FullType(String)]));
final $contentString = jsonSerializers.serialize(
contentString,
specifiedType: const FullType(ContentString, [
FullType(BuiltMap, [FullType(String), FullType(JsonObject)]),
]),
);
if ($contentString != null) {
headers['content_string'] = const dynamite_utils.HeaderEncoder().convert($contentString);
}

final $contentParameter = jsonSerializers.serialize(
contentParameter,
specifiedType: const FullType(ContentString, [
FullType(BuiltMap, [FullType(String), FullType(JsonObject)]),
]),
);
if ($contentParameter != null) {
headers['content_parameter'] = const dynamite_utils.HeaderEncoder().convert($contentParameter);
}

final $array = jsonSerializers.serialize(array, specifiedType: const FullType(BuiltList, [FullType(JsonObject)]));
if ($array != null) {
headers['array'] = ($array as List).map<String>((final e) => e as String).join();
headers['array'] = const dynamite_utils.HeaderEncoder().convert($array);
}

final $arrayString =
jsonSerializers.serialize(arrayString, specifiedType: const FullType(BuiltList, [FullType(String)]));
if ($arrayString != null) {
headers['array_string'] = const dynamite_utils.HeaderEncoder().convert($arrayString);
}

final $$bool = jsonSerializers.serialize($bool, specifiedType: const FullType(bool));
if ($$bool != null) {
headers['bool'] = $$bool.toString();
headers['bool'] = const dynamite_utils.HeaderEncoder().convert($$bool);
}

final $string = jsonSerializers.serialize(string, specifiedType: const FullType(String));
if ($string != null) {
headers['string'] = $string as String;
headers['string'] = const dynamite_utils.HeaderEncoder().convert($string);
}

final $stringBinary = jsonSerializers.serialize(stringBinary, specifiedType: const FullType(Uint8List));
if ($stringBinary != null) {
headers['string_binary'] = const dynamite_utils.HeaderEncoder().convert($stringBinary);
}

final $$int = jsonSerializers.serialize($int, specifiedType: const FullType(int));
if ($$int != null) {
headers['int'] = $$int.toString();
headers['int'] = const dynamite_utils.HeaderEncoder().convert($$int);
}

final $$double = jsonSerializers.serialize($double, specifiedType: const FullType(double));
if ($$double != null) {
headers['double'] = $$double.toString();
headers['double'] = const dynamite_utils.HeaderEncoder().convert($$double);
}

final $$num = jsonSerializers.serialize($num, specifiedType: const FullType(num));
if ($$num != null) {
headers['num'] = $$num.toString();
headers['num'] = const dynamite_utils.HeaderEncoder().convert($$num);
}

final $object = jsonSerializers.serialize(object, specifiedType: const FullType(JsonObject));
if ($object != null) {
headers['object'] = const dynamite_utils.HeaderEncoder().convert($object);
}

final $oneOf = jsonSerializers.serialize(oneOf, specifiedType: const FullType(GetHeadersOneOf));
if ($oneOf != null) {
headers['oneOf'] = const dynamite_utils.HeaderEncoder().convert($oneOf);
}

final $anyOf = jsonSerializers.serialize(anyOf, specifiedType: const FullType(GetHeadersAnyOf));
if ($anyOf != null) {
headers['anyOf'] = const dynamite_utils.HeaderEncoder().convert($anyOf);
}

final $enumPattern = jsonSerializers.serialize(enumPattern, specifiedType: const FullType(GetHeadersEnumPattern));
dynamite_utils.checkPattern($enumPattern as String?, RegExp('[a-z]'), 'enumPattern');
if ($enumPattern != null) {
headers['enum_pattern'] = const dynamite_utils.HeaderEncoder().convert($enumPattern);
}

final uri = Uri.parse(UriTemplate('/headers').expand(parameters));
Expand Down Expand Up @@ -393,10 +494,29 @@ class GetEnumPattern extends EnumClass {
static Serializer<GetEnumPattern> get serializer => _$getEnumPatternSerializer;
}

class GetHeadersEnumPattern extends EnumClass {
const GetHeadersEnumPattern._(super.name);

static const GetHeadersEnumPattern a = _$getHeadersEnumPatternA;

@BuiltValueEnumConst(wireName: '0')
static const GetHeadersEnumPattern $0 = _$getHeadersEnumPattern$0;

static BuiltSet<GetHeadersEnumPattern> get values => _$getHeadersEnumPatternValues;

static GetHeadersEnumPattern valueOf(final String name) => _$valueOfGetHeadersEnumPattern(name);

static Serializer<GetHeadersEnumPattern> get serializer => _$getHeadersEnumPatternSerializer;
}

typedef GetOneOf = ({bool? $bool, String? string});

typedef GetAnyOf = ({bool? $bool, String? string});

typedef GetHeadersOneOf = ({bool? $bool, String? string});

typedef GetHeadersAnyOf = ({bool? $bool, String? string});

typedef $BoolString = ({bool? $bool, String? string});

extension $BoolStringExtension on $BoolString {
Expand Down Expand Up @@ -468,9 +588,11 @@ final Serializers serializers = (Serializers().toBuilder()
ContentStringBuilder<BuiltMap<String, JsonObject>>.new,
)
..add(ContentString.serializer)
..addBuilderFactory(const FullType(BuiltList, [FullType(JsonObject)]), ListBuilder<JsonObject>.new)
..addBuilderFactory(const FullType(BuiltList, [FullType(String)]), ListBuilder<String>.new)
..add($BoolStringExtension.serializer)
..add(GetEnumPattern.serializer))
..add(GetEnumPattern.serializer)
..add(GetHeadersEnumPattern.serializer))
.build();

@visibleForTesting
Expand Down
Loading

0 comments on commit b2728f0

Please sign in to comment.