//------------------------------------------------------------------------------ // // This code was generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. // // Changes to this file may cause incorrect behavior and will be lost when // the code is regenerated. // //------------------------------------------------------------------------------ #nullable enable namespace LukeHagar.PlexAPI.SDK.Utils { using System; using System.Collections; using System.Collections.Generic; using System.Net; using System.Reflection; internal static class URLBuilder { public static string Build(string baseUrl, string relativeUrl, object? request) { var url = baseUrl; if (url.EndsWith("/")) { url = url.Substring(0, url.Length - 1); } var pathAndFragment = relativeUrl.Split('#'); if (pathAndFragment.Length > 2) { throw new ArgumentException($"Malformed URL: {relativeUrl}"); } url += pathAndFragment[0]; var parameters = GetPathParameters(request); url = ReplaceParameters(url, parameters); var queryParams = SerializeQueryParams(TrySerializeQueryParams(request)); if (queryParams != "") { url += $"?{queryParams}"; } if (pathAndFragment.Length == 2) { url += $"#{pathAndFragment[1]}"; } return url; } public static string ReplaceParameters(string url, Dictionary parameters) { foreach (var key in parameters.Keys) { url = url.Replace($"{{{key}}}", Uri.EscapeDataString(parameters[key])); } return url; } public static string SerializeQueryParams(Dictionary> queryParams) { var queries = new List(); foreach (var key in queryParams.Keys) { foreach (var value in queryParams[key]) { queries.Add($"{key}={WebUtility.UrlEncode(Utilities.ToString(value))}"); } } return string.Join("&", queries); } private static Dictionary GetPathParameters(object? request) { var parameters = new Dictionary(); if (request == null) { return parameters; } var props = request.GetType().GetProperties(); foreach (var prop in props) { var val = prop.GetValue(request); if (val == null) { continue; } if (prop.GetCustomAttribute()?.GetRequestMetadata() != null) { continue; } var metadata = prop.GetCustomAttribute()?.GetPathParamMetadata(); if (metadata == null) { continue; } if (metadata.Serialization != null) { switch (metadata.Serialization) { case "json": parameters.Add( metadata.Name ?? prop.Name, Utilities.SerializeJSON(val) ); break; default: throw new Exception( $"Unknown serialization type: {metadata.Serialization}" ); } } else { switch (metadata.Style) { case "simple": var simpleParams = SerializeSimplePathParams( metadata.Name ?? prop.Name, val, metadata.Explode ); foreach (var key in simpleParams.Keys) { parameters.Add(key, simpleParams[key]); } break; default: throw new Exception($"Unsupported path param style: {metadata.Style}"); } } } return parameters; } private static Dictionary> TrySerializeQueryParams(object? request) { var parameters = new Dictionary>(); if (request == null) { return parameters; } var props = request.GetType().GetProperties(); foreach (var prop in props) { var val = prop.GetValue(request); if (val == null) { continue; } if (prop.GetCustomAttribute()?.GetRequestMetadata() != null) { continue; } var metadata = prop.GetCustomAttribute()?.GetQueryParamMetadata(); if (metadata == null) { continue; } if (metadata.Serialization != null) { switch (metadata.Serialization) { case "json": if (!parameters.ContainsKey(metadata.Name ?? prop.Name)) { parameters.Add(metadata.Name ?? prop.Name, new List()); } parameters[metadata.Name ?? prop.Name].Add( Utilities.SerializeJSON(val) ); break; default: throw new Exception( $"Unknown serialization type: {metadata.Serialization}" ); } } else { switch (metadata.Style) { case "form": var formParams = SerializeFormQueryParams( metadata.Name ?? prop.Name, val, metadata.Explode, "," ); foreach (var key in formParams.Keys) { if (!parameters.ContainsKey(key)) { parameters.Add(key, new List()); } foreach (var v in formParams[key]) { parameters[key].Add(v); } } break; case "deepObject": var deepObjParams = SerializeDeepObjectQueryParams( metadata.Name ?? prop.Name, val ); foreach (var key in deepObjParams.Keys) { if (!parameters.ContainsKey(key)) { parameters.Add(key, new List()); } foreach (var v in deepObjParams[key]) { parameters[key].Add(v); } } break; case "pipeDelimited": var pipeParams = SerializeFormQueryParams( metadata.Name ?? prop.Name, val, metadata.Explode, "|" ); foreach (var key in pipeParams.Keys) { if (!parameters.ContainsKey(key)) { parameters.Add(key, new List()); } foreach (var v in pipeParams[key]) { parameters[key].Add(v); } } break; default: throw new Exception($"Unsupported query param style: {metadata.Style}"); } } } return parameters; } private static Dictionary SerializeSimplePathParams( string parentName, object value, bool explode ) { var parameters = new Dictionary(); if (Utilities.IsClass(value)) { var vals = new List(); var props = value.GetType().GetProperties(); foreach (var prop in props) { var val = prop.GetValue(value); if (val == null) { continue; } var metadata = prop.GetCustomAttribute()?.GetPathParamMetadata(); if (metadata == null) { continue; } if (explode) { vals.Add($"{metadata.Name}={Utilities.ToString(val)}"); } else { vals.Add($"{metadata.Name},{Utilities.ToString(val)}"); } } parameters.Add(parentName, string.Join(",", vals)); } else if (Utilities.IsDictionary(value)) { var vals = new List(); foreach (var key in ((IDictionary)value).Keys) { if (key == null) { continue; } var val = ((IDictionary)value)[key]; if (explode) { vals.Add($"{key}={Utilities.ToString(val)}"); } else { vals.Add($"{key},{Utilities.ToString(val)}"); } } parameters.Add(parentName, string.Join(",", vals)); } else if (Utilities.IsList(value)) { var vals = new List(); foreach (var val in (IEnumerable)value) { vals.Add(Utilities.ToString(val)); } parameters.Add(parentName, string.Join(",", vals)); } else { parameters.Add(parentName, Utilities.ToString(value)); } return parameters; } private static Dictionary> SerializeFormQueryParams( string parentName, object value, bool explode, string delimiter ) { var parameters = new Dictionary>(); if (Utilities.IsClass(value) && !Utilities.IsDate(value)) { var props = value.GetType().GetProperties(); var items = new List(); foreach (var prop in props) { var val = prop.GetValue(value); if (val == null) { continue; } var metadata = prop.GetCustomAttribute()?.GetQueryParamMetadata(); if (metadata == null || metadata.Name == null) { continue; } if (explode) { if (!parameters.ContainsKey(metadata.Name)) { parameters.Add(metadata.Name, new List()); } parameters[metadata.Name].Add( Utilities.ToString(val) ); } else { items.Add( $"{metadata.Name}{delimiter}{Utilities.ValueToString(val)}" ); } } if (items.Count > 0) { if (!parameters.ContainsKey(parentName)) { parameters.Add(parentName, new List()); } parameters[parentName].Add(string.Join(delimiter, items)); } } else if (Utilities.IsDictionary(value)) { var items = new List(); foreach (var k in ((IDictionary)value).Keys) { var key = k?.ToString(); if (key == null) { continue; } if (explode) { if (!parameters.ContainsKey(key)) { parameters.Add(key, new List()); } parameters[key].Add( Utilities.ValueToString(((IDictionary)value)[key]) ); } else { items.Add( $"{key}{delimiter}{Utilities.ValueToString(((IDictionary)value)[key])}" ); } } if (items.Count > 0) { if (!parameters.ContainsKey(parentName)) { parameters.Add(parentName, new List()); } parameters[parentName].Add(string.Join(delimiter, items)); } } else if (Utilities.IsList(value)) { var values = new List(); var items = new List(); foreach (var item in (IList)value) { if (explode) { values.Add(Utilities.ValueToString(item)); } else { items.Add(Utilities.ValueToString(item)); } } if (items.Count > 0) { values.Add(string.Join(delimiter, items)); } foreach (var val in values) { if (!parameters.ContainsKey(parentName)) { parameters.Add(parentName, new List()); } parameters[parentName].Add(val); } } else { if (!parameters.ContainsKey(parentName)) { parameters.Add(parentName, new List()); } parameters[parentName].Add(Utilities.ValueToString(value)); } return parameters; } private static Dictionary> SerializeDeepObjectQueryParams( string parentName, object value ) { var parameters = new Dictionary>(); if (Utilities.IsClass(value)) { var props = value.GetType().GetProperties(); foreach (var prop in props) { var val = prop.GetValue(value); if (val == null) { continue; } var metadata = prop.GetCustomAttribute()?.GetQueryParamMetadata(); if (metadata == null || metadata.Name == null) { continue; } var keyName = $"{parentName}[{metadata.Name}]"; if (val != null && Utilities.IsList(val)) { foreach (var v in (IList)val) { if (!parameters.ContainsKey(keyName)) { parameters.Add(keyName, new List()); } parameters[keyName].Add( Utilities.ValueToString(v) ); } } else { if (!parameters.ContainsKey(keyName)) { parameters.Add(keyName, new List()); } parameters[keyName].Add(Utilities.ValueToString(val)); } } } else if (Utilities.IsDictionary(value)) { foreach (var key in ((IDictionary)value).Keys) { if (key == null) { continue; } var val = ((IDictionary)value)[key]; var keyName = $"{parentName}[{key}]"; if (val != null && Utilities.IsList(val)) { foreach (var v in (IList)val) { if (!parameters.ContainsKey(keyName)) { parameters.Add(keyName, new List()); } parameters[keyName].Add( Utilities.ValueToString(v) ); } } else { if (!parameters.ContainsKey(keyName)) { parameters.Add(keyName, new List()); } parameters[keyName].Add(Utilities.ValueToString(val)); } } } return parameters; } } }