@@ -17,7 +17,9 @@ public static class ResponseBuilder
17
17
public const int BufferSize = 81920 ;
18
18
19
19
private static readonly Type [ ] SpecialTypes =
20
- { typeof ( StringResponse ) , typeof ( BytesResponse ) , typeof ( VoidResponse ) , typeof ( DynamicResponse ) } ;
20
+ {
21
+ typeof ( StringResponse ) , typeof ( BytesResponse ) , typeof ( VoidResponse ) , typeof ( DynamicResponse )
22
+ } ;
21
23
22
24
public static TResponse ToResponse < TResponse > (
23
25
RequestData requestData ,
@@ -31,8 +33,17 @@ public static TResponse ToResponse<TResponse>(
31
33
{
32
34
responseStream . ThrowIfNull ( nameof ( responseStream ) ) ;
33
35
var details = Initialize ( requestData , ex , statusCode , warnings , mimeType ) ;
36
+
34
37
//TODO take ex and (responseStream == Stream.Null) into account might not need to flow to SetBody in that case
35
- var response = SetBody < TResponse > ( details , requestData , responseStream , mimeType ) ?? new TResponse ( ) ;
38
+
39
+ TResponse response = null ;
40
+
41
+ // Only attempt to set the body if the response may have content
42
+ if ( MayHaveBody ( statusCode , requestData . Method ) )
43
+ response = SetBody < TResponse > ( details , requestData , responseStream , mimeType ) ;
44
+
45
+ response ??= new TResponse ( ) ;
46
+
36
47
response . ApiCall = details ;
37
48
return response ;
38
49
}
@@ -50,12 +61,25 @@ public static async Task<TResponse> ToResponseAsync<TResponse>(
50
61
{
51
62
responseStream . ThrowIfNull ( nameof ( responseStream ) ) ;
52
63
var details = Initialize ( requestData , ex , statusCode , warnings , mimeType ) ;
53
- var response = await SetBodyAsync < TResponse > ( details , requestData , responseStream , mimeType , cancellationToken ) . ConfigureAwait ( false )
54
- ?? new TResponse ( ) ;
64
+
65
+ TResponse response = null ;
66
+
67
+ // Only attempt to set the body if the response may have content
68
+ if ( MayHaveBody ( statusCode , requestData . Method ) )
69
+ response = await SetBodyAsync < TResponse > ( details , requestData , responseStream , mimeType , cancellationToken ) . ConfigureAwait ( false ) ;
70
+
71
+ response ??= new TResponse ( ) ;
72
+
55
73
response . ApiCall = details ;
56
74
return response ;
57
75
}
58
76
77
+ /// <summary>
78
+ /// A helper which returns true if the response could potentially have a body.
79
+ /// </summary>
80
+ private static bool MayHaveBody ( int ? statusCode , HttpMethod httpMethod ) =>
81
+ ! statusCode . HasValue || ( statusCode . Value != 204 && httpMethod != HttpMethod . HEAD ) ;
82
+
59
83
private static ApiCallDetails Initialize (
60
84
RequestData requestData , Exception exception , int ? statusCode , IEnumerable < string > warnings , string mimeType
61
85
)
@@ -70,7 +94,10 @@ private static ApiCallDetails Initialize(
70
94
success = requestData . ConnectionSettings
71
95
. StatusCodeToResponseSuccess ( requestData . Method , statusCode . Value ) ;
72
96
}
73
- if ( ! RequestData . ValidResponseContentType ( requestData . Accept , mimeType ) )
97
+
98
+ // We don't validate the content-type (MIME type) for HEAD requests or responses that have no content (204 status code).
99
+ // Elastic Cloud responses to HEAD requests strip the content-type header so we want to avoid validation in that case.
100
+ if ( MayHaveBody ( statusCode , requestData . Method ) && ! RequestData . ValidResponseContentType ( requestData . Accept , mimeType ) )
74
101
success = false ;
75
102
76
103
var details = new ApiCallDetails
@@ -143,7 +170,8 @@ private static async Task<TResponse> SetBodyAsync<TResponse>(
143
170
144
171
var serializer = requestData . ConnectionSettings . RequestResponseSerializer ;
145
172
if ( requestData . CustomResponseBuilder != null )
146
- return await requestData . CustomResponseBuilder . DeserializeResponseAsync ( serializer , details , responseStream , cancellationToken ) . ConfigureAwait ( false ) as TResponse ;
173
+ return await requestData . CustomResponseBuilder . DeserializeResponseAsync ( serializer , details , responseStream , cancellationToken )
174
+ . ConfigureAwait ( false ) as TResponse ;
147
175
148
176
return ! RequestData . ValidResponseContentType ( requestData . Accept , mimeType )
149
177
? null
@@ -171,8 +199,7 @@ private static bool SetSpecialTypes<TResponse>(string mimeType, byte[] bytes, IM
171
199
//if not json store the result under "body"
172
200
if ( ! RequestData . IsJsonMimeType ( mimeType ) )
173
201
{
174
- var dictionary = new DynamicDictionary ( ) ;
175
- dictionary [ "body" ] = new DynamicValue ( bytes . Utf8String ( ) ) ;
202
+ var dictionary = new DynamicDictionary { [ "body" ] = new ( bytes . Utf8String ( ) ) } ;
176
203
cs = new DynamicResponse ( dictionary ) as TResponse ;
177
204
}
178
205
else
0 commit comments