Skip to content

HTTPS

[Stable: 2 - Stable]

Stable: 2 Stability: 2 - Stable

Source Code: lib/https.js

HTTPS는 TLS/SSL을 통한 HTTP 프로토콜입니다. Node.js에서는 별도의 모듈로 구현됩니다.

crypto 지원이 없는지 확인

node:crypto 모듈에 대한 지원 없이 Node.js를 빌드할 수 있습니다. 이러한 경우 https에서 import하거나 require('node:https')를 호출하려고 하면 오류가 발생합니다.

CommonJS를 사용하는 경우 try/catch를 사용하여 발생한 오류를 catch할 수 있습니다.

js
let https
try {
  https = require('node:https')
} catch (err) {
  console.error('https 지원이 비활성화되었습니다!')
}

어휘적 ESM import 키워드를 사용하는 경우 모듈을 로드하려는 시도 전에 process.on('uncaughtException')에 대한 핸들러를 등록(예: 프리로드 모듈 사용)해야만 오류를 catch할 수 있습니다.

ESM을 사용하는 경우 코드가 crypto 지원이 활성화되지 않은 Node.js 빌드에서 실행될 가능성이 있는 경우 어휘적 import 키워드 대신 import() 함수를 사용하는 것을 고려하십시오.

js
let https
try {
  https = await import('node:https')
} catch (err) {
  console.error('https 지원이 비활성화되었습니다!')
}

클래스: https.Agent

[History]

버전변경 사항
v5.3.00 maxCachedSessions 지원하여 TLS 세션 캐싱 비활성화
v2.5.0TLS 세션 재사용을 위한 optionsmaxCachedSessions 매개변수 추가
v0.4.5추가됨: v0.4.5

http.Agent와 유사한 HTTPS용 Agent 객체입니다. 자세한 내용은 https.request()를 참조하십시오.

new Agent([options])

[History]

버전변경 사항
v12.5.0대상 호스트가 IP 주소를 사용하여 지정된 경우 서버 이름을 자동으로 설정하지 않음
  • options <Object> 에이전트에 설정할 구성 가능한 옵션 집합입니다. http.Agent(options)과 동일한 필드를 가질 수 있으며,
    • maxCachedSessions <number> TLS 캐시된 세션의 최대 수입니다. TLS 세션 캐싱을 비활성화하려면 0을 사용합니다. 기본값: 100.
    • servername <string> 서버에 전송할 Server Name Indication 확장의 값입니다. 확장 기능 전송을 비활성화하려면 빈 문자열 ''을 사용합니다. 기본값: 대상 서버의 호스트 이름입니다. 단, 대상 서버가 IP 주소를 사용하여 지정된 경우 기본값은 ''(확장 없음)입니다. TLS 세션 재사용에 대한 자세한 내용은 세션 재개를 참조하십시오.

이벤트: 'keylog'

추가됨: v13.2.0, v12.16.0

  • line <Buffer> NSS SSLKEYLOGFILE 형식의 ASCII 텍스트 줄.
  • tlsSocket <tls.TLSSocket> 생성된 tls.TLSSocket 인스턴스.

keylog 이벤트는 이 에이전트가 관리하는 연결에서 키 자료가 생성되거나 수신될 때 방출됩니다(일반적으로 핸드셰이크가 완료되기 전이지만 반드시 그런 것은 아님). 이 키 자료는 디버깅을 위해 저장할 수 있습니다. 캡처된 TLS 트래픽을 해독할 수 있기 때문입니다. 소켓마다 여러 번 방출될 수 있습니다.

일반적인 사용 사례는 수신된 줄을 공통 텍스트 파일에 추가하는 것입니다. 이 파일은 나중에 소프트웨어(예: Wireshark)에서 트래픽을 해독하는 데 사용됩니다.

js
// ...
https.globalAgent.on('keylog', (line, tlsSocket) => {
  fs.appendFileSync('/tmp/ssl-keys.log', line, { mode: 0o600 })
})

클래스: https.Server

추가됨: v0.3.4

자세한 내용은 http.Server를 참조하십시오.

server.close([callback])

추가됨: v0.1.90

node:http 모듈의 server.close()를 참조하십시오.

server[Symbol.asyncDispose]()

추가됨: v20.4.0

[안정성: 1 - 실험적]

안정성: 1 안정성: 1 - 실험적

server.close()를 호출하고 서버가 닫히면 완료되는 약속을 반환합니다.

server.closeAllConnections()

추가됨: v18.2.0

node:http 모듈의 server.closeAllConnections()를 참조하십시오.

server.closeIdleConnections()

추가됨: v18.2.0

node:http 모듈의 server.closeIdleConnections()를 참조하십시오.

server.headersTimeout

추가됨: v11.3.0

node:http 모듈의 server.headersTimeout 참조.

server.listen()

암호화된 연결을 수신 대기하는 HTTPS 서버를 시작합니다. 이 메서드는 net.Serverserver.listen()과 동일합니다.

server.maxHeadersCount

node:http 모듈의 server.maxHeadersCount 참조.

server.requestTimeout

[히스토리]

버전변경 사항
v18.0.0기본 요청 제한 시간이 제한 없음에서 300초(5분)로 변경되었습니다.
v14.11.0추가됨: v14.11.0

node:http 모듈의 server.requestTimeout 참조.

server.setTimeout([msecs][, callback])

추가됨: v0.11.2

node:http 모듈의 server.setTimeout() 참조.

server.timeout

[히스토리]

버전변경 사항
v13.0.0기본 제한 시간이 120초에서 0(제한 없음)으로 변경되었습니다.
v0.11.2추가됨: v0.11.2

node:http 모듈의 server.timeout 참조.

server.keepAliveTimeout

추가됨: v8.0.0

node:http 모듈에서 server.keepAliveTimeout을 참조하십시오.

https.createServer([options][, requestListener])

추가됨: v0.3.4

js
// curl -k https://localhost:8000/
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'

const options = {
  key: readFileSync('private-key.pem'),
  cert: readFileSync('certificate.pem'),
}

createServer(options, (req, res) => {
  res.writeHead(200)
  res.end('hello world\n')
}).listen(8000)
js
// curl -k https://localhost:8000/
const https = require('node:https')
const fs = require('node:fs')

const options = {
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
}

https
  .createServer(options, (req, res) => {
    res.writeHead(200)
    res.end('hello world\n')
  })
  .listen(8000)

또는

js
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'

const options = {
  pfx: readFileSync('test_cert.pfx'),
  passphrase: 'sample',
}

createServer(options, (req, res) => {
  res.writeHead(200)
  res.end('hello world\n')
}).listen(8000)
js
const https = require('node:https')
const fs = require('node:fs')

const options = {
  pfx: fs.readFileSync('test_cert.pfx'),
  passphrase: 'sample',
}

https
  .createServer(options, (req, res) => {
    res.writeHead(200)
    res.end('hello world\n')
  })
  .listen(8000)

이 예제에 대한 인증서와 키를 생성하려면 다음을 실행합니다.

bash
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
  -keyout private-key.pem -out certificate.pem

그런 다음 이 예제에 대한 pfx 인증서를 생성하려면 다음을 실행합니다.

bash
openssl pkcs12 -certpbe AES-256-CBC -export -out test_cert.pfx \
  -inkey private-key.pem -in certificate.pem -passout pass:sample

https.get(options[, callback])

https.get(url[, options][, callback])

[히스토리]

버전변경 사항
v10.9.0url 매개변수를 별도의 options 객체와 함께 전달할 수 있습니다.
v7.5.0options 매개변수가 WHATWG URL 객체일 수 있습니다.
v0.3.6추가됨: v0.3.6

http.get()과 유사하지만 HTTPS용입니다.

options는 객체, 문자열 또는 URL 객체일 수 있습니다. options가 문자열이면 new URL()을 사용하여 자동으로 구문 분석됩니다. URL 객체이면 일반적인 options 객체로 자동 변환됩니다.

js
import { get } from 'node:https'
import process from 'node:process'

get('https://encrypted.google.com/', res => {
  console.log('statusCode:', res.statusCode)
  console.log('headers:', res.headers)

  res.on('data', d => {
    process.stdout.write(d)
  })
}).on('error', e => {
  console.error(e)
})
js
const https = require('node:https')

https
  .get('https://encrypted.google.com/', res => {
    console.log('statusCode:', res.statusCode)
    console.log('headers:', res.headers)

    res.on('data', d => {
      process.stdout.write(d)
    })
  })
  .on('error', e => {
    console.error(e)
  })

https.globalAgent

[히스토리]

버전변경 사항
v19.0.0이제 에이전트는 기본적으로 HTTP Keep-Alive 및 5초 시간 제한을 사용합니다.
v0.5.9추가됨: v0.5.9

모든 HTTPS 클라이언트 요청에 대한 https.Agent의 글로벌 인스턴스입니다. keepAlive가 활성화되고 timeout이 5초로 설정되어 기본 https.Agent 구성과 다릅니다.

https.request(options[, callback])

https.request(url[, options][, callback])

[히스토리]

버전변경 사항
v22.4.0, v20.16.0clientCertEngine 옵션은 OpenSSL의 사용자 지정 엔진 지원에 따라 달라지며 OpenSSL 3에서 더 이상 사용되지 않습니다.
v16.7.0, v14.18.0URL 객체로 구문 분석된 사용자 이름과 암호는 이제 올바르게 URI 디코딩됩니다.
v14.1.0, v13.14.0이제 highWaterMark 옵션이 허용됩니다.
v10.9.0이제 별도의 options 객체와 함께 url 매개변수를 전달할 수 있습니다.
v9.3.0이제 options 매개변수에 clientCertEngine을 포함할 수 있습니다.
v7.5.0options 매개변수가 WHATWG URL 객체일 수 있습니다.
v0.3.6추가됨: v0.3.6

보안 웹 서버에 요청을 보냅니다.

tls.connect()의 다음 추가 options도 허용됩니다: ca, cert, ciphers, clientCertEngine (더 이상 사용되지 않음), crl, dhparam, ecdhCurve, honorCipherOrder, key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext, highWaterMark.

options는 객체, 문자열 또는 URL 객체일 수 있습니다. options가 문자열이면 new URL()로 자동으로 구문 분석됩니다. URL 객체이면 일반 options 객체로 자동 변환됩니다.

https.request()http.ClientRequest 클래스의 인스턴스를 반환합니다. ClientRequest 인스턴스는 쓰기 가능한 스트림입니다. POST 요청으로 파일을 업로드해야 하는 경우 ClientRequest 객체에 씁니다.

js
import { request } from 'node:https'
import process from 'node:process'

const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
}

const req = request(options, res => {
  console.log('statusCode:', res.statusCode)
  console.log('headers:', res.headers)

  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', e => {
  console.error(e)
})
req.end()
js
const https = require('node:https')

const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
}

const req = https.request(options, res => {
  console.log('statusCode:', res.statusCode)
  console.log('headers:', res.headers)

  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', e => {
  console.error(e)
})
req.end()

tls.connect()의 옵션을 사용하는 예:

js
const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
}
options.agent = new https.Agent(options)

const req = https.request(options, res => {
  // ...
})

또는 Agent를 사용하지 않고 연결 풀링을 사용하지 않도록 선택할 수 있습니다.

js
const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
  agent: false,
}

const req = https.request(options, res => {
  // ...
})

optionsURL을 사용하는 예:

js
const options = new URL('https://abc:')

const req = https.request(options, res => {
  // ...
})

인증서 지문 또는 공개 키에 대한 고정 예(pin-sha256과 유사):

js
import { checkServerIdentity } from 'node:tls'
import { Agent, request } from 'node:https'
import { createHash } from 'node:crypto'

function sha256(s) {
  return createHash('sha256').update(s).digest('base64')
}
const options = {
  hostname: 'github.com',
  port: 443,
  path: '/',
  method: 'GET',
  checkServerIdentity: function (host, cert) {
    // Make sure the certificate is issued to the host we are connected to
    const err = checkServerIdentity(host, cert)
    if (err) {
      return err
    }

    // Pin the public key, similar to HPKP pin-sha256 pinning
    const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
    if (sha256(cert.pubkey) !== pubkey256) {
      const msg =
        'Certificate verification error: ' +
        `The public key of '${cert.subject.CN}' ` +
        'does not match our pinned fingerprint'
      return new Error(msg)
    }

    // Pin the exact certificate, rather than the pub key
    const cert256 =
      'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' + '0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65'
    if (cert.fingerprint256 !== cert256) {
      const msg =
        'Certificate verification error: ' +
        `The certificate of '${cert.subject.CN}' ` +
        'does not match our pinned fingerprint'
      return new Error(msg)
    }

    // This loop is informational only.
    // Print the certificate and public key fingerprints of all certs in the
    // chain. Its common to pin the public key of the issuer on the public
    // internet, while pinning the public key of the service in sensitive
    // environments.
    let lastprint256
    do {
      console.log('Subject Common Name:', cert.subject.CN)
      console.log('  Certificate SHA256 fingerprint:', cert.fingerprint256)

      const hash = createHash('sha256')
      console.log('  Public key ping-sha256:', sha256(cert.pubkey))

      lastprint256 = cert.fingerprint256
      cert = cert.issuerCertificate
    } while (cert.fingerprint256 !== lastprint256)
  },
}

options.agent = new Agent(options)
const req = request(options, res => {
  console.log('All OK. Server matched our pinned cert or public key')
  console.log('statusCode:', res.statusCode)

  res.on('data', d => {})
})

req.on('error', e => {
  console.error(e.message)
})
req.end()
js
const tls = require('node:tls')
const https = require('node:https')
const crypto = require('node:crypto')

function sha256(s) {
  return crypto.createHash('sha256').update(s).digest('base64')
}
const options = {
  hostname: 'github.com',
  port: 443,
  path: '/',
  method: 'GET',
  checkServerIdentity: function (host, cert) {
    // Make sure the certificate is issued to the host we are connected to
    const err = tls.checkServerIdentity(host, cert)
    if (err) {
      return err
    }

    // Pin the public key, similar to HPKP pin-sha256 pinning
    const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
    if (sha256(cert.pubkey) !== pubkey256) {
      const msg =
        'Certificate verification error: ' +
        `The public key of '${cert.subject.CN}' ` +
        'does not match our pinned fingerprint'
      return new Error(msg)
    }

    // Pin the exact certificate, rather than the pub key
    const cert256 =
      'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' + '0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65'
    if (cert.fingerprint256 !== cert256) {
      const msg =
        'Certificate verification error: ' +
        `The certificate of '${cert.subject.CN}' ` +
        'does not match our pinned fingerprint'
      return new Error(msg)
    }

    // This loop is informational only.
    // Print the certificate and public key fingerprints of all certs in the
    // chain. Its common to pin the public key of the issuer on the public
    // internet, while pinning the public key of the service in sensitive
    // environments.
    do {
      console.log('Subject Common Name:', cert.subject.CN)
      console.log('  Certificate SHA256 fingerprint:', cert.fingerprint256)

      hash = crypto.createHash('sha256')
      console.log('  Public key ping-sha256:', sha256(cert.pubkey))

      lastprint256 = cert.fingerprint256
      cert = cert.issuerCertificate
    } while (cert.fingerprint256 !== lastprint256)
  },
}

options.agent = new https.Agent(options)
const req = https.request(options, res => {
  console.log('All OK. Server matched our pinned cert or public key')
  console.log('statusCode:', res.statusCode)

  res.on('data', d => {})
})

req.on('error', e => {
  console.error(e.message)
})
req.end()

예시 출력:

text
Subject Common Name: github.com
  Certificate SHA256 fingerprint: FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65
  Public key ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=
Subject Common Name: Sectigo ECC Domain Validation Secure Server CA
  Certificate SHA256 fingerprint: 61:E9:73:75:E9:F6:DA:98:2F:F5:C1:9E:2F:94:E6:6C:4E:35:B6:83:7C:E3:B9:14:D2:24:5C:7F:5F:65:82:5F
  Public key ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g=
Subject Common Name: USERTrust ECC Certification Authority
  Certificate SHA256 fingerprint: A6:CF:64:DB:B4:C8:D5:FD:19:CE:48:89:60:68:DB:03:B5:33:A8:D1:33:6C:62:56:A8:7D:00:CB:B3:DE:F3:EA
  Public key ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw=
Subject Common Name: AAA Certificate Services
  Certificate SHA256 fingerprint: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
  Public key ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=
All OK. Server matched our pinned cert or public key
statusCode: 200