@@ -35,13 +35,19 @@ const { services, close: closeServices } = fetchServices('http', true);
3535const =  useTemplateRef (' dialogRef' 
3636let  dialog:  Modal  |  undefined ;
3737const =  useTemplateRef <ComponentPublicInstance <typeof  RegexInput >>(' urlValue' 
38- const =  ref <any []>([])
38+ const =  ref <any []>([])
39+ const =  ref <any []>([])
3940type  CheckboxFilter  =  ' Not' |  ' Single' |  ' Multi' 
4041interface  Filter  {
4142    service:  MultiFilterItem  
4243    method:  MultiFilterItem  &  { custom? :  string } 
4344    url:  FilterItem  
44-     headers:  FilterItem  
45+     request:  { 
46+         headers:  FilterItem  
47+     } 
48+     response:  { 
49+         headers:  FilterItem  
50+     } 
4551} 
4652interface  FilterItem  {
4753    checkbox:  boolean  
@@ -56,15 +62,25 @@ const filter = reactive<Filter>({
5662    service: { state: ' Not' false , value: [] }, 
5763    method: { state: ' Not' false , value: [' GET'  
5864    url: { checkbox: false , value: null }, 
59-     headers: { checkbox: false , value: [{ name: ' ' ' '  
65+     request: { 
66+         headers: { checkbox: false , value: [{ name: ' ' ' '  
67+     }, 
68+     response: { 
69+          headers: { checkbox: false , value: [{ name: ' ' ' '  
70+     } 
6071}) 
6172
6273onMounted (() =>  {
6374    dialog  =  Modal .getOrCreateInstance (dialogRef .value ! ); 
6475    const =  localStorage .getItem (` http-requests-${getFilterCacheKey ()} ` ) 
6576    if  (s  &&  s  !==  ' '  
6677        const =  JSON .parse (s ) 
67-         Object .assign (filter , saved ) 
78+         type  Key  =  keyof  Filter  
79+         for  (const in  filter ) { 
80+             if  (saved [key ] !==  undefined ) { 
81+                 filter [key  as  Key ] =  saved [key ] 
82+             } 
83+         } 
6884    } 
6985}) 
7086
@@ -128,10 +144,22 @@ const events = computed<ServiceEvent[]>(() => {
128144        }) 
129145    } 
130146     
131-     if  (filter .headers .checkbox  &&  headerFilter .value ?.length  >  0 ) { 
147+     if  (filter .request .headers .checkbox  &&  requestHeaderFilter .value ?.length  >  0 ) { 
148+         result  =  result .filter (x  =>  { 
149+             const =  x .data  as  HttpEventData  
150+             for  (const of  requestHeaderFilter .value ) { 
151+                 if  (! filter (data )) { 
152+                     return  false  
153+                 } 
154+             } 
155+             return  true  
156+         }) 
157+     } 
158+ 
159+     if  (filter .response .headers .checkbox  &&  responseHeaderFilter .value ?.length  >  0 ) { 
132160        result  =  result .filter (x  =>  { 
133161            const =  x .data  as  HttpEventData  
134-             for  (const of  headerFilter .value ) { 
162+             for  (const of  responseHeaderFilter .value ) { 
135163                if  (! filter (data )) { 
136164                    return  false  
137165                } 
@@ -240,7 +268,10 @@ const activeFiltersCount = computed(() => {
240268    if  (filter .url .checkbox  &&  filter .url .value ) { 
241269        counter ++ ; 
242270    } 
243-     if  (filter .headers .checkbox  &&  filter .headers .value .length  >  1 ) { 
271+     if  (filter .request .headers .checkbox  &&  filter .request .headers .value .length  >  1 ) { 
272+         counter ++ ; 
273+     } 
274+     if  (filter .response .headers .checkbox  &&  filter .response .headers .value .length  >  1 ) { 
244275        counter ++ ; 
245276    } 
246277    return  counter ; 
@@ -254,73 +285,84 @@ function getFilterCacheKey() {
254285    } 
255286    return  ` filter-${props .serviceName }-${props .path }-${props .method } `  
256287} 
257- function  onHeaderInput(index :  number ) {
258-   const =  filter . headers .value [filter . headers .value .length  -  1 ] 
288+ function  onHeaderInput(headers :   FilterItem ,  index :  number ) {
289+      const =  headers .value [headers .value .length  -  1 ] 
259290
260-   //  If currently editing the last row and it has a name → add new empty row 
261-   if  (index  ===  filter . headers .value .length  -  1  &&  last .name .trim () !==  ' '  
262-     filter . headers .value .push ({ name: ' ' ' '  
263-   } 
291+      //  If currently editing the last row and it has a name → add new empty row 
292+      if  (index  ===  headers .value ? .length  -  1  &&  ( last .name ? .trim () !==  ' '   ||   last . value ?. trim ()) ) { 
293+          headers .value .push ({ name: ' ' ' '  
294+      } 
264295
265-   //  Optional: remove rows where both fields are empty (except last)  
266-   for  ( let  i  =   0 ;  i   <   filter . headers .value . length   -   1 ;  i ++ ) {  
267-     const  hf  =   filter . headers . value [ i ]  
268-     if  ( ! hf . name ?. trim ()  &&   ! hf .value ?. trim ()) {  
269-       filter . headers . value . splice ( i ,  1 )  
270-       break  
296+      for  ( let  i  =   0 ;  i   <   headers . value . length   -   1 ;  i ++ ) {  
297+          const  hf  =   headers .value [ i ]  
298+          if  ( ! hf . name ?. trim ()  &&   ! hf . value ?. trim ()) {  
299+          headers .value . splice ( i ,  1 )  
300+          break  
301+         }  
271302    } 
272-   } 
273303} 
274- function  removeHeaderFilter(index :  number ) {
275-   filter . headers .value .splice (index , 1 ) 
304+ function  removeHeaderFilter(headers :   FilterItem ,  index :  number ) {
305+   headers .value .splice (index , 1 ) 
276306
277307  //  Ensure at least one empty placeholder row 
278-   const =  filter . headers .value [filter . headers .value .length  -  1 ] 
308+   const =  headers .value [headers .value .length  -  1 ] 
279309  if  (last  &&  last .name ) { 
280-     filter . headers .value .push ({ name: ' ' ' '  
310+     headers .value .push ({ name: ' ' ' '  
281311  } 
282312} 
283- const headerErrors  =  computed (() =>  {
313+ const requestHeaderErrors  =  computed (() =>  {
284314    const =  [] 
285-     for  (const of  headerValueRefs .value ) { 
286-         if  (ref .regexError ) { 
315+     for  (const of  requestHeaderValueRefs .value ) { 
316+         if  (ref  &&  ref .regexError ) { 
317+             result .push (ref .regexError ) 
318+         } 
319+     } 
320+     return  result  
321+ }) 
322+ const =  computed (() =>  {
323+     const :  string [] =  [] 
324+     if  (! filter .response .headers .checkbox ) { 
325+         return  result  
326+     } 
327+     for  (const of  responseHeaderValueRefs .value ) { 
328+         if  (ref  &&  ref .regexError ) { 
287329            result .push (ref .regexError ) 
288330        } 
289331    } 
290332    return  result  
291333}) 
292- const headerFilter  =  computed (() =>  {
334+ const requestHeaderFilter  =  computed (() =>  {
293335    const :  ((data :  HttpEventData ) =>  boolean )[] =  [] 
294-     if  (! headerValueRefs .value ) { 
336+     if  (! requestHeaderValueRefs .value ) { 
295337        return  result ; 
296338    } 
297339
298-     for  (let  i =  0 ; i  <  filter .headers .value .length  -  1 ; i ++ ) { 
299-         if  (headerValueRefs .value [i ]?.regexError ) { 
340+     for  (let  i =  0 ; i  <  filter .request . headers .value .length  -  1 ; i ++ ) { 
341+         if  (requestHeaderValueRefs .value [i ]?.regexError ) { 
300342            continue  
301343        } 
302-         const =  filter .headers .value [i ]; 
344+         const =  filter .request . headers .value [i ]; 
303345        result .push ((data :  HttpEventData ) =>  { 
304346            const =  data .request .parameters  
305347            if  (! params ) { 
306348                return  false  
307349            } 
308350
351+             const =  fh .name ?.toLowerCase (); 
309352            for  (const of  params ) { 
310353                if  (param .type  !==  ' header'  
311354                    continue  
312355                } 
313-                 const =  fh .name ?.toLowerCase (); 
314356                if  (! name ) { 
315-                     const =  headerValueRefs .value [i ].regex  
357+                     const =  requestHeaderValueRefs .value [i ].regex  
316358                    if  (regex  &&  regex .test (param .raw )) { 
317359                        return  true  
318360                    } 
319361                } else  if  (param .name .toLowerCase () ===  name ) { 
320362                    if  (! fh .value ) { 
321363                        return  true  
322364                    } else  { 
323-                         const =  headerValueRefs .value [i ].regex  
365+                         const =  requestHeaderValueRefs .value [i ].regex  
324366                        if  (regex  &&  regex .test (param .raw )) { 
325367                            return  true  
326368                        } 
@@ -332,6 +374,47 @@ const headerFilter = computed(() => {
332374    } 
333375    return  result  
334376}) 
377+ const =  computed (() =>  {
378+     const :  ((data :  HttpEventData ) =>  boolean )[] =  [] 
379+     if  (! responseHeaderValueRefs .value ) { 
380+         return  result ; 
381+     } 
382+ 
383+     for  (let  i =  0 ; i  <  filter .response .headers .value .length  -  1 ; i ++ ) { 
384+         if  (responseHeaderValueRefs .value [i ]?.regexError ) { 
385+             continue  
386+         } 
387+         const =  filter .response .headers .value [i ]; 
388+         result .push ((data :  HttpEventData ) =>  { 
389+             const =  data .response .headers  
390+             if  (! headers ) { 
391+                 return  false  
392+             } 
393+ 
394+             const =  fh .name ?.toLowerCase (); 
395+             for  (const in  headers ) { 
396+                  
397+                 if  (! name ) { 
398+                     const =  responseHeaderValueRefs .value [i ].regex  
399+                     if  (regex  &&  regex .test (headers [name ])) { 
400+                         return  true  
401+                     } 
402+                 } else  if  (fieldName .toLowerCase () ===  name ) { 
403+                     if  (! fh .value ) { 
404+                         return  true  
405+                     } else  { 
406+                         const =  responseHeaderValueRefs .value [i ].regex  
407+                         if  (regex  &&  regex .test (headers [fieldName ])) { 
408+                             return  true  
409+                         } 
410+                     } 
411+                 } 
412+             } 
413+             return  false  
414+         }) 
415+     } 
416+     return  result  
417+ }) 
335418script >
336419
337420<template >
@@ -460,39 +543,76 @@ const headerFilter = computed(() => {
460543                        </div >
461544                    </div >
462545
463-                     <!--  Headers --> 
464-                     <div  class =" row" :class =" { 'mb-3': headerErrors.length == 0 }" 
546+                     <!--  Request Headers --> 
547+                     <div  class =" row" :class =" { 'mb-3': requestHeaderErrors.length == 0 }" 
548+                         <div  class =" col-4" 
549+                             <div  class =" form-check" 
550+                                 <input  class =" form-check-input" type =" checkbox" v-model =" filter.request.headers.checkbox" id =" request-headers" 
551+                                 <label  class =" form-check-label" for =" request-headers" label >
552+                             </div >
553+                         </div >
554+                         <div  class =" col" v-if =" filter.request.headers.checkbox" 
555+                             <div   v-for =" (hf, i) in filter.request.headers.value" 
556+                                 <div  class =" row me-0" :class =" { 'mb-2': i < filter.request.headers.value.length - 1 }" 
557+                                     <div  class =" col ps-0 pe-1" 
558+                                         <input  type =" text" class =" form-control form-control-sm" id =" reqeuest-header-name" v-model =" hf.name" placeholder =" Name" @input =" onHeaderInput(filter.request.headers, i)" 
559+                                     </div >
560+                                     <div  class =" col ps-1 pe-0" 
561+                                         <RegexInput  v-model =" hf.value" :ref =" el => requestHeaderValueRefs[i] = el" placeholder =" Value [Regex]" @input =" onHeaderInput(filter.request.headers, i)" 
562+                                     </div >
563+                                     <div  class =" col-1" 
564+                                         <button  v-if =" i < filter.request.headers.value.length -1" 
565+                                             class =" btn btn-outline-danger btn-sm" 
566+                                             @click =" removeHeaderFilter(filter.request.headers, i)" 
567+                                             <i  class =" bi bi-x" i >
568+                                         </button >
569+                                     </div >
570+                                 </div >
571+                             </div >
572+                         </div >
573+                     </div >
574+                     <div  class =" row mb-3" v-if =" requestHeaderErrors.length > 0" 
575+                         <div  class =" invalid-feedback" style =" display inline ;" 
576+                             Invalid regular expression:
577+                             <ul >
578+                                 <li  v-for =" err in requestHeaderErrors" li >
579+                             </ul >
580+                         </div >
581+                     </div >
582+ 
583+                     <!--  Response Headers --> 
584+                     <div  class =" row" :class =" { 'mb-3': responseHeaderErrors.length == 0 }" 
465585                        <div  class =" col-4" 
466586                            <div  class =" form-check" 
467-                                 <input  class =" form-check-input" type =" checkbox" v-model =" filter.headers.checkbox" id =" headers" 
468-                                 <label  class =" form-check-label" for =" url " >Request  Header</label >
587+                                 <input  class =" form-check-input" type =" checkbox" v-model =" filter.response. headers.checkbox" id =" response- headers" 
588+                                 <label  class =" form-check-label" for =" response-headers " >Response  Header</label >
469589                            </div >
470590                        </div >
471-                         <div  class =" col" v-if =" filter.headers.checkbox" 
472-                             <div   v-for =" (hf, i) in filter.headers.value" 
473-                                 <div  class =" row me-0" :class =" { 'mb-2': i < filter.headers.value.length - 1 }" 
591+                         <div  class =" col" v-if =" filter.response. headers.checkbox" 
592+                             <div   v-for =" (hf, i) in filter.response. headers.value" 
593+                                 <div  class =" row me-0" :class =" { 'mb-2': i < filter.response. headers.value.length - 1 }" 
474594                                    <div  class =" col ps-0 pe-1" 
475-                                         <input  type =" text" class =" form-control form-control-sm" id =" header-name" v-model =" hf.name" placeholder =" Name" @input =" onHeaderInput(i)" 
595+                                         <input  type =" text" class =" form-control form-control-sm" id =" response- header-name" v-model =" hf.name" placeholder =" Name" @input =" onHeaderInput(filter.response.headers,  i)" 
476596                                    </div >
477597                                    <div  class =" col ps-1 pe-0" 
478-                                         <RegexInput  v-model =" hf.value" :ref =" el => headerValueRefs [i] = el" placeholder =" Value [Regex]" @input =" onHeaderInput(i)" 
598+                                         <RegexInput  v-model =" hf.value" :ref =" el => responseHeaderValueRefs [i] = el" placeholder =" Value [Regex]" @input =" onHeaderInput(filter.response.headers,  i)" 
479599                                    </div >
480600                                    <div  class =" col-1" 
481-                                         <button  v-if =" i < filter.headers.value.length -1" 
601+                                         <button  v-if =" i < filter.response. headers.value.length -1" 
482602                                            class =" btn btn-outline-danger btn-sm" 
483-                                             @click =" removeHeaderFilter(i)" 
603+                                             @click =" removeHeaderFilter(filter.response.headers,  i)" 
484604                                            <i  class =" bi bi-x" i >
485605                                        </button >
486606                                    </div >
487607                                </div >
488608                            </div >
489609                        </div >
490610                    </div >
491-                     <div  class =" row mb-3" v-if =" headerErrors .length > 0" 
611+                     <div  class =" row mb-3" v-if =" responseHeaderErrors .length > 0" 
492612                        <div  class =" invalid-feedback" style =" display inline ;" 
493613                            Invalid regular expression:
494614                            <ul >
495-                                 <li  v-for =" err in headerErrors " li >
615+                                 <li  v-for =" err in responseHeaderErrors " li >
496616                            </ul >
497617                        </div >
498618                    </div >
0 commit comments