1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
let generate_state () =
let open Cryptokit in
let rng = Random.device_rng "/dev/urandom" in
transform_string (Hexa.encode ()) (Random.string rng 32)
let generate_code_verifier () =
let open Cryptokit in
let rng = Random.device_rng "/dev/urandom" in
transform_string (Hexa.encode ()) (Random.string rng 128)
let generate_code_challenge verifier =
let hasher = Cryptokit.Hash.sha256 () in
hasher#add_string verifier;
let base64_string = Base64.encode_string ~pad:false hasher#result in
String.map (function '+' -> '-' | '/' -> '_' | c -> c) base64_string
let form_encode p =
p |> List.map (fun (k, v) -> Printf.sprintf "%s=%s" k v)
|> String.concat "&"
|> Cohttp_lwt.Body.of_string
let replace_char_in_string str old_char new_char =
String.map (fun c -> if c = old_char then new_char else c) str
let form_decode p : (string, string) Hashtbl.t =
let params_tbl = Hashtbl.create 10 in
if String.length p = 0 then
params_tbl
else
begin
String.split_on_char '&' p
|> List.filter (fun s -> String.length s > 0)
|> List.iter (fun pair_str ->
let (raw_key, raw_value) =
match String.index_opt pair_str '=' with
| Some idx ->
(String.sub pair_str 0 idx,
String.sub pair_str (idx + 1) (String.length pair_str - idx - 1))
| None ->
(pair_str, "")
in
let key =
raw_key
|> (fun s -> replace_char_in_string s '+' ' ')
|> Uri.pct_decode
in
let value =
raw_value
|> (fun s -> replace_char_in_string s '+' ' ')
|> Uri.pct_decode
in
Hashtbl.replace params_tbl key value
);
params_tbl
end
module Uri = struct
include Uri
let to_yojson uri = `String (Uri.to_string uri)
let of_yojson = function
| `String s -> Ok (Uri.of_string s)
| _ -> Error "expected string for Uri.t"
end