@@ -24,6 +24,9 @@ const AcceptHeaderGraphMap: { key: string; value: string }[] = [
2424 { key : "TSV" , value : "text/tab-separated-values,*/*;q=0.9" } ,
2525] ;
2626
27+ // Type for key-value pairs (headers, args, etc.)
28+ type KeyValuePair = { name : string ; value : string } ;
29+
2730// Default API Key header name
2831const DEFAULT_API_KEY_HEADER = "X-API-Key" ;
2932
@@ -1380,6 +1383,81 @@ export default class TabSettingsModal {
13801383 acceptGraphSelect . setAttribute ( "data-config" , "acceptHeaderGraph" ) ;
13811384 acceptGraphSection . appendChild ( acceptGraphSelect ) ;
13821385 container . appendChild ( acceptGraphSection ) ;
1386+
1387+ // Custom Headers section
1388+ const headersSection = this . createSection ( "Custom HTTP Headers" ) ;
1389+ const headersContainer = document . createElement ( "div" ) ;
1390+ addClass ( headersContainer , "keyValueContainer" ) ;
1391+ headersContainer . setAttribute ( "data-config" , "headers" ) ;
1392+
1393+ // Get existing headers
1394+ const existingHeaders = typeof reqConfig . headers === "function" ? { } : reqConfig . headers || { } ;
1395+ const headerPairs : KeyValuePair [ ] = Object . entries ( existingHeaders ) . map ( ( [ name , value ] ) => ( {
1396+ name,
1397+ value,
1398+ } ) ) ;
1399+
1400+ // Draw existing headers
1401+ headerPairs . forEach ( ( pair , index ) => {
1402+ this . createKeyValueRow ( headersContainer , pair , index ) ;
1403+ } ) ;
1404+
1405+ // Add empty row for adding new headers
1406+ this . createKeyValueRow ( headersContainer , { name : "" , value : "" } , headerPairs . length ) ;
1407+
1408+ headersSection . appendChild ( headersContainer ) ;
1409+ container . appendChild ( headersSection ) ;
1410+ }
1411+
1412+ private createKeyValueRow ( container : HTMLElement , pair : KeyValuePair , index : number ) {
1413+ const row = document . createElement ( "div" ) ;
1414+ addClass ( row , "keyValueRow" ) ;
1415+
1416+ const nameInput = document . createElement ( "input" ) ;
1417+ nameInput . type = "text" ;
1418+ nameInput . placeholder = "Header Name" ;
1419+ nameInput . value = pair . name ;
1420+ addClass ( nameInput , "keyInput" ) ;
1421+
1422+ const valueInput = document . createElement ( "input" ) ;
1423+ valueInput . type = "text" ;
1424+ valueInput . placeholder = "Header Value" ;
1425+ valueInput . value = pair . value ;
1426+ addClass ( valueInput , "valueInput" ) ;
1427+
1428+ const removeButton = document . createElement ( "button" ) ;
1429+ removeButton . type = "button" ;
1430+ removeButton . innerHTML = '<i class="fas fa-times"></i>' ;
1431+ removeButton . title = "Remove header" ;
1432+ addClass ( removeButton , "removeButton" ) ;
1433+
1434+ // Auto-add new empty row when typing in the last row
1435+ const onInput = ( ) => {
1436+ const allRows = container . querySelectorAll ( ".keyValueRow" ) ;
1437+ const isLastRow = row === allRows [ allRows . length - 1 ] ;
1438+
1439+ if ( isLastRow && ( nameInput . value . trim ( ) || valueInput . value . trim ( ) ) ) {
1440+ // Add a new empty row
1441+ this . createKeyValueRow ( container , { name : "" , value : "" } , allRows . length ) ;
1442+ }
1443+ } ;
1444+
1445+ nameInput . addEventListener ( "input" , onInput ) ;
1446+ valueInput . addEventListener ( "input" , onInput ) ;
1447+
1448+ removeButton . onclick = ( ) => {
1449+ row . remove ( ) ;
1450+ // Ensure there's always at least one empty row
1451+ const remainingRows = container . querySelectorAll ( ".keyValueRow" ) ;
1452+ if ( remainingRows . length === 0 ) {
1453+ this . createKeyValueRow ( container , { name : "" , value : "" } , 0 ) ;
1454+ }
1455+ } ;
1456+
1457+ row . appendChild ( nameInput ) ;
1458+ row . appendChild ( valueInput ) ;
1459+ row . appendChild ( removeButton ) ;
1460+ container . appendChild ( row ) ;
13831461 }
13841462
13851463 private createSection ( title : string ) : HTMLElement {
@@ -1546,6 +1624,22 @@ export default class TabSettingsModal {
15461624 updates [ config ] = ( select as HTMLSelectElement ) . value ;
15471625 }
15481626 } ) ;
1627+
1628+ // Save custom headers
1629+ const headersContainer = requestContent . querySelector ( ".keyValueContainer[data-config='headers']" ) ;
1630+ if ( headersContainer ) {
1631+ const headers : { [ key : string ] : string } = { } ;
1632+ const rows = headersContainer . querySelectorAll ( ".keyValueRow" ) ;
1633+ rows . forEach ( ( row ) => {
1634+ const nameInput = row . querySelector ( ".keyInput" ) as HTMLInputElement ;
1635+ const valueInput = row . querySelector ( ".valueInput" ) as HTMLInputElement ;
1636+ if ( nameInput && valueInput && nameInput . value . trim ( ) ) {
1637+ headers [ nameInput . value . trim ( ) ] = valueInput . value ;
1638+ }
1639+ } ) ;
1640+ updates . headers = headers ;
1641+ }
1642+
15491643 this . tab . setRequestConfig ( updates ) ;
15501644 }
15511645
0 commit comments