1

RStudio / Hadley Wickham 'httr' R パッケージを使用して、Okta API GET 要求 (' List Users Assigned to Application ') からすべてのレコードを返そうとしています。次のリクエストは、呼び出しごとにレコードの最大制限 (500) を取得するために完全に正常に機能します。

oktaurl <- "https://mydomain.okta.com/api/v1/apps/applicationID/users?limit=500"

oktagetjson <- with_verbose(content(GET(oktaurl,
                                        add_headers("Authorization" = "bearer myapikey",
                                                       "Content-Type" =  "application/json;charset=UTF-8"))))

「oktagetjson」で返されたデータを「jsonlite」と R を使用して使用可能なデータ フレームに解析することは問題ではありません。ただし、この特定の API 呼び出しは、1 回の呼び出しで最大 500 レコードに制限されているため、すべての「Link:」ヘッダーを何らかの方法で取得してページ分割し、数千のレコードすべてを取得する必要があります。「Link:」ヘッダー自体は次の形式です。

Link: <https://mydomain.okta.com/api/v1/apps/applicationID/users?limit=500>; rel="self"

Link: <https://mydomain.okta.com/api/v1/apps/applicationID/users?after=random cursor string&limit=500>; rel="next"

(Okta API のドキュメントでは、ページネーションの構造についてここで説明しています)

私はここで立ち往生しています:

  1. 「oktagetjson <- with_verbose(content(GET(oktaurl, etc ... ) ...)」を呼び出して oktagetjstonオブジェクトを呼び出しますが、'Link:' ヘッダーはオブジェクト自体の一部として返されません。呼び出しheaders(HEAD("https://mydomain.okta.com/api/v1/apps/<applicationID>/users"))によっていくつかのヘッダーが返されますが、ページネーションの 'Link:' ヘッダーは返されません
  2. 「Link:」ヘッダーにはランダムなカーソル文字列が含まれているため、実際の形式を推測できません
  3. 必要な「Link:」ヘッダーをすべて取得できたとしても、R でそれらすべてを呼び出し、反復処理、ページ分割、再帰的に追跡して、数千レコードのデータセット全体のオブジェクトを構築する方法がわかりません。

残念ながら、要求、サービス プロバイダー、およびデータの性質上、実際のリンクとサンプル データを使用して完全に再現可能な例を提供することはできませんが、概念が明確であり、誰かが私を正しい方向に向けてくれることを願っています。この作業に 'httr' パッケージまたは R を使用しないようにします。

ご検討をお願いいたします。

4

2 に答える 2

0

少し前に何かを一緒にハッキングしましたが、それは機能しますが、確かにエレガンス賞を受賞することはありません. Okta アプリケーションにもユーザーを割り当てるように変更しました。他の会社/ディレクトリ データを監査/結合する場合に役立ちます。

library(jsonlite)
library(dplyr)
library(httr)
library(purrr)
library(stringi)
library(tidyr)

# create character vector to hold URLs we'll use later when we GET content
url_list <- as.character()

# list placeholder for GET content
okta_content <- list()

# initial URL construction parts for first URL
okta_urllimit = as.character("200")
okta_baseurl <- paste0("https://<your company>.okta.com/api/v1/users?limit=",okta_urllimit)

# next URL construction parts for 'next' URLs
basenexturl <- "https://<your company>.okta.com/api/v1/users?after="
baselimiturl <- "&limit=200"

# Pass initial URL to get first batch
okta_get01 <- httr::GET(okta_baseurl,
                         config = (
                           add_headers(Authorization = "SSWS <your Okta API key>")))


# append the URL vector 
url_list <- append(url_list, okta_baseurl)


# unlist the all_headers list element from the URL
testallheaders <- as.character(unlist(okta_get01$all_headers))

okta_content <- append(okta_content,content(okta_get01))

# if "next" is in the second link URL (testallheaders[16]) then iterate for as long as
# the next URL header element has "next" in it

while (
  grepl("next",testallheaders[16]) == 'TRUE'
)

{ 
  # parse the sha value 
  testparsenext <- regmatches(testallheaders[16], gregexpr('(?<=after=).*?(?=&limit)',testallheaders[16], perl=T))[[1]]
  # and create URL
  oktaurlnext <- paste0(basenexturl,testparsenext,baselimiturl)


  # iterate and replace 'okta_baseurl' with each subsquent oktaurlnext

  okta_get01 <- httr::GET(oktaurlnext,
                           config = (
                             add_headers(Authorization = "SSWS <your Okta API key>")))

  testallheaders <- as.character(unlist(okta_get01$all_headers))
  url_list <- append(url_list, oktaurlnext)
  okta_content <- append(okta_content,content(okta_get01))

  next
}


# Parse the results into something usable

oktagettojson <- toJSON(okta_content, simplifyDataFrame = TRUE, flatten = TRUE, recursive = TRUE)
oktagetdf <- fromJSON(oktagettojson, simplifyDataFrame = TRUE, flatten = TRUE)
dfnames <- names(oktagetdf)
oktagetdf <- oktagetdf %>% map_if(is.list, as.character)
oktagetdf <- do.call(cbind, lapply(oktagetdf, data.frame, stringsAsFactors=FALSE))
names(oktagetdf) <- dfnames

# adding columns to separate AD domain mastered account and domain names
oktagetdf <- separate(oktagetdf, profile.login,
                      into = c("credPrefix", "credSuffix"), sep = "@", remove = FALSE, extra = "drop")

# select some data frame columns of interest
okta_allusers <- subset(oktagetdf, select = c("id","status","created","lastLogin","profile.login","credPrefix", "credSuffix","profile.firstName","profile.lastName","profile.email","credentials.provider.type","credentials.provider.name"))
于 2016-07-26T19:01:19.817 に答える