REST API Confluence: HTTP 200 с пустым ответом

Кажется, я не могу создать новую страницу в Confluence Cloud v1000.957.0 через Rest API. Я пробовал использовать как cURL, так и Python, но безрезультатно: все, что я получаю, это HTTP 200 с пустым ответом JSON каждый раз. Если я изменю учетные данные на неверные, я получу HTTP 401.

curl -u ******@******.com:****** -X POST -H 'Content-Type: application/json' -d'{"type":"page","title":"TESTING123", "ancestors":[{"id":123456}], "space":{"key":"AA"},"body":{"storage":{"value":"<p>This is a new page</p>","representation":"storage"}}}' https://********.atlassian.net/wiki/rest/api/content/

Я изменил некоторые детали вызова cURL ради анонимности, но я знаю, что учетные данные, идентификатор предка, пробел и URL-адрес API верны. Я также проверил, что у этой учетной записи есть правильные разрешения в Confluence для создания страницы в этом пространстве, и что доступ API для Confluence включен.

Варианты вызова API, которые я пробовал:

  1. Добавление ?os_authType=basic в конец URL

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

    • status: current
    • operations: []
    • metadata: {}
  3. Изменение вызова API для создания страницы на верхнем уровне в пространстве Confluence (без поля ancestors).

  4. Добавление этого заголовка: Accept: application/json

  5. Добавление параметра view к части body вызова и последующее добавление его в конец URL-адреса: &expand=body.view. Я обнаружил, что добавление его в код Python дает тот же результат, но добавление его к вызову cURL выводит что-то вроде [1] 42999 (последняя часть меняется при каждом вызове); затем при новой команде или просто при нажатии Return он печатает [1]+ Done, за которым следует кусок пробела, а затем вызов cURL, который я только что сделал.

Я нашел очень похожую ошибку в JIRA от Atlassian для программного обеспечения JIRA, поэтому, по-видимому, это происходит и с JIRA, но с перерывами. https://jira.atlassian.com/browse/JRA-41559

Я не очень хорошо знаком с протоколом HTTP, поэтому может быть что-то, что я упускаю из виду, поэтому на самом деле я просто хочу попробовать больше вариантов (хотя решение, конечно, было бы идеальным).


person Ken K    schedule 15.02.2017    source источник
comment
Удалось ли вам получить список существующего содержимого или использовать другие запросы API? Попробуйте вызвать некоторые запросы API через ваш браузер (GET только через URL-адрес, POST с расширением браузера, например, YARC), чтобы различать проблемы аутентификации и запроса.   -  person Lukas Körfer    schedule 17.02.2017
comment
Я этого не сделал, но мне удалось заставить его работать, опустив домен имени пользователя в вызове cURL.   -  person Ken K    schedule 17.02.2017


Ответы (3)


Проблема в том, что вы используете имя пользователя с доменом в качестве учетных данных (******@******.com:******)

Вы можете проверить, работает ли это, просто запросив основной контент вики.
Попробуйте: curl -u <user>:<pass> https://<domain>.atlassian.net/wiki/rest/api/content/

Вы также можете не указывать пароль. Curl запросит его — это безопаснее с точки зрения безопасности.
Попробуйте: curl -u <user> https://<domain>.atlassian.net/wiki/rest/api/content/

person Maciej    schedule 17.02.2017
comment
На самом деле существует проблема, но Atlassian говорит, что это решено. - person Lukas Körfer; 17.02.2017
comment
@lukegv: Разница в том, что теперь мы даже не получаем 401:unauthorized. Вместо этого мы получаем HTTP 200 с пустым ответом (без JSON) и полем заголовка HTTP X-Seraph-LoginReason: OK, которое, кажется, указывает, что Логин в порядке. - person Maciej; 17.02.2017
comment
@maciej Вот что я получу, если удалю домен из имени пользователя. В контенте, который я пытаюсь опубликовать, нет b, поэтому, если это не странная проблема с кодировкой, я не думаю, что это происходит из контента, который я пытаюсь опубликовать. {"statusCode":500,"message":"org.codehaus.jackson.JsonParseException: Unexpected character ('b' (code 98)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')\n at [Source: com.atlassian.confluence.plugins.restapi.filters.LimitingRequestFilter$1@1097e3e; line: 1, column: 2]"} - person Ken K; 17.02.2017
comment
@maciej Извините, это то, что я получил, когда сделал это на Python. Однако это работает в cURL! Я поработаю со своей реализацией Python, чтобы посмотреть, смогу ли я заставить ее работать. Большое спасибо! - person Ken K; 17.02.2017
comment
Причина, по которой я получил 500, заключалась в том, что я забыл закодировать словарь Python как данные JSON: я передавал ему необработанный словарь. Исправлено таким образом: json.dumps(data) - person Ken K; 17.02.2017

Для всех, кто попадает сюда... У меня была именно эта проблема, когда r = requests.get(URL, auth=(USER, PASSWORD) URL-адрес, который был вики-страницей .../wiki/rest/api/content/123454, имел бы 200 r.status_code и r.text был пуст.

Исправление состоит в том, чтобы использовать request.session() и сделать два вызова. Один (я предполагаю) для установки сеанса, а второй для получения контента.

s = requests.session()
s.auth = (USER, PASSWORD)
r = s.get(url_base) # url_base = '.../wiki/rest/api'
r = s.get(url) # url = '.../wiki/rest/api/content/123453'

тогда r.text будет иметь контент.

person Patrick    schedule 20.04.2017

Это тоже сводило меня с ума. Мое решение было наконец найдено путем создания сеанса. Точно не знаю, как это сделать с помощью cURL. Возможно, придется использовать PHP или что-то в этом роде. Я использовал NodeJS

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

Мое приложение было написано на NodeJS. YMMV на других языках, но у меня сработало следующее:

var request = require('request');

/* GET home page. */
router.get('/', function(req, res, next) {
  var cookieJar = request.jar(); // <-- THIS IS THE IMPORTANT PART

  var options = { method: 'GET',
  url: 'https://test.atlassian.net/wiki/rest/api/content',
  jar: cookieJar,
  headers:
   {'cache-control': 'no-cache',
     authorization: 'Basic yourBase64AuthToken' } };

  // You'll need to make two requests, one to get the tokens,
  // and another to actually get your query to work
  request(options, function (error, response, body) {
    if (error) throw new Error(error);
    request(options, function (error, response, body) {
      if (error) throw new Error(error);
      console.log(body);
    });
  });

res.send('hello');
});
person rickrizzo    schedule 23.06.2017