Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 49 additions & 38 deletions cloudflare.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ const { request } = require('undici')
const CLOUDFLARE_API_URL = 'https://api.cloudflare.com/client/v4/'

class CloudFlare {
constructor (zoneId, domain, options) {
constructor (zoneId, domain, options, requestDelay = 0) {
this.zoneId = zoneId
this.domain = domain
this.requestDelay = requestDelay

this.authorizationHeaders = null
if (options.email !== undefined && options.apiKey !== undefined) {
Expand All @@ -28,7 +29,7 @@ class CloudFlare {
async setIPv6 (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/ipv6`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -49,7 +50,7 @@ class CloudFlare {
async setEmailObfuscation (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/email_obfuscation`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -70,7 +71,7 @@ class CloudFlare {
async setSSL (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/ssl`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -91,7 +92,7 @@ class CloudFlare {
async setBrotli (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/brotli`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -112,7 +113,7 @@ class CloudFlare {
async getDNSRecords () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/dns_records`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -152,7 +153,7 @@ class CloudFlare {
async createDNSRecord (dnsRecord) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/dns_records`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand All @@ -173,7 +174,7 @@ class CloudFlare {
async updateDNSRecord (id, dnsRecord) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/dns_records/${id}`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -194,7 +195,7 @@ class CloudFlare {
async getFirewallRules () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/rulesets/phases/http_request_firewall_custom/entrypoint`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -228,7 +229,7 @@ class CloudFlare {
const rule = { ...firewallRule, ...filter }
delete rule.filter

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -258,7 +259,7 @@ class CloudFlare {
const rule = { ...firewallRule, ...filter }
delete rule.filter

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -309,7 +310,7 @@ class CloudFlare {
async getRedirectRules () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/rulesets/phases/http_request_dynamic_redirect/entrypoint`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand All @@ -335,7 +336,7 @@ class CloudFlare {
rules: []
}

const { statusCode: createStatusCode, body: createBody } = await request(createRulesetUrl, {
const { statusCode: createStatusCode, body: createBody } = await this.requestWithDelay(createRulesetUrl, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -373,7 +374,7 @@ class CloudFlare {
async createRedirectRule (rulesetId, redirectRule) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/rulesets/${rulesetId}/rules`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand All @@ -399,7 +400,7 @@ class CloudFlare {
async updateRedirectRule (rulesetId, ruleId, redirectRule) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/rulesets/${rulesetId}/rules/${ruleId}`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -450,7 +451,7 @@ class CloudFlare {
async setPolish (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/polish`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -471,7 +472,7 @@ class CloudFlare {
async setMinify (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/minify`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -492,7 +493,7 @@ class CloudFlare {
async setHTTP2Prioritization (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/h2_prioritization`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -513,7 +514,7 @@ class CloudFlare {
async setPrefetchURLs (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/prefetch_preload`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -534,7 +535,7 @@ class CloudFlare {
async setHttp2 (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/http2`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -555,7 +556,7 @@ class CloudFlare {
async setHttp3 (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/http3`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -576,7 +577,7 @@ class CloudFlare {
async set0RTT (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/0rtt`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -597,7 +598,7 @@ class CloudFlare {
async setArgoSmartRouting (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/argo/smart_routing`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -618,7 +619,7 @@ class CloudFlare {
async getPageRules () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand All @@ -638,7 +639,7 @@ class CloudFlare {
async updatePageRule (pageRuleId, pageRule) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules/${pageRuleId}`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PUT',
headers: {
...this.authorizationHeaders,
Expand All @@ -659,7 +660,7 @@ class CloudFlare {
async createPageRule (pageRule) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -708,7 +709,7 @@ class CloudFlare {
async getAvailablePageRules () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/pagerules/settings`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand All @@ -728,7 +729,7 @@ class CloudFlare {
async createWorkerRoute (workerRoute) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/workers/routes`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -762,7 +763,7 @@ class CloudFlare {
async getWorkerRoutes () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/workers/routes`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand All @@ -782,7 +783,7 @@ class CloudFlare {
async deleteWorkerRoute (routeId) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/workers/routes/${routeId}`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'DELETE',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -826,7 +827,7 @@ class CloudFlare {
async setHotlinkProtection (value) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/hotlink_protection`

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -895,7 +896,7 @@ class CloudFlare {

async getClientCerts () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/origin_tls_client_auth`
const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand All @@ -914,7 +915,7 @@ class CloudFlare {

async getCaCerts () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/acm/custom_trust_store`
const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'GET',
headers: {
...this.authorizationHeaders,
Expand All @@ -933,7 +934,7 @@ class CloudFlare {

async deleteClientCert (certId) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/origin_tls_client_auth/${certId}`
const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'DELETE',
headers: {
...this.authorizationHeaders,
Expand All @@ -951,7 +952,7 @@ class CloudFlare {

async deleteCaCert (certId) {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/acm/custom_trust_store/${certId}`
const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'DELETE',
headers: {
...this.authorizationHeaders,
Expand All @@ -975,7 +976,7 @@ class CloudFlare {
private_key: clientKey.replace(/\r?\n/g, '\n')
}

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand Down Expand Up @@ -1005,7 +1006,7 @@ class CloudFlare {
certificate: caCert.replace(/\r?\n/g, '\n')
}

const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'POST',
headers: {
...this.authorizationHeaders,
Expand All @@ -1030,7 +1031,7 @@ class CloudFlare {

async enableTLSClientAuth () {
const url = CLOUDFLARE_API_URL + `zones/${this.zoneId}/settings/tls_client_auth`
const { statusCode, body } = await request(url, {
const { statusCode, body } = await this.requestWithDelay(url, {
method: 'PATCH',
headers: {
...this.authorizationHeaders,
Expand All @@ -1047,6 +1048,16 @@ class CloudFlare {

console.log(`Enabled TSL Client Auth setting for domain ${this.domain}`, new Date().toISOString())
}

async requestWithDelay (url, options) {
const response = await request(url, options)
await delay(this.requestDelay)
return response
}
}

function delay (delayMs) {
return new Promise(resolve => setTimeout(resolve, delayMs))
}

module.exports = CloudFlare
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ async function applyCloudflareSettings (config) {
const accountEmail = process.env.CLOUDFLARE_EMAIL
const accountKey = process.env.CLOUDFLARE_API_KEY
const accountToken = process.env.CLOUDFLARE_TOKEN
const requestDelayMs = isNaN(parseInt(process.env.DELAY_MS, 10)) ? 500 : parseInt(process.env.DELAY_MS, 10)

if (config.enabled === false) {
console.log('Config is disabled and would not be applied:', config.domains)
Expand All @@ -56,7 +57,7 @@ async function applyCloudflareSettings (config) {
(accountToken && { token: accountToken }) ||
{ email: accountEmail, apiKey: accountKey }

const cloudFlare = new CloudFlare(zoneId, site.domain, options)
const cloudFlare = new CloudFlare(zoneId, site.domain, options, requestDelayMs)
const domainSettings = substituteDomainName(settings, site.domain)

for (const [key, value] of Object.entries(domainSettings)) {
Expand Down