Skip to content

Commit

Permalink
adds support for verbose response when chacking domains
Browse files Browse the repository at this point in the history
- adds a new `checkVerbose` function to both hosting-node.js and hosting-api.js
- for checking a single domain, `checkVerbose` returns the entire payload from the api.thegreenwebfoundation.org endpoint
- for checking multiple domains, `checkVerbose` returns a dictionary of each domain mapped to its response payload

Fixes #189
  • Loading branch information
sfishel18 committed Feb 18, 2024
1 parent 0ed8775 commit 2f69619
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 29 deletions.
2 changes: 1 addition & 1 deletion __mocks__/https.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ https.get.mockImplementation((url, options, callback) => {
stream.emit(
"data",
Buffer.from(
`{"google.com": {"url":"google.com","hosted_by":"Google Inc.","hosted_by_website":"https://www.google.com","partner":null,"green":true}}`
`{"google.com": {"url":"google.com","hosted_by":"Google Inc.","hosted_by_website":"https://www.google.com","partner":null,"green":true}, "pchome.com": {"url":"pchome.com","green":false} }`
)
);
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import {
FIRST_TIME_VIEWING_PERCENTAGE,
RETURNING_VISITOR_PERCENTAGE,
} from "../constants/index.js";

// Shared type definitions to be used across different files

/**
* @typedef {Object} DomainCheckOptions options to control the behavior when checking a domain
* @property {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @property {boolean} verbose - Optional. Whether to return a verbose response.
*/

const formatNumber = (num) => parseFloat(num.toFixed(2));

function parseOptions(options) {
Expand Down
53 changes: 40 additions & 13 deletions src/hosting-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,50 +11,76 @@ import { getApiRequestHeaders } from "./helpers/index.js";
function check(domain, userAgentIdentifier) {
// is it a single domain or an array of them?
if (typeof domain === "string") {
return checkAgainstAPI(domain, userAgentIdentifier);
return checkAgainstAPI(domain, { userAgentIdentifier });
} else {
return checkDomainsAgainstAPI(domain, userAgentIdentifier);
return checkDomainsAgainstAPI(domain, { userAgentIdentifier });
}
}

/**
* Check if a domain is hosted by a green web host.
*
* Returns all information about the domain host instead of just a boolean indicator of green web hosting.
*
* @param {string|array} domain - The domain to check, or an array of domains to be checked.
* @param {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @returns {object} - An object representing the domain host information if a string was provided,
* or a dictionary of domain to host information if an array of domains was provided.
*/
function checkVerbose(domain, userAgentIdentifier) {
// is it a single domain or an array of them?
if (typeof domain === "string") {
return checkAgainstAPI(domain, { userAgentIdentifier, verbose: true });
} else {
return checkDomainsAgainstAPI(domain, {
userAgentIdentifier,
verbose: true,
});
}
}

/**
* Check if a domain is hosted by a green web host by querying the Green Web Foundation API.
* @param {string} domain - The domain to check.
* @param {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host.
* @param {DomainCheckOptions} options
* @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host if `options.verbose` is false,
* otherwise an object representing the domain host information.
*/
async function checkAgainstAPI(domain, userAgentIdentifier) {
async function checkAgainstAPI(domain, options = {}) {
const req = await fetch(
`https://api.thegreenwebfoundation.org/greencheck/${domain}`,
{
headers: getApiRequestHeaders(userAgentIdentifier),
headers: getApiRequestHeaders(options.userAgentIdentifier),
}
);
const res = await req.json();
return res.green;
return options.verbose ? res : res.green;
}

/**
* Check if an array of domains is hosted by a green web host by querying the Green Web Foundation API.
* @param {array} domains - An array of domains to check.
* @param {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @returns {array} - An array of domains that are hosted by a green web host.
* @param {DomainCheckOptions} options
* @returns {array} - An array of domains that are hosted by a green web host if `options.verbose` is false,
* otherwise a dictionary of domain to host information.
*/

async function checkDomainsAgainstAPI(domains, userAgentIdentifier) {
async function checkDomainsAgainstAPI(domains, options = {}) {
try {
const apiPath = "https://api.thegreenwebfoundation.org/v2/greencheckmulti";
const domainsString = JSON.stringify(domains);

const req = await fetch(`${apiPath}/${domainsString}`, {
headers: getApiRequestHeaders(userAgentIdentifier),
headers: getApiRequestHeaders(options.userAgentIdentifier),
});

const allGreenCheckResults = await req.json();

return greenDomainsFromResults(allGreenCheckResults);
return options.verbose
? allGreenCheckResults
: greenDomainsFromResults(allGreenCheckResults);
} catch (e) {
return [];
return options.verbose ? {} : [];
}
}

Expand All @@ -71,4 +97,5 @@ function greenDomainsFromResults(greenResults) {

export default {
check,
checkVerbose,
};
66 changes: 66 additions & 0 deletions src/hosting-api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,71 @@ describe("hostingAPI", () => {
expect(res).toContain("google.com");
});
});

describe("checking a single domain with #checkVerbose", () => {
it("using the API", async () => {
fetch.mockImplementation(() =>
Promise.resolve({
json: () =>
Promise.resolve({
url: "google.com",
hosted_by: "Google Inc.",
hosted_by_website: "https://www.google.com",
green: true,
}),
})
);
const res = await hosting.checkVerbose("google.com");
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenLastCalledWith(
expect.any(String),
expect.objectContaining({
headers: { "User-Agent": "co2js/1.2.34 " },
})
);
expect(res).toMatchObject({
green: true,
hosted_by: "Google Inc.",
hosted_by_website: "https://www.google.com",
url: "google.com",
});
});
});

describe("implicitly checking multiple domains with #checkVerbose", () => {
it("using the API", async () => {
fetch.mockImplementation(() =>
Promise.resolve({
json: () =>
Promise.resolve({
"google.com": {
url: "google.com",
hosted_by: "Google Inc.",
hosted_by_website: "https://www.google.com",
green: true,
},
"kochindustries.com": { url: "kochindustries.com", green: false },
}),
})
);
const res = await hosting.checkVerbose([
"google.com",
"kochindustries.com",
]);
expect(fetch).toHaveBeenCalledTimes(1);
expect(res).toEqual({
"google.com": expect.objectContaining({
green: true,
hosted_by: "Google Inc.",
hosted_by_website: "https://www.google.com",
url: "google.com",
}),
"kochindustries.com": expect.objectContaining({
url: "kochindustries.com",
green: false,
}),
});
});
});
});
/* eslint-enable jest/no-disabled-tests */
44 changes: 44 additions & 0 deletions src/hosting-json.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,52 @@ function checkDomainsInJSON(domains, db) {
return greenDomains;
}

/**
* Find the provided information a string or array of domains
* @param {string|array} domain - The domain to check, or an array of domains to be checked.
*/
function find(domain, db) {
// is it a single domain or an array of them?
if (typeof domain === "string") {
return findInJSON(domain, db);
} else {
return findDomainsInJSON(domain, db);
}
}

/**
* Check if a domain is hosted by a green web host by querying the database.
* @param {string} domain - The domain to check.
* @param {object} db - The database to check against.
* @returns {object} - An object representing the domain provided host information.
*/
function findInJSON(domain, db) {
if (db.indexOf(domain) > -1) {
return domain;
}
return {
url: domain,
green: false,
};
}

/**
* Check if an array of domains is hosted by a green web host by querying the database.
* @param {array} domains - An array of domains to check.
* @param {object} db - The database to check against.
* @returns {array} - A dictionary of domain to provided host information.
*/
function findDomainsInJSON(domains, db) {
const result = {};
for (let domain of domains) {
result[domain] = findInJSON(domain, db);
}
return result;
}

module.exports = {
check,
loadJSON,
greenDomainsFromResults,
find,
};
63 changes: 48 additions & 15 deletions src/hosting-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getApiRequestHeaders } from "./helpers/index.js";
* @return {string}
*/
async function getBody(url, userAgentIdentifier) {
debugger;

Check failure on line 25 in src/hosting-node.js

View workflow job for this annotation

GitHub Actions / build (14.x)

Unexpected 'debugger' statement

Check failure on line 25 in src/hosting-node.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected 'debugger' statement
return new Promise(function (resolve, reject) {
// Do async job
const req = https.get(
Expand Down Expand Up @@ -63,47 +64,78 @@ function check(domain, db, userAgentIdentifier) {

// is it a single domain or an array of them?
if (typeof domain === "string") {
return checkAgainstAPI(domain, userAgentIdentifier);
return checkAgainstAPI(domain, { userAgentIdentifier });
} else {
return checkDomainsAgainstAPI(domain, userAgentIdentifier);
return checkDomainsAgainstAPI(domain, { userAgentIdentifier });
}
}

/**
* Check if a domain is hosted by a green web host.
*
* Returns all information about the domain host instead of just a boolean indicator of green web hosting.
*
* @param {string|array} domain - The domain to check, or an array of domains to be checked.
* @param {object} db - Optional. A database object to use for lookups.
* @param {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @returns {object} - An object representing the domain host information if a string was provided,
* or a dictionary of domain to host information if an array of domains was provided.
*/
function checkVerbose(domain, db, userAgentIdentifier) {
if (db) {
return hostingJSON.check(domain, db);
}
// is it a single domain or an array of them?
if (typeof domain === "string") {
return checkAgainstAPI(domain, { userAgentIdentifier, verbose: true });
} else {
return checkDomainsAgainstAPI(domain, {
userAgentIdentifier,
verbose: true,
});
}
}

/**
* Check if a domain is hosted by a green web host by querying the Green Web Foundation API.
* @param {string} domain - The domain to check.
* @param {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host.
* @param {DomainCheckOptions} options
* @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host if `options.verbose` is false,
* otherwise an object representing the domain host information.
*/
async function checkAgainstAPI(domain, userAgentIdentifier) {
async function checkAgainstAPI(domain, options = {}) {
const res = JSON.parse(
await getBody(
`https://api.thegreenwebfoundation.org/greencheck/${domain}`,
userAgentIdentifier
options.userAgentIdentifier
)
);
return res.green;
return options.verbose ? res : res.green;
}

/**
* Check if an array of domains is hosted by a green web host by querying the Green Web Foundation API.
* @param {array} domains - An array of domains to check.
* @param {string} userAgentIdentifier - Optional. The app, site, or organisation that is making the request.
* @returns {array} - An array of domains that are hosted by a green web host.
* @param {DomainCheckOptions} options
* @returns {array} - An array of domains that are hosted by a green web host if `options.verbose` is false,
* otherwise a dictionary of domain to host information.
*/
async function checkDomainsAgainstAPI(domains, userAgentIdentifier) {
async function checkDomainsAgainstAPI(domains, options = {}) {
try {
debugger;

Check failure on line 125 in src/hosting-node.js

View workflow job for this annotation

GitHub Actions / build (14.x)

Unexpected 'debugger' statement

Check failure on line 125 in src/hosting-node.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected 'debugger' statement
const allGreenCheckResults = JSON.parse(
await getBody(
`https://api.thegreenwebfoundation.org/v2/greencheckmulti/${JSON.stringify(
domains
`https://api.thegreenwebfoundation.org/v2/greencheckmulti/${encodeURIComponent(
JSON.stringify(domains)
)}`,
userAgentIdentifier
options.userAgentIdentifier
)
);
return hostingJSON.greenDomainsFromResults(allGreenCheckResults);
return options.verbose
? allGreenCheckResults
: hostingJSON.greenDomainsFromResults(allGreenCheckResults);
} catch (e) {
return [];
return options.verbose ? {} : [];
}
}

Expand All @@ -121,6 +153,7 @@ async function checkPage(pageXray, db) {
export default {
check,
checkPage,
checkVerbose,
greendomains: hostingJSON.greenDomainsFromResults,
loadJSON: hostingJSON.loadJSON,
};
30 changes: 30 additions & 0 deletions src/hosting.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,34 @@ describe("hosting", () => {
expect(res).toContain("google.com");
});
});

describe("checking a single domain with #checkVerbose", () => {
it("use the API instead", async () => {
const res = await hosting.checkVerbose("google.com");
expect(res).toMatchObject({
green: true,
hosted_by: "Google Inc.",
hosted_by_website: "https://www.google.com",
url: "google.com",
});
});
});

describe("checking multiple domains with #checkVerbose", () => {
it("use the API instead", async () => {
const res = await hosting.checkVerbose(["google.com", "pchome.com"]);
expect(res).toEqual({
"google.com": expect.objectContaining({
green: true,
hosted_by: "Google Inc.",
hosted_by_website: "https://www.google.com",
url: "google.com",
}),
"pchome.com": expect.objectContaining({
url: "pchome.com",
green: false,
}),
});
});
});
});

0 comments on commit 2f69619

Please sign in to comment.