HTTP GET с телом запроса

Я разрабатываю новый веб-сервис RESTful для нашего приложения.

При выполнении GET для определенных объектов клиенты могут запрашивать содержимое объекта. Если они хотят добавить некоторые параметры (например, сортировать список), они могут добавить эти параметры в строку запроса.

В качестве альтернативы я хочу, чтобы люди могли указывать эти параметры в теле запроса. HTTP / 1.1 явно не запрещает это. Это позволит им указывать больше информации, может упростить указание сложных запросов XML.

Мои вопросы:

  • Это хорошая идея в целом?
  • Будут ли у HTTP-клиентов проблемы с использованием тел запросов в GET-запросе?

http://tools.ietf.org/html/rfc2616

26 ответов

Решение

Комментарий Роя Филдинга о включении тела в запрос GET.

Да. Другими словами, любое сообщение HTTP-запроса может содержать тело сообщения и, следовательно, должно анализировать сообщения с учетом этого. Однако семантика сервера для GET ограничена таким образом, что тело, если оно есть, не имеет семантического значения для запроса. Требования к синтаксическому анализу отделены от требований к семантике метода.

Итак, да, вы можете отправить тело с GET, и нет, это никогда не полезно.

Это часть многоуровневой структуры HTTP/1.1, которая станет понятной после разделения спецификации (работа в процессе).

....Рой

Да, вы можете отправить тело запроса с помощью GET, но это не должно иметь никакого значения. Если вы придаете ему значение, анализируя его на сервере и изменяя свой ответ на основании его содержимого, то вы игнорируете эту рекомендацию в спецификации HTTP/1.1, раздел 4.3:

[...] если метод запроса не включает определенную семантику для тела объекта, то тело сообщения ДОЛЖНО игнорироваться при обработке запроса.

И описание метода GET в спецификации HTTP/1.1, раздел 9.3:

Метод GET означает извлечение любой информации ([...]), идентифицированной посредством Request-URI.

в котором говорится, что тело запроса не является частью идентификации ресурса в запросе GET, а только URI запроса.

Обновление RFC2616, называемый "HTTP/1.1 spec", теперь устарел. В 2014 году он был заменен RFC 7230-7237. Цитата "тело сообщения ДОЛЖНО игнорироваться при обработке запроса" была удалена. Теперь это просто "Запрос на создание кадра не зависит от семантики метода, даже если метод не определяет никакого использования для тела сообщения". Вторая цитата: "Метод GET означает получение любой информации... идентифицированной по Request-URI" был удален - из комментария

Хотя вы можете сделать это, поскольку это явно не исключено спецификацией HTTP, я бы посоветовал избегать этого просто потому, что люди не ожидают, что все будет работать именно так. В цепочке HTTP-запросов есть много этапов, и хотя они "в основном" соответствуют спецификации HTTP, единственное, что вы уверены, это то, что они будут вести себя так, как традиционно используются веб-браузерами. (Я имею в виду такие вещи, как прозрачные прокси, ускорители, A/V инструментарий и т. Д.)

Этот принцип лежит в основе принципа надежности: "будьте либеральными в том, что вы принимаете, и консервативными в том, что вы отправляете", вы не хотите выходить за пределы спецификации без уважительной причины.

Однако, если у вас есть веская причина, сделайте это.

Скорее всего, вы столкнетесь с проблемами, если когда-нибудь попробуете воспользоваться кешированием. Прокси не будут искать в теле GET, чтобы увидеть, влияют ли параметры на ответ.

Elasticsearch принимает запросы GET с телом. Даже кажется, что это предпочтительный способ: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/common-options.html

Некоторые клиентские библиотеки (например, драйвер Ruby) могут регистрировать команду cry в stdout в режиме разработки, и он широко использует этот синтаксис.

GET, с телом!?

С точки зрения спецификации вы могли бы, но, как мы увидим, не стоит делать это неразумно.

В RFC 7231 §4.3.1 говорится, что тело «не имеет определенной семантики», но это не значит, что это запрещено. Если вы прикрепите тело к запросу, и то, что ваш сервер/приложение сделает из него, зависит от вас. Далее в RFC говорится, что GET может быть «программным представлением различных записей базы данных». Очевидно, что такое представление многократно настраивается большим количеством входных параметров, которые не всегда удобно или даже безопасно задавать в компоненте запроса запроса-цели.

Достоинства: Мне нравится словоблудие. Понятно, что одно чтение/получение ресурса без каких-либо наблюдаемых побочных эффектов на сервере (метод «безопасен»), и запрос может быть повторен с тем же предполагаемым эффектом независимо от результата первого запроса (метод «идемпотент»).

Плохое: ранний проект HTTP/1.1 запрещал GET иметь тело, и, как утверждается, некоторые реализации вплоть до сегодняшнего дня будут отбрасывать тело, игнорировать тело или отклонять сообщение. Например, тупой HTTP-кеш может создать ключ кэша только из цели запроса, не обращая внимания на наличие или содержимое тела. Еще более тупой сервер может быть настолько невежественным, что рассматривает тело как новый запрос, что фактически называется «контрабандой запросов» (что представляет собой действие по отправке «запроса на одно устройство без ведома другого устройства» - источник).

Из-за того, что, как я считаю, в первую очередь связано с неработоспособностью среди реализаций, в текущей работе предлагается классифицировать тело GET как «НЕ ДОЛЖНО», « если только [запрос] не направляется непосредственно на исходный сервер, который ранее указывал, в или совершенно неожиданно, что такая просьба имеет цель и будет адекватно поддержана» (выделено мной).

Исправление: Есть несколько хаков, которые можно использовать для решения некоторых проблем с этим подходом. Например, кэши, не поддерживающие тело, могут косвенно стать осведомленными о теле, просто добавив хэш, полученный из тела, к компоненту запроса, или полностью отключить кэширование, отвечая на запрос. cache-control: no-cacheзаголовок с сервера.

Увы, когда дело доходит до цепочки запросов, вы часто не контролируете или даже не знаете обо всех существующих и будущих посредниках HTTP и о том, как они будут работать с телом GET. Вот почему этот подход следует считать в целом ненадежным.

Но , не является идемпотентом!

POSTявляется альтернативой. Запрос POST обычно включает в себя тело сообщения (просто для записи, тело не является обязательным, см. RFC 7230 §3.3.2). Самый первый пример использования из RFC 7231 (§4.3.3) - это «предоставление блока данных [...] процессу обработки данных». Так же, как GET с телом, что происходит с телом на внутренней стороне, зависит от вас.

Плюсы: возможно, более распространенный метод, который можно применить, когда кто-то хочет отправить тело запроса для какой-либо цели, и поэтому, скорее всего, вызовет наименьшее количество шума со стороны членов вашей команды (некоторые все еще могут ошибочно полагать, что POST должен создавать ресурс). ).

Кроме того, мы часто передаем параметры функции поиска, работающей с постоянно меняющимися данными, а ответ POST кэшируется только в том случае, если в ответе предоставлена ​​явная информация о свежести.

Плохо: POST-запросы не определены как идемпотентные, что приводит к нерешительности повторных попыток. Например, при перезагрузке страницы браузеры не желают повторно отправлять HTML-форму без запроса пользователю нечитаемого загадочного сообщения.

Исправление: Ну, только потому, что POST не определен как идемпотентный, не означает, что он не должен быть таковым. Действительно, RFC 7230 §6.3.1 пишет: «пользовательский агент, который знает (посредством дизайна или конфигурации), что запрос POST к данному ресурсу безопасен, может автоматически повторить этот запрос». Итак, если ваш клиент не является HTML-формой, это, вероятно, не является реальной проблемой.

Святой Грааль

Есть предложение по новому методу QUERYкоторый определяет семантику для тела сообщения и определяет метод как идемпотентный. Смотрите это.

Изменить . В качестве примечания я наткнулся на этот вопрос StackOverflow после того, как обнаружил кодовую базу, в которой они использовали исключительно PUTзапросы на поисковые функции на стороне сервера. Это была их идея включить тело с параметрами, а также быть идемпотентным. Увы, проблема с PUT заключается в том, что тело запроса имеет очень точную семантику. В частности, PUT «запрашивает, чтобы состояние целевого ресурса было создано или заменено состоянием [в теле]» ( RFC 7231 §4.3.4). Ясно, что это исключает PUT как жизнеспособный вариант.

Ни консоль restclient, ни консоль REST не поддерживают это, но curl поддерживает.

Спецификация HTTP говорится в разделе 4.3

Тело сообщения НЕ ДОЛЖНО быть включено в запрос, если спецификация метода запроса (раздел 5.1.1) не позволяет отправлять тело объекта в запросах.

Раздел 5.1.1 перенаправляет нас в раздел 9.x для различных методов. Ни один из них явно не запрещает включение тела сообщения. Тем не мение...

Раздел 5.2 говорит

Точный ресурс, идентифицируемый интернет-запросом, определяется путем изучения URI-запроса и поля заголовка хоста.

и раздел 9.3 говорит

Метод GET означает получение любой информации (в форме объекта), идентифицируемой посредством Request-URI.

Что вместе указывает на то, что при обработке запроса GET серверу не требуется проверять что-либо, кроме поля заголовка Request-URI и Host.

Таким образом, спецификация HTTP не мешает вам отправлять тело сообщения с помощью GET, но существует достаточно двусмысленности, чтобы меня не удивило, если бы она не поддерживалась всеми серверами.

Я поставил этот вопрос в IETF HTTP WG. Комментарий Роя Филдинга (автора документа http/1.1 в 1998 году) заключался в том, что

"... реализация будет нарушена для выполнения чего-либо, кроме анализа и удаления этого тела, если оно получено"

RFC 7213 (HTTPbis) заявляет:

"Полезная нагрузка в сообщении запроса GET не имеет определенной семантики;"

Теперь очевидно, что подразумевалось, что семантическое значение в телах запросов GET запрещено, что означает, что тело запроса не может использоваться для воздействия на результат.

Существуют прокси-серверы, которые определенным образом нарушат ваш запрос, если вы включите тело в GET.

Итак, в заключение, не делайте этого.

То, чего вы пытаетесь достичь, уже давно сделано гораздо более распространенным методом, который не использует полезную нагрузку с GET.

Вы можете просто создать свой конкретный медиатип поиска или, если вы хотите быть более RESTful, использовать что-то вроде OpenSearch и отправить POST запрос к URI, указанному сервером, скажем /search. Затем сервер может сгенерировать результат поиска или построить окончательный URI и перенаправить с помощью 303.

Это имеет преимущество в следовании традиционному методу PRG, помогает кеширующим посредникам кэшировать результаты и т.д.

Тем не менее, URI в любом случае кодируются для всего, что не является ASCII, как и application/x-www-form-urlencoded и multipart/form-data. Я бы порекомендовал использовать это, а не создавать еще один пользовательский формат json, если вы намерены поддерживать сценарии ReSTful.

Вы можете отправить GET с телом или отправить POST и отказаться от RESTish религиозности (это не так уж и плохо, 5 лет назад в этой вере был только один член - его комментарии связаны выше).

Это также не хорошие решения, но отправка тела GET может предотвратить проблемы для некоторых клиентов - и некоторых серверов.

Выполнение POST может иметь препятствия с некоторыми средами RESTish.

Джулиан Решке предложил выше использовать нестандартный HTTP-заголовок, такой как "SEARCH", который может быть элегантным решением, за исключением того, что он еще менее вероятно будет поддерживаться.

Может оказаться наиболее продуктивным перечислить клиентов, которые могут и не могут выполнять все вышеперечисленное.

Клиенты, которые не могут отправить GET с телом (о котором я знаю):

  • XmlHTTPRequest Fiddler

Клиенты, которые могут отправить GET с телом:

  • большинство браузеров

Серверы и библиотеки, которые могут получить тело из GET:

  • апаш
  • PHP

Серверы (и прокси), которые снимают тело с GET:

  • ?

Из RFC 2616, раздел 4.3, "Тело сообщения":

Сервер ДОЛЖЕН прочитать и переслать тело сообщения по любому запросу; если метод запроса не включает определенную семантику для тела объекта, то тело сообщения ДОЛЖНО игнорироваться при обработке запроса.

Таким образом, серверы всегда должны читать любое предоставленное тело запроса из сети (проверьте Content-Length или прочитайте разделенное тело и т. Д.). Кроме того, прокси-серверы должны перенаправлять любое полученное тело запроса. Затем, если RFC определяет семантику для тела для данного метода, сервер может фактически использовать тело запроса при генерации ответа. Однако, если RFC не определяет семантику для тела, то сервер должен игнорировать это.

Это соответствует цитате из Филдинга выше.

Раздел 9.3, "GET", описывает семантику метода GET и не упоминает тела запросов. Поэтому сервер должен игнорировать любое тело запроса, которое он получает по запросу GET.

Какой сервер будет игнорировать это? - fijiaaron 30 августа '12 в 21:27

Google, например, делает хуже, чем игнорирует его, он будет считать это ошибкой!

Попробуйте сами с помощью простого netcat:

$ netcat www.google.com 80
GET / HTTP/1.1
Host: www.google.com
Content-length: 6

1234

(за содержимым 1234 следует CR-LF, то есть всего 6 байтов)

и вы получите:

HTTP/1.1 400 Bad Request
Server: GFE/2.0
(....)
Error 400 (Bad Request)
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know.

Вы также получаете 400 плохих запросов от Bing, Apple и т. Д., Которые обслуживаются AkamaiGhost.

Поэтому я бы не советовал использовать GET-запросы с сущностью body.

Согласно XMLHttpRequest, это недействительно. Из стандарта:

4.5.6 send() метод

client . send([body = null])

Инициирует запрос. Необязательный аргумент предоставляет тело запроса. Аргумент игнорируется, если метод запроса GET или же HEAD,

Бросает InvalidStateError исключение, если либо состояние не открыто или send() флаг установлен.

send(body) Метод должен выполнить эти шаги:

  1. Если состояние не открыто, бросьте InvalidStateError исключение.
  2. Если send() флаг установлен, бросить InvalidStateError исключение.
  3. Если метод запроса GET или же HEAD, установите тело в нуль.
  4. Если тело пусто, переходите к следующему шагу.

Хотя я не думаю, что так должно быть, потому что для запроса GET может потребоваться большой объем содержимого.

Итак, если вы используете XMLHttpRequest браузера, скорее всего, он не будет работать.

Если вы действительно хотите отправить кэшируемое тело JSON/XML в веб-приложение, единственное разумное место для размещения ваших данных - это строка запроса, закодированная с помощью RFC4648: кодировка Base 64 с URL-адресом и безопасным алфавитом имени файла. Конечно, вы могли бы просто urlencode JSON и указать значение параметра URL, но Base64 дает меньший результат. Помните, что существуют ограничения по размеру URL-адреса, см. Какова максимальная длина URL-адреса в разных браузерах?,

Вы можете подумать, что заполнение Base64 = символ может быть плохим для значения параметра URL, однако, похоже, что нет - см. это обсуждение: http://mail.python.org/pipermail/python-bugs-list/2007-February/037195.html. Однако не следует помещать закодированные данные без имени параметра, потому что закодированная строка с отступом будет интерпретироваться как ключ параметра с пустым значением. Я бы использовал что-то вроде ?_b64=<encodeddata>,

Я бы не советовал это, это идет вразрез со стандартными практиками и не предлагает так много взамен. Вы хотите сохранить тело для контента, а не вариантов.

У вас есть список опций, которые намного лучше, чем использование тела запроса с GET.

Предположим, у вас есть категории и предметы для каждой категории. Оба идентифицируются по идентификатору ("catid" / "itemid" для примера). Вы хотите сортировать по другому параметру sortby в определенном порядке. Вы хотите передать параметры для "sortby" и "order":

Вы можете:

  1. Используйте строки запроса, напримерexample.com/category/{catid}/item/{itemid}?sortby=itemname&order=asc
  2. Используйте mod_rewrite (или аналогичный) для путей:example.com/category/{catid}/item/{itemid}/{sortby}/{order}
  3. Используйте отдельные заголовки HTTP, которые вы передаете с запросом
  4. Используйте другой метод, например POST, для извлечения ресурса.

У всех есть свои недостатки, но они намного лучше, чем использование GET с телом.

Я расстроен, что REST как протокол не поддерживает ООП и Get Метод является доказательством. В качестве решения вы можете сериализовать ваш DTO в JSON, а затем создать строку запроса. На стороне сервера вы сможете десериализовать строку запроса в DTO.

Посмотрите на:

Подход, основанный на сообщениях, может помочь решить проблему ограничения метода Get. Вы можете отправить любой DTO, как с телом запроса

Платформа веб-службы Nelibur предоставляет функциональность, которую вы можете использовать

var client = new JsonServiceClient(Settings.Default.ServiceAddress);
var request = new GetClientRequest
    {
        Id = new Guid("2217239b0e-b35b-4d32-95c7-5db43e2bd573")
    };
var response = client.Get<GetClientRequest, ClientResponse>(request);

as you can see, the GetClientRequest was encoded to the following query string

http://localhost/clients/GetWithResponse?type=GetClientRequest&data=%7B%22Id%22:%2217239b0e-b35b-4d32-95c7-5db43e2bd573%22%7D

Даже если популярный инструмент использует это, как часто цитируется на этой странице, я думаю, что это все еще довольно плохая идея, слишком экзотическая, несмотря на то, что она не запрещена спецификацией.

Многие промежуточные инфраструктуры могут просто отклонять такие запросы.

К примеру, забудьте об использовании некоторых из доступных CDN в передней части вашего веб - сайта, как этот один:

Если зритель GET Если запрос включает тело, CloudFront возвращает зрителю код состояния HTTP 403 (Запрещено).

И да, ваши клиентские библиотеки также могут не поддерживать отправку таких запросов, как указано в этом комментарии.

Как насчет несоответствующих закодированных base64 заголовков? "SOMETHINGAPP-Титулы:sdfSD45fdg45/ СОС"

Длина ограничения хм. Разве вы не можете сделать вашу обработку POST различать значения? Если вам нужны простые параметры, такие как сортировка, я не понимаю, почему это будет проблемой. Я думаю, это уверенность, что вы беспокоитесь.

Если вы хотите разрешить запрос GET с телом, можно поддержать запрос POST с заголовком «X-HTTP-Method-Override: GET». Это описано здесь: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields . Этот заголовок означает, что хотя метод POST, запрос следует обрабатывать так, как будто это GET. Тело разрешено для POST, поэтому вы уверены, что никто не потеряет полезную нагрузку ваших запросов GET.

Этот заголовок часто используется для отправки запросов PATCH или HEAD через некоторые прокси, которые не распознают эти методы и заменяют их на GET (отлаживать всегда интересно!).

ИМХО можно просто отправить JSON закодированы (т.е. encodeURIComponent) в URLТаким образом, вы не нарушаете HTTP спецификации и получить свой JSON на сервер.

Например, он работает с Curl, Apache и PHP.

PHP-файл:

<?php
echo $_SERVER['REQUEST_METHOD'] . PHP_EOL;
echo file_get_contents('php://input') . PHP_EOL;

Консольная команда:

$ curl -X GET -H "Content-Type: application/json" -d '{"the": "body"}' 'http://localhost/test/get.php'

Выход:

GET
{"the": "body"}

Я использую RestTemplate инфраструктуры Spring в своей клиентской программе, а на стороне сервера я определил запрос GET с телом Json. Моя основная цель такая же, как и у вас: когда запрос имеет множество параметров, помещать их в тело кажется более аккуратным, чем помещать их в удлиненную строку URI. Да?

Но, к сожалению, это не работает! На стороне сервера возникло следующее исключение:

org.springframework.http.converter.HttpMessageNotReadableException: требуемое тело запроса отсутствует...

Но я почти уверен, что тело сообщения правильно предоставлено моим клиентским кодом, так что же не так?

Я проследил до метода RestTemplate.exchange() и нашел следующее:

// SimpleClientHttpRequestFactory.class
public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {
    ...
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
        ...
        if (!"POST".equals(httpMethod) && !"PUT".equals(httpMethod) && !"PATCH".equals(httpMethod) && !"DELETE".equals(httpMethod)) {
            connection.setDoOutput(false);
        } else {
            connection.setDoOutput(true);
        }
        ...
    }
}

// SimpleBufferingClientHttpRequest.class
final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttpRequest {
    ...
    protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
        ...
        if (this.connection.getDoOutput() && this.outputStreaming) {
            this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
        }

        this.connection.connect();
        if (this.connection.getDoOutput()) {
            FileCopyUtils.copy(bufferedOutput, this.connection.getOutputStream());
        } else {
            this.connection.getResponseCode();
        }
        ...
    }
}

Обратите внимание, что в методе executeInternal() входной аргумент bufferedOutput содержит тело сообщения, предоставленное моим кодом. Я видел это через отладчик.

Однако из-за prepareConnection() getDoOutput() в executeInternal() всегда возвращает false, что, в свою очередь, полностью игнорирует bufferedOutput! Он не копируется в выходной поток.

Следовательно, моя серверная программа не получила тела сообщения и вызвала это исключение.

Это пример RestTemplate фреймворка Spring. Дело в том, что даже если тело сообщения больше не запрещено спецификацией HTTP, некоторые клиентские или серверные библиотеки или фреймворки могут по-прежнему соответствовать старой спецификации и отклонять тело сообщения из запроса GET.

Идея по старому вопросу:

Добавьте полное содержимое в тело и короткий хеш тела в строку запроса, чтобы кэширование не было проблемой (хеш изменится, если содержимое тела изменится), и вы сможете отправлять тонны данных, когда нужный :)

Отправка данных в теле запроса GET API не рекомендуется спецификацией HTTP , но могут быть сценарии, в которых использование API POST, PUT или PATCH не подходит.

Например, Elasticsearch отправляет тело запроса с помощью GET API, поскольку полезная нагрузка, отправляемая в теле запроса, довольно сложна и не подходит для отправки по параметрам запроса в GET API.

Но в большинстве случаев нам не следует отправлять данные в теле запроса с помощью GET API, поскольку ожидается, что в GET API не будет тела запроса и он может быть проигнорирован клиентом обработки API.

Google, IBM, Microsoft и apigee, похоже, используют заголовок для обозначения действительно ожидаемого метода, что-то вроде X-HTTP-Method-Override: GET.
Согласно блогу выше, первоначально это вводится для POST как PUT в форме.
Я думаю, что это решение может быть использовано в этой проблеме.

Другими словами, я думаю, что POST с X-HTTP-Method-Override: GET заголовок - лучшее решение.

Создайте класс Requestfactory

import java.net.URI;

import javax.annotation.PostConstruct;

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class RequestFactory {
    private RestTemplate restTemplate = new RestTemplate();

    @PostConstruct
    public void init() {
        this.restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestWithBodyFactory());
    }

    private static final class HttpComponentsClientHttpRequestWithBodyFactory extends HttpComponentsClientHttpRequestFactory {
        @Override
        protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
            if (httpMethod == HttpMethod.GET) {
                return new HttpGetRequestWithEntity(uri);
            }
            return super.createHttpUriRequest(httpMethod, uri);
        }
    }

    private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase {
        public HttpGetRequestWithEntity(final URI uri) {
            super.setURI(uri);
        }

        @Override
        public String getMethod() {
            return HttpMethod.GET.name();
        }
    }

    public RestTemplate getRestTemplate() {
        return restTemplate;
    }
}

и @Autowired, где бы вы ни потребовали и не использовали, Вот один пример кода GET-запроса с RequestBody

 @RestController
 @RequestMapping("/v1/API")
public class APIServiceController {
    
    @Autowired
    private RequestFactory requestFactory;
    

    @RequestMapping(method = RequestMethod.GET, path = "/getData")
    public ResponseEntity<APIResponse> getLicenses(@RequestBody APIRequest2 APIRequest){
        APIResponse response = new APIResponse();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Gson gson = new Gson();
        try {
            StringBuilder createPartUrl = new StringBuilder(PART_URL).append(PART_URL2);
            
            HttpEntity<String> entity = new HttpEntity<String>(gson.toJson(APIRequest),headers);
            ResponseEntity<APIResponse> storeViewResponse = requestFactory.getRestTemplate().exchange(createPartUrl.toString(), HttpMethod.GET, entity, APIResponse.class); //.getForObject(createLicenseUrl.toString(), APIResponse.class, entity);
    
            if(storeViewResponse.hasBody()) {
                response = storeViewResponse.getBody();
            }
            return new ResponseEntity<APIResponse>(response, HttpStatus.OK);
        }catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<APIResponse>(response, HttpStatus.INTERNAL_SERVER_ERROR);
        }
        
    }
}
Другие вопросы по тегам