0

Below I have a url:

https://test.com/login/?response_type=code&redirect_uri=https%3A%2F%2Ftest.com&client=testclient&successUrl=https%3A%2F%2Flocalhost%3A4444%2Ftestsite%2Foauth%2Ftestendpoint%3Fresponse_type%3Dcode%26redirect_uri%3Dhttps%253A%252F%252Ftest.com%26client%3Dtestclient

I decode it so that it looks like a much tidier url string:

 public void testMethod() {

        final String url = URLDecoder.decode(getLastResponse().getHeaders().getFirst("location"), "UTF-8");

}

Now what I want to do is break this url apart by domain and query params and assign them. This is so I can perform asserts against them. I head the way to do this is through value key pairs but I am struggling to grasp the concept of it.

This is my attempt below but it is in a mess. Does anybody know how I can use the LinkedHashMap to help perform the key value pairs? Also, as you see in the url, some params appear twice so will need help in checking against multiple params

final Map<String, List<String>> query_pairs = new LinkedHashMap<>();
    final String[] pairs = url.split("&|\\?");
    for (String pair : pairs) {
        final int idx = pair.indexOf("=");
        final String key = idx > 0 ? url : pair;
        if (!query_pairs.containsKey(key)) {
            query_pairs.put(key, new LinkedList<>());
        }
        final String value = idx > 0 && pair.length() > idx + 1 ? url : null;
        query_pairs.get(key).add(value);
    }
BruceyBandit
  • 3,978
  • 19
  • 72
  • 144

1 Answers1

1

It would be easier to start with URL, and decode the parameter values as mentioned in the other references noted in the comments. Here is an example that uses Java streams to break the url:

public static Map<String, List<String>> split(URL url) {
    return Arrays.stream(url.getQuery().split("&"))
            .map(s -> s.split("="))
            // filter out empty parameter names (as in Tomcat) "?&=&&=value&"
            .filter(arr -> arr.length > 0 && arr[0].length() > 0)
            //.peek(a -> System.out.println(Arrays.toString(a)))
            .collect(Collectors.groupingBy(key -> URLDecoder.decode(key[0], StandardCharsets.UTF_8),
                        LinkedHashMap::new,
                        Collectors.mapping(value -> value.length < 2 ? "" : URLDecoder.decode(value[1], StandardCharsets.UTF_8), Collectors.toList())))
           ;
}

You may want to adjust the filter to ignore empty property fields (queries with &&) or give zero length param values as null or "". Example call:

String s = "http://stackoverflow.com/page?&source=somewhere&date=2020-10-01&flag3&name1=val%20ue1&date=2020-12-31&&=&flag&name1=secondvalue&arg=v";
URL url = new URL(s);
Map<String, List<String>> map = split(url);
System.out.println("  => "+map);
List<String> list = map.get("name1");
System.out.println("KEYS of name1 ="+list);

Prints:

{date=[2020-10-01, 2020-12-31], =[, ], flag=[], arg=[v], flag3=[], source=[somewhere], name1=[val ue1, secondvalue]}
KEYS of name1 =[val ue1, secondvalue]
DuncG
  • 12,137
  • 2
  • 21
  • 33