Skip to content

Commit 67bf035

Browse files
committed
mimicked elasticsearch's create index's indexname validation on the client side to throw hard validation error
1 parent 621316d commit 67bf035

File tree

4 files changed

+97
-6
lines changed

4 files changed

+97
-6
lines changed

src/Nest/ConvenienceExtensions/CreateIndexExtensions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ private static TResponse CreateIndex<TResponse>(IElasticClient client, string in
5656
Func<Func<CreateIndexDescriptor, CreateIndexDescriptor>, TResponse> createIndexMethod)
5757
{
5858
index.ThrowIfNullOrEmpty("index");
59-
index.ThrownIfNotLowercase("index");
6059
createIndexSelector = createIndexSelector ?? (c => c);
6160
return createIndexMethod(c => createIndexSelector(c).Index(index));
6261
}

src/Nest/DSL/CreateIndexDescriptor.cs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
5+
using System.Text;
46
using Elasticsearch.Net;
57
using Newtonsoft.Json;
68

@@ -15,23 +17,47 @@ public interface ICreateIndexRequest : IIndexPath<CreateIndexRequestParameters>
1517

1618
internal static class CreateIndexPathInfo
1719
{
20+
private static char[] _invalidChars = new[] { '\\', '/', '*', '?', '"', '<', '>', '|', ' ', ',', '#' };
21+
private static string _invalidCharsMessage = string.Join(", ", _invalidChars);
22+
1823
public static void Update(ElasticsearchPathInfo<CreateIndexRequestParameters> pathInfo, ICreateIndexRequest request)
1924
{
2025
pathInfo.HttpMethod = PathInfoHttpMethod.POST;
2126
}
27+
28+
public static void Validate(ElasticsearchPathInfo<CreateIndexRequestParameters> pathInfo, ICreateIndexRequest request)
29+
{
30+
var index = pathInfo.Index;
31+
if (index.StartsWith("_"))
32+
throw new DslException("indexname {0} may not start with an underscore".F(index));
33+
34+
if (Encoding.UTF8.GetByteCount(index) > 255)
35+
throw new DslException("indexname {0} exceeds maximum index name length of 255".F(index));
36+
37+
if (index.Any(char.IsUpper))
38+
throw new DslException("indexname {0} contains uppercase characters".F(index));
39+
40+
if (index.Any(c => _invalidChars.Contains(c)))
41+
throw new DslException("indexname {0} contains one of {1} invalid characters".F(index, _invalidCharsMessage));
42+
43+
}
2244
}
23-
45+
2446
public partial class CreateIndexRequest : IndexPathBase<CreateIndexRequestParameters>, ICreateIndexRequest
2547
{
2648
public CreateIndexRequest(IndexNameMarker index) : base(index) { }
2749

2850
public IndexSettings IndexSettings { get; set; }
29-
51+
3052
protected override void UpdatePathInfo(IConnectionSettingsValues settings, ElasticsearchPathInfo<CreateIndexRequestParameters> pathInfo)
3153
{
3254
CreateIndexPathInfo.Update(pathInfo, this);
3355
}
3456

57+
protected override void ValidatePathInfo(ElasticsearchPathInfo<CreateIndexRequestParameters> pathInfo)
58+
{
59+
CreateIndexPathInfo.Validate(pathInfo, this);
60+
}
3561
}
3662

3763
[DescriptorFor("IndicesCreate")]
@@ -131,7 +157,7 @@ public CreateIndexDescriptor AddAlias(string aliasName, Func<CreateAliasDescript
131157

132158
return this;
133159
}
134-
160+
135161

136162
private CreateIndexDescriptor RemoveMapping(TypeNameMarker marker)
137163
{
@@ -185,7 +211,7 @@ public CreateIndexDescriptor AddMapping<T>(RootObjectMapping rootObjectMapping,
185211
}
186212
else
187213
{
188-
typeMapping.Name = typeof (T);
214+
typeMapping.Name = typeof(T);
189215
}
190216

191217
this._indexSettings.Mappings.Add(typeMapping);
@@ -220,7 +246,7 @@ public CreateIndexDescriptor Analysis(Func<AnalysisDescriptor, AnalysisDescripto
220246
this._indexSettings.Analysis = analysis == null ? null : analysis._AnalysisSettings;
221247
return this;
222248
}
223-
249+
224250
public CreateIndexDescriptor Similarity(Func<SimilarityDescriptor, SimilarityDescriptor> similaritySelector)
225251
{
226252
similaritySelector.ThrowIfNull("similaritySelector");
@@ -234,5 +260,10 @@ protected override void UpdatePathInfo(IConnectionSettingsValues settings, Elast
234260
CreateIndexPathInfo.Update(pathInfo, this);
235261
}
236262

263+
protected override void ValidatePathInfo(ElasticsearchPathInfo<CreateIndexRequestParameters> pathInfo)
264+
{
265+
CreateIndexPathInfo.Validate(pathInfo, this);
266+
}
267+
237268
}
238269
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using System.Linq;
3+
using FluentAssertions;
4+
using NUnit.Framework;
5+
using Nest.Tests.MockData.Domain;
6+
7+
namespace Nest.Tests.Unit.Internals.Inferno
8+
{
9+
[TestFixture]
10+
public class IndexNameResolverTests : BaseJsonTests
11+
{
12+
[Test]
13+
public void Uppercase_Characters_AreNotAllowed()
14+
{
15+
var e = Assert.Throws<DslException>(() => this._client.CreateIndex(c => c
16+
.Index("Hello")
17+
));
18+
e.Message.Should().Contain("contains uppercase characters");
19+
}
20+
21+
[Test]
22+
public void SanityCheckCharacters()
23+
{
24+
var e = Assert.Throws<DslException>(() => this._client.CreateIndex(c => c
25+
.Index("rel>lo")
26+
));
27+
e.Message.Should().Contain("contains one of");
28+
}
29+
30+
[Test]
31+
public void IndexNameMayNotStartWithUnderscore()
32+
{
33+
var e = Assert.Throws<DslException>(() => this._client.CreateIndex(c => c
34+
.Index("_hello")
35+
));
36+
e.Message.Should().Contain("may not start with an underscore");
37+
}
38+
39+
[Test]
40+
public void MaxLengthCheck()
41+
{
42+
var indexName = new String('a', 300);
43+
44+
var e = Assert.Throws<DslException>(() => this._client.CreateIndex(c => c
45+
.Index(indexName)
46+
));
47+
e.Message.Should().Contain(indexName);
48+
e.Message.Should().Contain("exceeds maximum");
49+
}
50+
51+
[Test]
52+
public void ValidIndexNameShouldNotThrow()
53+
{
54+
Assert.DoesNotThrow(() => this._client.CreateIndex(c => c
55+
.Index("index_name")
56+
));
57+
}
58+
59+
}
60+
}

src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@
236236
<Compile Include="Internals\Inferno\EscapedFormatTests.cs" />
237237
<Compile Include="Internals\Inferno\HostNameWithPathTests.cs" />
238238
<Compile Include="Internals\Inferno\MapTypeNamesTests.cs" />
239+
<Compile Include="Internals\Inferno\IndexNameResolverTests.cs" />
239240
<Compile Include="Internals\Serialize\ConnectionSettingsTests.cs" />
240241
<Compile Include="Internals\Serialize\NullValueHandlingTests.cs" />
241242
<Compile Include="Internals\Serialize\OptOutTests.cs" />

0 commit comments

Comments
 (0)