Skip to content

Commit 4fab90d

Browse files
committed
Update InMemoryConnection to support product checks
1 parent 09f2e6a commit 4fab90d

File tree

1 file changed

+122
-27
lines changed

1 file changed

+122
-27
lines changed

src/Elasticsearch.Net/Connection/InMemoryConnection.cs

Lines changed: 122 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,95 @@
33
// See the LICENSE file in the project root for more information
44

55
using System;
6+
using System.Collections.Generic;
67
using System.IO;
78
using System.IO.Compression;
9+
using System.Linq;
810
using System.Text;
911
using System.Threading;
1012
using System.Threading.Tasks;
1113

1214
namespace Elasticsearch.Net
1315
{
16+
public class InMemoryHttpResponse
17+
{
18+
public int StatusCode { get; set; } = 200;
19+
public byte[] ResponseBytes { get; set; } = Array.Empty<byte>();
20+
public Dictionary<string, List<string>> Headers { get; set; } = new();
21+
public string ContentType { get; set; }
22+
}
23+
1424
public class InMemoryConnection : IConnection
1525
{
16-
internal static readonly byte[] EmptyBody = Encoding.UTF8.GetBytes("");
26+
private readonly string _basePath = "/";
27+
private const string DefaultProductName = "Elasticsearch";
28+
private static readonly byte[] EmptyBody = Encoding.UTF8.GetBytes("");
1729
private readonly string _contentType;
1830
private readonly Exception _exception;
1931
private readonly byte[] _responseBody;
2032
private readonly int _statusCode;
33+
private readonly InMemoryHttpResponse _productCheckResponse;
34+
private readonly string _productHeader;
35+
36+
public static InMemoryHttpResponse ValidProductCheckResponse(string productName = null)
37+
{
38+
var responseJson = new
39+
{
40+
name = "es01",
41+
cluster_name = "elasticsearch-test-cluster",
42+
version = new
43+
{
44+
number = "7.14.0",
45+
build_flavor = "default",
46+
build_hash = "af1dc6d8099487755c3143c931665b709de3c764",
47+
build_timestamp = "2020-08-11T21:36:48.204330Z",
48+
build_snapshot = false,
49+
lucene_version = "8.6.0"
50+
},
51+
tagline = "You Know, for Search"
52+
};
53+
54+
using var ms = RecyclableMemoryStreamFactory.Default.Create();
55+
LowLevelRequestResponseSerializer.Instance.Serialize(responseJson, ms);
56+
57+
var response = new InMemoryHttpResponse
58+
{
59+
ResponseBytes = ms.ToArray()
60+
};
61+
62+
response.Headers.Add("X-elastic-product", new List<string>{ productName ?? DefaultProductName });
63+
64+
return response;
65+
}
2166

2267
/// <summary>
2368
/// Every request will succeed with this overload, note that it won't actually return mocked responses
2469
/// so using this overload might fail if you are using it to test high level bits that need to deserialize the response.
2570
/// </summary>
26-
public InMemoryConnection() => _statusCode = 200;
71+
public InMemoryConnection()
72+
{
73+
_statusCode = 200;
74+
_productCheckResponse = ValidProductCheckResponse();
75+
}
2776

28-
public InMemoryConnection(byte[] responseBody, int statusCode = 200, Exception exception = null, string contentType = null)
77+
public InMemoryConnection(string basePath) : this() => _basePath = $"/{basePath.Trim('/')}/";
78+
79+
public InMemoryConnection(InMemoryHttpResponse productCheckResponse = null, int statusCode = 200, string productHeader = null)
2980
{
81+
_statusCode = statusCode;
82+
_productCheckResponse = productCheckResponse ?? ValidProductCheckResponse();
83+
_productHeader = productHeader;
84+
}
3085

86+
public InMemoryConnection(
87+
byte[] responseBody,
88+
int statusCode = 200,
89+
Exception exception = null,
90+
string contentType = null,
91+
InMemoryHttpResponse productCheckResponse = null,
92+
string productNameFromHeader = null) : this(productCheckResponse, statusCode, productNameFromHeader)
93+
{
3194
_responseBody = responseBody;
32-
_statusCode = statusCode;
3395
_exception = exception;
3496
_contentType = contentType ?? RequestData.DefaultJsonMimeType;
3597
}
@@ -43,59 +105,92 @@ public virtual Task<TResponse> RequestAsync<TResponse>(RequestData requestData,
43105
ReturnConnectionStatusAsync<TResponse>(requestData, cancellationToken);
44106

45107
void IDisposable.Dispose() => DisposeManagedResources();
46-
47-
protected TResponse ReturnConnectionStatus<TResponse>(RequestData requestData, byte[] responseBody = null, int? statusCode = null,
48-
string contentType = null
108+
109+
protected TResponse ReturnConnectionStatus<TResponse>(
110+
RequestData requestData,
111+
byte[] responseBody = null,
112+
int? statusCode = null,
113+
string contentType = null,
114+
InMemoryHttpResponse productCheckResponse = null
49115
)
50116
where TResponse : class, IElasticsearchResponse, new()
51117
{
118+
if (_basePath.Equals(requestData.Uri.AbsolutePath, StringComparison.Ordinal) && requestData.Method == HttpMethod.GET)
119+
return ReturnProductCheckResponse<TResponse>(requestData, statusCode, productCheckResponse);
120+
52121
var body = responseBody ?? _responseBody;
53122
var data = requestData.PostData;
54-
if (data != null)
123+
124+
if (data is not null)
55125
{
56-
using (var stream = requestData.MemoryStreamFactory.Create())
57-
{
58-
if (requestData.HttpCompression)
59-
using (var zipStream = new GZipStream(stream, CompressionMode.Compress))
60-
data.Write(zipStream, requestData.ConnectionSettings);
61-
else
62-
data.Write(stream, requestData.ConnectionSettings);
63-
}
126+
using var stream = requestData.MemoryStreamFactory.Create();
127+
128+
if (requestData.HttpCompression)
129+
using (var zipStream = new GZipStream(stream, CompressionMode.Compress))
130+
data.Write(zipStream, requestData.ConnectionSettings);
131+
else
132+
data.Write(stream, requestData.ConnectionSettings);
64133
}
134+
65135
requestData.MadeItToResponse = true;
66136

67137
var sc = statusCode ?? _statusCode;
68138
Stream s = body != null ? requestData.MemoryStreamFactory.Create(body) : requestData.MemoryStreamFactory.Create(EmptyBody);
69139
return ResponseBuilder.ToResponse<TResponse>(requestData, _exception, sc, null, s, contentType ?? _contentType ?? RequestData.DefaultJsonMimeType);
70140
}
71141

72-
protected async Task<TResponse> ReturnConnectionStatusAsync<TResponse>(RequestData requestData, CancellationToken cancellationToken,
73-
byte[] responseBody = null, int? statusCode = null, string contentType = null
142+
protected async Task<TResponse> ReturnConnectionStatusAsync<TResponse>(
143+
RequestData requestData,
144+
CancellationToken cancellationToken,
145+
byte[] responseBody = null,
146+
int? statusCode = null,
147+
string contentType = null,
148+
InMemoryHttpResponse productCheckResponse = null
74149
)
75150
where TResponse : class, IElasticsearchResponse, new()
76151
{
152+
if (_basePath.Equals(requestData.Uri.AbsolutePath, StringComparison.Ordinal) && requestData.Method == HttpMethod.GET)
153+
return ReturnProductCheckResponse<TResponse>(requestData, statusCode, productCheckResponse);
154+
77155
var body = responseBody ?? _responseBody;
78156
var data = requestData.PostData;
157+
79158
if (data != null)
80159
{
81-
using (var stream = requestData.MemoryStreamFactory.Create())
82-
{
83-
if (requestData.HttpCompression)
84-
using (var zipStream = new GZipStream(stream, CompressionMode.Compress))
85-
await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false);
86-
else
87-
await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false);
88-
}
160+
using var stream = requestData.MemoryStreamFactory.Create();
161+
if (requestData.HttpCompression)
162+
using (var zipStream = new GZipStream(stream, CompressionMode.Compress))
163+
await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false);
164+
else
165+
await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false);
89166
}
90167
requestData.MadeItToResponse = true;
91168

92169
var sc = statusCode ?? _statusCode;
93170
Stream s = body != null ? requestData.MemoryStreamFactory.Create(body) : requestData.MemoryStreamFactory.Create(EmptyBody);
94171
return await ResponseBuilder
95-
.ToResponseAsync<TResponse>(requestData, _exception, sc, null, s, contentType ?? _contentType, cancellationToken)
172+
.ToResponseAsync<TResponse>(requestData, _exception, sc, null, s, contentType ?? _contentType, _productHeader, cancellationToken)
96173
.ConfigureAwait(false);
97174
}
98175

176+
private TResponse ReturnProductCheckResponse<TResponse>(
177+
RequestData requestData,
178+
int? statusCode = null,
179+
InMemoryHttpResponse productCheckResponse = null
180+
) where TResponse : class, IElasticsearchResponse, new()
181+
{
182+
productCheckResponse ??= _productCheckResponse;
183+
productCheckResponse.Headers.TryGetValue("X-elastic-product", out var productNames);
184+
185+
requestData.MadeItToResponse = true;
186+
187+
using var ms = requestData.MemoryStreamFactory.Create(productCheckResponse.ResponseBytes);
188+
189+
return ResponseBuilder.ToResponse<TResponse>(
190+
requestData, _exception, statusCode ?? productCheckResponse.StatusCode, null, ms,
191+
RequestData.DefaultJsonMimeType, productNames?.FirstOrDefault());
192+
}
193+
99194
protected virtual void DisposeManagedResources() { }
100195
}
101196
}

0 commit comments

Comments
 (0)