Invoke-WebRequest Canvas LMS API нумерация страниц
Я не могу найти какие-либо примеры по этой теме, и я хотел бы знать, как это сделать. Может кто-нибудь показать мне пример или указать ссылку на то, как сделать пагинацию в powershell с помощью веб-запроса Invoke? Проблема, с которой я сталкиваюсь, заключается в том, что я выполняю вызовы API на сервере, который возвращает только 100 строк за раз. Чтобы получить больше строк, мне нужно было бы сделать второй вызов на сервер. Я понятия не имею, как это сделать. Если это поможет, вот ссылка, предоставленная Canvas LMS и моим кодом, который у меня есть.
пагинация
По умолчанию запросы, возвращающие несколько элементов, будут разбиты на 10 элементов. Вы можете установить пользовательское количество для каждой страницы с параметром? Per_page. Существует неограниченное ограничение на размер per_page, поэтому всегда проверяйте заголовок ссылки.
Для получения дополнительных страниц следует использовать возвращаемые заголовки ссылок. Эти ссылки должны рассматриваться как непрозрачные. Это будут абсолютные URL-адреса, которые включают все параметры, необходимые для извлечения нужной текущей, следующей, предыдущей, первой или последней страницы. Единственным исключением является то, что если для аутентификации отправляется параметр access_token, он не будет включен в возвращаемые ссылки и должен быть добавлен повторно.
Информация о нумерации страниц предоставляется в заголовке ссылки:
Link: <https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueA>; rel="current", <https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueB>;> rel="next", <https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueC>;> rel="first", <https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueD>;> rel="last"
Возможные значения rel:
current - ссылка на текущую страницу результатов. next - ссылка на следующую страницу результатов. prev - ссылка на предыдущую страницу результатов. first - ссылка на первую страницу результатов. last - ссылка на последнюю страницу результатов. Они будут включены только в том случае, если они актуальны. Например, первая страница результатов не будет содержать ссылку rel="prev". rel="last" также может быть исключен, если общее количество слишком дорого для вычисления по каждому запросу.
Начальный продукт
$curlly=""
$url_main="https://[instance].instructure.com/api/v1/accounts/1/courses?per_page=1"
$security_token="imhungry"
$header = @{"Authorization"="Bearer "+ $security_token; "rel"="last"}
$curlly=Invoke-WebRequest -Headers $header -Method Get -Uri $url_main
$curlly = ConvertFrom-Json $curlly.Content
foreach($course in $curlly)
{
$course.name
}
$curlly.Count
Конечный продукт
##This is an example on how to use pagination in powershell
$url_main="https://[instance].instructure.com/api/v1/accounts/1/courses?per_page=100"
$security_token="boyimhungry"
$header = @{"Authorization"="Bearer "+ $security_token}
$purlly=Invoke-WebRequest -Headers $header -Method Get -Uri $url_main
$curlly = ConvertFrom-Json $purlly.Content
$url_main = $purlly.Headers.Link.Split(",")[1].Replace("<","").Replace(">","") ## you can get away with just doing one replace("<","") but it looks neater this way
while( !$url_main.Contains("prev"))
{
$purlly=Invoke-WebRequest -Headers $header -Method Get -Uri $url_main
$curlly += ConvertFrom-Json $purlly.Content
$url_main = $purlly.Headers.Link.Split(",")[1].Replace("<","").Replace(">","")
cls
$curlly.Count
$url_main
}
foreach($course in $curlly)
{
$course.name
}
$curlly.Count
2 ответа
Это похоже на настоящую боль.
На каждый постраничный запрос вы получите Link
заголовок, который содержит одну или несколько ссылок, которые они описывают.
Для ваших целей (последовательное чтение каждого результата) вам действительно нужно иметь дело со ссылкой rel=next
ссылка на сайт. Вы бы продолжали называть это, пока нет rel=next
больше, как вы узнаете, что вы на последней странице.
Вы не предоставляете релевантную часть; это не заголовок. Это то, что позволяет вам определить, какую ссылку использовать, а затем использовать эту ссылку как есть.
Итак, основной обзор того, что вам нужно сделать:
- Сделайте первый запрос.
- Прочитайте возвращенное
Link
заголовок и найдите тот, который соответствуетrel=next
(если его там нет, все готово). - Сделайте следующий запрос прямо по найденной вами ссылке.
- Разобрать
Link
Заголовок еще раз, повторите.
Я знаю, что вы приняли ответ, но я подумал, что приведу пример кода на тот случай, если кому-то понадобится. Этот пример получает список всех наших пользователей Canvas. Не страшный процесс - большая часть работы выполняется с помощью цикла из четырех строк do.. while.
$token = "YOUR_ACCESS_TOKEN"
$headers = @{"Authorization"="Bearer "+$token}
$allCanvasUsers = New-Object System.Collections.ArrayList @()
$pageNumber = 1
Function RequestPageOfUsers($page) {
$script:resultsPage = Invoke-WebRequest -Method GET -Headers $headers -Uri "https://$domain/api/v1/accounts/self/users?per_page=100&search_term=P00&page=$page"
$usersPage = ConvertFrom-Json $resultsPage.Content
foreach ($user in $usersPage) {
$script:allCanvasUsers.Add($user)
}
}
do {
RequestPageOfUsers $pageNumber
$pageNumber++
} while ($resultsPage.Headers.Link.Contains('rel="next"'))
Ответ Дэвида Бейкера фантастический и почти сработал для меня, но возвращал только одну страницу. Не знаю почему, но тест CONTAINS('...') всегда возвращал FALSE.
Чтобы заставить это работать, мне пришлось внести незначительные изменения в условие WHILE. Для меня объект ResultsPage был возвращен со свойством RelationLink, которое представляет собой словарь, содержащий пары ключ-значение. На последней странице в наборе результатов с разбивкой на страницы нет клавиши "Далее". Итак, мой цикл DO-WHILE выполняется до тех пор, пока значение "Next" не будет равно нулю.
$Token = '<YOUR-TOKEN>'
$headers = @{"Authorization"="Bearer "+$token}
$allCanvasUsers = New-Object System.Collections.ArrayList @()
$pageNumber = 1
Function RequestPageOfUsers($page) {
$script:resultsPage = Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://<DOMAIN>:443/api/v1/accounts/self/users?per_page=100&page=$page"
$usersPage = ConvertFrom-Json $resultsPage.Content
foreach ($user in $usersPage) {
$script:allCanvasUsers.Add($user)
}
}
do {
RequestPageOfUsers $pageNumber
$pageNumber++
} while ($resultsPage.RelationLink.Next -NE $NULL)