In my program I have a Google Places API client and to build URL
I use Boost.URL
library:
#include <iostream>
#include <boost/url/src.hpp>
#include <boost/url/encode.hpp>
#include <boost/json/src.hpp>
...
boost::urls::url endpoint("https://maps.googleapis.com/maps/api/place/autocomplete/json");
auto params = endpoint.params();
params.append({"key", "PLACE_API_KEY" });
params.append({"input", "Tower" });
params.append({"radius", "500" });
auto location = std::make_pair(51.507351, -0.127758);
std::string locationString = std::to_string(location.first) + "," + std::to_string(location.secod);
params.append({"location", locationString});
std::cout << endpoint.encoded_target().substr() << '\n';
Unfortunately due to the URL RFC specification, it doesn't encode ,
(comma) symbol because it's reserved
So the code above print:
/maps/api/place/autocomplete/json?key=PLACE_API_KEY&input=Tower&radius=500&location=51.507351,-0.127758
If I replace ,
with %2C
in locationString
variable, the output will be:
/maps/api/place/autocomplete/json?key=PLACE_API_KEY&input=Tower&radius=500&location=51.507351%252C-0.127758
because %
was encoded to %25
Is there a way to percent-encode ,
in a query param value with Boost.URL
API?
As you correctly analyse, the RFC requires the comma to be preserved as-given.
It follows that you can give it as "%2C".
I figured out by reversing the path:
urls::url ep("https://maps.googleapis.com/maps/api/place/autocomplete/"
"json?key=PLACE_API_KEY&input=Tower&radius=500&location=51.507351%2C-0.127758");
for (auto [k, v, h] : ep.params())
std::cout << k << " -> " << v << " (" << std::boolalpha << h << ")" << std::endl;
for (auto [k, v, h] : ep.encoded_params())
std::cout << k << " -> " << v << " (" << std::boolalpha << h << ")" << std::endl;
Which prints
key -> PLACE_API_KEY (true)
input -> Tower (true)
radius -> 500 (true)
location -> 51.507351,-0.127758 (true)
key -> PLACE_API_KEY (true)
input -> Tower (true)
radius -> 500 (true)
location -> 51.507351%2C-0.127758 (true)
It follows, that appending to encoded_params
should work:
urls::param_pct_view p("location", "51.507351%2C-0.127758");
endpoint.encoded_params().append(p);
And indeed it does:
#include <iostream>
#include <boost/url/src.hpp>
#include <boost/url/encode.hpp>
namespace urls = boost::urls;
int main() {
urls::url endpoint("https://maps.googleapis.com/maps/api/place/autocomplete/json");
auto params = endpoint.params();
params.append({"key", "PLACE_API_KEY"});
params.append({"input", "Tower" });
params.append({"radius", "500" });
urls::param_pct_view p("location", "51.507351%2C-0.127758");
endpoint.encoded_params().append(p);
std::cout << endpoint << std::endl;
}
Prints
https://maps.googleapis.com/maps/api/place/autocomplete/json?key=PLACE_API_KEY&input=Tower&radius=500&location=51.507351%2C-0.127758