Hello! I am writing a client that talks to HTTPS APIs. The configuration can add sources from which to pull data, and I want it to be as flexible as possible. So I have a "Source" class that is the API source config. It has vars like:
RootUrl - the base of the API's URL, e.g. "https://www.service.com/api.php";
QueryPosts - the construction of the post query URL, e.g. "%RootUrl%%Query%%Page%%PostResultLimit%"
ComponentQuery - the query component, e.g. "tag=%value%"
ComponentPage - the page number component, e.g. "pid=%value%"
ComponentPostResultLimit - the post result limit component, e.g. "limit=%value%"
I was doing:
It worked great until I realized if the QueryPosts had the order of components different than what my replace was doing, it breaks the decision of whether or not to use ? or & when adding vars to the querystring. So like if I had QueryPosts = "%RootUrl%%Page%%Query%%PostResultLimit%" and I passed in page 0, query of hi and limit of 50 the resultant URL would be:
I realized then I need to process the tag replacement in the order they appear in the QueryPosts string. This is where I hit my conundrum. I'm sure there must be some easy way to do that, but I can't think of it. This was my solution:
This works, but seems like a real kludge lol. Is there a more efficient way?
RootUrl - the base of the API's URL, e.g. "https://www.service.com/api.php";
QueryPosts - the construction of the post query URL, e.g. "%RootUrl%%Query%%Page%%PostResultLimit%"
ComponentQuery - the query component, e.g. "tag=%value%"
ComponentPage - the page number component, e.g. "pid=%value%"
ComponentPostResultLimit - the post result limit component, e.g. "limit=%value%"
I was doing:
C#:
public string GetQueryString(string query, string page = "0", string limit = "") {
if (RootUrl.Trim() == "") return "";
string ret = QueryPosts.Replace("%RootUrl%", RootUrl);
ret = ret.Replace("%Query%", ComponentQuery.Trim() == "" ? "" : ((ret.IndexOf("?") == -1 ? "?" : "&") + ComponentQuery.Replace("%value%", query)));
ret = ret.Replace("%Page%", ComponentPage.Trim() == "" ? "" : (page.Trim() == "" ? "" : (ret.IndexOf("?") == -1 ? "?" : "&") + ComponentPage.Replace("%value%", page)));
ret = ret.Replace("%PostResultLimit%", ComponentPostResultLimit.Trim() == "" ? "" : (limit.Trim() == "" ? "" : (ret.IndexOf("?") == -1 ? "?" : "&") + ComponentPostResultLimit.Replace("%value%", limit)));
return ret;
}
C#:
https://www.service.com/api.php&pid=0?tag=hi&limit=50
C#:
public string GetQueryString(string query, string page = "0", string limit = "") {
if (RootUrl.Trim() == "") return "";
SortedDictionary<int, string> keyorder = new SortedDictionary<int, string>();
foreach (string var in new string[] { "query", "page", "postresultlimit" }) {
if (QueryPosts.ToLower().IndexOf("%" + var + "%") == -1) continue;
keyorder.Add(QueryPosts.ToLower().IndexOf("%" + var + "%"), var);
}
string ret = QueryPosts.Replace("%RootUrl%", RootUrl);
foreach (KeyValuePair<int, string> keys in keyorder) {
switch (keys.Value) {
case "query":
ret = ret.Replace("%Query%", ComponentQuery.Trim() == "" ? "" : ((ret.IndexOf("?") == -1 ? "?" : "&") + ComponentQuery.Replace("%value%", query)));
break;
case "page":
ret = ret.Replace("%Page%", ComponentPage.Trim() == "" ? "" : (page.Trim() == "" ? "" : (ret.IndexOf("?") == -1 ? "?" : "&") + ComponentPage.Replace("%value%", page)));
break;
case "postresultlimit":
ret = ret.Replace("%PostResultLimit%", ComponentPostResultLimit.Trim() == "" ? "" : (limit.Trim() == "" ? "" : (ret.IndexOf("?") == -1 ? "?" : "&") + ComponentPostResultLimit.Replace("%value%", limit)));
break;
}
}
return ret;
}