diff --git a/src/Search/Microsoft.Azure.Search/Customizations/SearchIndexClient.Customization.cs b/src/Search/Microsoft.Azure.Search/Customizations/SearchIndexClient.Customization.cs index 72a709440e68..d3e2f90314fa 100644 --- a/src/Search/Microsoft.Azure.Search/Customizations/SearchIndexClient.Customization.cs +++ b/src/Search/Microsoft.Azure.Search/Customizations/SearchIndexClient.Customization.cs @@ -100,8 +100,30 @@ public SearchCredentials SearchCredentials private static Uri BuildBaseUriForIndex(string searchServiceName, string indexName) { - return TypeConversion.TryParseUri( + if (searchServiceName.Length == 0) + { + throw new ArgumentException( + "Invalid search service name. Name cannot be an empty string.", + "searchServiceName"); + } + + if (indexName.Length == 0) + { + throw new ArgumentException("Invalid index name. Name cannot be an empty string.", "indexName"); + } + + Uri uri = TypeConversion.TryParseUri( "https://" + searchServiceName + ".search.windows.net/indexes/" + indexName + "/"); + + if (uri == null) + { + // Parsing will still succeed for index names with weird characters. + throw new ArgumentException( + "Invalid search service name. Name contains characters that are not valid in a URL.", + "searchServiceName"); + } + + return uri; } } } diff --git a/src/Search/Microsoft.Azure.Search/Customizations/SearchServiceClient.Customization.cs b/src/Search/Microsoft.Azure.Search/Customizations/SearchServiceClient.Customization.cs index 0bdd3f9b84ae..226387e0ffd5 100644 --- a/src/Search/Microsoft.Azure.Search/Customizations/SearchServiceClient.Customization.cs +++ b/src/Search/Microsoft.Azure.Search/Customizations/SearchServiceClient.Customization.cs @@ -83,7 +83,23 @@ public SearchCredentials SearchCredentials private static Uri BuildBaseUriForService(string searchServiceName) { - return TypeConversion.TryParseUri("https://" + searchServiceName + ".search.windows.net/"); + if (searchServiceName.Length == 0) + { + throw new ArgumentException( + "Invalid search service name. Name cannot be an empty string.", + "searchServiceName"); + } + + Uri uri = TypeConversion.TryParseUri("https://" + searchServiceName + ".search.windows.net/"); + + if (uri == null) + { + throw new ArgumentException( + "Invalid search service name. Name contains characters that are not valid in a URL.", + "searchServiceName"); + } + + return uri; } } } diff --git a/src/Search/Search.Tests/Tests/SearchIndexClientTests.cs b/src/Search/Search.Tests/Tests/SearchIndexClientTests.cs index 7bfa36d202bc..2a940d028403 100644 --- a/src/Search/Search.Tests/Tests/SearchIndexClientTests.cs +++ b/src/Search/Search.Tests/Tests/SearchIndexClientTests.cs @@ -5,8 +5,8 @@ namespace Microsoft.Azure.Search.Tests { using System; - using System.Globalization; using System.Net; + using System.Net.Http; using Microsoft.Azure.Search.Models; using Microsoft.Azure.Search.Tests.Utilities; using Microsoft.Rest.Azure; @@ -31,5 +31,71 @@ public void RequestIdIsReturnedInResponse() Assert.Equal(options.RequestId.Value.ToString("D"), countResponse.RequestId); }); } + + [Fact] + public void ConstructorThrowsForBadParameters() + { + var creds = new SearchCredentials("abc"); + var searchServiceName = "abc"; + var indexName = "xyz"; + var handler = new HttpClientHandler(); + var uri = new Uri("http://tempuri.org"); + var invalidName = ")#%&/?''+&@)#*@%#"; + + Assert.Throws("credentials", () => new SearchIndexClient(credentials: null)); + Assert.Throws( + "searchServiceName", + () => new SearchIndexClient(searchServiceName: null, indexName: indexName, credentials: creds)); + Assert.Throws( + "searchServiceName", + () => new SearchIndexClient(searchServiceName: String.Empty, indexName: indexName, credentials: creds)); + Assert.Throws( + "searchServiceName", + () => new SearchIndexClient(searchServiceName: invalidName, indexName: indexName, credentials: creds)); + Assert.Throws( + "indexName", + () => new SearchIndexClient(searchServiceName, indexName: null, credentials: creds)); + Assert.Throws( + "indexName", + () => new SearchIndexClient(searchServiceName, indexName: String.Empty, credentials: creds)); + Assert.Throws( + "credentials", + () => new SearchIndexClient(searchServiceName, indexName, credentials: null)); + Assert.Throws( + "credentials", + () => new SearchIndexClient(credentials: null, rootHandler: handler)); + Assert.Throws(() => new SearchIndexClient(credentials: creds, rootHandler: null)); + Assert.Throws( + "baseUri", + () => new SearchIndexClient(baseUri: null, credentials: creds)); + Assert.Throws("credentials", () => new SearchIndexClient(uri, credentials: null)); + Assert.Throws( + "searchServiceName", + () => new SearchIndexClient(searchServiceName: null, indexName: indexName, credentials: creds, rootHandler: handler)); + Assert.Throws( + "searchServiceName", + () => new SearchIndexClient(searchServiceName: String.Empty, indexName: indexName, credentials: creds, rootHandler: handler)); + Assert.Throws( + "searchServiceName", + () => new SearchIndexClient(searchServiceName: invalidName, indexName: indexName, credentials: creds, rootHandler: handler)); + Assert.Throws( + "indexName", + () => new SearchIndexClient(searchServiceName, indexName: null, credentials: creds, rootHandler: handler)); + Assert.Throws( + "indexName", + () => new SearchIndexClient(searchServiceName, indexName: String.Empty, credentials: creds, rootHandler: handler)); + Assert.Throws( + "credentials", + () => new SearchIndexClient(searchServiceName, indexName, credentials: null, rootHandler: handler)); + Assert.Throws( + () => new SearchIndexClient(searchServiceName, indexName, creds, rootHandler: null)); + Assert.Throws( + "baseUri", + () => new SearchIndexClient(baseUri: null, credentials: creds, rootHandler: handler)); + Assert.Throws( + "credentials", + () => new SearchIndexClient(uri, credentials: null, rootHandler: handler)); + Assert.Throws(() => new SearchIndexClient(uri, creds, rootHandler: null)); + } } } diff --git a/src/Search/Search.Tests/Tests/SearchServiceClientTests.cs b/src/Search/Search.Tests/Tests/SearchServiceClientTests.cs index 64282f75af30..1e7dfaad6db3 100644 --- a/src/Search/Search.Tests/Tests/SearchServiceClientTests.cs +++ b/src/Search/Search.Tests/Tests/SearchServiceClientTests.cs @@ -5,8 +5,8 @@ namespace Microsoft.Azure.Search.Tests { using System; - using System.Globalization; using System.Net; + using System.Net.Http; using Microsoft.Azure.Search.Models; using Microsoft.Azure.Search.Tests.Utilities; using Microsoft.Rest.Azure; @@ -57,5 +57,58 @@ public void CanGetAnIndexClientAfterUsingServiceClient() serviceClient.Indexes.GetClient("test"); }); } + + [Fact] + public void ConstructorThrowsForBadParameters() + { + var creds = new SearchCredentials("abc"); + var searchServiceName = "abc"; + var handler = new HttpClientHandler(); + var uri = new Uri("http://tempuri.org"); + var invalidName = ")#%&/?''+&@)#*@%#"; + + Assert.Throws("credentials", () => new SearchServiceClient(credentials: null)); + Assert.Throws( + "searchServiceName", + () => new SearchServiceClient(searchServiceName: null, credentials: creds)); + Assert.Throws( + "searchServiceName", + () => new SearchServiceClient(searchServiceName: String.Empty, credentials: creds)); + Assert.Throws( + "searchServiceName", + () => new SearchServiceClient(searchServiceName: invalidName, credentials: creds)); + Assert.Throws( + "credentials", + () => new SearchServiceClient(searchServiceName, credentials: null)); + Assert.Throws( + "credentials", + () => new SearchServiceClient(credentials: null, rootHandler: handler)); + Assert.Throws(() => new SearchServiceClient(credentials: creds, rootHandler: null)); + Assert.Throws( + "baseUri", + () => new SearchServiceClient(baseUri: null, credentials: creds)); + Assert.Throws("credentials", () => new SearchServiceClient(uri, credentials: null)); + Assert.Throws( + "searchServiceName", + () => new SearchServiceClient(searchServiceName: null, credentials: creds, rootHandler: handler)); + Assert.Throws( + "searchServiceName", + () => new SearchServiceClient(searchServiceName: String.Empty, credentials: creds, rootHandler: handler)); + Assert.Throws( + "searchServiceName", + () => new SearchServiceClient(searchServiceName: invalidName, credentials: creds, rootHandler: handler)); + Assert.Throws( + "credentials", + () => new SearchServiceClient(searchServiceName, credentials: null, rootHandler: handler)); + Assert.Throws( + () => new SearchServiceClient(searchServiceName, creds, rootHandler: null)); + Assert.Throws( + "baseUri", + () => new SearchServiceClient(baseUri: null, credentials: creds, rootHandler: handler)); + Assert.Throws( + "credentials", + () => new SearchServiceClient(uri, credentials: null, rootHandler: handler)); + Assert.Throws(() => new SearchServiceClient(uri, creds, rootHandler: null)); + } } }