javascriptnode.jstypescriptquery-stringquerystringparameter

query-string pick method returns the first match from a filter and corrupted URL


I am trying to clean a URL and only keep some parameters that I need in order to parse them so I was using pick method providing it the url, and the filter which is a regex test method here I am testing to check if the key in the query parameter matches the regular expression

const groupRegex = new RegExp('^(GRP_)[a-zA-Z0-9/-]','g');
export const parseGroups= (url:string)=>{
    let pickedURL = qs.pick(url,(key,value)=>groupRegex.test(key));
    console.log(pickedURL);
}
var url=`http://localhost:3000/tat?GRP_Bob[]=SW&GRP_sa[]=QW&GRP_sa[]=AA&projects[]=MP,PM&releases[]=2021.4,2022.1`
parseGroups(url)

for example http://localhost:3000/tat?GRP_Bob[]=SW&GRP_sa[]=QW&GRP_sa[]=AA&projects[]=MP,PM&releases[]=2021.4,2022.1 it should return http://localhost:3000/tat?GRP_Bob=SW&GRP_sa=QW&GRP_sa=AA yet it only tests for the first request parameter only and logs http://localhost:3000/tat?GRP_Bob%5B%5D=SW

I am trying to clean the url from any other parameters that doesn't match my regular expression so I can parse the URL and extract the object so it can be like this for example

{
       GRP_Bob:["SW"],
       GRP_sa:["QW","AA"]
 }

Instead of having other parameters parsed also which are not necessary. I know I can just parse the url normally, and then loop on the returned query object, and remove any key that doesn't match the regex, but is there anything wrong I am doing in the above snippet?

UPDATE: I changed the filter function to be (key,value)=>key.startsWith('GRP_'))

export const parseGroups= (url:string)=>{
    let pickedURL = qs.pick(url,(key,value)=>key.startsWith('GRP_'));
    console.log(pickedURL);
    let parsedURL = qs.parseUrl(pickedURL)
    console.log(parsedURL.query)
}
var url=`http://localhost:3000/tat?GRP_Bob[]=SW&GRP_sa[]=QW&GRP_sa[]=AA&projects[]=MP,PM&releases[]=2021.4,2022.1`
parseGroups(url)

and the pickedURL logged this http://localhost:3000/tat?GRP_Bob%5B%5D=SW&GRP_sa%5B%5D=QW&GRP_sa%5B%5D=AA which is likely to be correct. it came out like that

GRP_Bob[]: "SW"
GRP_sa[]: (2) ['QW', 'AA']

So I am confused actually what's going on with the regular expression approach, and why the keys in the second approach have [] in it?


Solution

  • Ah yeh! This one is a rare gotcha and totally unexpected every time I see it. RegExp actually has state. See Why does JavaScript's RegExp maintain state between calls? and Why does Javascript's regex.exec() not always return the same value?.

    In your case, you don't need the g flag, so removing that should also fix your problem since that makes the regex stateless.