Skip to content

Commit

Permalink
Merge pull request #13 from daquinoaldo/develop-4.1.0
Browse files Browse the repository at this point in the history
Develop 4.1.0
  • Loading branch information
daquinoaldo authored Apr 23, 2019
2 parents 49792e1 + 3dc0988 commit 186b5ba
Show file tree
Hide file tree
Showing 10 changed files with 2,026 additions and 1,497 deletions.
7 changes: 3 additions & 4 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Pull Request Details

## Related Issue
Please, open a issue before a pull request. It will help in understanding better the PR aim.
Please, open an issue before a pull request. It will help in understanding better the PR aim.

## Types of changes
<!-- Put an `x` in all the boxes that apply -->
Expand All @@ -19,8 +19,7 @@ Please, open a issue before a pull request. It will help in understanding better
<!-- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have updated the documentation or my changes dont require it.
- [ ] I have read the [CONTRIBUTING](CONTRIBUTING.md) document.
- [ ] I have added tests to cover my changes (or the exist one were enough).
- [ ] I have added tests to cover my changes (or the existing one were enough).
- [ ] All new and existing tests passed.
11 changes: 3 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
# MacOS
.DS_STORE

# IDEs
.idea
*.iml

# Node & npm
# Node, npm & CI
node_modules
coverage
.nyc_output

# Certificates
cert/localhost.*
cert/mkcert-*
# Build
build
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ language: node_js
node_js:
- node
- 10
- 7.6
- 8
after_success: npm run coveralls
49 changes: 43 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,32 @@ It works with MacOS, Linux and Windows, on Chrome and Firefox, and requires you
[![Known Vulnerabilities](https://snyk.io/test/npm/https-localhost/badge.svg)](https://snyk.io/test/npm/https-localhost)
[![GitHub issues](https://img.shields.io/github/issues/daquinoaldo/https-localhost.svg)](https://github.com/daquinoaldo/https-localhost/issues)


## Install and use standalone
```
npm i -g https-localhost
npm i -g --only=prod https-localhost
```
```
serve ~/myproj
```
- `sudo` may be necessary.
- If a static path is not provided the current directory content will be served.
- You can change the port setting the PORT environmental variable: `PORT=4433 serve ~/myproj`.
- You can change the **port** setting the `PORT` environmental variable: `PORT=4433 serve ~/myproj`. Specifying port number will also prevent http to https redirect.

### Binaries
If you don't have Node.js installed just use a packaged version! Download it from the [release page](https://github.com/daquinoaldo/https-localhost/releases).
```
// Linux
./https-localhost-linux ~/myproj
// MacOS
./https-localhost-macos ~/myproj
// Windows
./https-localhost-win.exe C:\User\me\myproj
```
**Tip 1:** on Windows just drag the folder on the executable to serve itV.
**Tip 2:** on all platform put the executable on the folder you want to serve and double-click it.


## Use as module
Expand All @@ -36,9 +52,13 @@ const app = httpLocalhost()
// app is an express app, do what you usually do with express
app.listen(port)
```
- If the port number is not provided, it will listen on 443.
- To redirect the http traffic to https use `app.redirect()`.
- You can serve static files with `app.serve(path)`.
- If the **port** number is not provided, it will listen on 443.
- To **redirect** the http traffic to https use `app.redirect()`.
- You can serve **static files** with `app.serve(path)`.

**Tip:** consider installing it as a dev dependency: this is not a production tool!
`npm i --save-dev https-localhost`


## Production
This tool has a production version that activates **HTTP/2**, **compression** and **minify**.
Expand All @@ -49,6 +69,7 @@ I decide to not activate it by default since it is usually an unwanted behaviour

**IMPORTANT**: the fact that there is a production enviornment doesn't mean that this tool is suitable for production. It's intended to be used only for local testing.


## Why and how it works
Serving static content on localhost in a trusted SSL connection is not so simple.
It requires to manually generate and trust certificates, with complicate commands and many manual steps.
Expand Down Expand Up @@ -76,9 +97,19 @@ Checkout the updated list [here](https://github.com/FiloSottile/mkcert/blob/mast

## Troubleshooting
### Node.js version
https-localhost requires Node.js 7.6 or higher.
https-localhost requires Node.js 8 or higher.
<sub>If you need compatibility with previously Node.js versions let me know, I'll try to rearrange the code.</sub>

### root required
- **At first run** this tool generate a trusted certificate. The sudo password may be required. If you cannot provide the sudo password generate a `localhost.key` and `localhost.crt` and specify its path with `CERT_PATH=/diractory/containing/certificates/ serve ~/myproj`.
- **At each run** the password may be required to run the server on port 443 and 80. To avoid the script ask for password specify a different port number: `PORT=4433 serve ~/myproj`.

### EACCES
Run with sudo to use the default ports 443 and 80. You can also change port with: `PORT=4433 serve ~/myproj`.

### EADDRINUSE
Another service on your machine is using port 443 or port 80. Stop it or change port with `PORT=4433 serve ~/myproj`.

### RangeError
```
RangeError: Invalid typed array length: -4095
Expand All @@ -89,6 +120,12 @@ It should be present only with `NODE_ENV=production`, hence the easiest fix is t

I've tried to reproduce this error without any success (checkout the [Travis build logs](https://travis-ci.org/daquinoaldo/https-localhost)). If you can help please open an issue and describe as better as you can how to reproduce it, I'll be happy to help you.


## Contributing
Each contribute is welcome!
Please, checkout the [contributing guidelines](.github/CONTRIBUTING.md).


## License
Is released under [AGPL-3.0 - GNU Affero General Public License v3.0](LICENSE).

Expand Down
85 changes: 0 additions & 85 deletions cert/generate.js

This file was deleted.

140 changes: 140 additions & 0 deletions certs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env node

const path = require("path")
const fs = require("fs")
const exec = require("child_process").exec
const https = require("https")
const getAppDataPath = require("appdata-path")

const MKCERT_VERSION = "v1.3.0"
const CERT_PATH = getAppDataPath("https-localhost")

// get the executable name
function getExe() {
/* istanbul ignore next: tested on all platform on travis */
switch (process.platform) {
case "darwin":
return "mkcert-" + MKCERT_VERSION + "-darwin-amd64"
case "linux":
return "mkcert-" + MKCERT_VERSION + "-linux-amd64"
case "win32":
return "mkcert-" + MKCERT_VERSION + "-windows-amd64.exe"
default:
console.warn("Cannot generate the localhost certificate on your " +
"platform. Please, consider contacting the developer if you can help.")
process.exit(0)
}
}

// download a binary file
function download(url, path) {
console.log("Downloading the mkcert executable...")
const file = fs.createWriteStream(path)
return new Promise(resolve => {
function get(url, file) {
https.get(url, (response) => {
if (response.statusCode === 302) get(response.headers.location, file)
else response.pipe(file).on("finish", resolve)
})
}
get(url, file)
})
}

// execute the binary executable to generate the certificates
function mkcert(appDataPath, exe) {
const logPath = path.join(appDataPath, "mkcert.log")
const errPath = path.join(appDataPath, "mkcert.err")
// escape spaces in appDataPath (Mac OS)
appDataPath = appDataPath.replace(" ", "\\ ")
const exePath = path.join(appDataPath, exe)
const crtPath = path.join(appDataPath, "localhost.crt")
const keyPath = path.join(appDataPath, "localhost.key")
const cmd = exePath + " -install -cert-file " + crtPath +
" -key-file " + keyPath + " localhost"
return new Promise((resolve, reject) => {
console.log("Running mkcert to generate certificates...")
exec(cmd, (err, stdout, stderr) => {
// log
const errFun = err => {
/* istanbul ignore if: cannot be tested */
if (err) console.error(err)
}
fs.writeFile(logPath, stdout, errFun)
fs.writeFile(errPath, stderr, errFun)
/* istanbul ignore if: cannot be tested */
if (err) reject(err)
resolve()
})
})
}

async function generate(appDataPath = CERT_PATH) {
console.info("Generating certificates...")
// mkdir if not exists
/* istanbul ignore else: not relevant */
if (!fs.existsSync(appDataPath))
fs.mkdirSync(appDataPath)
// build the executable url and path
const url = "https://github.com/FiloSottile/mkcert/releases/download/" +
MKCERT_VERSION + "/"
const exe = getExe()
const exePath = path.join(appDataPath, exe)
// download the executable
await download(url + exe, exePath)
// make binary executable
fs.chmodSync(exePath, "0755")
// execute the binary
await mkcert(appDataPath, exe)
console.log("Certificates generated, installed and trusted. Ready to go!")
}

async function getCerts() {
const certPath = process.env.CERT_PATH || CERT_PATH
try {
return {
key: fs.readFileSync(path.join(certPath, "localhost.key")),
cert: fs.readFileSync(path.join(certPath, "localhost.crt"))
}
} catch (e) {
if (certPath !== CERT_PATH) {
console.error("Cannot find localhost.key and localhost.crt in the" +
" specified path: " + certPath)
process.exit(1)
} else {
// Missing certificates (first run)
// generate the certificate
await generate(CERT_PATH)
// recursive call
return getCerts()
}
}
}

// delete a folder and the file inside it
function remove(appDataPath = CERT_PATH) {
if (fs.existsSync(appDataPath)) {
fs.readdirSync(appDataPath)
.forEach(file => fs.unlinkSync(path.join(appDataPath, file)))
fs.rmdirSync(appDataPath)
}
}

// run as script
/* istanbul ignore if: cannot be tested */
if (require.main === module)
// if run with -u or --uninstall
if (process.argv.length === 3 &&
(process.argv[2] === "-u" || process.argv[2] === "--uninstall")) {
remove()
console.info("Certificates removed.")
} else try { // install
generate()
} catch (err) { console.error("\nExec error: " + err) }

// export as module
module.exports = {
getCerts,
generate,
remove
}
Loading

0 comments on commit 186b5ba

Please sign in to comment.