Очевидно TRestCLient
пытается действовать слишком умно в вашем сценарии.Однако есть регулярный путь к этому.Ключ:
- для добавления отдельного контента в тело запроса, который не должен быть любым из
ctNone
, ctMULTIPART_FORM_DATA
или ctAPPLICATION_X_WWW_FORM_URLENCODED
. - для переопределения
Content-Type
с использованиемпользовательское значение заголовка.
Пример кода:
uses
System.NetConsts;
RESTClient1.BaseURL := 'https://postman-echo.com/post';
RESTRequest1.Method := rmPOST;
RESTRequest1.Body.Add('{ "some": "data" }', ctAPPLICATION_JSON);
RESTRequest1.AddParameter(sContentType, 'application/vnd.hmlr.corres.corres-data+json',
pkHTTPHEADER, [poDoNotEncode]);
RESTRequest1.Execute;
Ответ от службы эха:
{
"args":{
},
"data":{
"some":"data"
},
"files":{
},
"form":{
},
"headers":{
"x-forwarded-proto":"https",
"host":"postman-echo.com",
"content-length":"18",
"accept":"application/json, text/plain; q=0.9, text/html;q=0.8,",
"accept-charset":"UTF-8, *;q=0.8",
"content-type":"application/vnd.hmlr.corres.corres-data+json",
"user-agent":"Embarcadero RESTClient/1.0",
"x-forwarded-port":"443"
},
"json":{
"some":"data"
},
"url":"https://postman-echo.com/post"
}
Обратите внимание на отраженные заголовки, особенно Content-Type
конечно.Я тестировал образец в Delphi 10.2 Tokyo, поэтому, надеюсь, он также будет работать в XE8.
Edit
Наблюдаемое вами поведение - это ошибка (RSP-14001) , котораябыло исправлено в RAD Studio 10.2 Токио .
Существуют различные способы решения этой проблемы.Чтобы назвать несколько:
- Адаптируйте свой API для удаления вторичного типа MIME.
- Вместо этого измените реализацию клиента на
TNetHttpClient
, если вы можете отказаться от всех дополнительных преимуществ, которые предоставляет TRestClient
. - Обновите до RAD Studio 10.2 +.
- Взломайте! Этооднако опция настоятельно не рекомендуется , но она может помочь вам лучше понять
TRestClient
подробности реализации.
Самый простой способ взломать его - это пропатчить метод TCustomRESTRequest.ContentType
(примечаниемы говорим об инварианте с единственным аргументом), который возвращает ContentType
параметра, если его аргумент AParamsArray
содержит единственный параметр вида pkREQUESTBODY
.Это позволило бы нам добавить тело к запросу типа ctNone
, чтобы исправленный метод также возвратил ctNone
, и это эффективно предотвратило бы добавление другого значения в заголовок Content-Type
.
Другой вариант будетчтобы пропатчить метод TRESTHTTP.PrepareRequest
, чтобы предпочесть пользовательский заголовок Content-Type
перед предполагаемым типом содержимого запроса.Вот как работает текущая реализация после того, как она была исправлена в RAD Studio 10.2 Tokyo.Эта логика также применяется к другим заголовкам - Accept
, Accept-Charset
, Accept-Encoding
, User-Agent
.Метод исправления TRESTHTTP.PrepareRequest
немного сложнее реализовать, поскольку он имеет private
видимость.
Самым сложным вариантом будет установка исправления TWinHTTPRequest.SetHeaderValue
для отбрасывания значения типа вторичного контента.Это также самый опасный вариант, поскольку он может повлиять на все, что связано с HTTP (что зависит от THTTPClient
) в вашем приложении.Также сложно, но не невозможно, пропатчить класс, потому что он полностью скрыт в implementation
разделе System.Net.HttpClient.Win.pas
.Это позор, потому что он также не позволяет создавать собственные подклассы.Может быть, по уважительной причине .. кто знает;)