// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Azure.Core;
using Azure.Core.Pipeline;
using Azure.Core.Serialization;
using Microsoft.Extensions.Configuration;
using Typespec = Microsoft.TypeSpec.Generator.Customizations;
#pragma warning disable SA1402 // File may only contain a single type
namespace Azure.Search.Documents
{
///
/// Provides the client configuration options for connecting to Azure
/// Cognitive Search.
///
[Typespec.CodeGenType("DocumentsClientOptions")]
public partial class SearchClientOptions : ClientOptions
{
///
/// The versions of Azure Cognitive Search supported by this client
/// library. For more, see
///
/// API versions in Azure Cognitive Search.
///
public enum ServiceVersion
{
#pragma warning disable CA1707 // Identifiers should not contain underscores
///
/// The 2020-06-30 version of the Azure Cognitive Search service.
///
V2020_06_30 = 1,
///
/// The 2023-11-01 version of the Azure Cognitive Search service.
///
V2023_11_01 = 2,
///
/// The 2024-07-01 version of the Azure Cognitive Search service.
///
V2024_07_01 = 3,
///
/// The 2025-09-01 version of the Azure Cognitive Search service.
///
V2025_09_01 = 4,
///
/// The 2026-04-01 version of the Azure AI Search service.
///
V2026_04_01 = 5,
///
/// The 2026-05-01-preview version of the Azure AI Search service.
///
V2026_05_01_Preview = 6,
#pragma warning restore CA1707
}
///
/// The Latest service version supported by this client library.
///
internal const ServiceVersion LatestVersion = ServiceVersion.V2026_05_01_Preview;
///
/// The service version to use when creating continuation tokens that
/// can be passed between different client libraries. Changing this
/// value requires updating .
///
internal const ServiceVersion ContinuationTokenVersion = ServiceVersion.V2020_06_30;
[Typespec.CodeGenMember("Version")]
internal string RawVersion { get; }
///
/// Gets the of the service API used when
/// making requests. For more, see
///
/// API versions in Azure Cognitive Search.
///
public ServiceVersion Version { get; }
///
/// Gets or sets an that can be used to
/// customize the serialization of strongly typed models. The
/// serializer needs to support JSON and
/// will be used if no value is provided.
///
public ObjectSerializer Serializer { get; set; }
///
/// Gets or sets the Audience to use for authentication with Azure Active Directory (AAD). The audience is not considered when using a shared key.
///
/// If null, will be assumed.
public SearchAudience? Audience { get; set; }
///
/// Initializes a new instance of the
/// class.
///
///
/// An optional to specify the version of
/// the REST API to use. For more, see
///
/// API versions in Azure Cognitive Search.
///
/// If not provided, the will default to the
/// latest supported by this client library. It is recommended that
/// application authors allow the version to float to the latest and
/// library authors pin to a specific version.
///
///
/// Thrown when the is not supported by this
/// client library.
///
public SearchClientOptions(ServiceVersion version = LatestVersion)
{
Version = version.Validate();
AddLoggingHeaders();
AddLoggingQueryParameters();
}
///
/// Initializes a new instance of from configuration.
///
/// The configuration section.
[Experimental("SCME0002")]
internal SearchClientOptions(IConfigurationSection section) : base(section, null)
{
Version = LatestVersion;
if (section is null || !section.Exists())
{
return;
}
if (section["Version"] is string version && TryGetServiceVersion(version, out ServiceVersion serviceVersion))
{
Version = serviceVersion;
}
AddLoggingHeaders();
AddLoggingQueryParameters();
}
///
/// Create an to send requests to the Search
/// Service.
///
///
/// The to authenticate requests.
///
/// An to send requests.
internal HttpPipeline Build(AzureKeyCredential credential)
{
Debug.Assert(credential != null);
return HttpPipelineBuilder.Build(
options: this,
perCallPolicies: new[] { new AzureKeyCredentialPolicy(credential, Constants.ApiKeyHeaderName) },
perRetryPolicies: Array.Empty(),
responseClassifier: null);
}
///
/// Create an to send requests to the Search service.
///
///
/// The to authenticate requests.
///
/// An to send requests.
internal HttpPipeline Build(TokenCredential credential)
{
Debug.Assert(credential != null);
var authorizationScope = $"{(string.IsNullOrEmpty(Audience?.ToString()) ? SearchAudience.AzurePublicCloud : Audience)}/.default";
return HttpPipelineBuilder.Build(
options: this,
perCallPolicies: new[] { new BearerTokenAuthenticationPolicy(credential, authorizationScope) },
perRetryPolicies: Array.Empty(),
responseClassifier: null);
}
///
/// Add the allow list headers to the
/// that are considered safe for logging/exceptions by default.
///
private void AddLoggingHeaders()
{
Diagnostics.LoggedHeaderNames.Add("Access-Control-Allow-Credentials");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Allow-Headers");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Allow-Methods");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Allow-Origin");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Expose-Headers");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Max-Age");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Request-Headers");
Diagnostics.LoggedHeaderNames.Add("Access-Control-Request-Method");
Diagnostics.LoggedHeaderNames.Add("client-request-id");
Diagnostics.LoggedHeaderNames.Add("elapsed-time");
Diagnostics.LoggedHeaderNames.Add("Location");
Diagnostics.LoggedHeaderNames.Add("OData-MaxVersion");
Diagnostics.LoggedHeaderNames.Add("OData-Version");
Diagnostics.LoggedHeaderNames.Add("Origin");
Diagnostics.LoggedHeaderNames.Add("Prefer");
Diagnostics.LoggedHeaderNames.Add("request-id");
Diagnostics.LoggedHeaderNames.Add("return-client-request-id");
Diagnostics.LoggedHeaderNames.Add("throttle-reason");
}
///
/// Add the allow list query parameters to the
/// that are considered safe for
/// logging/exceptions by default.
///
private void AddLoggingQueryParameters()
{
Diagnostics.LoggedQueryParameters.Add("allowIndexDowntime");
}
///
/// Attempts to parse a version string into a value.
///
/// The version string to parse (e.g. "2024-07-01").
/// When this method returns true, the parsed .
/// true if the version string corresponds to a valid API version; otherwise, false.
internal static bool TryGetServiceVersion(string version, out ServiceVersion serviceVersion)
{
serviceVersion = default;
switch (version)
{
case "2020-06-30":
serviceVersion = ServiceVersion.V2020_06_30;
return true;
case "2023-11-01":
serviceVersion = ServiceVersion.V2023_11_01;
return true;
case "2024-07-01":
serviceVersion = ServiceVersion.V2024_07_01;
return true;
case "2025-09-01":
serviceVersion = ServiceVersion.V2025_09_01;
return true;
case "2026-04-01":
serviceVersion = ServiceVersion.V2026_04_01;
return true;
case "2026-05-01-preview":
serviceVersion = ServiceVersion.V2026_05_01_Preview;
return true;
default:
return false;
}
}
}
///
/// Search extension methods.
///
internal static partial class InternalSearchExtensions
{
///
/// Validate a .
///
///
/// The to validate.
///
///
/// The validated version.
///
///
/// Thrown when the is not supported by this
/// client library.
///
public static SearchClientOptions.ServiceVersion Validate(this SearchClientOptions.ServiceVersion version) =>
version switch
{
SearchClientOptions.ServiceVersion.V2020_06_30 => version,
SearchClientOptions.ServiceVersion.V2023_11_01 => version,
SearchClientOptions.ServiceVersion.V2024_07_01 => version,
SearchClientOptions.ServiceVersion.V2025_09_01 => version,
SearchClientOptions.ServiceVersion.V2026_04_01 => version,
SearchClientOptions.ServiceVersion.V2026_05_01_Preview => version,
_ => throw CreateInvalidVersionException(version)
};
///
/// Get a version string, like "2020-06-30", corresponding to a given
/// value.
///
///
/// The value to
/// convert into a version string.
///
///
/// The version string.
///
///
/// Thrown when the is not supported by this
/// client library.
///
public static string ToVersionString(this SearchClientOptions.ServiceVersion version) =>
version switch
{
SearchClientOptions.ServiceVersion.V2020_06_30 => "2020-06-30",
SearchClientOptions.ServiceVersion.V2023_11_01 => "2023-11-01",
SearchClientOptions.ServiceVersion.V2024_07_01 => "2024-07-01",
SearchClientOptions.ServiceVersion.V2025_09_01 => "2025-09-01",
SearchClientOptions.ServiceVersion.V2026_04_01 => "2026-04-01",
SearchClientOptions.ServiceVersion.V2026_05_01_Preview => "2026-05-01-preview",
_ => throw CreateInvalidVersionException(version)
};
///
/// Convert a version string into a .
///
public static SearchClientOptions.ServiceVersion ToServiceVersion(this string version) =>
version switch
{
"2020-06-30" => SearchClientOptions.ServiceVersion.V2020_06_30,
"2023-11-01" => SearchClientOptions.ServiceVersion.V2023_11_01,
"2024-07-01" => SearchClientOptions.ServiceVersion.V2024_07_01,
"2025-09-01" => SearchClientOptions.ServiceVersion.V2025_09_01,
"2026-04-01" => SearchClientOptions.ServiceVersion.V2026_04_01,
"2026-05-01-preview" => SearchClientOptions.ServiceVersion.V2026_05_01_Preview,
_ => throw new ArgumentOutOfRangeException(
nameof(version),
version,
$"The version string specified is not supported by this library.")
};
///
/// Create an to throw when
/// an invalid value
/// is provided.
///
/// The invalid version value.
/// An exception to throw.
private static ArgumentOutOfRangeException CreateInvalidVersionException(SearchClientOptions.ServiceVersion version) =>
new ArgumentOutOfRangeException(
nameof(version),
version,
$"The {nameof(SearchClientOptions)}.{nameof(SearchClientOptions.ServiceVersion)} specified is not supported by this library.");
}
}