lwsjs / local-web-server

A lean, modular web server for rapid full-stack development.
MIT License
1.2k stars 85 forks source link

"Redirect all HTTP requests to HTTPS" plugin required #86

Closed 75lb closed 5 years ago

75lb commented 6 years ago

Requested by @bennypowers in a separate thread:

One of the Lighthouse criteria is that the site redirects requests from http to https. Of course, I can set up rewrite according to the wiki page's instructions, but that doesn't give me the 302 Redirect I need to pass this audit. I'd very much like some feature like ws --server http2 --redirect-http-to-https which will take all requests and redirect them to https.

Could someone read this wiki page about extending ws and come up with something to achieve this?

This would be the typical use case - server one serves the main HTTPS app: (you'll probably need admin privileges to serve on system ports like 443 and 80).

$ ws --https --port 443 

Server two catches stray HTTP traffic, loading a custom stack comprising your custom middleware (a local file called "redirect-everything.js" in this case) which returns the appropriate 302 response for each request received.

$ ws --port 80 --stack ./redirect-everything.js

It should be quite straight forward, not much code.

maxorlovsky commented 6 years ago

Here

module.exports = MiddlewareBase => class Redirector extends MiddlewareBase {
    optionDefinitions() {
        return [
            { name: 'redirectPort', type: Number, description: 'Port which is used to redirect to https' }
        ]
    }
    middleware(options) {
        if (!options.redirectPort) {
            console.warn('\x1b[33m%s\x1b[0m', 'redirectPort parameter is not set, defaulting to 4443');
            options.redirectPort = 4443;
        }

        return (ctx, next) => {
            // Check if protocol is http
            if (ctx.protocol === 'http') {
                // Replacing url with https parameter
                const httpsUrl = ctx.request.href
                    .replace('http', 'https')
                    .replace(options.port, options.redirectPort);

                // Enforcing redirect
                ctx.redirect(httpsUrl);
            }
        }
    }
}

Usage:

$ ws --stack ./redirect-everything.js --redirectPort 4443

redirectPort is where user going to be redirected with https change and should be with 302 header

75lb commented 6 years ago

cool, thanks. Did this pass the Lighthouse audit for you?

bennypowers commented 6 years ago

Seems middleware is processing request but ctx.redirect is not actually redirecting the request maybe this is a middleware order problem

module.exports = {
  stack: [
    'lws-body-parser',
    'lws-request-monitor',
    'lws-log',
    'lws-compress',
    'lws-mock-response',
    'lws-static',
    'lws-cors',
    'redirect-everything',
  ],
  http2: true,
  port: 4443,
  redirectPort: 4443,
  compress: true,
  mocks: 'restaurant-mocks.js',
  logFormat: 'combined',
};
bennypowers commented 6 years ago

Ok the following configuration works:

lws.config.js

module.exports = {
  stack: [
    'lws-body-parser',
    'lws-request-monitor',
    'lws-log',
    'lws-compress',
    'lws-mock-response',
    'lws-static',
    'lws-cors',
  ],
  http2: true,
  port: 443,
  compress: true,
  mocks: 'restaurant-mocks.js',
  logFormat: 'combined',
};

lws.redirect.config.js

module.exports = {
  stack: ['redirect-everything'],
  port: 80,
  redirectPort: 443,
  logFormat: 'combined',
};

package.json

{
  "name": "mws-restaurant-stage-1",
  "version": "1.0.0",
  "description": "Project files for MWS Nanodegree",
  "main": "index.html",
  "dependencies": {
    "express": "^4.16.2",
    "local-web-server": "^2.5.0",
    "lws-compress": "^0.2.1",
    "lws-http2": "^0.2.2",
    "node": "^8.9.4"
  },
  "scripts": {
    "postinstall": "bower i --allow-root",
    "start": "npx ws & npx ws -c lws.redirect.config.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
}

If i sudo npm start then I get the right behaviour

bennypowers commented 6 years ago

I receive this error on windows

Path must be a string. Received undefined
C:\Users\bennyp\Documents\mws-restaurant-stage-1\node_modules\local-web-server\bin\cli.js
75lb commented 6 years ago

I'll having success with this middleware too, thanks. I launch the main server like so:

$ sudo ws --http2 --port 443

And the "catch HTTP" server like this:

$ sudo ws --stack ./redirect-everything.js --redirectPort 443 --port 80
doppelganger9 commented 5 years ago

Wow, thanks! That's exactly what I needed to solve this step in Lighthouse Audit.

Though, it took me a while to understand that I needed to run 2 ws processes, even if it was clearly written in the above 2 responses... 🙄

75lb commented 5 years ago

Resolved by the lws-redirect plugin.

Usage:

$ npm install --save-dev lws-redirect

$ lws --port 80 --stack lws-redirect --redirect 'http -> https'
Listening on http://mba4.local:80, http://127.0.0.1:80, http://192.168.0.200:80

$ $ curl -I http://127.0.0.1/
HTTP/1.1 302 Found
Location: https://127.0.0.1/
Content-Type: text/html; charset=utf-8
Content-Length: 67
Date: Sun, 09 Jun 2019 16:53:38 GMT
Connection: keep-alive