From aa065fa4d84552a6110bffe9a1928d12c59bb637 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 2 Jan 2021 16:54:50 -0500 Subject: [PATCH] Do not Server-Side Render the markdown (#1177) 1) Rendering is fast enough on the client we don't need to provide SSR for the brew contents. 2) This leaves our server open to REDOS attacks if users create ridiculously long single lines of text. The Markdown parser slows down with exponential time which becomes noticeable at 10,000+ characters in one line, and at 200,000+ characters will stall the server and eventually crash. 3) This now shows a nice loading circle for the half-second that a page takes to render. If a user tries to load a huge line of text the loading circle will be there instead of a blank white page. --- client/homebrew/brewRenderer/brewRenderer.jsx | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index f47738f12..d34025a0a 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -58,9 +58,7 @@ const BrewRenderer = createClass({ updateSize : function() { this.setState({ - height : this.refs.main.parentNode.clientHeight, - isMounted : true, - visibility : 'visible' + height : this.refs.main.parentNode.clientHeight, }); }, @@ -116,7 +114,7 @@ const BrewRenderer = createClass({ renderPages : function(){ if(this.state.usePPR){ return _.map(this.state.pages, (page, index)=>{ - if(this.shouldRender(page, index)){ + if(this.shouldRender(page, index) && typeof window !== 'undefined'){ return this.renderPage(page, index); } else { return this.renderDummyPage(index); @@ -125,7 +123,11 @@ const BrewRenderer = createClass({ } if(this.props.errors && this.props.errors.length) return this.lastRender; this.lastRender = _.map(this.state.pages, (page, index)=>{ - return this.renderPage(page, index); + if(typeof window !== 'undefined') { + return this.renderPage(page, index); + } else { + return this.renderDummyPage(index); + } }); return this.lastRender; }, @@ -134,13 +136,28 @@ const BrewRenderer = createClass({ setTimeout(()=>{ //We still see a flicker where the style isn't applied yet, so wait 100ms before showing iFrame this.updateSize(); window.addEventListener('resize', this.updateSize); + this.renderPages(); //Make sure page is renderable before showing + this.setState({ + isMounted : true, + visibility : 'visible' + }); }, 100); }, render : function(){ //render in iFrame so broken code doesn't crash the site. + //Also render dummy page while iframe is mounting. + return ( + {!this.state.isMounted + ?
+
+ {this.renderDummyPage(1)} +
+
+ : null} +
- {this.renderPages()} + {this.state.isMounted + ? this.renderPages() + : null}