2022-11-08 06:18:47 +01:00
/**
* A function to make HTTP requests via the server to avoid CORS-errors.
*
* @param {string} url the url to fetch from
* @param {string} type what contenttype to expect in the response, can be "json" or "xml"
* @param {boolean} useCorsProxy A flag to indicate
* @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send
2023-02-20 20:04:40 +01:00
* @param {Array.<string>} expectedResponseHeaders the expected HTTP headers to receive
* @returns {Promise} resolved when the fetch is done. The response headers is placed in a headers-property (provided the response does not already contain a headers-property).
2022-11-08 06:18:47 +01:00
*/
async function performWebRequest ( url , type = "json" , useCorsProxy = false , requestHeaders = undefined , expectedResponseHeaders = undefined ) {
const request = {};
if ( useCorsProxy ) {
url = getCorsUrl ( url , requestHeaders , expectedResponseHeaders );
} else {
request . headers = getHeadersToSend ( requestHeaders );
}
const response = await fetch ( url , request );
const data = await response . text ();
if ( type === "xml" ) {
return new DOMParser (). parseFromString ( data , "text/html" );
} else {
if ( ! data || ! data . length > 0 ) return undefined ;
const dataResponse = JSON . parse ( data );
if ( ! dataResponse . headers ) {
dataResponse . headers = getHeadersFromResponse ( expectedResponseHeaders , response );
}
return dataResponse ;
}
}
/**
* Gets a URL that will be used when calling the CORS-method on the server.
*
* @param {string} url the url to fetch from
* @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send
2023-02-20 20:04:40 +01:00
* @param {Array.<string>} expectedResponseHeaders the expected HTTP headers to receive
2022-11-08 06:18:47 +01:00
* @returns {string} to be used as URL when calling CORS-method on server.
*/
const getCorsUrl = function ( url , requestHeaders , expectedResponseHeaders ) {
if ( ! url || url . length < 1 ) {
throw new Error ( `Invalid URL: ${ url } ` );
} else {
let corsUrl = ` ${ location . protocol } // ${ location . host } /cors?` ;
const requestHeaderString = getRequestHeaderString ( requestHeaders );
if ( requestHeaderString ) corsUrl = ` ${ corsUrl } sendheaders= ${ requestHeaderString } ` ;
const expectedResponseHeadersString = getExpectedResponseHeadersString ( expectedResponseHeaders );
if ( requestHeaderString && expectedResponseHeadersString ) {
corsUrl = ` ${ corsUrl } &expectedheaders= ${ expectedResponseHeadersString } ` ;
} else if ( expectedResponseHeadersString ) {
corsUrl = ` ${ corsUrl } expectedheaders= ${ expectedResponseHeadersString } ` ;
}
if ( requestHeaderString || expectedResponseHeadersString ) {
return ` ${ corsUrl } &url= ${ url } ` ;
}
return ` ${ corsUrl } url= ${ url } ` ;
}
};
/**
* Gets the part of the CORS URL that represents the HTTP headers to send.
*
* @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send
* @returns {string} to be used as request-headers component in CORS URL.
*/
const getRequestHeaderString = function ( requestHeaders ) {
let requestHeaderString = "" ;
if ( requestHeaders ) {
for ( const header of requestHeaders ) {
if ( requestHeaderString . length === 0 ) {
requestHeaderString = ` ${ header . name } : ${ encodeURIComponent ( header . value ) } ` ;
} else {
requestHeaderString = ` ${ requestHeaderString } , ${ header . name } : ${ encodeURIComponent ( header . value ) } ` ;
}
}
return requestHeaderString ;
}
return undefined ;
};
/**
2023-02-20 20:04:40 +01:00
* Gets headers and values to attach to the web request.
2022-11-08 06:18:47 +01:00
*
* @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send
* @returns {object} An object specifying name and value of the headers.
*/
const getHeadersToSend = ( requestHeaders ) => {
const headersToSend = {};
if ( requestHeaders ) {
for ( const header of requestHeaders ) {
headersToSend [ header . name ] = header . value ;
}
}
return headersToSend ;
};
/**
2023-02-20 20:04:40 +01:00
* Gets the part of the CORS URL that represents the expected HTTP headers to receive.
2022-11-08 06:18:47 +01:00
*
2023-02-20 20:04:40 +01:00
* @param {Array.<string>} expectedResponseHeaders the expected HTTP headers to receive
2022-11-08 06:18:47 +01:00
* @returns {string} to be used as the expected HTTP-headers component in CORS URL.
*/
const getExpectedResponseHeadersString = function ( expectedResponseHeaders ) {
let expectedResponseHeadersString = "" ;
if ( expectedResponseHeaders ) {
for ( const header of expectedResponseHeaders ) {
if ( expectedResponseHeadersString . length === 0 ) {
expectedResponseHeadersString = ` ${ header } ` ;
} else {
expectedResponseHeadersString = ` ${ expectedResponseHeadersString } , ${ header } ` ;
}
}
return expectedResponseHeaders ;
}
return undefined ;
};
/**
* Gets the values for the expected headers from the response.
*
2023-02-20 20:04:40 +01:00
* @param {Array.<string>} expectedResponseHeaders the expected HTTP headers to receive
2022-11-08 06:18:47 +01:00
* @param {Response} response the HTTP response
* @returns {string} to be used as the expected HTTP-headers component in CORS URL.
*/
const getHeadersFromResponse = ( expectedResponseHeaders , response ) => {
const responseHeaders = [];
if ( expectedResponseHeaders ) {
for ( const header of expectedResponseHeaders ) {
const headerValue = response . headers . get ( header );
responseHeaders . push ({ name : header , value : headerValue });
}
}
return responseHeaders ;
};
if ( typeof module !== "undefined" )
module . exports = {
performWebRequest
};