|
| 1 | +import express from "express"; |
| 2 | +import { expect, test } from "vitest"; |
| 3 | +import * as https from "node:https"; |
| 4 | +import { Agent } from "undici"; |
| 5 | +import createClient from "../../src/index.js"; |
| 6 | +import * as forge from "node-forge"; |
| 7 | +import * as crypto from "crypto"; |
| 8 | +import httpServer from "express/lib/application.js"; |
| 9 | + |
| 10 | +const pki = forge.pki; |
| 11 | + |
| 12 | +const genCACert = async (options = {}) => { |
| 13 | + options = { |
| 14 | + ...{ |
| 15 | + commonName: "Testing CA - DO NOT TRUST", |
| 16 | + bits: 2048, |
| 17 | + }, |
| 18 | + ...options, |
| 19 | + }; |
| 20 | + |
| 21 | + let keyPair = await new Promise((res, rej) => { |
| 22 | + pki.rsa.generateKeyPair({ bits: options.bits }, (error, pair) => { |
| 23 | + if (error) rej(error); |
| 24 | + else res(pair); |
| 25 | + }); |
| 26 | + }); |
| 27 | + |
| 28 | + let cert = pki.createCertificate(); |
| 29 | + cert.publicKey = keyPair.publicKey; |
| 30 | + cert.serialNumber = crypto.randomUUID().replace(/-/g, ""); |
| 31 | + |
| 32 | + cert.validity.notBefore = new Date(); |
| 33 | + cert.validity.notBefore.setDate(cert.validity.notBefore.getDate() - 1); |
| 34 | + cert.validity.notAfter = new Date(); |
| 35 | + cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); |
| 36 | + |
| 37 | + cert.setSubject([{ name: "commonName", value: options.commonName }]); |
| 38 | + cert.setExtensions([{ name: "basicConstraints", cA: true }]); |
| 39 | + |
| 40 | + cert.setIssuer(cert.subject.attributes); |
| 41 | + cert.sign(keyPair.privateKey, forge.md.sha256.create()); |
| 42 | + |
| 43 | + return { |
| 44 | + ca: { |
| 45 | + key: pki.privateKeyToPem(keyPair.privateKey), |
| 46 | + cert: pki.certificateToPem(cert), |
| 47 | + }, |
| 48 | + fingerprint: forge.util.encode64( |
| 49 | + pki.getPublicKeyFingerprint(keyPair.publicKey, { |
| 50 | + type: "SubjectPublicKeyInfo", |
| 51 | + md: forge.md.sha256.create(), |
| 52 | + encoding: "binary", |
| 53 | + }), |
| 54 | + ), |
| 55 | + }; |
| 56 | +}; |
| 57 | + |
| 58 | +const caToBuffer = (ca) => { |
| 59 | + return { |
| 60 | + key: Buffer.from(ca.key), |
| 61 | + cert: Buffer.from(ca.cert), |
| 62 | + }; |
| 63 | +}; |
| 64 | + |
| 65 | +const API_PORT = process.env.API_PORT || 4578; |
| 66 | + |
| 67 | +const app = express(); |
| 68 | +app.get("/v1/foo", (req, res) => { |
| 69 | + res.send("bar"); |
| 70 | +}); |
| 71 | + |
| 72 | +test("requestInitExt", async () => { |
| 73 | + let cert = await genCACert(); |
| 74 | + let buffers = caToBuffer(cert.ca); |
| 75 | + let options = {}; |
| 76 | + options.key = buffers.key; |
| 77 | + options.cert = buffers.cert; |
| 78 | + const httpsServer = https.createServer(options, app); |
| 79 | + httpsServer.listen(4578); |
| 80 | + const dispatcher = new Agent({ |
| 81 | + connect: { |
| 82 | + rejectUnauthorized: false, |
| 83 | + }, |
| 84 | + }); |
| 85 | + const client = createClient({ baseUrl: `https://localhost:${API_PORT}`, requestInitExt: { dispatcher } }); |
| 86 | + const fetchResponse = await client.GET("/v1/foo", { parseAs: "text" }); |
| 87 | + httpsServer.closeAllConnections(); |
| 88 | + httpsServer.close(); |
| 89 | + expect(fetchResponse.response.ok).toBe(true); |
| 90 | +}); |
0 commit comments