fix(jobspec): switch tcp tput back to 100b
[csit.git] / resources / tools / dash / app / pal / utils / url_processing.py
1 # Copyright (c) 2022 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """URL decoding and parsing and URL encoding.
15 """
16
17 import logging
18
19 from base64 import urlsafe_b64encode, urlsafe_b64decode
20 from urllib.parse import urlencode, urlunparse, urlparse, parse_qs
21 from zlib import compress, decompress
22 from zlib import error as ZlibErr
23 from binascii import Error as BinasciiErr
24
25
26 def url_encode(params: dict) -> str:
27     """Encode the URL parameters and zip them and create the whole URL using
28     given data.
29
30     :param params: All data necessary to create the URL:
31         - scheme,
32         - network location,
33         - path,
34         - query,
35         - parameters.
36     :type params: dict
37     :returns: Encoded URL.
38     :rtype: str
39     """
40
41     url_params = params.get("params", None)
42     if url_params:
43         encoded_params = urlsafe_b64encode(
44             compress(urlencode(url_params).encode("utf-8"), level=9)
45         ).rstrip(b"=").decode("utf-8")
46     else:
47         encoded_params = str()
48
49     return urlunparse((
50         params.get("scheme", "http"),
51         params.get("netloc", str()),
52         params.get("path", str()),
53         str(),  # params
54         params.get("query", str()),
55         encoded_params
56     ))
57
58
59 def url_decode(url: str) -> dict:
60     """Parse the given URL and decode the parameters.
61
62     :param url: URL to be parsed and decoded.
63     :type url: str
64     :returns: Paresed URL.
65     :rtype: dict
66     """
67
68     try:
69         parsed_url = urlparse(url)
70     except ValueError as err:
71         logging.warning(f"\nThe url {url} is not valid, ignoring.\n{repr(err)}")
72         return None
73
74     if parsed_url.fragment:
75         try:
76             padding = b"=" * (4 - (len(parsed_url.fragment) % 4))
77             params = parse_qs(decompress(
78                 urlsafe_b64decode(
79                     (parsed_url.fragment.encode("utf-8") + padding)
80                 )).decode("utf-8")
81             )
82         except (BinasciiErr, UnicodeDecodeError, ZlibErr) as err:
83             logging.warning(
84                 f"\nNot possible to decode the parameters from url: {url}"
85                 f"\nEncoded parameters: '{parsed_url.fragment}'"
86                 f"\n{repr(err)}"
87             )
88             return None
89     else:
90         params = None
91
92     return {
93         "scheme": parsed_url.scheme,
94         "netloc": parsed_url.netloc,
95         "path":  parsed_url.path,
96         "query":  parsed_url.query,
97         "fragment":  parsed_url.fragment,
98         "params": params
99     }