@@ -17,6 +17,11 @@ describe('parseAccept Comprehensive Tests', () => {
1717 // eslint-disable-next-line @typescript-eslint/no-explicit-any
1818 expect ( parseAccept ( null as any ) ) . toEqual ( [ ] )
1919 } )
20+
21+ test ( 'handles whitespace-only header' , ( ) => {
22+ expect ( parseAccept ( ' ' ) ) . toEqual ( [ ] )
23+ expect ( parseAccept ( ' \t\n ' ) ) . toEqual ( [ ] )
24+ } )
2025 } )
2126
2227 describe ( 'Quality Values' , ( ) => {
@@ -46,11 +51,9 @@ describe('parseAccept Comprehensive Tests', () => {
4651 const result = parseAccept ( header )
4752 expect ( result [ 0 ] . params ) . toEqual ( {
4853 a : '1' ,
49- b : '"2"' ,
50-
54+ b : '2' ,
5155 c : "'3'" ,
52- d : '"semi;colon"' ,
53- e : '"nested"quoted""' ,
56+ d : 'semi;colon' ,
5457 } )
5558 } )
5659
@@ -105,6 +108,100 @@ describe('parseAccept Comprehensive Tests', () => {
105108 const result = parseAccept ( header )
106109 expect ( result . map ( ( x ) => x . type ) ) . toEqual ( [ 'b' , 'a' ] )
107110 } )
111+
112+ test ( 'handles comma inside quoted parameter value' , ( ) => {
113+ const header = 'text/plain;meta="a,b";q=0.8,application/json;q=0.7'
114+ const result = parseAccept ( header )
115+ expect ( result ) . toEqual ( [
116+ {
117+ type : 'text/plain' ,
118+ params : {
119+ meta : 'a,b' ,
120+ q : '0.8' ,
121+ } ,
122+ q : 0.8 ,
123+ } ,
124+ {
125+ type : 'application/json' ,
126+ params : {
127+ q : '0.7' ,
128+ } ,
129+ q : 0.7 ,
130+ } ,
131+ ] )
132+ } )
133+
134+ test ( 'handles escaped quote and semicolon inside quoted parameter' , ( ) => {
135+ const header = 'text/plain;meta="a\\\";b";q=0.5'
136+ const result = parseAccept ( header )
137+ expect ( result ) . toEqual ( [
138+ {
139+ type : 'text/plain' ,
140+ params : {
141+ meta : 'a";b' ,
142+ q : '0.5' ,
143+ } ,
144+ q : 0.5 ,
145+ } ,
146+ ] )
147+ } )
148+
149+ test ( 'handles escaped character inside quoted parameter' , ( ) => {
150+ const header = 'text/plain;meta="a\\\\z;c";q=0.3'
151+ const result = parseAccept ( header )
152+ expect ( result ) . toEqual ( [
153+ {
154+ type : 'text/plain' ,
155+ params : {
156+ meta : 'a\\z;c' ,
157+ q : '0.3' ,
158+ } ,
159+ q : 0.3 ,
160+ } ,
161+ ] )
162+ } )
163+
164+ test ( 'skips invalid param without swallowing next media type' , ( ) => {
165+ const header = 'a;foo, b;q=0.5'
166+ const result = parseAccept ( header )
167+ expect ( result ) . toEqual ( [
168+ { type : 'a' , params : { } , q : 1 } ,
169+ { type : 'b' , params : { q : '0.5' } , q : 0.5 } ,
170+ ] )
171+ } )
172+
173+ test ( 'skips malformed quoted param tail without creating bogus media type' , ( ) => {
174+ const header = 'a;foo="x"bar,b'
175+ const result = parseAccept ( header )
176+ expect ( result ) . toEqual ( [
177+ { type : 'a' , params : { } , q : 1 } ,
178+ { type : 'b' , params : { } , q : 1 } ,
179+ ] )
180+ } )
181+
182+ test ( 'parses params after quoted value with trailing whitespace' , ( ) => {
183+ const header = 'a;foo="x" ;q=0.5,b;q=0.4'
184+ const result = parseAccept ( header )
185+ expect ( result ) . toEqual ( [
186+ { type : 'a' , params : { foo : 'x' , q : '0.5' } , q : 0.5 } ,
187+ { type : 'b' , params : { q : '0.4' } , q : 0.4 } ,
188+ ] )
189+ } )
190+
191+ test ( 'handles quoted param followed immediately by comma' , ( ) => {
192+ const header = 'a;foo="x",b'
193+ const result = parseAccept ( header )
194+ expect ( result ) . toEqual ( [
195+ { type : 'a' , params : { foo : 'x' } , q : 1 } ,
196+ { type : 'b' , params : { } , q : 1 } ,
197+ ] )
198+ } )
199+
200+ test ( 'skips empty media type that starts with semicolon' , ( ) => {
201+ const header = ';q=0.5,b;q=0.4'
202+ const result = parseAccept ( header )
203+ expect ( result ) . toEqual ( [ { type : 'b' , params : { q : '0.4' } , q : 0.4 } ] )
204+ } )
108205 } )
109206
110207 describe ( 'Security Cases' , ( ) => {
@@ -121,6 +218,12 @@ describe('parseAccept Comprehensive Tests', () => {
121218 } )
122219 } )
123220
221+ test ( 'handles many semicolons with an unbalanced quote' , ( ) => {
222+ const header = `text/plain;${ 'a;' . repeat ( 8000 ) } "`
223+ const result = parseAccept ( header )
224+ expect ( result [ 0 ] . type ) . toBe ( 'text/plain' )
225+ } )
226+
124227 test ( 'handles extremely large input' , ( ) => {
125228 const header = 'a;q=0.9,' . repeat ( 100000 )
126229 expect ( ( ) => parseAccept ( header ) ) . not . toThrow ( )
0 commit comments