next-csrf
Version:
CSRF mitigation library for Next.js
182 lines (171 loc) • 5.92 kB
JavaScript
/**
* Copyright 2017 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
;
const treeParser = require('./TreeParser');
const log = require('./log');
let fetch = require('cross-fetch');
const RuntimeVersion = require('@ampproject/toolbox-runtime-version/lib/RuntimeVersion');
const fetchRuntimeParameters = require('./fetchRuntimeParameters');
/**
* AMP Optimizer Configuration only applying AMP validity perserving transformations.
*/
const TRANSFORMATIONS_AMP_FIRST = [
// Adds missing AMP tags
'AddMandatoryTags',
// Optional Markdown compatibility
// needs to run before ServerSideRendering
'Markdown',
// Adds missing AMP extensions
'AutoExtensionImporter',
// Applies image optimizations, must run before PreloadHeroImage
'OptimizeImages',
// Detect hero image and preload link rel=preload, needs to run after OptimizeImages
'PreloadHeroImage',
// Applies server-side-rendering optimizations
'ServerSideRendering',
// Removes the boilerplate
// needs to run after ServerSideRendering
'AmpBoilerplateTransformer',
// Optimizes script import order
// needs to run after ServerSideRendering
'ReorderHeadTransformer',
// needs to run after ReorderHeadTransformer
'RewriteAmpUrls',
'GoogleFontsPreconnect',
'PruneDuplicateResourceHints',
// Move keyframes into a separate style tag
'SeparateKeyframes',
'AddTransformedFlag',
// Minifies HTML, JSON, inline amp-script
'MinifyHtml',
// Inject CSP script has required for inline amp-script
// needs to run after MinifyHtml which changes the inline script
'AmpScriptCsp',
];
/**
* AMP Optimizer Configuration for transformations resulting in invalid AMP pages setting up paired AMP mode.
*
* @deprecated
*/
const TRANSFORMATIONS_PAIRED_AMP = [
// Adds missing AMP extensions
'AutoExtensionImporter',
// Adds a link to the valid AMP version
'AddAmpLink',
// Applies image optimizations, must run before PreloadHeroImage
'OptimizeImages',
// Detect hero image and preload link rel=preload
'PreloadHeroImage',
// Applies server-side-rendering optimizations
'ServerSideRendering',
// Removes ⚡ or 'amp' from the html tag
'RemoveAmpAttribute',
// Removes the boilerplate
// needs to run after ServerSideRendering
'AmpBoilerplateTransformer',
// Optimizes script import order
// needs to run after ServerSideRendering
'ReorderHeadTransformer',
// needs to run after ReorderHeadTransformer
'RewriteAmpUrls',
'GoogleFontsPreconnect',
'PruneDuplicateResourceHints',
'AddBlurryImagePlaceholders',
'SeparateKeyframes',
'AddTransformedFlag',
// Minifies HTML, JSON, inline amp-script
'MinifyHtml',
// Inject CSP script has required for inline amp-script
// needs to run after MinifyHtml which changes the inline script
'AmpScriptCsp',
];
const DEFAULT_CONFIG = {
fetch,
log,
transformations: TRANSFORMATIONS_AMP_FIRST,
verbose: false,
};
/**
* Applies a set of transformations to a DOM tree.
*/
class DomTransformer {
/**
* Create a DomTransformer.
* @param {Object} config - The config.
* @param {Array.<Transformer>} config.transformers - a list of transformers to be applied.
*/
constructor(config = DEFAULT_CONFIG) {
this.setConfig(config);
}
/**
* Transforms an html string.
* @param {string} html - a string containing valid HTML.
* @param {Object} params - a dictionary containing transformer specific parameters.
* @return {string} - the transformed html string
*/
async transformHtml(html, params) {
const tree = await treeParser.parse(html);
await this.transformTree(tree, params);
return treeParser.serialize(tree);
}
/**
* Transforms a DOM tree.
* @param {Tree} tree - a DOM tree.
* @param {Object} customParams - a dictionary containing transformer specific parameters.
*/
async transformTree(tree, customParams = {}) {
log.verbose(customParams.verbose || false);
const runtimeParameters = await fetchRuntimeParameters(this.config, customParams);
const sequence = async (promise, transformer) => {
await promise;
return transformer.transform(tree, runtimeParameters);
};
return this.transformers_.reduce(sequence, Promise.resolve());
}
/**
* Set the config.
* @param {Object} config - The config.
* @param {boolean} config.verbose - true if verbose mode should be enabled [default: false].
* @param {Object} config.fetch - the fetch implementation to use.
* @param {Array.<Transformer>} config.transformations - a list of transformers to be applied.
*/
setConfig(config) {
this.config = Object.assign({}, DEFAULT_CONFIG, config);
if (!this.config.runtimeVersion) {
// Re-use custom fetch implementation for runtime version provider
this.config.runtimeVersion = new RuntimeVersion(this.config.fetch);
}
log.verbose(this.config.verbose);
this.initTransformers_(this.config);
}
/**
* @private
*/
initTransformers_(config) {
this.transformers_ = config.transformations.map((Transformer) => {
if (typeof Transformer === 'string') {
Transformer = require(`./transformers/${Transformer}.js`);
}
return new Transformer(config);
});
}
}
module.exports = {
DomTransformer,
DEFAULT_CONFIG,
TRANSFORMATIONS_AMP_FIRST,
TRANSFORMATIONS_PAIRED_AMP,
};