mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-30 15:22:39 +00:00
feat(core, cli): builtin support of https and unix sockets (#3831)
Co-authored-by: Aurélien Chrétien <aurelien@manager.one> Co-authored-by: Rémy Sanchez <remy.sanchez@hyperthese.net>
This commit is contained in:
parent
4f6a048a4b
commit
72479687d9
@ -52,3 +52,22 @@ exports.loadNuxtConfig = (argv) => {
|
|||||||
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getLatestHost = (argv) => {
|
||||||
|
const port =
|
||||||
|
argv.port ||
|
||||||
|
process.env.NUXT_PORT ||
|
||||||
|
process.env.PORT ||
|
||||||
|
process.env.npm_package_config_nuxt_port
|
||||||
|
const host =
|
||||||
|
argv.hostname ||
|
||||||
|
process.env.NUXT_HOST ||
|
||||||
|
process.env.HOST ||
|
||||||
|
process.env.npm_package_config_nuxt_host
|
||||||
|
const socket =
|
||||||
|
argv['unix-socket'] ||
|
||||||
|
process.env.UNIX_SOCKET ||
|
||||||
|
process.env.npm_package_config_unix_socket
|
||||||
|
|
||||||
|
return { port, host, socket }
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ const parseArgs = require('minimist')
|
|||||||
const consola = require('consola')
|
const consola = require('consola')
|
||||||
const { version } = require('../package.json')
|
const { version } = require('../package.json')
|
||||||
const { Nuxt, Builder } = require('..')
|
const { Nuxt, Builder } = require('..')
|
||||||
const { loadNuxtConfig } = require('./common/utils')
|
const { loadNuxtConfig, getLatestHost } = require('./common/utils')
|
||||||
|
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
const argv = parseArgs(process.argv.slice(2), {
|
||||||
alias: {
|
alias: {
|
||||||
@ -75,7 +75,7 @@ const errorHandler = (err, instance) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get latest environment variables
|
// Get latest environment variables
|
||||||
const { port, host } = nuxt.options.server
|
const { port, host, socket } = getLatestHost(argv)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Promise.resolve()
|
Promise.resolve()
|
||||||
@ -91,7 +91,7 @@ const errorHandler = (err, instance) => {
|
|||||||
})
|
})
|
||||||
.then(() => oldInstance && oldInstance.nuxt.close())
|
.then(() => oldInstance && oldInstance.nuxt.close())
|
||||||
// Start listening
|
// Start listening
|
||||||
.then(() => nuxt.listen(port, host))
|
.then(() => nuxt.listen(port, host, socket))
|
||||||
// Show ready message first time, others will be shown through WebpackBar
|
// Show ready message first time, others will be shown through WebpackBar
|
||||||
.then(() => !oldInstance && nuxt.showReady(false))
|
.then(() => !oldInstance && nuxt.showReady(false))
|
||||||
.then(() => builder.watchServer())
|
.then(() => builder.watchServer())
|
||||||
|
@ -4,19 +4,20 @@ const { resolve } = require('path')
|
|||||||
const parseArgs = require('minimist')
|
const parseArgs = require('minimist')
|
||||||
const consola = require('consola')
|
const consola = require('consola')
|
||||||
const { Nuxt } = require('../dist/nuxt-start')
|
const { Nuxt } = require('../dist/nuxt-start')
|
||||||
const { loadNuxtConfig } = require('./common/utils')
|
const { loadNuxtConfig, getLatestHost } = require('./common/utils')
|
||||||
|
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
const argv = parseArgs(process.argv.slice(2), {
|
||||||
alias: {
|
alias: {
|
||||||
h: 'help',
|
h: 'help',
|
||||||
H: 'hostname',
|
H: 'hostname',
|
||||||
p: 'port',
|
p: 'port',
|
||||||
|
n: 'unix-socket',
|
||||||
c: 'config-file',
|
c: 'config-file',
|
||||||
s: 'spa',
|
s: 'spa',
|
||||||
u: 'universal'
|
u: 'universal'
|
||||||
},
|
},
|
||||||
boolean: ['h', 's', 'u'],
|
boolean: ['h', 's', 'u'],
|
||||||
string: ['H', 'c'],
|
string: ['H', 'c', 'n'],
|
||||||
default: {
|
default: {
|
||||||
c: 'nuxt.config.js'
|
c: 'nuxt.config.js'
|
||||||
}
|
}
|
||||||
@ -36,6 +37,7 @@ if (argv.help) {
|
|||||||
Options
|
Options
|
||||||
--port, -p A port number on which to start the application
|
--port, -p A port number on which to start the application
|
||||||
--hostname, -H Hostname on which to start the application
|
--hostname, -H Hostname on which to start the application
|
||||||
|
--unix-socket, -n Path to a UNIX socket
|
||||||
--spa Launch in SPA mode
|
--spa Launch in SPA mode
|
||||||
--universal Launch in Universal mode (default)
|
--universal Launch in Universal mode (default)
|
||||||
--config-file, -c Path to Nuxt.js config file (default: nuxt.config.js)
|
--config-file, -c Path to Nuxt.js config file (default: nuxt.config.js)
|
||||||
@ -77,8 +79,8 @@ if (nuxt.options.render.ssr === true) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { port, host } = nuxt.options.server
|
const { port, host, socket } = getLatestHost(argv)
|
||||||
|
|
||||||
nuxt.listen(port, host).then(() => {
|
nuxt.listen(port, host, socket).then(() => {
|
||||||
nuxt.showReady(false)
|
nuxt.showReady(false)
|
||||||
})
|
})
|
||||||
|
@ -16,6 +16,7 @@ export default {
|
|||||||
|
|
||||||
// Server options
|
// Server options
|
||||||
server: {
|
server: {
|
||||||
|
https: false,
|
||||||
port: process.env.NUXT_PORT ||
|
port: process.env.NUXT_PORT ||
|
||||||
process.env.PORT ||
|
process.env.PORT ||
|
||||||
process.env.npm_package_config_nuxt_port,
|
process.env.npm_package_config_nuxt_port,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Module from 'module'
|
import Module from 'module'
|
||||||
import { resolve, join } from 'path'
|
import { resolve, join } from 'path'
|
||||||
|
import https from 'https'
|
||||||
|
|
||||||
import enableDestroy from 'server-destroy'
|
import enableDestroy from 'server-destroy'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
@ -141,25 +142,62 @@ export default class Nuxt {
|
|||||||
this.readyMessage = null
|
this.readyMessage = null
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(port = 3000, host = 'localhost') {
|
listen(port = 3000, host = 'localhost', socket = null) {
|
||||||
return this.ready().then(() => new Promise((resolve, reject) => {
|
return this.ready().then(() => new Promise((resolve, reject) => {
|
||||||
const server = this.renderer.app.listen(
|
if (!socket && typeof this.options.server.socket === 'string') {
|
||||||
{ port, host, exclusive: false },
|
socket = this.options.server.socket
|
||||||
|
}
|
||||||
|
|
||||||
|
const args = { exclusive: false }
|
||||||
|
|
||||||
|
if (socket) {
|
||||||
|
args.path = socket
|
||||||
|
} else {
|
||||||
|
args.port = port
|
||||||
|
args.host = host
|
||||||
|
}
|
||||||
|
|
||||||
|
let appServer
|
||||||
|
const isHttps = Boolean(this.options.server.https)
|
||||||
|
|
||||||
|
if (isHttps) {
|
||||||
|
let httpsOptions
|
||||||
|
|
||||||
|
if (this.options.server.https === true) {
|
||||||
|
httpsOptions = {}
|
||||||
|
} else {
|
||||||
|
httpsOptions = this.options.server.https
|
||||||
|
}
|
||||||
|
|
||||||
|
appServer = https.createServer(httpsOptions, this.renderer.app)
|
||||||
|
} else {
|
||||||
|
appServer = this.renderer.app
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = appServer.listen(
|
||||||
|
args,
|
||||||
(err) => {
|
(err) => {
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
({ address: host, port } = server.address())
|
let listenURL
|
||||||
if (host === '127.0.0.1') {
|
|
||||||
host = 'localhost'
|
|
||||||
} else if (host === '0.0.0.0') {
|
|
||||||
host = ip.address()
|
|
||||||
}
|
|
||||||
|
|
||||||
const listenURL = chalk.underline.blue(`http://${host}:${port}`)
|
if (!socket) {
|
||||||
this.readyMessage = `Listening on ${listenURL}`
|
({ address: host, port } = server.address())
|
||||||
|
if (host === '127.0.0.1') {
|
||||||
|
host = 'localhost'
|
||||||
|
} else if (host === '0.0.0.0') {
|
||||||
|
host = ip.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
listenURL = chalk.underline.blue(`http${isHttps ? 's' : ''}://${host}:${port}`)
|
||||||
|
this.readyMessage = `Listening on ${listenURL}`
|
||||||
|
} else {
|
||||||
|
listenURL = chalk.underline.blue(`unix+http://${socket}`)
|
||||||
|
this.readyMessage = `Listening on ${listenURL}`
|
||||||
|
}
|
||||||
|
|
||||||
// Close server on nuxt close
|
// Close server on nuxt close
|
||||||
this.hook(
|
this.hook(
|
||||||
@ -178,7 +216,11 @@ export default class Nuxt {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
this.callHook('listen', server, { port, host }).then(resolve)
|
if (socket) {
|
||||||
|
this.callHook('listen', server, { path: socket }).then(resolve)
|
||||||
|
} else {
|
||||||
|
this.callHook('listen', server, { port, host }).then(resolve)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
3
test/fixtures/https/https.test.js
vendored
Normal file
3
test/fixtures/https/https.test.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { buildFixture } from '../../utils/build'
|
||||||
|
|
||||||
|
buildFixture('https')
|
11
test/fixtures/https/nuxt.config.js
vendored
Normal file
11
test/fixtures/https/nuxt.config.js
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
server: {
|
||||||
|
https: {
|
||||||
|
key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
|
||||||
|
cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
test/fixtures/https/pages/index.vue
vendored
Normal file
3
test/fixtures/https/pages/index.vue
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<h1>Served over HTTPS!</h1>
|
||||||
|
</template>
|
19
test/fixtures/https/server.crt
vendored
Normal file
19
test/fixtures/https/server.crt
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDIjCCAougAwIBAgIJALww5SutcTujMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV
|
||||||
|
BAYTAkJSMRIwEAYDVQQIEwlTYW8gUGF1bG8xETAPBgNVBAcTCEJhcnJldG9zMQ0w
|
||||||
|
CwYDVQQKEwROdXh0MREwDwYDVQQLEwhGaXh0dXJlczESMBAGA1UEAxMJbG9jYWxo
|
||||||
|
b3N0MB4XDTE4MDkwMTIzMTk0OVoXDTE4MTAwMTIzMTk0OVowajELMAkGA1UEBhMC
|
||||||
|
QlIxEjAQBgNVBAgTCVNhbyBQYXVsbzERMA8GA1UEBxMIQmFycmV0b3MxDTALBgNV
|
||||||
|
BAoTBE51eHQxETAPBgNVBAsTCEZpeHR1cmVzMRIwEAYDVQQDEwlsb2NhbGhvc3Qw
|
||||||
|
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALoFJlquH9KNTPS3E0jbdKWLVw+N
|
||||||
|
oQaV+yPGPJb/IEAtg2cgMy62UlBS8eMTnMAv6JntuSuqS9wWdrvrTvcJkbbCRnKp
|
||||||
|
P13OTPpzhXO8R9pgzsopaO0DfLM8mTpFi1UPhzRm5riRCVIcg/KYH5JybI7LVzVu
|
||||||
|
v6LT3DhOtqp3tufRAgMBAAGjgc8wgcwwHQYDVR0OBBYEFIHCFtBMyB2w+os85zPR
|
||||||
|
AkI05z4FMIGcBgNVHSMEgZQwgZGAFIHCFtBMyB2w+os85zPRAkI05z4FoW6kbDBq
|
||||||
|
MQswCQYDVQQGEwJCUjESMBAGA1UECBMJU2FvIFBhdWxvMREwDwYDVQQHEwhCYXJy
|
||||||
|
ZXRvczENMAsGA1UEChMETnV4dDERMA8GA1UECxMIRml4dHVyZXMxEjAQBgNVBAMT
|
||||||
|
CWxvY2FsaG9zdIIJALww5SutcTujMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
|
||||||
|
BQADgYEARaylCmK13yfaARc3utZLmD+vW7P1S4CO25skgaaQasKsKtABTURz92Ju
|
||||||
|
fShBFvP6d8AQH3yvHEC2+QBUibg6tc9oT1hE1GXYczp11AvYry3hcbalB+V1vqN+
|
||||||
|
/vMAWDmg5Y0cE/QnJ8YZi2fHFoxkxJdDIfx5/w19vvE5h18IMro=
|
||||||
|
-----END CERTIFICATE-----
|
15
test/fixtures/https/server.key
vendored
Normal file
15
test/fixtures/https/server.key
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICXAIBAAKBgQC6BSZarh/SjUz0txNI23Sli1cPjaEGlfsjxjyW/yBALYNnIDMu
|
||||||
|
tlJQUvHjE5zAL+iZ7bkrqkvcFna76073CZG2wkZyqT9dzkz6c4VzvEfaYM7KKWjt
|
||||||
|
A3yzPJk6RYtVD4c0Zua4kQlSHIPymB+ScmyOy1c1br+i09w4Traqd7bn0QIDAQAB
|
||||||
|
AoGAWZpBb0yQZ4tIllfZIi8TcOo9dXBzMAjuf7ztUo5xqnhB41rPTKDl5WsOuKKp
|
||||||
|
zqlFEWBA4ZeWEt1/M+WUk8o4NU2M03Q5N7cubw2T6/q43pZkCjvdTScsP6sJgGK9
|
||||||
|
zR0o4+Owu9J5j+X9e7ChfZFVeZa3WCX6dCB17AVfUdCh7EECQQDpPdkLirOsiu5x
|
||||||
|
/b42+/dLpL4gq+mnAqLzaeHI0Eb2Gt9A8RyxPicdjZGOJ3bmGZPFWcu2xUbmEsic
|
||||||
|
pSbAmZujAkEAzCvBLokZ2ETJN1pZJgT3luUDmd6LsaW8BJoJ42ECM/k8ARKMJfIS
|
||||||
|
/tqZPJhdkZ6JhYc36m4lNwPaY7x4Cbxl+wJBAM1WBZ6DnWppZUI1gSAm8q9FeZyJ
|
||||||
|
vEmrqIlizcNcmRxQy/sASaJAdW8vEtVzKNmp6s3zH8ToKGKkZriBLHyivsECQALF
|
||||||
|
zVfOcNVpCbqAtZk4lAwui//477i34XfGh7/Yv2jpR5FUKScSxINFgLM79nlVx9RS
|
||||||
|
Y8YBPOwkV0DnfFHVhyUCQFYYp2B8XgghJGapOcWvp7QogkDWqCra5mrSlI+jzi5W
|
||||||
|
b1LjJqCCCq4kGK6nKEzT7gd75lb2LbcUdc5JfFHbcE0=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
7
test/fixtures/sockets/nuxt.config.js
vendored
Normal file
7
test/fixtures/sockets/nuxt.config.js
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
server: {
|
||||||
|
socket: path.resolve(__dirname, 'nuxt.socket')
|
||||||
|
}
|
||||||
|
}
|
3
test/fixtures/sockets/pages/index.vue
vendored
Normal file
3
test/fixtures/sockets/pages/index.vue
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<h1>Served over sockets!</h1>
|
||||||
|
</template>
|
3
test/fixtures/sockets/sockets.test.js
vendored
Normal file
3
test/fixtures/sockets/sockets.test.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { buildFixture } from '../../utils/build'
|
||||||
|
|
||||||
|
buildFixture('sockets')
|
22
test/unit/https.test.js
Normal file
22
test/unit/https.test.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { loadFixture, getPort, Nuxt } from '../utils'
|
||||||
|
|
||||||
|
let nuxt = null
|
||||||
|
|
||||||
|
describe('basic https', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const options = await loadFixture('https')
|
||||||
|
nuxt = new Nuxt(options)
|
||||||
|
const port = await getPort()
|
||||||
|
await nuxt.listen(port, '0.0.0.0')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/', async () => {
|
||||||
|
const { html } = await nuxt.renderRoute('/')
|
||||||
|
expect(html.includes('<h1>Served over HTTPS!</h1>')).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Close server and ask nuxt to stop listening to file changes
|
||||||
|
afterAll(async () => {
|
||||||
|
await nuxt.close()
|
||||||
|
})
|
||||||
|
})
|
21
test/unit/sockets.test.js
Normal file
21
test/unit/sockets.test.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { loadFixture, Nuxt } from '../utils'
|
||||||
|
|
||||||
|
let nuxt = null
|
||||||
|
|
||||||
|
describe.skip.appveyor('basic sockets', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const options = await loadFixture('sockets')
|
||||||
|
nuxt = new Nuxt(options)
|
||||||
|
await nuxt.listen()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/', async () => {
|
||||||
|
const { html } = await nuxt.renderRoute('/')
|
||||||
|
expect(html.includes('<h1>Served over sockets!</h1>')).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Close server and ask nuxt to stop listening to file changes
|
||||||
|
afterAll(async () => {
|
||||||
|
await nuxt.close()
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user