/// <summary> /// Initializes a new instance of the <see cref="EventHubConnection"/> class. /// </summary> /// /// <param name="connectionString">The connection string to use for connecting to the Event Hubs namespace; it is expected that the shared key properties are contained in this connection string, but not the Event Hub name.</param> /// <param name="eventHubName">The name of the specific Event Hub to associate the connection with.</param> /// <param name="connectionOptions">A set of options to apply when configuring the connection.</param> /// /// <remarks> /// If the connection string is copied from the Event Hub itself, it will contain the name of the desired Event Hub, /// and can be used directly without passing the <paramref name="eventHubName" />. The name of the Event Hub should be /// passed only once, either as part of the connection string or separately. /// </remarks> /// public EventHubConnection(string connectionString, string eventHubName, EventHubConnectionOptions connectionOptions) { Argument.AssertNotNullOrEmpty(connectionString, nameof(connectionString)); connectionOptions = connectionOptions?.Clone() ?? new EventHubConnectionOptions(); ValidateConnectionOptions(connectionOptions); var connectionStringProperties = EventHubsConnectionStringProperties.Parse(connectionString); connectionStringProperties.Validate(eventHubName, nameof(connectionString)); var fullyQualifiedNamespace = connectionStringProperties.FullyQualifiedNamespace; if (string.IsNullOrEmpty(eventHubName)) { eventHubName = connectionStringProperties.EventHubName; } SharedAccessSignature sharedAccessSignature; if (string.IsNullOrEmpty(connectionStringProperties.SharedAccessSignature)) { sharedAccessSignature = new SharedAccessSignature( BuildConnectionAudience(connectionOptions.TransportType, fullyQualifiedNamespace, eventHubName), connectionStringProperties.SharedAccessKeyName, connectionStringProperties.SharedAccessKey); } else { sharedAccessSignature = new SharedAccessSignature(connectionStringProperties.SharedAccessSignature); } var sharedCredentials = new SharedAccessSignatureCredential(sharedAccessSignature); var tokenCredentials = new EventHubTokenCredential(sharedCredentials, BuildConnectionAudience(connectionOptions.TransportType, fullyQualifiedNamespace, eventHubName)); FullyQualifiedNamespace = fullyQualifiedNamespace; EventHubName = eventHubName; Options = connectionOptions; #pragma warning disable CA2214 // Do not call overridable methods in constructors. This internal method is virtual for testing purposes. InnerClient = CreateTransportClient(fullyQualifiedNamespace, eventHubName, tokenCredentials, connectionOptions); #pragma warning restore CA2214 // Do not call overridable methods in constructors. }
/// <summary> /// Parses the specified Event Hubs connection string into its component properties. /// </summary> /// /// <param name="connectionString">The connection string to parse.</param> /// /// <returns>The component properties parsed from the connection string.</returns> /// /// <exception cref="FormatException">The specified connection string was malformed and could not be parsed.</exception> /// public static EventHubsConnectionStringProperties Parse(string connectionString) { Argument.AssertNotNullOrEmpty(connectionString, nameof(connectionString)); var parsedValues = new EventHubsConnectionStringProperties(); var tokenPositionModifier = (connectionString[0] == TokenValuePairDelimiter) ? 0 : 1; var lastPosition = 0; var currentPosition = 0; int valueStart; string slice; string token; string value; while (currentPosition != -1) { // Slice the string into the next token/value pair. currentPosition = connectionString.IndexOf(TokenValuePairDelimiter, lastPosition + 1); if (currentPosition >= 0) { slice = connectionString.Substring(lastPosition, (currentPosition - lastPosition)); } else { slice = connectionString.Substring(lastPosition); } // Break the token and value apart, if this is a legal pair. valueStart = slice.IndexOf(TokenValueSeparator); if (valueStart >= 0) { token = slice.Substring((1 - tokenPositionModifier), (valueStart - 1 + tokenPositionModifier)); value = slice.Substring(valueStart + 1); // Guard against leading and trailing spaces, only trimming if there is a need. if ((!string.IsNullOrEmpty(token)) && (char.IsWhiteSpace(token[0])) || char.IsWhiteSpace(token[token.Length - 1])) { token = token.Trim(); } if ((!string.IsNullOrEmpty(value)) && (char.IsWhiteSpace(value[0]) || char.IsWhiteSpace(value[value.Length - 1]))) { value = value.Trim(); } // If there was no value for a key, then consider the connection string to // be malformed. if (string.IsNullOrEmpty(value)) { throw new FormatException(Resources.InvalidConnectionString); } // Compare the token against the known connection string properties and capture the // pair if they are a known attribute. if (string.Compare(EndpointToken, token, StringComparison.OrdinalIgnoreCase) == 0) { var endpointBuilder = new UriBuilder(value) { Scheme = EventHubsEndpointScheme, Port = -1 }; if ((string.Compare(endpointBuilder.Scheme, EventHubsEndpointSchemeName, StringComparison.OrdinalIgnoreCase) != 0) || (Uri.CheckHostName(endpointBuilder.Host) == UriHostNameType.Unknown)) { throw new FormatException(Resources.InvalidConnectionString); } parsedValues.Endpoint = endpointBuilder.Uri; } else if (string.Compare(EventHubNameToken, token, StringComparison.OrdinalIgnoreCase) == 0) { parsedValues.EventHubName = value; } else if (string.Compare(SharedAccessKeyNameToken, token, StringComparison.OrdinalIgnoreCase) == 0) { parsedValues.SharedAccessKeyName = value; } else if (string.Compare(SharedAccessKeyValueToken, token, StringComparison.OrdinalIgnoreCase) == 0) { parsedValues.SharedAccessKey = value; } else if (string.Compare(SharedAccessSignatureToken, token, StringComparison.OrdinalIgnoreCase) == 0) { parsedValues.SharedAccessSignature = value; } } else if ((slice.Length != 1) || (slice[0] != TokenValuePairDelimiter)) { // This wasn't a legal pair and it is not simply a trailing delimiter; consider // the connection string to be malformed. throw new FormatException(Resources.InvalidConnectionString); } tokenPositionModifier = 0; lastPosition = currentPosition; } return(parsedValues); }