Home > OS >  How to escape curly braces in URI
How to escape curly braces in URI

Time:12-05

I'm trying to consume a REST API using curly braces, but I can't figure out how to send them unescaped through 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 = "{type:"posts"}";
//Working URI (in browser and Postman) : https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=1VQXp8053OlOs05XcoWX3L46TEQ4JaPnPtJMwUH6k0xUkgXWMd&query={"type":"posts"}

I tried different approaches:

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);
...

Whatever method I try with HttpClient:

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

I always get the same result:

System.Net.Http.HttpRequestException: TypeError: Failed to fetch

The URI sent by HttpClient always is :

https://api.cosmicjs.com/v2/buckets/ffm-blog-blog/objects?read_key=xxxx&query={"type":"posts"}

and, of course, I doesn't work.

It works when sending a request without the query part:

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

However, I need to use the query part.

I know using curly braces in an API is bad practice, but I didn't write the API and I'm just trying to consume it.

Would someone happen to know how to send "{" and "}" instead of "{" and "}" with HttpClient?

FULL CODE

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 = "{type:"posts"}";
    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;
}

FINAL WORDS

It turns out it was a CORS issue. As Postman doesn't enforce CORS policy, I falsely thought the problem was linked to HttpClient. I solved the problem by going through a proxy.

CodePudding user response:

Better let the library does the work for you. Use NameValueCollection returned by HttpUtility.ParseQueryString (note that they return a different derived type HttpValueCollection which you cannot initialize by yourself). See more here.

Since you didn't give the class definition, I switched the type to object so the test code can run:

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))!;    
}
  • Related