Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sitecore-jss/sitecore-jss-proxy

Package Overview
Dependencies
Maintainers
4
Versions
1399
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sitecore-jss/sitecore-jss-proxy - npm Package Compare versions

Comparing version 6.0.0 to 7.0.0

235

dist/index.js

@@ -1,1 +0,234 @@

'use strict';var _extends=Object.assign||function(a){for(var b,c=1;c<arguments.length;c++)for(var d in b=arguments[c],b)Object.prototype.hasOwnProperty.call(b,d)&&(a[d]=b[d]);return a},_httpProxyMiddleware=require('http-proxy-middleware'),_httpProxyMiddleware2=_interopRequireDefault(_httpProxyMiddleware),_setCookieParser=require('set-cookie-parser'),_setCookieParser2=_interopRequireDefault(_setCookieParser),_zlib=require('zlib'),_zlib2=_interopRequireDefault(_zlib),_util=require('./util');Object.defineProperty(exports,'__esModule',{value:!0}),exports.rewriteRequestPath=exports.removeEmptyAnalyticsCookie=void 0;function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var removeEmptyAnalyticsCookie=exports.removeEmptyAnalyticsCookie=function(a){var b=_setCookieParser2.default.parse(a.headers['set-cookie']);if(b){var c=b.findIndex(function(a){return'SC_ANALYTICS_GLOBAL_COOKIE'===a.name});if(-1!==c){var d=b[c];d&&''===d.value&&(b.splice(c,1),a.headers['set-cookie']=b)}}},renderAppToResponse=function(a,b,c,d,e){var f=c.writeHead,g=c.write,h=c.end;delete a.headers['content-length'],a.headers['content-type']='text/html; charset=utf-8';var i=a.headers['content-encoding'];i&&(-1!==i.indexOf('gzip')||-1!==i.indexOf('deflate'))&&delete a.headers['content-encoding'],c.writeHead=function(){};var j=new Buffer('');c.write=function(a,b){if(j=Buffer.isBuffer(a)?Buffer.concat([j,a]):Buffer.concat([j,new Buffer(a,b)]),10485760<j.length)throw new Error('Document too large')},c.end=function(){var k;if(i&&(-1!==i.indexOf('gzip')||-1!==i.indexOf('deflate'))){var n=_zlib2.default.unzipSync(j);n&&(k=n.toString('utf-8'))}else k=j.toString('utf-8');var l=(0,_util.tryParseJson)(k)||null,m=function(b,d){var i=new Buffer(d.html);a.headers['content-length']=i.length,e.debug&&console.log('FINAL response headers for output',JSON.stringify(a.headers,!0,2)),f.apply(c,[a.statusCode,a.headers]),g.call(c,i),h.call(c)};try{d(m,b.originalUrl,l,{})}catch(a){console.error(a);var o={statusCode:500,content:'Internal Server Error'};e.onError&&(o=e.onError(a)),f.apply(c,[o.statusCode,{}]),g.call(c,new Buffer(o.content)),h.call(c)}}},handleProxyResponse=function(a,b,c,d,e){removeEmptyAnalyticsCookie(a),e.debug&&(console.log('request url',b.url),console.log('request query',b.query),console.log('request original url',b.originalUrl),console.log('RAW request headers',JSON.stringify(b.headers,!0,2)),console.log('RAW response headers from the target',JSON.stringify(a.headers,!0,2)));e.pathRewriteExcludeRoutes.find(function(a){return-1!==b.originalUrl.indexOf(a)})||renderAppToResponse(a,b,c,d,e)},rewriteRequestPath=exports.rewriteRequestPath=function(a,b,c,d){if(c.pathRewriteExcludeRoutes.find(function(b){return-1!==a.indexOf(b)}))return a;if(-1!==a.indexOf(c.layoutServiceRoute))return a;var e,f=a.indexOf('?');-1<f&&(e=(0,_util.buildQueryString)(b.query),a=a.slice(0,f));var g;if(d){var i=d(a);i&&(a=i.sitecoreRoute?i.sitecoreRoute:'/',!a.startsWith('/')&&(a='/'+a),g=i.lang)}var h=c.layoutServiceRoute+'?item='+encodeURIComponent(a)+'&sc_apikey='+c.apiKey;return g&&(h=h+'&sc_lang='+g),e&&(h=h+'&'+e),h},createOptions=function(a,b,c){return _extends({target:b.apiHost,changeOrigin:!0,ws:!0,pathRewrite:function pathRewrite(a,d){return rewriteRequestPath(a,d,b,c)},logLevel:b.debug?'debug':'info',onProxyRes:function onProxyRes(c,d,e){return handleProxyResponse(c,d,e,a,b)}},b.proxyOptions)};exports.default=function(a,b,c){var d=createOptions(a,b,c);return(0,_httpProxyMiddleware2.default)(d)};
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.rewriteRequestPath = exports.removeEmptyAnalyticsCookie = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; // node.js standard lib
var _httpProxyMiddleware = require('http-proxy-middleware');
var _httpProxyMiddleware2 = _interopRequireDefault(_httpProxyMiddleware);
var _setCookieParser = require('set-cookie-parser');
var _setCookieParser2 = _interopRequireDefault(_setCookieParser);
var _zlib = require('zlib');
var _zlib2 = _interopRequireDefault(_zlib);
var _util = require('./util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// For some reason, every other response returned by Sitecore contains the 'set-cookie' header with the SC_ANALYTICS_GLOBAL_COOKIE value as an empty string.
// This effectively sets the cookie to empty on the client as well, so if a user were to close their browser
// after one of these 'empty value' responses, they would not be tracked as a returning visitor after re-opening their browser.
// To address this, we simply parse the response cookies and if the analytics cookie is present but has an empty value, then we
// remove it from the response header. This means the existing cookie in the browser remains intact.
var removeEmptyAnalyticsCookie = exports.removeEmptyAnalyticsCookie = function removeEmptyAnalyticsCookie(proxyResponse) {
var cookies = _setCookieParser2.default.parse(proxyResponse.headers['set-cookie']);
if (cookies) {
var analyticsCookieIndex = cookies.findIndex(function (c) {
return c.name === 'SC_ANALYTICS_GLOBAL_COOKIE';
});
if (analyticsCookieIndex !== -1) {
var analyticsCookie = cookies[analyticsCookieIndex];
if (analyticsCookie && analyticsCookie.value === '') {
cookies.splice(analyticsCookieIndex, 1);
/* eslint-disable no-param-reassign */
proxyResponse.headers['set-cookie'] = cookies;
/* eslint-enable no-param-reassign */
}
}
}
};
// inspired by: http://stackoverflow.com/a/22487927/9324
var renderAppToResponse = function renderAppToResponse(proxyResponse, request, serverResponse, renderer, config) {
/* eslint-disable no-param-reassign */
// monkey-patch FTW
var originalWriteHead = serverResponse.writeHead;
var originalWrite = serverResponse.write;
var originalEnd = serverResponse.end;
// these lines are necessary and must happen before we do any writing to the response
// still don't fully understand why they have to be done at this point
// ideally, we'd set the content-type header when we render the app below and set the content-length header
// unfortunately, that doesn't work
// same with deleting the content-length header. not sure why it needs to happen at this point as opposed to just overwriting it later
// but again, unfortunately, that doesn't work
delete proxyResponse.headers['content-length'];
proxyResponse.headers['content-type'] = 'text/html; charset=utf-8';
var contentEncoding = proxyResponse.headers['content-encoding'];
if (contentEncoding && (contentEncoding.indexOf('gzip') !== -1 || contentEncoding.indexOf('deflate') !== -1)) {
delete proxyResponse.headers['content-encoding'];
}
// we are going to set our own status code if rendering fails
serverResponse.writeHead = function () {};
// buffer the response body as it is written for later processing
var buf = new Buffer('');
serverResponse.write = function (data, encoding) {
if (Buffer.isBuffer(data)) {
buf = Buffer.concat([buf, data]); // append raw buffer
} else {
buf = Buffer.concat([buf, new Buffer(data, encoding)]); // append string with optional character encoding (default utf8)
}
// sanity check: if the response is huge, bail.
// ...we don't want to let someone bring down the server by filling up all our RAM.
if (buf.length > 10 * 1024 * 1024) {
throw new Error('Document too large');
}
};
// as the response is ending, we parse the current response body which is JSON, then
// render the app using that JSON, but return HTML to the final response.
serverResponse.end = function () {
var bufStr = void 0;
if (contentEncoding && (contentEncoding.indexOf('gzip') !== -1 || contentEncoding.indexOf('deflate') !== -1)) {
var decoded = _zlib2.default.unzipSync(buf);
if (decoded) {
bufStr = decoded.toString('utf-8');
}
} else {
bufStr = buf.toString('utf-8');
}
var data = (0, _util.tryParseJson)(bufStr) || null;
var handleResult = function handleResult(emptyArg, result) {
var content = new Buffer(result.html); // we have to convert back to a buffer so that we can get the *byte count* (rather than character count) of the body
// setting the content-length header is not absolutely necessary, but is recommended
proxyResponse.headers['content-length'] = content.length;
if (config.debug) {
console.log('FINAL response headers for output', JSON.stringify(proxyResponse.headers, true, 2));
}
originalWriteHead.apply(serverResponse, [proxyResponse.statusCode, proxyResponse.headers]);
originalWrite.call(serverResponse, content);
originalEnd.call(serverResponse);
};
try {
renderer(handleResult, request.originalUrl, data, {});
} catch (err) {
console.error(err);
var errorResponse = {
statusCode: 500,
content: "Internal Server Error"
};
if (config.onError) {
errorResponse = config.onError(err);
}
originalWriteHead.apply(serverResponse, [errorResponse.statusCode, {}]);
originalWrite.call(serverResponse, new Buffer(errorResponse.content));
originalEnd.call(serverResponse);
}
};
/* eslint-enable no-param-reassign */
};
var handleProxyResponse = function handleProxyResponse(proxyResponse, request, serverResponse, renderer, config) {
removeEmptyAnalyticsCookie(proxyResponse);
if (config.debug) {
console.log('request url', request.url);
console.log('request query', request.query);
console.log('request original url', request.originalUrl);
console.log('RAW request headers', JSON.stringify(request.headers, true, 2));
console.log('RAW response headers from the target', JSON.stringify(proxyResponse.headers, true, 2));
}
// if the request URL contains any of the excluded rewrite routes, we assume the response does not need to be server rendered.
// instead, the response should just be relayed as usual.
if (config.pathRewriteExcludeRoutes.find(function (r) {
return request.originalUrl.indexOf(r) !== -1;
})) {
return;
}
// your first thought might be: why do we need to render the app here? why not just pass the JSON response to another piece of middleware that will render the app?
// the answer: the proxy middleware ends the response and does not "chain"
renderAppToResponse(proxyResponse, request, serverResponse, renderer, config);
};
var rewriteRequestPath = exports.rewriteRequestPath = function rewriteRequestPath(reqPath, req, config, parseRouteUrl) {
// necessary to make sure proxy doesn't fail if target server sends gzipped
// delete req.headers['accept-encoding'];
// if the request URL contains a path/route that should not be re-written, then just pass it along as-is
if (config.pathRewriteExcludeRoutes.find(function (r) {
return reqPath.indexOf(r) !== -1;
})) {
return reqPath;
}
// if the request URL doesn't contain the layout service controller path, assume we need to rewrite the request URL so that it does
// if this seems redundant, it is. the config.pathRewriteExcludeRoutes should contain the layout service path, but can't always assume that it will...
if (reqPath.indexOf(config.layoutServiceRoute) !== -1) {
return reqPath;
}
var qsIndex = reqPath.indexOf('?');
var qs = void 0;
if (qsIndex > -1) {
qs = (0, _util.buildQueryString)(req.query);
reqPath = reqPath.slice(0, qsIndex);
}
var lang = void 0;
if (parseRouteUrl) {
var routeParams = parseRouteUrl(reqPath);
if (routeParams) {
if (routeParams.sitecoreRoute) {
reqPath = routeParams.sitecoreRoute;
} else {
reqPath = '/';
}
if (!reqPath.startsWith('/')) {
reqPath = '/' + reqPath;
}
lang = routeParams.lang;
}
}
var path = config.layoutServiceRoute + '?item=' + encodeURIComponent(reqPath) + '&sc_apikey=' + config.apiKey;
if (lang) {
path = path + '&sc_lang=' + lang;
}
if (qs) {
path = path + '&' + qs;
}
return path;
};
var createOptions = function createOptions(renderer, config, parseRouteUrl) {
return _extends({
target: config.apiHost,
changeOrigin: true, // required otherwise need to include CORS headers
ws: true,
pathRewrite: function pathRewrite(reqPath, req) {
return rewriteRequestPath(reqPath, req, config, parseRouteUrl);
},
logLevel: config.debug ? 'debug' : 'info',
onProxyRes: function onProxyRes(proxyRes, req, res) {
return handleProxyResponse(proxyRes, req, res, renderer, config);
}
}, config.proxyOptions);
};
exports.default = function (renderer, config, parseRouteUrl) {
var options = createOptions(renderer, config, parseRouteUrl);
return (0, _httpProxyMiddleware2.default)(options);
};

@@ -1,1 +0,28 @@

'use strict';var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&'function'==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?'symbol':typeof a},tryParseJson=exports.tryParseJson=function(a){try{var b=JSON.parse(a);if(b&&'object'===('undefined'==typeof b?'undefined':_typeof(b))&&null!==b)return b}catch(b){console.error('error parsing json string \''+a+'\'',b)}return!1},buildQueryString=exports.buildQueryString=function(a){return Object.keys(a).map(function(b){return encodeURIComponent(b)+'='+encodeURIComponent(a[b])}).join('&')};Object.defineProperty(exports,'__esModule',{value:!0});
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var tryParseJson = exports.tryParseJson = function tryParseJson(jsonString) {
try {
var json = JSON.parse(jsonString);
// handle non-exception-throwing cases
if (json && (typeof json === 'undefined' ? 'undefined' : _typeof(json)) === 'object' && json !== null) {
return json;
}
} catch (e) {
// todo: write to stdout or callback
console.error('error parsing json string \'' + jsonString + '\'', e);
}
return false;
};
var buildQueryString = exports.buildQueryString = function buildQueryString(params) {
return Object.keys(params).map(function (k) {
return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]);
}).join('&');
};

4

package.json
{
"name": "@sitecore-jss/sitecore-jss-proxy",
"version": "6.0.0",
"version": "7.0.0",
"description": "Proxy middleware for express.js server.",

@@ -40,2 +40,2 @@ "main": "dist/index.js",

}
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc