1+ import { promisify } from 'util' ;
2+ import * as fs from 'fs' ;
3+
4+ import { getLocal , Mockttp } from 'mockttp' ;
5+
6+ import { HttpsPathOptions } from 'mockttp/dist/util/tls' ;
7+
8+ const readFile = promisify ( fs . readFile ) ;
9+
10+ // Make the types for some of the browser code below happy.
11+ let targetUrl : string ;
12+ let installingCert : boolean ;
13+
14+ // Check if an HTTPS cert to a server using the certificate succeeds
15+ // If it doesn't, redirect to the certificate itself (the browser will prompt to install)
16+ // Note that this function is stringified, and run in the browser, not here in node.
17+ function ensureCertificateIsInstalled ( ) {
18+ const testUrl = window . location . href . replace ( 'http://' , 'https://' ) . replace ( 'check-cert' , 'test-https' ) ;
19+ const downloadUrl = window . location . href . replace ( 'check-cert' , 'download-cert' ) ;
20+
21+ fetch ( testUrl )
22+ . then ( ( ) => true )
23+ . catch ( ( ) => false )
24+ . then ( ( certificateIsTrusted ) => {
25+ if ( certificateIsTrusted ) {
26+ window . location . replace ( targetUrl ) ;
27+ } else {
28+ if ( ! installingCert ) {
29+ installingCert = true ;
30+ const iframe = document . createElement ( 'iframe' ) ;
31+ iframe . src = downloadUrl ;
32+ document . body . appendChild ( iframe ) ;
33+ setInterval ( ensureCertificateIsInstalled , 500 ) ;
34+ }
35+ }
36+ } ) ;
37+ }
38+
39+ export class CertCheckServer {
40+
41+ constructor ( private config : { https : HttpsPathOptions } ) { }
42+
43+ private server : Mockttp | undefined ;
44+
45+ async start ( targetUrl : string ) {
46+ this . server = getLocal ( { https : this . config . https , debug : true , cors : true } ) ;
47+ await this . server . start ( ) ;
48+
49+ const certificatePem = await readFile ( this . config . https . certPath ) ;
50+
51+ this . server . get ( '/test-https' ) . thenReply ( 200 ) ;
52+
53+ this . server . get ( '/download-cert' ) . thenReply ( 200 , certificatePem , {
54+ 'Content-type' : 'application/x-x509-ca-cert'
55+ } ) ;
56+
57+ this . server . get ( '/check-cert' ) . thenReply ( 200 , `
58+ <html>
59+ <title>HTTP Toolkit Certificate Setup</title>
60+ <meta charset="UTF-8" />
61+ <link href="http://fonts.googleapis.com/css?family=Lato" rel="stylesheet" />
62+ <style>
63+ body {
64+ margin: 20px;
65+ background-color: #d8e2e6;
66+ font-family: Lato, Arial;
67+ }
68+
69+ h1 {
70+ font-size: 36pt;
71+ }
72+
73+ p {
74+ font-size: 16pt;
75+ }
76+
77+ iframe {
78+ display: none;
79+ }
80+ </style>
81+ <script>
82+ let installingCert = false;
83+ const targetUrl = ${ JSON . stringify ( targetUrl ) } ;
84+
85+ ${ ensureCertificateIsInstalled . toString ( ) }
86+ ensureCertificateIsInstalled();
87+ </script>
88+ <body>
89+ <h1>
90+ Configuring Firefox to use HTTP Toolkit
91+ </h1>
92+ <p>
93+ To intercept HTTPS traffic, you need to trust the HTTP Toolkit certificate.
94+ </p>
95+ <p>
96+ Select 'Trust this CA to identify web sites' and press 'OK' to continue.
97+ </p>
98+
99+ <svg
100+ version="1.1"
101+ xmlns="http://www.w3.org/2000/svg"
102+ xmlns:xlink="http://www.w3.org/1999/xlink"
103+ x="0px"
104+ y="0px"
105+ width="400px"
106+ height="400px"
107+ viewBox="0 0 50 50"
108+ style="enable-background:new 0 0 50 50;"
109+ >
110+ <path fill="#b6c2ca" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z">
111+ <animateTransform
112+ attributeType="xml"
113+ attributeName="transform"
114+ type="rotate"
115+ from="0 25 25"
116+ to="360 25 25"
117+ dur="6s"
118+ repeatCount="indefinite"
119+ />
120+ </path>
121+ </svg>
122+ </div>
123+ </body>
124+ </html>
125+ ` ) ;
126+ }
127+
128+ get host ( ) : string {
129+ return this . server ! . url
130+ . replace ( 'https://' , '' ) ;
131+ }
132+
133+ get checkCertUrl ( ) : string {
134+ return this . server ! . url
135+ . replace ( 'https://' , 'http://' )
136+ . replace ( / \/ ? $ / , '/check-cert' ) ;
137+ }
138+
139+ async stop ( ) {
140+ if ( this . server ) {
141+ await this . server . stop ( ) ;
142+ this . server = undefined ;
143+ }
144+ }
145+ }
0 commit comments