From d7099fbed0e358ba1bc8d9e938f191fde91d1dd6 Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Thu, 20 Aug 2020 02:51:19 -0400 Subject: [PATCH] trying to be clever in error handling didn't work.... will fix later --- functions/send_view.js | 101 +++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/functions/send_view.js b/functions/send_view.js index 98de8d59..c2d48159 100644 --- a/functions/send_view.js +++ b/functions/send_view.js @@ -2,79 +2,82 @@ const axios = require("axios"); exports.handler = function (event, context, callback) { try { - // if triggered as an image without JS (i.e. from AMP pages) set `?noscript=true` - const noScript = event.queryStringParameters["noscript"] === "true"; + // attach a timer to axios to debug response time from endpoint + // https://stackoverflow.com/questions/62186171/measure-network-latency-in-react-native/62257712#62257712 + (function (instance) { + instance.interceptors.request.use((request) => { + request.startTime = Date.now(); + return request; + }); - // https://docs.simpleanalytics.com/without-javascript - const endpointHost = "queue.simpleanalyticscdn.com"; - const endpointPath = noScript ? "noscript.gif" : "simple.gif"; - const endpointUrl = "https://" + endpointHost + "/" + endpointPath; + instance.interceptors.response.use((response) => { + response.elapsedTime = Number(Date.now() - response.config.startTime).toFixed(); + return response; + }); + })(axios); - // pass these headers along to SA + // pass these URL parameters along to endpoint + const reqQuery = event.queryStringParameters; + reqQuery["ignore-dnt"] = "true"; // this isn't nefarious, we're not tracking in the first place! + + // pass these optional headers along to endpoint const reqHeaders = { referer: event.headers["referer"] || "", "user-agent": event.headers["user-agent"] || "", }; - // pass these URL parameters along to SA - const reqQuery = event.queryStringParameters; - reqQuery["ignore-dnt"] = "true"; // this isn't nefarious, we're not tracking in the first place! - - const reqConfig = { - method: "GET", - url: endpointUrl, - headers: reqHeaders, - params: reqQuery, - responseType: "arraybuffer", - timeout: 2000, - }; - - console.info(`Proxying ${reqQuery["type"]} to ${endpointPath} ...`); + // if triggered as an image without JS (i.e. from AMP pages) set `?noscript=true` + // https://docs.simpleanalytics.com/without-javascript + const endpointHost = "queue.simpleanalyticscdn.com"; + const endpointPath = reqQuery["noscript"] === "true" ? "noscript.gif" : "simple.gif"; + const endpointUrl = "https://" + endpointHost + "/" + endpointPath; axios - .request(reqConfig) + .request({ + method: "GET", + url: endpointUrl, + headers: reqHeaders, + params: reqQuery, + responseType: "arraybuffer", + timeout: 2000, + }) .then(function (response) { - // parse the feedback message from SA + console.info( + `${response.status} ${response.statusText} | ${response.elapsedTime}ms | ${response.headers["simple-analytics-feedback"]}` + ); + + // parse the feedback message from endpoint const apiFeedback = response.headers["simple-analytics-feedback"] || "No feedback from Simple Analytics."; - const shortFeedback = apiFeedback.toLowerCase().includes("thanks for sending") ? "OK" : `ERROR: ${apiFeedback}`; - - console.info(response.status, apiFeedback); - - // imitate the headers that would normally be sent back from SA's pixel - const resHeaders = { - "Content-Type": "image/gif", - "Cache-Control": "private, no-cache, no-store, must-revalidate", - Expires: "0", - Pragma: "no-cache", - "X-API-Response": shortFeedback, - "X-API-Endpoint": endpointHost, - }; + const shortFeedback = apiFeedback.toLowerCase().includes("thanks for sending ") + ? "OK" + : `ERROR: ${apiFeedback}`; // reasoning for base64 encoding: // https://community.netlify.com/t/debugging-a-function-returns-502/429/12 callback(null, { statusCode: response.status, - headers: resHeaders, + headers: { + "Content-Type": "image/gif", + "Cache-Control": "private, no-cache, no-store, must-revalidate", + Expires: "0", + Pragma: "no-cache", + "x-api-response": shortFeedback, + "x-api-latency": response.elapsedTime, + }, body: response.data.toString("base64"), isBase64Encoded: true, }); }) .catch(function (error) { - // this indicates a function error, NOT an error returned from SA - throw error; + // this indicates a request error, NOT an error in the endpoint's reponse + console.error(error.message); + + callback(Error(error)); }); } catch (error) { // something went VERY wrong... - console.log(error.message); + console.error(error.message); - callback(null, { - statusCode: 500, - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - error: error.message, - }), - }); + callback(Error(error)); } };