All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kiwiproject.changelog.github.GitHubPagingHelper.kt Maven / Gradle / Ivy

package org.kiwiproject.changelog.github

import com.google.common.annotations.VisibleForTesting
import org.apache.commons.lang3.StringUtils.abbreviate
import org.kiwiproject.changelog.github.GitHubApi.GitHubResponse

private const val NO_NEXT_PAGE = "none"

class GitHubPagingHelper {

    fun paginate(api: GitHubApi, firstPageUrl: String, responseHandler: (Int, GitHubResponse) -> Unit) {
        var nextPageUrl = firstPageUrl
        var page = 1

        while (hasNextPage(nextPageUrl)) {
            val response = api.get(nextPageUrl)
            checkOkResponse(response)

            responseHandler(page, response)

            nextPageUrl = getNextPageUrl(response.linkHeader)

            ++page
        }
    }

    private fun hasNextPage(nextPageUrl: String): Boolean {
        return NO_NEXT_PAGE != nextPageUrl
    }

    @VisibleForTesting
    fun checkOkResponse(response: GitHubResponse) {
        check(response.statusCode == 200) {
            val truncatedContent = abbreviate(response.content, 100)
            "GET ${response.requestUri} failed, response code ${response.statusCode}, response body\n:$truncatedContent"
        }
    }

    @VisibleForTesting
    fun getNextPageUrl(linkHeader: String?) : String {
        if (linkHeader == null) {
            return NO_NEXT_PAGE
        }

        // See GitHub API doc : https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api

        // Example Link header and value:
        // Link: ; rel="next",
        //       ; rel="last"

        val linkRel = linkHeader.split(",")
            .firstOrNull { url -> url.contains("rel=\"next\"") }

        return linkRel?.substring(
            startIndex = linkRel.indexOf("http"),
            endIndex = linkRel.indexOf(">; rel=\"next\"")
        ) ?: NO_NEXT_PAGE
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy