//----------------------------------------------------------------------------- // // Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). // You may not use this file except in compliance with the License. // A copy of the License is located at // // http://aws.amazon.com/apache2.0 // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. // //----------------------------------------------------------------------------- using System; using System.Text.RegularExpressions; using Amazon.Runtime.Internal.Util; using Amazon.XRay.Recorder.Core.Internal.Utils; #if NETFRAMEWORK using System.Net.Http; #else using Microsoft.AspNetCore.Http; #endif namespace Amazon.XRay.Recorder.Core.Strategies { /// /// Try to match the Host field from HTTP header first, if not match then use the fallback name as segment name. /// /// [CLSCompliant(false)] public class DynamicSegmentNamingStrategy : SegmentNamingStrategy { private static readonly Logger _logger = Logger.GetLogger(typeof(DynamicSegmentNamingStrategy)); /// /// Initializes a new instance of the class. /// /// Name of the fallback segment. /// The host name pattern. /// /// fallbackSegmentName cannot be null or empty. - fallbackSegmentName /// or /// hostNamePattern cannot be null or empty. - hostNamePattern /// public DynamicSegmentNamingStrategy(string fallbackSegmentName, string hostNamePattern = "*") { if (string.IsNullOrEmpty(fallbackSegmentName)) { throw new ArgumentException("fallbackSegmentName cannot be null or empty.", nameof(fallbackSegmentName)); } if (string.IsNullOrEmpty(hostNamePattern)) { throw new ArgumentException("hostNamePattern cannot be null or empty.", nameof(hostNamePattern)); } this.FallbackSegmentName = fallbackSegmentName; string overrideName = GetSegmentNameFromEnvironmentVariable(); if (!string.IsNullOrEmpty(overrideName)) { _logger.DebugFormat("{0} is set, overriding segment name to: {1}.", SegmentNamingStrategy.EnvironmentVariableSegmentName, overrideName); this.FallbackSegmentName = overrideName; } this.HostNamePattern = hostNamePattern; } /// /// Gets or sets the host name pattern regex. /// public string HostNamePattern { get; set; } /// /// Gets or sets the name of the fallback segment. /// public string FallbackSegmentName { get; set; } #if NETFRAMEWORK /// /// Gets the name of the segment. /// /// The request. /// /// The segment name. /// public override string GetSegmentName(HttpRequestMessage httpRequest) { string hostField = httpRequest.Headers.Host; return ValidateHostField(hostField); } /// /// Gets the name of the segment. /// /// The HTTP request. /// /// The segment name. /// public override string GetSegmentName(System.Web.HttpRequest httpRequest) { string hostField = httpRequest.Headers.Get("Host"); return ValidateHostField(hostField); } private string ValidateHostField(string hostField) { try { if (hostField != null && hostField.WildcardMatch(HostNamePattern)) { return hostField; } } catch (RegexMatchTimeoutException e) { _logger.Debug(e, "Timed out when matching host name to get segment name. Host: {0}", hostField); } return FallbackSegmentName; } #else /// /// Gets the name of the segment. /// /// The HTTP request. /// /// The segment name. /// [CLSCompliant(false)] public override string GetSegmentName(HttpRequest httpRequest) { string hostField = httpRequest.Host.Host; try { if (hostField != null && hostField.WildcardMatch(HostNamePattern)) { return hostField; } } catch (RegexMatchTimeoutException e) { _logger.Debug(e, "Timed out when matching host name to get segment name. Host: {0}", hostField); } return FallbackSegmentName; } #endif } }