Обработка фигурных скобок в curl/libcurl

Из командной строки у меня есть запрос curl с двумя параметрами запроса, которые используют фигурные скобки. Однако один работает только при кодировании URL-адреса, а другой работает только тогда, когда он не кодируется URL-адресом.

Вот пример запроса, который (как ни странно) работает из командной строки и возвращает данные для 3 идентификаторов. Я бы не ожидал, что это сработает, потому что TIME URL-кодируется фигурными скобками (%7B и %7D), а P_ID нет:

  1. curl -X GET "https://example.com/search?TIME=%7B%22TIME_TYPE%22%3A%22MESSAGE%22%2C%22MESSAGENUMBER%22%3A5%7D&P_ID = {1,2,3}"

Что еще более странно, следующие вызовы не работают и, кажется, игнорируют поле P_ID и дают мне данные для каждого человека:

  1. curl -X GET "https://example.com/search?TIME=%7B%22TIME_TYPE%22%3A%22MESSAGE%22%2C%22MESSAGENUMBER%22%3A5%7D&P_ID=%7B1,2,3%7D"

  2. curl -X GET "https://example.com/search?TIME=%7B%22TIME_TYPE%22%3A%22MESSAGE%22%2C%22MESSAGENUMBER%22%3A5%7D&P_ID=1&P_ID=2&P_ID=3"

  3. curl -X GET "https://example.com/search?TIME = {%22TIME_TYPE%22%3A%22MESSAGE%22%2C%22MESSAGENUMBER%22%3A5}&P_ID=1&P_ID=2&P_ID=3"

Учитывая эти ограничения, когда первый вызов работает так, как я хочу, а второй и третий нет, как мне использовать libcurl в C++, чтобы первый вызов реплицировался? Я знаю, что CURLOPT_URL кодирует все, поэтому он будет кодировать обе фигурные скобки в TIME и P_ID. Я пытался использовать CURLUPART, как показано ниже, но безрезультатно.

void *curlHandle;
curl_easy_reset(curlHandle);
CURLU *url = curl_url();
curl_url_set(url, CURLUPART_URL, "example.com", 0);
curl_url_set(url, CURLUPART_QUERY, "P_ID = {1,2,3}", CURLU_APPENDQUERY);
curl_url_set(url, CURLUPART_QUERY, "TIME=%7B%22TIME_TYPE%22%3A%22MESSAGE%22%2C%22MESSAGENUMBER%22%3A5%7D", CURLU_APPENDQUERY);
curl_url_set(url, CURLUPART_SCHEME, "https", 0);
curl_url_set(url, CURLUPART_PATH, "/search/", 0);
curl_easy_setopt(curlHandle, CURLOPT_CURLU, url);
curl_easy_perform(curlHandle);

Я получаю этот ответ:

* URL не задан
Сбой Curl с ошибкой 3: URL-адрес использует неверный/недопустимый формат или отсутствует URL-адрес. Осталось 0 попыток

Подводя итог: как мне заставить libcurl сделать странный запрос на скручивание, подобный первому? Потому что это единственный способ выполнить команду из командной строки с ожидаемым результатом получения данных только трех человек.

В качестве альтернативы, возможно, есть другой способ попробовать этот запрос на завивание, кроме 4 попыток выше? Должен ли я просто обратиться к владельцу API и спросить, почему ему нравится { закодировано в одних местах, а не в других?

CURLOPT_URL ничего не кодирует, я не понимаю, почему этот первый URL-адрес не будет работать как есть. Это не работает для инструмента командной строки, потому что он «забивается» на фигурные скобки, поэтому вам нужно отключить это с помощью -g, и тогда инструмент также должен принять этот URL-адрес L. АФАИКС.

Daniel Stenberg 25.11.2022 09:53

Все примеры команд не имеют закрытия " и имеют недопустимые URL-адреса https:example.com. Это сделано намеренно?

273K 25.11.2022 16:58

@ 273K Нет, это было непреднамеренно, извините за это! Только что исправлено.

rabbitdude 25.11.2022 19:14

@DanielStenberg, когда я запускаю CURLOPT_VERBOSE, вывод говорит мне, что он преобразует каждую фигурную скобку в %7D/%7B. Из того, что я видел в Интернете, добавление -g помогло бы, но я не уверен, как это сделать с libcurl? Не могу найти документацию по добавлению -g

rabbitdude 25.11.2022 19:14

Команды по-прежнему не могут выполняться из-за незакрытого файла «. Как мы можем вам помочь, если мы не знаем, что вы делаете в execatly.

273K 25.11.2022 19:21
curl -X GET "https://httpbin.org/get?TIME=%7B%22TIME_TYPE%22%3A%22MESSAG‌​E%22%2C%22MESSAGENUM‌​BER%22%3A5%7D&P_ID=%‌​7B1,2,3%7D" -H "accept: application/json" работает хорошо. Ошибка может быть на вашем сервере. Кстати, если {1,2,3} должен быть JSON, как TIME, это недопустимый JSON. Возможно, вы захотите [1,2,3]
273K 25.11.2022 19:31

@ 273K Извините, я не могу предоставить точный API из соображений безопасности, я закрыл кавычки. TIME_TYPE предназначен для JSON, но P_ID обычно принимает один целочисленный идентификатор, за исключением того, что он работает для нескольких целочисленных идентификаторов, когда вы выполняете {x,y,z}. Мне нужна помощь, как заставить libcurl кодировать URL-адрес одного запроса (TIME_TYPE), но не кодировать URL-адрес другого (P_ID). Я также должен упомянуть, что он выдает ошибку с квадратными скобками [], поэтому единственная команда curl, которая работает, как и ожидалось, и возвращает данные 3 человек, является первой в моем вопросе. Я просто не могу понять, как точно передать это через libcurl

rabbitdude 25.11.2022 20:00
CURLOPT_URL ничего не кодирует. { и } не являются escape-символами, см. ibm.com/docs/en/planning-analytics/…. Проблема где-то, но не в завитке. Если вы не можете предоставить точные запросы, почему вы просите нас помочь? Спросите своих коллег.
273K 25.11.2022 20:07
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это ваши 4 строки запроса после декодирования URL.

TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID = {1,2,3}
TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID = {1,2,3}
TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3
TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3

Ни один из символов в строке вашего запроса не должен быть закодирован urlencode.
Учитывая, что у вас в основном есть два URL-адреса.
Это и URL-адреса, и URL-адреса строк запроса, декодированные на сервере:

https://example.com?TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3
TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3


https://example.com?TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID = {1,2,3}
TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID = {1,2,3}

Я не думаю, что ваша строка запроса вызывает ошибку. Похоже, вы ошиблись:

CURLU *url = curl_url();

Может быть, это должно быть:

CURLU *url= curl_url();
curl_url_set(url, CURLUPART_URL,
R"(https://example.com?TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID = {1,2,3})", 0);

Или просто передайте URL-адрес непосредственно в простой дескриптор:

curl_easy_setopt(curlHandle, CURLOPT_URL, R"(https://example.com?TIME = {"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID = {1,2,3})");

Другие вопросы по теме

Похожие вопросы

Как узнать, какой заголовочный файл включить для документированной функции при разработке для MacOS?
Как получить серийный номер в цифровом отпечатке пальца SDK в С++
Напечатать все возможные слова из 5 букв, используя рекурсию
У меня есть вопрос о функции printf()
Std::equal не работает при использовании векторов, возвращаемых геттером
Сопоставление нескольких объектов в MOCK_METHOD
Определение конструктора по умолчанию приводит к C2600 {невозможно определить специальную функцию-член, сгенерированную компилятором (сначала необходимо объявить в классе)
CMake: некоторые включают каталоги, определенные в исходных файлах, но не определенные в заголовках для вложенной цели
Допустимые формы внеклассовых определений функций-членов шаблона с конечными предложениями require
Рекомендуемый способ обертывания функции c сторонней библиотеки с аргументами void * в С++?