UNPKG

@shopify/shopify-api

Version:

Shopify API Library for Node - accelerate development with support for authentication, graphql proxy, webhooks

119 lines (115 loc) 5.27 kB
'use strict'; var types = require('../types.js'); var index$1 = require('../../runtime/http/index.js'); var error = require('../error.js'); var index = require('../logger/index.js'); var types$1 = require('./types.js'); var validate = require('./validate.js'); const STATUS_TEXT_LOOKUP = { [types.StatusCode.Ok]: 'OK', [types.StatusCode.BadRequest]: 'Bad Request', [types.StatusCode.Unauthorized]: 'Unauthorized', [types.StatusCode.NotFound]: 'Not Found', [types.StatusCode.InternalServerError]: 'Internal Server Error', }; function process(config, webhookRegistry) { return async function process({ context, rawBody, ...adapterArgs }) { const response = { statusCode: types.StatusCode.Ok, statusText: STATUS_TEXT_LOOKUP[types.StatusCode.Ok], headers: {}, }; await index.logger(config).info('Receiving webhook request'); const webhookCheck = await validate.validateFactory(config)({ rawBody, ...adapterArgs, }); let errorMessage = 'Unknown error while handling webhook'; if (webhookCheck.valid) { const handlerResult = await callWebhookHandlers(config, webhookRegistry, webhookCheck, rawBody, context); response.statusCode = handlerResult.statusCode; if (!index$1.isOK(response)) { errorMessage = handlerResult.errorMessage || errorMessage; } } else { const errorResult = await handleInvalidWebhook(config, webhookCheck); response.statusCode = errorResult.statusCode; response.statusText = STATUS_TEXT_LOOKUP[response.statusCode]; errorMessage = errorResult.errorMessage; } const returnResponse = await index$1.abstractConvertResponse(response, adapterArgs); if (!index$1.isOK(response)) { throw new error.InvalidWebhookError({ message: errorMessage, response: returnResponse, }); } return Promise.resolve(returnResponse); }; } async function callWebhookHandlers(config, webhookRegistry, webhookCheck, rawBody, context) { const log = index.logger(config); const { hmac: _hmac, valid: _valid, ...loggingContext } = webhookCheck; await log.debug('Webhook request is valid, looking for HTTP handlers to call', loggingContext); const handlers = webhookRegistry[webhookCheck.topic] || []; const response = { statusCode: types.StatusCode.Ok }; let found = false; for (const handler of handlers) { if (handler.deliveryMethod !== types$1.DeliveryMethod.Http) { continue; } if (!handler.callback) { response.statusCode = types.StatusCode.InternalServerError; response.errorMessage = "Cannot call webhooks.process with a webhook handler that doesn't have a callback"; throw new error.MissingWebhookCallbackError({ message: response.errorMessage, response, }); } found = true; await log.debug('Found HTTP handler, triggering it', loggingContext); try { await handler.callback(webhookCheck.topic, webhookCheck.domain, rawBody, webhookCheck.webhookId, webhookCheck.apiVersion, ...(webhookCheck?.subTopic ? webhookCheck.subTopic : ''), context); } catch (error) { response.statusCode = types.StatusCode.InternalServerError; response.errorMessage = error.message; } } if (!found) { await log.debug('No HTTP handlers found', loggingContext); response.statusCode = types.StatusCode.NotFound; response.errorMessage = `No HTTP webhooks registered for topic ${webhookCheck.topic}`; } return response; } async function handleInvalidWebhook(config, webhookCheck) { const response = { statusCode: types.StatusCode.InternalServerError, errorMessage: 'Unknown error while handling webhook', }; switch (webhookCheck.reason) { case types$1.WebhookValidationErrorReason.MissingHeaders: response.statusCode = types.StatusCode.BadRequest; response.errorMessage = `Missing one or more of the required HTTP headers to process webhooks: [${webhookCheck.missingHeaders.join(', ')}]`; break; case types$1.WebhookValidationErrorReason.MissingBody: response.statusCode = types.StatusCode.BadRequest; response.errorMessage = 'No body was received when processing webhook'; break; case types$1.WebhookValidationErrorReason.MissingHmac: response.statusCode = types.StatusCode.BadRequest; response.errorMessage = `Missing HMAC header in request`; break; case types$1.WebhookValidationErrorReason.InvalidHmac: response.statusCode = types.StatusCode.Unauthorized; response.errorMessage = `Could not validate request HMAC`; break; } await index.logger(config).debug(`Webhook request is invalid, returning ${response.statusCode}: ${response.errorMessage}`); return response; } exports.process = process; //# sourceMappingURL=process.js.map