gsturi: Add API to order query strings

Add gst_uri_get_query_string_ordered() and gst_uri_to_string_with_keys() that
allow constructing the URI string with query arguments in a specific order.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3803>
This commit is contained in:
Jan Schmidt 2022-11-26 02:49:33 +11:00 committed by Edward Hervey
parent ae200a4d62
commit 138863b327
3 changed files with 153 additions and 9 deletions

View file

@ -1994,10 +1994,13 @@ gst_uri_make_writable (GstUri * uri)
}
/**
* gst_uri_to_string:
* @uri: This #GstUri to convert to a string.
* gst_uri_to_string_with_keys:
* @uri: (nullable): This #GstUri to convert to a string.
* @keys: (transfer none) (nullable) (element-type utf8): A GList containing
* the query argument key strings.
*
* Convert the URI to a string.
* Convert the URI to a string, with the query arguments in a specific order.
* Only the keys in the @keys list will be added to the resulting string.
*
* Returns the URI as held in this object as a #gchar* nul-terminated string.
* The caller should g_free() the string once they are finished with it.
@ -2005,10 +2008,10 @@ gst_uri_make_writable (GstUri * uri)
*
* Returns: (transfer full): The string version of the URI.
*
* Since: 1.6
* Since: 1.24
*/
gchar *
gst_uri_to_string (const GstUri * uri)
gst_uri_to_string_with_keys (const GstUri * uri, const GList * keys)
{
GString *uri_str;
gchar *escaped;
@ -2052,10 +2055,15 @@ gst_uri_to_string (const GstUri * uri)
}
if (uri->query) {
g_string_append (uri_str, "?");
escaped = gst_uri_get_query_string (uri);
g_string_append (uri_str, escaped);
g_free (escaped);
if (keys != NULL)
escaped = gst_uri_get_query_string_ordered (uri, keys);
else
escaped = gst_uri_get_query_string (uri);
if (escaped) {
g_string_append (uri_str, "?");
g_string_append (uri_str, escaped);
g_free (escaped);
}
}
if (uri->fragment != NULL) {
@ -2067,6 +2075,26 @@ gst_uri_to_string (const GstUri * uri)
return g_string_free (uri_str, FALSE);
}
/**
* gst_uri_to_string:
* @uri: This #GstUri to convert to a string.
*
* Convert the URI to a string.
*
* Returns the URI as held in this object as a #gchar* nul-terminated string.
* The caller should g_free() the string once they are finished with it.
* The string is put together as described in RFC 3986.
*
* Returns: (transfer full): The string version of the URI.
*
* Since: 1.6
*/
gchar *
gst_uri_to_string (const GstUri * uri)
{
return gst_uri_to_string_with_keys (uri, NULL);
}
/**
* gst_uri_is_normalized:
* @uri: (nullable): The #GstUri to test to see if it is normalized.
@ -2636,6 +2664,67 @@ gst_uri_set_query_string (GstUri * uri, const gchar * query)
return TRUE;
}
/**
* gst_uri_get_query_string_ordered:
* @uri: (nullable): The #GstUri to get the query string from.
* @keys: (transfer none) (nullable) (element-type utf8): A GList containing the
* query argument key strings.
*
* Get a percent encoded URI query string from the @uri, with query parameters
* in the order provided by the @keys list. Only parameter keys in the list will
* be added to the resulting URI string. This method can be used by retrieving
* the keys with gst_uri_get_query_keys() and then sorting the list, for
* example.
*
* Returns: (transfer full) (nullable): A percent encoded query string. Use
* g_free() when no longer needed.
*
* Since: 1.24
*/
gchar *
gst_uri_get_query_string_ordered (const GstUri * uri, const GList * keys)
{
const gchar *sep = "";
gchar *escaped;
GString *ret = NULL;
const GList *key;
if (!uri)
return NULL;
g_return_val_if_fail (GST_IS_URI (uri), NULL);
if (!uri->query)
return NULL;
for (key = keys; key; key = key->next) {
const gchar *query_key = key->data;
const gchar *arg;
/* Key isn't present, skip */
if (!g_hash_table_contains (uri->query, query_key))
continue;
if (ret == NULL)
ret = g_string_new (NULL);
/* Append the key */
g_string_append (ret, sep);
escaped = _gst_uri_escape_http_query_element (query_key);
g_string_append (ret, escaped);
g_free (escaped);
if ((arg = g_hash_table_lookup (uri->query, query_key))) {
/* Append the argument */
escaped = _gst_uri_escape_http_query_element (arg);
g_string_append_printf (ret, "=%s", escaped);
g_free (escaped);
}
sep = "&";
}
/* If no keys were seen, return NULL string instead of empty string */
return ret ? g_string_free (ret, FALSE) : NULL;
}
/**
* gst_uri_get_query_table:
* @uri: (nullable): The #GstUri to get the query table from.

View file

@ -259,6 +259,9 @@ GstUri * gst_uri_make_writable (GstUri * uri) G_GNUC_WARN_UNUSED_RESULT;
GST_API
gchar * gst_uri_to_string (const GstUri * uri) G_GNUC_MALLOC;
GST_API
gchar * gst_uri_to_string_with_keys (const GstUri * uri, const GList *keys);
GST_API
gboolean gst_uri_is_normalized (const GstUri * uri);
@ -316,6 +319,9 @@ gboolean gst_uri_append_path_segment (GstUri * uri,
GST_API
gchar * gst_uri_get_query_string (const GstUri * uri);
GST_API
gchar * gst_uri_get_query_string_ordered (const GstUri * uri, const GList *keys);
GST_API
gboolean gst_uri_set_query_string (GstUri * uri, const gchar * query);

View file

@ -1043,6 +1043,55 @@ GST_START_TEST (test_url_get_set)
"//example.com/path/to/file/there/segment?key=value&query#fragment");
g_free (tmp_str);
/* query string (full) */
tmp_str = gst_uri_get_query_string (url);
fail_unless_equals_string (tmp_str, "key=value&query");
g_free (tmp_str);
/* query string (single key, no value) */
tmp_list = g_list_append (NULL, g_strdup ("query"));
tmp_str = gst_uri_get_query_string_ordered (url, tmp_list);
fail_unless_equals_string (tmp_str, "query");
g_free (tmp_str);
tmp_str = gst_uri_to_string_with_keys (url, tmp_list);
fail_unless_equals_string (tmp_str,
"//example.com/path/to/file/there/segment?query#fragment");
g_free (tmp_str);
g_list_free_full (tmp_list, g_free);
/* query string (single key, with value) */
tmp_list = g_list_append (NULL, g_strdup ("key"));
tmp_str = gst_uri_get_query_string_ordered (url, tmp_list);
fail_unless_equals_string (tmp_str, "key=value");
g_free (tmp_str);
tmp_str = gst_uri_to_string_with_keys (url, tmp_list);
fail_unless_equals_string (tmp_str,
"//example.com/path/to/file/there/segment?key=value#fragment");
g_free (tmp_str);
g_list_free_full (tmp_list, g_free);
/* query string (key not present) */
tmp_list = g_list_append (NULL, g_strdup ("absent"));
tmp_str = gst_uri_get_query_string_ordered (url, tmp_list);
fail_if (tmp_str != NULL);
tmp_str = gst_uri_to_string_with_keys (url, tmp_list);
fail_unless_equals_string (tmp_str,
"//example.com/path/to/file/there/segment#fragment");
g_free (tmp_str);
g_list_free_full (tmp_list, g_free);
/* query string (both keys, inverse order) */
tmp_list = g_list_append (NULL, g_strdup ("query"));
tmp_list = g_list_append (tmp_list, g_strdup ("key"));
tmp_str = gst_uri_get_query_string_ordered (url, tmp_list);
fail_unless_equals_string (tmp_str, "query&key=value");
g_free (tmp_str);
tmp_str = gst_uri_to_string_with_keys (url, tmp_list);
fail_unless_equals_string (tmp_str,
"//example.com/path/to/file/there/segment?query&key=value#fragment");
g_free (tmp_str);
g_list_free_full (tmp_list, g_free);
fail_unless (gst_uri_set_query_value (url, "key", NULL));
tmp_str = gst_uri_to_string (url);
fail_unless_equals_string (tmp_str,