Skip to content

Instantly share code, notes, and snippets.

@Radiergummi
Created July 26, 2018 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Radiergummi/eccf7acd7916b833f65fc65005c85fdb to your computer and use it in GitHub Desktop.
Save Radiergummi/eccf7acd7916b833f65fc65005c85fdb to your computer and use it in GitHub Desktop.
Micro ajax wrapper in vanilla JS
/**
* 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