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: * gst_uri_to_string_with_keys:
* @uri: This #GstUri to convert to a string. * @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. * 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 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. * Returns: (transfer full): The string version of the URI.
* *
* Since: 1.6 * Since: 1.24
*/ */
gchar * gchar *
gst_uri_to_string (const GstUri * uri) gst_uri_to_string_with_keys (const GstUri * uri, const GList * keys)
{ {
GString *uri_str; GString *uri_str;
gchar *escaped; gchar *escaped;
@ -2052,11 +2055,16 @@ gst_uri_to_string (const GstUri * uri)
} }
if (uri->query) { if (uri->query) {
g_string_append (uri_str, "?"); if (keys != NULL)
escaped = gst_uri_get_query_string_ordered (uri, keys);
else
escaped = gst_uri_get_query_string (uri); escaped = gst_uri_get_query_string (uri);
if (escaped) {
g_string_append (uri_str, "?");
g_string_append (uri_str, escaped); g_string_append (uri_str, escaped);
g_free (escaped); g_free (escaped);
} }
}
if (uri->fragment != NULL) { if (uri->fragment != NULL) {
escaped = _gst_uri_escape_fragment (uri->fragment); escaped = _gst_uri_escape_fragment (uri->fragment);
@ -2067,6 +2075,26 @@ gst_uri_to_string (const GstUri * uri)
return g_string_free (uri_str, FALSE); 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: * gst_uri_is_normalized:
* @uri: (nullable): The #GstUri to test to see if it 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; 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: * gst_uri_get_query_table:
* @uri: (nullable): The #GstUri to get the query table from. * @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 GST_API
gchar * gst_uri_to_string (const GstUri * uri) G_GNUC_MALLOC; 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 GST_API
gboolean gst_uri_is_normalized (const GstUri * uri); gboolean gst_uri_is_normalized (const GstUri * uri);
@ -316,6 +319,9 @@ gboolean gst_uri_append_path_segment (GstUri * uri,
GST_API GST_API
gchar * gst_uri_get_query_string (const GstUri * uri); 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 GST_API
gboolean gst_uri_set_query_string (GstUri * uri, const gchar * query); 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"); "//example.com/path/to/file/there/segment?key=value&query#fragment");
g_free (tmp_str); 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)); fail_unless (gst_uri_set_query_value (url, "key", NULL));
tmp_str = gst_uri_to_string (url); tmp_str = gst_uri_to_string (url);
fail_unless_equals_string (tmp_str, fail_unless_equals_string (tmp_str,