Cloudflare Workers integration

In a traditional Cloudflare setup, Cloudflare acts as a http proxy, and proxifies each and every request to your application, completely hiding your stack. You can however take advantage of Cloudflare Workers to make more from Cloudflare, and directly run redirection.io "on the edge", without even using your own infrastructure.

Cloudflare with redirection.io setup

Using redirection.io with Cloudflare Workers is pretty straightforward:

  1. create a redirection.io account;
  2. create a redirection.io organization and a project. At this step, you may want to invite your co-workers ;
  3. redirection.io project dashboardhead to the dashboard of your project and locate your "project token"
  4. Cloudflare Workers menulogin to your Cloudflare account, then click the "Workers" menu and hit the "launch editor" button ;
  5. Cloudflare Workers editorin the left part of the editor, paste our redirection.io Cloudflare Worker code, and replace the project token with your own value ;
  6. hit the "Save" button at the bottom of the editor ;
  7. Cloudflare Workers route tabin the "Routes" tab, enable this Cloudflare Worker for your whole website.

With all these steps completed, you should start getting traffic logs in your redirection.io's manager. You're all set :-)

redirection.io Cloudflare Worker code

addEventListener('fetch', event => {
  event.respondWith(redirectAndLog(event.request))
})

const options = {
  token: 'PASTE YOUR PROJECT TOKEN HERE',
  timeout: 2000,
}

async function redirectAndLog(request) {
  const [response, ruleId] = await redirectOrPass(request)
  log(request, response, ruleId)

  return response
}

async function redirectOrPass(request) {
  const urlObject = new URL(request.url)
  const context = {
    host: urlObject.host,
    request_uri: urlObject.pathname,
    user_agent: request.headers.get('user-agent'),
    referer: request.headers.get('referer'),
    scheme: urlObject.protocol.includes('https') ? 'https' : 'http',
    use_json: true,
  }

  let response

  try {
    response = await Promise.race([
      fetch('https://proxy.redirection.io/' + options.token + '/get', {
        method: 'POST',
        body: JSON.stringify(context),
      }),
      new Promise((_, reject) =>
        setTimeout(() => reject(new Error('Timeout')), options.timeout)
      ),
    ])
  } catch (error) {
    return [await fetch(request), null]
  }

  const data = await response.text()

  try {
    response = JSON.parse(data)
  } catch (error) {
    // If some errors play regular request, anyway request will be in error when no redirection (404)
    return [await fetch(request), null]
  }

  // Send gone response
  if (response.status_code === 410) {
    return [new Response('', { status: 410 }), response.matched_rule.id]
  }

  // Send redirection response
  return [new Response('', {
    status: Number(response.status_code),
    headers: {
      Location: response.location,
    },
  }),
  response.matched_rule.id]
}

async function log(request, response, ruleId) {
  const urlObject = new URL(request.url)
  const context = {
    status_code: response.status,
    host: urlObject.host,
    request_uri: urlObject.pathname,
    user_agent: request.headers.get('user-agent'),
    referer: request.headers.get('referer'),
    scheme: urlObject.protocol.includes('https') ? 'https' : 'http',
    use_json: true,
  }

  if (response.headers.get('Location')) {
    context.target = response.headers.get('Location');
  }

  if (ruleId) {
    context.rule_id = ruleId;
  }

  try {
    return await fetch(
      'https://proxy.redirection.io/' + options.token + '/log',
      {
        method: 'POST',
        body: JSON.stringify(context),
      }
    )
  } catch (error) {
    // Do nothing, do not matters if some logs are in errors
  }
}
Can't find your answer?