Сообщение о выходе из 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));