BrowserSync / browser-sync

Keep multiple browsers & devices in sync when building websites. https://browsersync.io
https://discord.gg/2d2xUThp
Apache License 2.0
12.19k stars 757 forks source link

middleware prevents browser-sync client.js to be injected #217

Open soenkekluth opened 10 years ago

soenkekluth commented 10 years ago

I need to process requested html files. if i do it like this client.js injection gets eaten.

middleware: function(req, res, next) {

        var url = req.url === '/' ? ('/index.html') : req.url;
        var filename = __dirname + '/src' + url;

        if (url.indexOf('.html') > -1 && fs.existsSync(filename)) {

          var contents = fs.readFileSync(filename, {
            encoding: 'utf8'
          });
          res.end(contents);

        } else {
          next();
        }
      }
shakyShane commented 10 years ago

"maybe injection should happen after all middleware did their job?" - That's exactly what it does already. I copied your middleware and everything worked fine for me... can you show me your entire config?

soenkekluth commented 10 years ago

well I guess you didn't set the folder right in: var filename = __dirname + '/src' + url; where src is the folder.

here is the example. it does not work.. https://github.com/soenkekluth/browsersynctest

soenkekluth commented 10 years ago

meanwhile I am using a pretty messy workaround. for example: https://github.com/soenkekluth/browsersync-ssi/blob/master/browsersync-ssi.js

shakyShane commented 10 years ago

I havn't had a chance to look at this again yet, but I think it's probably to do with the fact you're calling res.end() in your middleware. Meaning, why would any other middlewares run if you've explicitly ended the response?

pkyeck commented 10 years ago

@shakyShane what would have been the "standard" way of changing/setting the response body?

pkyeck commented 10 years ago

ok, found a solution for the above problem.

another thing we have to tackle is the one where our initial file looks like this:

<!--#include virtual="head.html" -->
<!--#include virtual="body.html" -->
<!--#include virtual="footer.html" -->

and the resp-modifier won't inject the scriptTag because it can't find the body-tag because you add it by overriding the res.write(). wouldn't it be a better idea to do this in the res.end() when all other middleware modules ran their res.write()s?

rikschennink commented 10 years ago

I'm trying to run a template engine as middleware but now I'm having the above problem as well? Is there a solution?

How to I pass the resulting rendered HTML (i'm using swig) to the 'inner' middleware so it can still inject the required script tags?

shakyShane commented 10 years ago

Can everyone in this thread post the middlewares they are using please

rikschennink commented 10 years ago

Mine looks like this:

browserSync({
    port:4000,
    open:false,
    notify:false,
    server:{
        baseDir:'www',
        middleware:function (req, res, next) {

            // get the path to the requested resource
            var path = req.url.slice(-1) === '/' ? req.url + 'index.html' : req.url;

            // test if the requested file exists
            fs.exists('www' + path,function(exists) {

                // render this file using swig and send it back
                if (exists) {

                    //console.log('[BS] Serving resource: ',path);

                    var html = swig.renderFile('www' + path, {});
                    html = html.replace(/<\/head>/, '<script async src="//' + req.headers.host + '/browser-sync-client.js"></script></head>');

                    res.end(html);

                }
                // move to next middleware, if setup
                else {
                    next();
                }

            });

        }
    }
});
altano commented 9 years ago

I would reword the problem. I should be able to modify the body in any middleware and something as simple as this doesn't work:

function (req, res, next) {
        res.body = res.body + "modified";
        next();
}
shakyShane commented 9 years ago

@altano - res.body does not exist - that's a property added by express, and Browsersync does not use express

kidwm commented 8 years ago

@soenkekluth After #372 merged, now you can improving browsersync-ssi without script injection.