@@ -32,7 +32,8 @@ import { IconButton } from '../common/icon-button';
3232import {
3333 SettingsButton ,
3434 SettingsExplanation ,
35- SettingsSubheading
35+ SettingsSubheading ,
36+ SettingsSubheadingRow
3637} from './settings-components' ;
3738import { StringSettingsList } from './string-settings-list' ;
3839
@@ -91,6 +92,24 @@ const Http2Select = styled(Select)`
9192 padding: 3px;
9293` ;
9394
95+ const TlsPassthroughModeToggle = styled . button . attrs ( ( ) => ( {
96+ type : 'button' as const
97+ } ) ) `
98+ display: flex;
99+ align-items: center;
100+ gap: 6px;
101+ cursor: pointer;
102+
103+ margin-left: auto;
104+
105+ background: none;
106+ border: none;
107+ padding: 0;
108+ color: ${ p => p . theme . mainColor } ;
109+ font-family: ${ p => p . theme . fontFamily } ;
110+ font-size: ${ p => p . theme . textSize } ;
111+ ` ;
112+
94113const TlsKeyLogInputContainer = styled . div `
95114 margin: 10px 0;
96115 display: flex;
@@ -177,22 +196,45 @@ export class ProxySettingsCard extends React.Component<
177196 else this . props . proxyStore ! . setPortConfig ( this . portConfig ) ;
178197 }
179198
199+ private get tlsHostnames ( ) {
200+ const config = this . props . proxyStore ! . tlsInterceptionConfig ;
201+ return 'tlsPassthrough' in config
202+ ? config . tlsPassthrough
203+ : config . tlsInterceptOnly ;
204+ }
205+
206+ private get tlsMode ( ) : 'passthrough' | 'intercept-only' {
207+ return 'tlsInterceptOnly' in this . props . proxyStore ! . tlsInterceptionConfig
208+ ? 'intercept-only'
209+ : 'passthrough' ;
210+ }
211+
180212 @action . bound
181213 addTlsPassthroughHostname ( hostname : string ) {
182- const { tlsPassthroughConfig } = this . props . proxyStore ! ;
183- tlsPassthroughConfig . push ( { hostname } ) ;
214+ this . tlsHostnames . push ( { hostname } ) ;
184215 }
185216
186217 @action . bound
187218 removeTlsPassthroughHostname ( hostname : string ) {
188- const { tlsPassthroughConfig } = this . props . proxyStore ! ;
189- const hostnameIndex = _ . findIndex ( tlsPassthroughConfig , ( passthroughItem ) =>
190- passthroughItem . hostname === hostname
219+ const hostnames = this . tlsHostnames ;
220+ const hostnameIndex = _ . findIndex ( hostnames , ( item ) =>
221+ item . hostname === hostname
191222 ) ;
192223
193224 if ( hostnameIndex === - 1 ) return ;
194225
195- tlsPassthroughConfig . splice ( hostnameIndex , 1 ) ;
226+ hostnames . splice ( hostnameIndex , 1 ) ;
227+ }
228+
229+ @action . bound
230+ toggleTlsMode ( ) {
231+ const proxyStore = this . props . proxyStore ! ;
232+ const hostnames = this . tlsHostnames ;
233+ if ( this . tlsMode === 'passthrough' ) {
234+ proxyStore . tlsInterceptionConfig = { tlsInterceptOnly : hostnames } ;
235+ } else {
236+ proxyStore . tlsInterceptionConfig = { tlsPassthrough : hostnames } ;
237+ }
196238 }
197239
198240 @observable
@@ -233,13 +275,16 @@ export class ProxySettingsCard extends React.Component<
233275 http2Enabled,
234276 http2CurrentlyEnabled,
235277
236- tlsPassthroughConfig ,
237- currentTlsPassthroughConfig ,
278+ tlsInterceptionConfig ,
279+ currentTlsInterceptionConfig ,
238280
239281 keyLogFilePath,
240282 currentKeyLogFilePath
241283 } = proxyStore ! ;
242284
285+ const tlsMode = this . tlsMode ;
286+ const tlsHostnames = this . tlsHostnames ;
287+
243288 return < CollapsibleCard { ...cardProps } >
244289 < header >
245290 < CollapsibleCardHeading onCollapseToggled = {
@@ -252,7 +297,7 @@ export class ProxySettingsCard extends React.Component<
252297 visible = {
253298 ( this . isCurrentPortConfigValid && ! this . isCurrentPortInRange ) ||
254299 http2Enabled !== http2CurrentlyEnabled ||
255- ! _ . isEqual ( tlsPassthroughConfig , currentTlsPassthroughConfig ) ||
300+ ! _ . isEqual ( tlsInterceptionConfig , currentTlsInterceptionConfig ) ||
256301 keyLogFilePath !== currentKeyLogFilePath
257302 }
258303 />
@@ -301,36 +346,67 @@ export class ProxySettingsCard extends React.Component<
301346
302347 {
303348 versionSatisfies ( serverVersion . value , TLS_PASSTHROUGH_SUPPORTED ) && < >
304- < SettingsSubheading >
305- TLS Passthrough { ! _ . isEqual ( tlsPassthroughConfig , currentTlsPassthroughConfig ) &&
349+ < SettingsSubheadingRow >
350+ < SettingsSubheading > TLS Passthrough</ SettingsSubheading >
351+
352+ { ! _ . isEqual ( tlsInterceptionConfig , currentTlsInterceptionConfig ) &&
306353 < UnsavedIcon title = "Restart app to apply changes" />
307354 }
308- </ SettingsSubheading >
355+
356+ < TlsPassthroughModeToggle
357+ title = { tlsMode === 'passthrough'
358+ ? "Listed hostnames are not intercepted. Click to switch to intercept-only mode."
359+ : "Only listed hostnames are intercepted. Click to switch to passthrough mode."
360+ }
361+ onClick = { this . toggleTlsMode }
362+ >
363+ { tlsMode === 'passthrough'
364+ ? 'Exclude hostnames'
365+ : 'Intercept only these hostnames'
366+ }
367+ < Icon icon = { [ 'fas' ,
368+ tlsMode === 'passthrough' ? 'toggle-on' : 'toggle-off'
369+ ] } />
370+ </ TlsPassthroughModeToggle >
371+ </ SettingsSubheadingRow >
309372
310373 < StringSettingsList
311- values = { tlsPassthroughConfig . map ( c => c . hostname ) }
374+ values = { tlsHostnames . map ( c => c . hostname ) }
312375 onAdd = { this . addTlsPassthroughHostname }
313376 onDelete = { this . removeTlsPassthroughHostname }
314- placeholder = 'A hostname whose TLS connections should not be intercepted'
377+ placeholder = { tlsMode === 'intercept-only'
378+ ? 'A hostname whose TLS connections should be intercepted'
379+ : 'A hostname whose TLS connections should not be intercepted'
380+ }
315381 validationFn = { hostnameValidation }
316382 />
317383
318384 < SettingsExplanation >
319- Incoming TLS connections to these hostnames will bypass HTTP Toolkit, and will
320- be forwarded upstream untouched instead of being intercepted. Clients will not see
321- HTTP Toolkit's certificate, which may solve some connection issues, but traffic
322- within these TLS connections will not be accessible.
385+ { tlsMode === 'intercept-only'
386+ ? < >
387+ Only TLS connections to these hostnames will be intercepted by HTTP Toolkit.
388+ All other TLS connections will be forwarded upstream without
389+ interception. Non-TLS traffic is always visible regardless of this setting.
390+ </ >
391+ : < >
392+ TLS connections to these hostnames will be forwarded upstream untouched, without
393+ interception. This may solve some certificate trust connectivity issues,
394+ but traffic within these TLS connections will not be accessible.
395+ </ >
396+ }
323397 </ SettingsExplanation >
324398 </ >
325399 }
326400
327401 {
328402 versionSatisfies ( serverVersion . value , INITIAL_HTTP2_RANGE ) && < >
329- < SettingsSubheading >
330- HTTP/2 Support { http2Enabled !== http2CurrentlyEnabled &&
403+ < SettingsSubheadingRow >
404+ < SettingsSubheading > HTTP/2 Support</ SettingsSubheading >
405+
406+ { http2Enabled !== http2CurrentlyEnabled &&
331407 < UnsavedIcon title = "Restart app to apply changes" />
332408 }
333- </ SettingsSubheading >
409+ </ SettingsSubheadingRow >
334410
335411 < Http2Select
336412 value = { JSON . stringify ( http2Enabled ) }
@@ -350,11 +426,13 @@ export class ProxySettingsCard extends React.Component<
350426
351427 {
352428 versionSatisfies ( serverVersion . value , KEY_LOG_FILE_SUPPORTED ) && < >
353- < SettingsSubheading >
354- TLS Key Log File { keyLogFilePath !== currentKeyLogFilePath &&
429+ < SettingsSubheadingRow >
430+ < SettingsSubheading > TLS Key Log File</ SettingsSubheading >
431+
432+ { keyLogFilePath !== currentKeyLogFilePath &&
355433 < UnsavedIcon title = "Restart app to apply changes" />
356434 }
357- </ SettingsSubheading >
435+ </ SettingsSubheadingRow >
358436
359437 < TlsKeyLogInputContainer >
360438 { versionSatisfies ( desktopVersion . value , DESKTOP_SELECT_SAVE_FILE_SUPPORTED )
0 commit comments