Created
July 26, 2018 21:31
-
-
Save Radiergummi/eccf7acd7916b833f65fc65005c85fdb to your computer and use it in GitHub Desktop.
Micro ajax wrapper in vanilla JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Micro-wrapper for HTTP requests | |
* | |
* @type {Object} | |
*/ | |
window.http = { | |
/** | |
* Builds a valid URL. Unless a full URL (including a protocol) is given, the current origin will be used. | |
* | |
* @param {String} uri Request URI. | |
* @param {Object} params Query params as key-value pairs. | |
* @returns {URL} URL instance. | |
* @private | |
*/ | |
_buildUrl ( uri, params ) { | |
const url = uri.match( /^([a-z]+):\/\// ) ? new URL( '', uri ) : new URL( uri, window.location.origin ); | |
for ( let [ key, value ] of Object.entries( params ) ) { | |
if ( Array.isArray( value ) ) { | |
for ( let item of value ) { | |
url.searchParams.append( `${key}[]`, encodeURIComponent( item ) ); | |
} | |
continue; | |
} | |
url.searchParams.append( key, encodeURIComponent( value ) ); | |
} | |
return url; | |
}, | |
/** | |
* Assigns the defaults headers and any additional headers | |
* | |
* @param {Object} additionalHeaders | |
* @returns {Headers} | |
* @private | |
*/ | |
_buildHeaders ( additionalHeaders = {} ) { | |
return new Headers( | |
Object.assign( | |
{}, | |
additionalHeaders, | |
{ | |
// Set the content type to JSON | |
'Content-Type': 'application/json', | |
// Include the API token | |
Authorization: `Bearer ${window.api_token}`, | |
// Include the CSRF token | |
'X-CSRF-Token': window.csrf_token | |
} | |
) | |
); | |
}, | |
/** | |
* Holds all methods that can carry a request body | |
* | |
* @type {String[]} | |
* @private | |
*/ | |
_methodsWithBody: [ | |
'POST', | |
'PUT', | |
'PATCH' | |
], | |
/** | |
* Requests a resource | |
* | |
* @param {Object} [options] Request options | |
* @param {String} [options.uri] Request URI, defaults to "/" | |
* @param {Object} [options.params] URL query params, defaults to {} | |
* @param {String} [options.method] Request method, defaults to "GET" | |
* @param {Object} [options.headers] Request headers, defaults to {} | |
* @param {Object} [options.body] Optional request body, defaults to {} | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} Parsed response data | |
*/ | |
async request ( options = {} ) { | |
// Build the URL | |
const url = this._buildUrl( | |
options.hasOwnProperty( 'uri' ) ? options.uri : '/', | |
options.hasOwnProperty( 'params' ) ? options.params : {} | |
); | |
// Create the basic request options | |
const requestOptions = { | |
method: options.hasOwnProperty( 'method' ) ? options.method.toUpperCase() : 'GET', | |
headers: this._buildHeaders( options.hasOwnProperty( 'headers' ) ? options.headers : {} ) | |
}; | |
// If this is a method with a body, include any body now | |
if ( this._methodsWithBody.includes( requestOptions.method ) ) { | |
requestOptions.body = typeof options.body === 'string' | |
? options.body | |
: JSON.stringify( typeof options.body !== 'undefined' ? options.body : {} ); | |
} | |
// Fetch the response async | |
const response = await fetch( url, requestOptions ); | |
// If something has gone wrong, create a helpful error | |
if ( !response.ok ) { | |
throw new Error( `${options.method} Request failed [${response.status}]: ` + await response.text() ); | |
} | |
// Return the response JSON promise | |
return response.json(); | |
}, | |
/** | |
* Performs an HTTP GET request. | |
* | |
* @param {String} [uri] Request URL. May be relative to the origin. | |
* @param {Object} [params] Request query parameters as key-value pairs. | |
* @param {Object} [headers] Request headers as key-value pairs. | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} | |
*/ | |
async get ( uri = apiPrefix, params = {}, headers = {} ) { | |
return this.request( { method: 'GET', uri, params, headers } ); | |
}, | |
/** | |
* Performs an HTTP HEAD request. | |
* | |
* @param {String} [uri] Request URL. May be relative to the origin. | |
* @param {Object} [params] Request query parameters as key-value pairs. | |
* @param {Object} [headers] Request headers as key-value pairs. | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} | |
*/ | |
async head ( uri = apiPrefix, params = {}, headers = {} ) { | |
return this.request( { method: 'HEAD', uri, params, headers } ); | |
}, | |
/** | |
* Performs an HTTP DELETE request. | |
* | |
* @param {String} [uri] Request URL. May be relative to the origin. | |
* @param {Object} [params] Request query parameters as key-value pairs. | |
* @param {Object} [headers] Request headers as key-value pairs. | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} | |
*/ | |
async delete ( uri = apiPrefix, params = {}, headers = {} ) { | |
return this.request( { method: 'DELETE', uri, params, headers } ); | |
}, | |
/** | |
* Performs an HTTP POST request. | |
* | |
* @param {String} [uri] Request URL. May be relative to the origin. | |
* @param {Object|String} [body] Request body data. Will be converted to JSON. | |
* @param {Object} [params] Request query parameters as key-value pairs. | |
* @param {Object} [headers] Request headers as key-value pairs. | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} | |
*/ | |
async post ( uri = apiPrefix, body = {}, params = {}, headers = {} ) { | |
return this.request( { method: 'POST', uri, params, body, headers } ); | |
}, | |
/** | |
* Performs an HTTP PUT request. | |
* | |
* @param {String} [uri] Request URL. May be relative to the origin. | |
* @param {Object|String} [body] Request body data. Will be converted to JSON. | |
* @param {Object} [params] Request query parameters as key-value pairs. | |
* @param {Object} [headers] Request headers as key-value pairs. | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} | |
*/ | |
put ( uri = apiPrefix, body = {}, params = {}, headers = {} ) { | |
return this.request( { method: 'PUT', uri, params, body, headers } ); | |
}, | |
/** | |
* Performs an HTTP PATCH request. | |
* | |
* @param {String} [uri] Request URL. May be relative to the origin. | |
* @param {Object|String} [body] Request body data. Will be converted to JSON. | |
* @param {Object} [params] Request query parameters as key-value pairs. | |
* @param {Object} [headers] Request headers as key-value pairs. | |
* @returns {Promise<Array|Object|String|Boolean|Number|null>} | |
*/ | |
async patch ( uri = apiPrefix, body = {}, params = {}, headers = {} ) { | |
return this.request( { method: 'PATCH', uri, params, body, headers } ); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment