如何在 URI 中转义大括号

Posted

技术标签:

【中文标题】如何在 URI 中转义大括号【英文标题】:How to escape curly braces in URI 【发布时间】:2022-01-10 11:51:28 【问题描述】:

我正在尝试使用花括号来使用 REST API,但我不知道如何通过 HttpClient.GetFromJsonAsync 将它们发送到非转义状态。

string readKey = "1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd";
string endpoint = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=readKey";
string queryOperator = "&query=";
string query = "%7Btype%3A%22posts%22%7D";
//Working URI (in browser and Postman) : https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd&query=%7B%22type%22%3A%22posts%22%7D

我尝试了不同的方法:

string uriA = endpoint + queryOperator + query;
string uriB = endpoint + queryOperator + Uri.UnescapedDataString(query);
Uri uriC = new Uri(endpoint + queryOperator + query);
Uri uriD = new Uri(endpoint + queryOperator + Uri.UnescapedDataString(query);
Uri uriE = new Uri(Uri.UnescapedDataString(endpoint + queryOperator + query);
...

无论我用 HttpClient 尝试什么方法:

CosmicResponse cosmicReponse = await _http.GetFromJsonAsync<CosmicResponse>(uri);

我总是得到相同的结果:

System.Net.Http.HttpRequestException: TypeError: 获取失败

HttpClient 发送的 URI 总是:

https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=xxxx&query=%22type%22%3A%22posts%22

当然,我不工作。

在发送没有查询部分的请求时有效:

string uri = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=xxxx";
CosmicResponse cosmicReponse = await _http.GetFromJsonAsync<CosmicResponse>(uri);

但是,我需要使用查询部分。

我知道在 API 中使用花括号是不好的做法,但我没有编写 API,我只是想使用它。

有人会碰巧知道如何使用 HttpClient 发送“%7B”和“%7D”而不是“”和“”吗?

完整代码

public async Task<List<Post>> GetAllPosts()

    HttpClient http = new();
    string _rootUrl = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog";
    string _readKey = "1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd";
    string endpoint = $"_rootUrl/objects?read_key=_readKey";
    string query = "%7Btype%3A%22posts%22%7D";
    Uri uri = new Uri(Uri.UnescapeDataString(endpoint + "&query=" + query));
    CosmicResponse cosmicReponse = await http.GetFromJsonAsync<CosmicResponse>(uri);
    List<Post> posts = new();
    foreach (CosmicPost c in cosmicReponse.Objects)
    
        posts.Add(GetPostFromCosmic(c));
    
    return posts;

结束语

事实证明这是一个 CORS 问题。由于 Postman 不执行 CORS 策略,我错误地认为问题与 HttpClient 相关。我通过代理解决了这个问题。

【问题讨论】:

这能回答你的问题吗? HttpClient problem with URLs which include curly braces 感谢@Luuk,我已经尝试用 %7B 和 %7D 替换花括号。但是 HttpClient 似乎仍然坚持发送 和 。 你能添加完整的代码来获得Type error failed to fetch吗?通过我的测试,我得到了StatusCode: 401, ReasonPhrase: 'Unauthorized',.... 我添加了真正的 readKey 以便于测试。您可能会因为使用我的虚拟 readKey (xxxx) 而不是好的那个而得到 401。 您想转义,而不是转义。您应该编辑标题。 【参考方案1】:

最好让图书馆为您完成工作。使用HttpUtility.ParseQueryString 返回的NameValueCollection(请注意,它们返回不同的派生类型HttpValueCollection,您无法自行初始化)。 See more here.

由于你没有给出类定义,所以我将类型切换为object,这样测试代码就可以运行了:

static async Task<object> GetAllPosts()

    HttpClient http = new();
    string _rootUrl = "https://api.cosmicjs.com/v2/buckets/ffm-blog-blog";
    string _readKey = "1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd";

    var query = HttpUtility.ParseQueryString("");
    query.Add("read_key", _readKey);
    query.Add("query", "\"type\":\"posts\"");

    string endpoint = $"_rootUrl/objects?" + query.ToString();
    return (await http.GetFromJsonAsync<object>(endpoint))!;    

【讨论】:

感谢您建议使用 NameValueCollection,它使我的代码更加简洁。 URI 与预期一样干净(其中没有 或 )。遗憾的是它仍然无法工作,并且在通过 httpClient 之后,URI 仍然有未编码的花括号。似乎 httpclient 重新编码了 URI(但只有大括号)。 我测试了上面的代码,它对我有用。确定是同一个问题吗? 非常感谢。原来这是与 API V2 相关的 CORS 问题。邮递员或控制台应用程序不强制执行 CORS,并且与您的代码(甚至我的代码)一起工作得很好。 Httpclient 不应该受到责备......

以上是关于如何在 URI 中转义大括号的主要内容,如果未能解决你的问题,请参考以下文章

string.format格式化字符串中转义大括号“{}”

在 bash 脚本中转义引号和大括号的问题

<![CDATA[ ... ]]> 在 TYPO3 v8 Fluid 中不起作用

如何在 LIKE 子句中转义方括号?

在需要搜索和替换的代码中转义括号(Sublime Text2)

T-SQL - 如何在LIKE子句中转义斜杠/方括号