source/http/HttpJsonRequest.js
import HttpJsonResponse from "./HttpJsonResponse"
import HttpRequest from "./HttpRequest"
import ObjectManager from '../utils/ObjectManager'
/**
* Extends {@link HttpRequest} with transparent JSON request/response handling.
*
* @example <caption>Make a GET request</caption>
* const request = new JsonHttpRequest('http://example.com/api/users/')
* request.urlParser.queryString.set('search', 'doe')
* request.get()
* .then((response) => {
* console.log('Success!', response.bodydata)
* })
* .catch((error) => {
* console.error('Error:', error.toString())
* })
*/
export default class JsonHttpRequest extends HttpRequest {
/**
* Overridden to automatically convert request data to JSON.
*/
makeRequestBody(data) {
return JSON.stringify(data)
}
/**
* Overridden to return the response as a
* {@link HttpJsonResponse} instead if a HttpResponse.
*
* @returns {HttpJsonResponse}
*/
makeResponse() {
return new HttpJsonResponse(this.request)
}
/**
* Overridden to ensure we send the correct content-type header for
* json requests.
*/
setDefaultRequestHeaders(method) {
super.setDefaultRequestHeaders(method)
this.setRequestHeader('Accept', 'application/json')
this.setRequestHeader('Content-Type', 'application/json; charset=UTF-8')
}
/**
* Shortcut for getting all pagination pages and resolve an array
* of the results for all pages.
*
* Assumes your API uses pagination where the ``next`` page is returned as
* an URL, and that the results for each pagination page is an array.
*
* The first page retrived is whatever this request is configured for,
* so you can use this to do things like request pagination page 10 -> 20,
* just ensure the request is configured so that the page that would have
* been retrieved if you just used ``get()`` would have been page 10.
*
* @param {string} resultsAttribute The attribute in the response data that
* contains the results array. Defaults to ``results``.
* @param {string} nextUrlAttribute The attribute in the response data that
* contains the URL of the next pagination page. Defaults to ``next``.
* @param {number} maxPages The max number of pages to load. If this is ``null``
* (the default) we load all pages until the ``nextUrlAttribute`` value is ``null``
* or ``undefined``.
* @returns {Promise<any>}
*/
getAllPaginationPages (maxPages = null, resultsAttribute = 'results', nextUrlAttribute = 'next') {
return new Promise((resolve, reject) => {
const results = []
let loadedPageCount = 0
const recursiveLoadAllPagesFromApi = (request) => {
request.get()
.then((response) => {
results.push(...response.bodydata[resultsAttribute])
loadedPageCount += 1
let hasMaxPageCount = maxPages !== null && loadedPageCount >= maxPages
if (!hasMaxPageCount && ObjectManager.validate(response, 'bodydata', nextUrlAttribute)) {
const nextRequest = request.deepCopy()
nextRequest.setUrl(response.bodydata.next)
recursiveLoadAllPagesFromApi(nextRequest)
} else {
resolve(results)
}
})
.catch((error) => {
reject(error)
})
}
recursiveLoadAllPagesFromApi(this)
})
}
}