Сообщение о выходе из POST на сервере Tableau не выполняется с помощью Indy или TWebBrowser

При работе с API-интерфейсом Tableau Server для бета-версии 2018.2 в документации указан вызов API REST, который завершает / завершает защищенный сеанс между пользовательским приложением и сервером Tableau.

Сеанс защищен выполнением запроса POST (входа в систему) с использованием имени пользователя и пароля, который получает токен, который будет использоваться для дальнейших запросов.

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

При выполнении выхода есть одно существенное отличие в том, что запрос на "выход" является запросом POST, а не запросом GET. Хотя это не должно вызывать проблем, похоже, что так оно и есть.

Основное различие между POST-запросом на выход и любым другим POST-запросом состоит в том, что данные для запроса на выход - nil / null. Основываясь на том факте, что документация API не упоминает об этом, а дает простой пример CURL:

curl "http://MY-SERVER/api/3.0/auth/signout" -X POST -H "X-Tableau-Auth:12ab34cd56ef78ab90cd12ef34ab56cd"

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

Я пробовал этот запрос, используя компонент TIdHTTP и предоставляя пустой TStringStream или пустой TStringList для параметров данных POST в вызове post:

try
  tss := TStringStream.Create('');
  http.Request.RawHeaders.AddValue('X-Tableau-Auth',FToken);
  http.Post('http://<myserver>/api/3.0/auth/signout',tss);
finally
  tss.Free;
end;

... но получите исключение "HTTP/1.1 401 Unauthorized".

Если я пытаюсь сделать это с интерфейсом TWebBrowser:

var
  flags,headers,postdata,targetframe,url: OleVariant;
begin
  url := 'http://<myserver>/api/3.0/auth/signout';
  headers := 'X-Tableau-Auth: ' + FToken + #13#10;
  targetframe := 1;
  flags := 1;
  postdata := VarArrayCreate([0,1],varByte);
  postdata[0] := 1;
  Navigate2(URL,flags,targetframe,postdata,Headers);
end;

... в первый раз я получаю нежелательный запуск Internet Explorer с URL-адресом выхода в окне URL-адреса и отображаемой страницей с надписью "Навигация отменена".

При повторном запуске кода я получаю еще один нежелательный запуск Internet Explorer, на этот раз со следующим ответом / страницей:

<?xml version="1.0" encoding="UTF-8"?>
-<tsResponse xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-3.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tableau.com/api">
-<error code="401002">
<summary>Unauthorized Access</summary>
<detail>Invalid authentication credentials were provided.</detail>
</error>

Я бы предпочел использовать компонент TIdHttp для этой незначительной задачи, но для визуальных задач пришлось бы использовать TWebBrowser, так что я тоже мог бы это использовать.

Вот ссылка на документацию Tableau Server для вызова API выхода из системы:

https://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm

2 ответа

Решение

Ок, разобрался. В моем коде заголовок с информацией об аутентификации не добавлялся. Также установите http.Connection закрывать'.

Это решило проблему.

Когда TIdHTTP готовит новый HTTP-запрос для отправки, TIdHTTP.Request.RawHeaders свойство очищается и повторно заполняется фактическими заголовками, которые должны быть отправлены. Поскольку вы храните свой токен сеанса в RawHeaders, он стирается и не отправляется на сервер, поэтому вы получаете 401 ошибка.

Вам нужно использовать TIdHTTP.Request.CustomHeaders вместо этого свойства, которое добавляется к RawHeaders при подготовке запроса:

tss := TStringStream.Create('');
try
  http.Request.CustomHeaders.AddValue('X-Tableau-Auth',FToken);
  // or:
  // http.Request.CustomHeaders.Values['X-Tableau-Auth'] := FToken;
  http.Post('http://<myserver>/api/3.0/auth/signout', tss);
finally
  tss.Free;
end;

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

http.Post('http://<myserver>/api/3.0/auth/signout', TStream(nil));

http.Post('http://<myserver>/api/3.0/auth/signout', TStrings(nil));
Другие вопросы по тегам