Skip to content

Commit 43544c1

Browse files
committed
Make sure we take body: null into account from the spec and not send any body if no body is documented we relied on serializing empty bodies but the server is now (rightfully) much stricter here.
elastic/elasticsearch#44902
1 parent cd86174 commit 43544c1

File tree

3 files changed

+173
-169
lines changed

3 files changed

+173
-169
lines changed

src/CodeGeneration/ApiGenerator/Views/LowLevel/RequestParameters/RequestParameters.cshtml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ namespace Elasticsearch.Net@(ns)
2626
@foreach (var endpoint in endpoints)
2727
{
2828
var r = endpoint.RequestParameterImplementation;
29+
var supportsBody = endpoint.Body != null;
2930
var names = r.CsharpNames;
3031
<text>
3132
///<summary>Request options for @names.MethodName <para>@r.OfficialDocumentationLink</para></summary>
3233
public class @names.ParametersName : RequestParameters<@names.ParametersName>
3334
{
3435
public override HttpMethod DefaultHttpMethod => HttpMethod.@r.HttpMethod;
36+
public override bool SupportsBody => @(supportsBody ? "true" : "false");
3537
@foreach (var param in r.Params)
3638
{
3739
<text> @Raw(param.InitializerGenerator(param.TypeLowLevel, param.ClsName, param.QueryStringKey, param.SetterLowLevel, param.Description))

src/Elasticsearch.Net/Api/RequestParameters/IRequestParameters.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ namespace Elasticsearch.Net
88
public interface IRequestParameters
99
{
1010
HttpMethod DefaultHttpMethod { get; }
11+
12+
bool SupportsBody { get; }
1113

1214
/// <summary> Allows you to completely circumvent the serializer to build the final response.</summary>
1315
CustomResponseBuilderBase CustomResponseBuilder { get; set; }

src/Nest/ElasticClient.cs

Lines changed: 169 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,169 @@
1-
using System;
2-
using System.Threading;
3-
using System.Threading.Tasks;
4-
using Elasticsearch.Net;
5-
using Elasticsearch.Net.Specification.MachineLearningApi;
6-
7-
namespace Nest
8-
{
9-
10-
public class NamespacedClientProxy
11-
{
12-
private readonly ElasticClient _client;
13-
14-
protected NamespacedClientProxy(ElasticClient client) => _client = client;
15-
16-
internal TResponse DoRequest<TRequest, TResponse>(
17-
TRequest p,
18-
IRequestParameters parameters,
19-
Action<IRequestConfiguration> forceConfiguration = null
20-
)
21-
where TRequest : class, IRequest
22-
where TResponse : class, IElasticsearchResponse, new() =>
23-
_client.DoRequest<TRequest, TResponse>(p, parameters, forceConfiguration);
24-
25-
internal Task<TResponse> DoRequestAsync<TRequest, TResponse>(
26-
TRequest p,
27-
IRequestParameters parameters,
28-
CancellationToken ct,
29-
Action<IRequestConfiguration> forceConfiguration = null
30-
)
31-
where TRequest : class, IRequest
32-
where TResponse : class, IElasticsearchResponse, new() =>
33-
_client.DoRequestAsync<TRequest, TResponse>(p, parameters, ct, forceConfiguration);
34-
35-
protected CatResponse<TCatRecord> DoCat<TRequest, TParams, TCatRecord>(TRequest request)
36-
where TCatRecord : ICatRecord
37-
where TParams : RequestParameters<TParams>, new()
38-
where TRequest : class, IRequest<TParams>
39-
{
40-
if (typeof(TCatRecord) == typeof(CatHelpRecord))
41-
{
42-
request.RequestParameters.CustomResponseBuilder = CatHelpResponseBuilder.Instance;
43-
return DoRequest<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, r => ElasticClient.ForceTextPlain(r));
44-
}
45-
request.RequestParameters.CustomResponseBuilder = CatResponseBuilder<TCatRecord>.Instance;
46-
return DoRequest<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, r => ElasticClient.ForceJson(r));
47-
}
48-
49-
protected Task<CatResponse<TCatRecord>> DoCatAsync<TRequest, TParams, TCatRecord>(TRequest request, CancellationToken ct)
50-
where TCatRecord : ICatRecord
51-
where TParams : RequestParameters<TParams>, new()
52-
where TRequest : class, IRequest<TParams>
53-
{
54-
if (typeof(TCatRecord) == typeof(CatHelpRecord))
55-
{
56-
request.RequestParameters.CustomResponseBuilder = CatHelpResponseBuilder.Instance;
57-
return DoRequestAsync<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, ct, r => ElasticClient.ForceTextPlain(r));
58-
}
59-
request.RequestParameters.CustomResponseBuilder = CatResponseBuilder<TCatRecord>.Instance;
60-
return DoRequestAsync<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, ct, r => ElasticClient.ForceJson(r));
61-
}
62-
63-
internal IRequestParameters ResponseBuilder(PreviewDatafeedRequestParameters parameters, CustomResponseBuilderBase builder)
64-
{
65-
parameters.CustomResponseBuilder = builder;
66-
return parameters;
67-
}
68-
}
69-
/// <summary>
70-
/// ElasticClient is NEST's strongly typed client which exposes fully mapped Elasticsearch endpoints
71-
/// </summary>
72-
public partial class ElasticClient : IElasticClient
73-
{
74-
public ElasticClient() : this(new ConnectionSettings(new Uri("http://localhost:9200"))) { }
75-
76-
public ElasticClient(Uri uri) : this(new ConnectionSettings(uri)) { }
77-
78-
public ElasticClient(IConnectionSettingsValues connectionSettings)
79-
: this(new Transport<IConnectionSettingsValues>(connectionSettings ?? new ConnectionSettings())) { }
80-
81-
public ElasticClient(ITransport<IConnectionSettingsValues> transport)
82-
{
83-
transport.ThrowIfNull(nameof(transport));
84-
transport.Settings.ThrowIfNull(nameof(transport.Settings));
85-
transport.Settings.RequestResponseSerializer.ThrowIfNull(nameof(transport.Settings.RequestResponseSerializer));
86-
transport.Settings.Inferrer.ThrowIfNull(nameof(transport.Settings.Inferrer));
87-
88-
Transport = transport;
89-
LowLevel = new ElasticLowLevelClient(Transport);
90-
SetupNamespaces();
91-
}
92-
93-
partial void SetupNamespaces();
94-
95-
public IConnectionSettingsValues ConnectionSettings => Transport.Settings;
96-
public Inferrer Infer => Transport.Settings.Inferrer;
97-
98-
public IElasticLowLevelClient LowLevel { get; }
99-
public IElasticsearchSerializer RequestResponseSerializer => Transport.Settings.RequestResponseSerializer;
100-
101-
public IElasticsearchSerializer SourceSerializer => Transport.Settings.SourceSerializer;
102-
103-
private ITransport<IConnectionSettingsValues> Transport { get; }
104-
105-
internal TResponse DoRequest<TRequest, TResponse>(TRequest p, IRequestParameters parameters, Action<IRequestConfiguration> forceConfiguration = null)
106-
where TRequest : class, IRequest
107-
where TResponse : class, IElasticsearchResponse, new()
108-
{
109-
if (forceConfiguration != null) ForceConfiguration(p, forceConfiguration);
110-
if (p.ContentType != null) ForceContentType(p, p.ContentType);
111-
112-
var url = p.GetUrl(ConnectionSettings);
113-
var b = (p.HttpMethod == HttpMethod.GET || p.HttpMethod == HttpMethod.HEAD) ? null : new SerializableData<TRequest>(p);
114-
115-
return LowLevel.DoRequest<TResponse>(p.HttpMethod, url, b, parameters);
116-
}
117-
118-
internal Task<TResponse> DoRequestAsync<TRequest, TResponse>(
119-
TRequest p,
120-
IRequestParameters parameters,
121-
CancellationToken ct,
122-
Action<IRequestConfiguration> forceConfiguration = null
123-
)
124-
where TRequest : class, IRequest
125-
where TResponse : class, IElasticsearchResponse, new()
126-
{
127-
if (forceConfiguration != null) ForceConfiguration(p, forceConfiguration);
128-
if (p.ContentType != null) ForceContentType(p, p.ContentType);
129-
130-
var url = p.GetUrl(ConnectionSettings);
131-
var b = (p.HttpMethod == HttpMethod.GET || p.HttpMethod == HttpMethod.HEAD) ? null : new SerializableData<TRequest>(p);
132-
133-
return LowLevel.DoRequestAsync<TResponse>(p.HttpMethod, url, ct, b, parameters);
134-
}
135-
136-
private static void ForceConfiguration(IRequest request, Action<IRequestConfiguration> forceConfiguration)
137-
{
138-
if (forceConfiguration == null) return;
139-
140-
var configuration = request.RequestParameters.RequestConfiguration ?? new RequestConfiguration();
141-
forceConfiguration(configuration);
142-
request.RequestParameters.RequestConfiguration = configuration;
143-
}
144-
private void ForceContentType<TRequest>(TRequest request, string contentType) where TRequest : class, IRequest
145-
{
146-
var configuration = request.RequestParameters.RequestConfiguration ?? new RequestConfiguration();
147-
configuration.Accept = contentType;
148-
configuration.ContentType = contentType;
149-
request.RequestParameters.RequestConfiguration = configuration;
150-
}
151-
152-
internal static void ForceJson(IRequestConfiguration requestConfiguration)
153-
{
154-
requestConfiguration.Accept = RequestData.MimeType;
155-
requestConfiguration.ContentType = RequestData.MimeType;
156-
}
157-
internal static void ForceTextPlain(IRequestConfiguration requestConfiguration)
158-
{
159-
requestConfiguration.Accept = RequestData.MimeTypeTextPlain;
160-
requestConfiguration.ContentType = RequestData.MimeTypeTextPlain;
161-
}
162-
163-
internal IRequestParameters ResponseBuilder(SourceRequestParameters parameters, CustomResponseBuilderBase builder)
164-
{
165-
parameters.CustomResponseBuilder = builder;
166-
return parameters;
167-
}
168-
}
169-
}
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Elasticsearch.Net;
5+
using Elasticsearch.Net.Specification.MachineLearningApi;
6+
7+
namespace Nest
8+
{
9+
10+
public class NamespacedClientProxy
11+
{
12+
private readonly ElasticClient _client;
13+
14+
protected NamespacedClientProxy(ElasticClient client) => _client = client;
15+
16+
internal TResponse DoRequest<TRequest, TResponse>(
17+
TRequest p,
18+
IRequestParameters parameters,
19+
Action<IRequestConfiguration> forceConfiguration = null
20+
)
21+
where TRequest : class, IRequest
22+
where TResponse : class, IElasticsearchResponse, new() =>
23+
_client.DoRequest<TRequest, TResponse>(p, parameters, forceConfiguration);
24+
25+
internal Task<TResponse> DoRequestAsync<TRequest, TResponse>(
26+
TRequest p,
27+
IRequestParameters parameters,
28+
CancellationToken ct,
29+
Action<IRequestConfiguration> forceConfiguration = null
30+
)
31+
where TRequest : class, IRequest
32+
where TResponse : class, IElasticsearchResponse, new() =>
33+
_client.DoRequestAsync<TRequest, TResponse>(p, parameters, ct, forceConfiguration);
34+
35+
protected CatResponse<TCatRecord> DoCat<TRequest, TParams, TCatRecord>(TRequest request)
36+
where TCatRecord : ICatRecord
37+
where TParams : RequestParameters<TParams>, new()
38+
where TRequest : class, IRequest<TParams>
39+
{
40+
if (typeof(TCatRecord) == typeof(CatHelpRecord))
41+
{
42+
request.RequestParameters.CustomResponseBuilder = CatHelpResponseBuilder.Instance;
43+
return DoRequest<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, r => ElasticClient.ForceTextPlain(r));
44+
}
45+
request.RequestParameters.CustomResponseBuilder = CatResponseBuilder<TCatRecord>.Instance;
46+
return DoRequest<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, r => ElasticClient.ForceJson(r));
47+
}
48+
49+
protected Task<CatResponse<TCatRecord>> DoCatAsync<TRequest, TParams, TCatRecord>(TRequest request, CancellationToken ct)
50+
where TCatRecord : ICatRecord
51+
where TParams : RequestParameters<TParams>, new()
52+
where TRequest : class, IRequest<TParams>
53+
{
54+
if (typeof(TCatRecord) == typeof(CatHelpRecord))
55+
{
56+
request.RequestParameters.CustomResponseBuilder = CatHelpResponseBuilder.Instance;
57+
return DoRequestAsync<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, ct, r => ElasticClient.ForceTextPlain(r));
58+
}
59+
request.RequestParameters.CustomResponseBuilder = CatResponseBuilder<TCatRecord>.Instance;
60+
return DoRequestAsync<TRequest, CatResponse<TCatRecord>>(request, request.RequestParameters, ct, r => ElasticClient.ForceJson(r));
61+
}
62+
63+
internal IRequestParameters ResponseBuilder(PreviewDatafeedRequestParameters parameters, CustomResponseBuilderBase builder)
64+
{
65+
parameters.CustomResponseBuilder = builder;
66+
return parameters;
67+
}
68+
}
69+
/// <summary>
70+
/// ElasticClient is NEST's strongly typed client which exposes fully mapped Elasticsearch endpoints
71+
/// </summary>
72+
public partial class ElasticClient : IElasticClient
73+
{
74+
public ElasticClient() : this(new ConnectionSettings(new Uri("http://localhost:9200"))) { }
75+
76+
public ElasticClient(Uri uri) : this(new ConnectionSettings(uri)) { }
77+
78+
public ElasticClient(IConnectionSettingsValues connectionSettings)
79+
: this(new Transport<IConnectionSettingsValues>(connectionSettings ?? new ConnectionSettings())) { }
80+
81+
public ElasticClient(ITransport<IConnectionSettingsValues> transport)
82+
{
83+
transport.ThrowIfNull(nameof(transport));
84+
transport.Settings.ThrowIfNull(nameof(transport.Settings));
85+
transport.Settings.RequestResponseSerializer.ThrowIfNull(nameof(transport.Settings.RequestResponseSerializer));
86+
transport.Settings.Inferrer.ThrowIfNull(nameof(transport.Settings.Inferrer));
87+
88+
Transport = transport;
89+
LowLevel = new ElasticLowLevelClient(Transport);
90+
SetupNamespaces();
91+
}
92+
93+
partial void SetupNamespaces();
94+
95+
public IConnectionSettingsValues ConnectionSettings => Transport.Settings;
96+
public Inferrer Infer => Transport.Settings.Inferrer;
97+
98+
public IElasticLowLevelClient LowLevel { get; }
99+
public IElasticsearchSerializer RequestResponseSerializer => Transport.Settings.RequestResponseSerializer;
100+
101+
public IElasticsearchSerializer SourceSerializer => Transport.Settings.SourceSerializer;
102+
103+
private ITransport<IConnectionSettingsValues> Transport { get; }
104+
105+
internal TResponse DoRequest<TRequest, TResponse>(TRequest p, IRequestParameters parameters, Action<IRequestConfiguration> forceConfiguration = null)
106+
where TRequest : class, IRequest
107+
where TResponse : class, IElasticsearchResponse, new()
108+
{
109+
if (forceConfiguration != null) ForceConfiguration(p, forceConfiguration);
110+
if (p.ContentType != null) ForceContentType(p, p.ContentType);
111+
112+
var url = p.GetUrl(ConnectionSettings);
113+
var b = (p.HttpMethod == HttpMethod.GET || p.HttpMethod == HttpMethod.HEAD || !parameters.SupportsBody) ? null : new SerializableData<TRequest>(p);
114+
115+
return LowLevel.DoRequest<TResponse>(p.HttpMethod, url, b, parameters);
116+
}
117+
118+
internal Task<TResponse> DoRequestAsync<TRequest, TResponse>(
119+
TRequest p,
120+
IRequestParameters parameters,
121+
CancellationToken ct,
122+
Action<IRequestConfiguration> forceConfiguration = null
123+
)
124+
where TRequest : class, IRequest
125+
where TResponse : class, IElasticsearchResponse, new()
126+
{
127+
if (forceConfiguration != null) ForceConfiguration(p, forceConfiguration);
128+
if (p.ContentType != null) ForceContentType(p, p.ContentType);
129+
130+
var url = p.GetUrl(ConnectionSettings);
131+
var b = (p.HttpMethod == HttpMethod.GET || p.HttpMethod == HttpMethod.HEAD || !parameters.SupportsBody) ? null : new SerializableData<TRequest>(p);
132+
133+
return LowLevel.DoRequestAsync<TResponse>(p.HttpMethod, url, ct, b, parameters);
134+
}
135+
136+
private static void ForceConfiguration(IRequest request, Action<IRequestConfiguration> forceConfiguration)
137+
{
138+
if (forceConfiguration == null) return;
139+
140+
var configuration = request.RequestParameters.RequestConfiguration ?? new RequestConfiguration();
141+
forceConfiguration(configuration);
142+
request.RequestParameters.RequestConfiguration = configuration;
143+
}
144+
private void ForceContentType<TRequest>(TRequest request, string contentType) where TRequest : class, IRequest
145+
{
146+
var configuration = request.RequestParameters.RequestConfiguration ?? new RequestConfiguration();
147+
configuration.Accept = contentType;
148+
configuration.ContentType = contentType;
149+
request.RequestParameters.RequestConfiguration = configuration;
150+
}
151+
152+
internal static void ForceJson(IRequestConfiguration requestConfiguration)
153+
{
154+
requestConfiguration.Accept = RequestData.MimeType;
155+
requestConfiguration.ContentType = RequestData.MimeType;
156+
}
157+
internal static void ForceTextPlain(IRequestConfiguration requestConfiguration)
158+
{
159+
requestConfiguration.Accept = RequestData.MimeTypeTextPlain;
160+
requestConfiguration.ContentType = RequestData.MimeTypeTextPlain;
161+
}
162+
163+
internal IRequestParameters ResponseBuilder(SourceRequestParameters parameters, CustomResponseBuilderBase builder)
164+
{
165+
parameters.CustomResponseBuilder = builder;
166+
return parameters;
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)