XFFXFF commited on
Commit
575a7f9
2 Parent(s): d1eea5b 9d2fb6c

Merge branch 'rolling' into feat-error-box-for-engine-errors

Browse files
.cspell.json CHANGED
@@ -11,6 +11,10 @@
11
  ],
12
  "language": "en",
13
  "noConfigSearch": true,
14
- "words": ["megalinter", "oxsecurity"],
 
 
 
 
15
  "version": "0.2"
16
  }
 
11
  ],
12
  "language": "en",
13
  "noConfigSearch": true,
14
+ "words": [
15
+ "megalinter",
16
+ "oxsecurity",
17
+ "websurfx"
18
+ ],
19
  "version": "0.2"
20
  }
Cargo.lock CHANGED
@@ -14,7 +14,7 @@ dependencies = [
14
  "futures-sink",
15
  "memchr",
16
  "pin-project-lite",
17
- "tokio 1.29.1",
18
  "tokio-util",
19
  "tracing",
20
  ]
@@ -90,7 +90,7 @@ dependencies = [
90
  "rand 0.8.5",
91
  "sha1",
92
  "smallvec 1.11.0",
93
- "tokio 1.29.1",
94
  "tokio-util",
95
  "tracing",
96
  "zstd",
@@ -102,8 +102,8 @@ version = "0.2.4"
102
  source = "registry+https://github.com/rust-lang/crates.io-index"
103
  checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
104
  dependencies = [
105
- "quote 1.0.32",
106
- "syn 2.0.28",
107
  ]
108
 
109
  [[package]]
@@ -126,7 +126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
126
  checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e"
127
  dependencies = [
128
  "futures-core",
129
- "tokio 1.29.1",
130
  ]
131
 
132
  [[package]]
@@ -142,8 +142,8 @@ dependencies = [
142
  "futures-util",
143
  "mio 0.8.8",
144
  "num_cpus",
145
- "socket2",
146
- "tokio 1.29.1",
147
  "tracing",
148
  ]
149
 
@@ -204,7 +204,7 @@ dependencies = [
204
  "serde_json",
205
  "serde_urlencoded 0.7.1",
206
  "smallvec 1.11.0",
207
- "socket2",
208
  "time 0.3.25",
209
  "url 2.4.0",
210
  ]
@@ -217,7 +217,7 @@ checksum = "2262160a7ae29e3415554a3f1fc04c764b1540c116aa524683208078b7a75bc9"
217
  dependencies = [
218
  "actix-router",
219
  "proc-macro2 1.0.66",
220
- "quote 1.0.32",
221
  "syn 1.0.109",
222
  ]
223
 
@@ -261,9 +261,9 @@ dependencies = [
261
 
262
  [[package]]
263
  name = "aho-corasick"
264
- version = "1.0.2"
265
  source = "registry+https://github.com/rust-lang/crates.io-index"
266
- checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
267
  dependencies = [
268
  "memchr",
269
  ]
@@ -297,9 +297,9 @@ checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
297
 
298
  [[package]]
299
  name = "anyhow"
300
- version = "1.0.72"
301
  source = "registry+https://github.com/rust-lang/crates.io-index"
302
- checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
303
 
304
  [[package]]
305
  name = "askama_escape"
@@ -309,13 +309,13 @@ checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
309
 
310
  [[package]]
311
  name = "async-trait"
312
- version = "0.1.72"
313
  source = "registry+https://github.com/rust-lang/crates.io-index"
314
- checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
315
  dependencies = [
316
  "proc-macro2 1.0.66",
317
- "quote 1.0.32",
318
- "syn 2.0.28",
319
  ]
320
 
321
  [[package]]
@@ -386,9 +386,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
386
 
387
  [[package]]
388
  name = "bitflags"
389
- version = "2.3.3"
390
  source = "registry+https://github.com/rust-lang/crates.io-index"
391
- checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
392
 
393
  [[package]]
394
  name = "block-buffer"
@@ -475,9 +475,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
475
 
476
  [[package]]
477
  name = "cc"
478
- version = "1.0.81"
479
  source = "registry+https://github.com/rust-lang/crates.io-index"
480
- checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0"
481
  dependencies = [
482
  "jobserver",
483
  "libc",
@@ -533,18 +533,18 @@ dependencies = [
533
 
534
  [[package]]
535
  name = "clap"
536
- version = "4.3.19"
537
  source = "registry+https://github.com/rust-lang/crates.io-index"
538
- checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
539
  dependencies = [
540
  "clap_builder",
541
  ]
542
 
543
  [[package]]
544
  name = "clap_builder"
545
- version = "4.3.19"
546
  source = "registry+https://github.com/rust-lang/crates.io-index"
547
- checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
548
  dependencies = [
549
  "anstyle",
550
  "clap_lex",
@@ -810,8 +810,8 @@ version = "0.6.1"
810
  source = "registry+https://github.com/rust-lang/crates.io-index"
811
  checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
812
  dependencies = [
813
- "quote 1.0.32",
814
- "syn 2.0.28",
815
  ]
816
 
817
  [[package]]
@@ -828,7 +828,7 @@ checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
828
  dependencies = [
829
  "convert_case",
830
  "proc-macro2 1.0.66",
831
- "quote 1.0.32",
832
  "rustc_version 0.4.0",
833
  "syn 1.0.109",
834
  ]
@@ -956,7 +956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
956
  checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
957
  dependencies = [
958
  "proc-macro2 1.0.66",
959
- "quote 1.0.32",
960
  "syn 1.0.109",
961
  "synstructure",
962
  ]
@@ -980,9 +980,9 @@ checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
980
 
981
  [[package]]
982
  name = "flate2"
983
- version = "1.0.26"
984
  source = "registry+https://github.com/rust-lang/crates.io-index"
985
- checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
986
  dependencies = [
987
  "crc32fast",
988
  "miniz_oxide",
@@ -1188,7 +1188,7 @@ dependencies = [
1188
  "http 0.2.9",
1189
  "indexmap",
1190
  "slab",
1191
- "tokio 1.29.1",
1192
  "tokio-util",
1193
  "tracing",
1194
  ]
@@ -1250,7 +1250,7 @@ dependencies = [
1250
  "mac",
1251
  "markup5ever 0.11.0",
1252
  "proc-macro2 1.0.66",
1253
- "quote 1.0.32",
1254
  "syn 1.0.109",
1255
  ]
1256
 
@@ -1313,9 +1313,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
1313
 
1314
  [[package]]
1315
  name = "httpdate"
1316
- version = "1.0.2"
1317
  source = "registry+https://github.com/rust-lang/crates.io-index"
1318
- checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
1319
 
1320
  [[package]]
1321
  name = "humantime"
@@ -1370,8 +1370,8 @@ dependencies = [
1370
  "httpdate",
1371
  "itoa 1.0.9",
1372
  "pin-project-lite",
1373
- "socket2",
1374
- "tokio 1.29.1",
1375
  "tower-service",
1376
  "tracing",
1377
  "want 0.3.1",
@@ -1399,7 +1399,7 @@ dependencies = [
1399
  "bytes 1.4.0",
1400
  "hyper 0.14.27",
1401
  "native-tls",
1402
- "tokio 1.29.1",
1403
  "tokio-native-tls",
1404
  ]
1405
 
@@ -1583,9 +1583,9 @@ dependencies = [
1583
 
1584
  [[package]]
1585
  name = "log"
1586
- version = "0.4.19"
1587
  source = "registry+https://github.com/rust-lang/crates.io-index"
1588
- checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
1589
 
1590
  [[package]]
1591
  name = "mac"
@@ -1817,9 +1817,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
1817
 
1818
  [[package]]
1819
  name = "openssl"
1820
- version = "0.10.55"
1821
  source = "registry+https://github.com/rust-lang/crates.io-index"
1822
- checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
1823
  dependencies = [
1824
  "bitflags 1.3.2",
1825
  "cfg-if 1.0.0",
@@ -1837,8 +1837,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1837
  checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
1838
  dependencies = [
1839
  "proc-macro2 1.0.66",
1840
- "quote 1.0.32",
1841
- "syn 2.0.28",
1842
  ]
1843
 
1844
  [[package]]
@@ -1849,9 +1849,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
1849
 
1850
  [[package]]
1851
  name = "openssl-sys"
1852
- version = "0.9.90"
1853
  source = "registry+https://github.com/rust-lang/crates.io-index"
1854
- checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
1855
  dependencies = [
1856
  "cc",
1857
  "libc",
@@ -1955,8 +1955,8 @@ dependencies = [
1955
  "pest",
1956
  "pest_meta",
1957
  "proc-macro2 1.0.66",
1958
- "quote 1.0.32",
1959
- "syn 2.0.28",
1960
  ]
1961
 
1962
  [[package]]
@@ -2057,8 +2057,8 @@ dependencies = [
2057
  "phf_generator 0.11.2",
2058
  "phf_shared 0.11.2",
2059
  "proc-macro2 1.0.66",
2060
- "quote 1.0.32",
2061
- "syn 2.0.28",
2062
  ]
2063
 
2064
  [[package]]
@@ -2090,9 +2090,9 @@ dependencies = [
2090
 
2091
  [[package]]
2092
  name = "pin-project-lite"
2093
- version = "0.2.11"
2094
  source = "registry+https://github.com/rust-lang/crates.io-index"
2095
- checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c"
2096
 
2097
  [[package]]
2098
  name = "pin-utils"
@@ -2185,9 +2185,9 @@ dependencies = [
2185
 
2186
  [[package]]
2187
  name = "quote"
2188
- version = "1.0.32"
2189
  source = "registry+https://github.com/rust-lang/crates.io-index"
2190
- checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
2191
  dependencies = [
2192
  "proc-macro2 1.0.66",
2193
  ]
@@ -2361,16 +2361,16 @@ dependencies = [
2361
 
2362
  [[package]]
2363
  name = "redis"
2364
- version = "0.23.1"
2365
  source = "registry+https://github.com/rust-lang/crates.io-index"
2366
- checksum = "ff5d95dd18a4d76650f0c2607ed8ebdbf63baf9cb934e1c233cd220c694db1d7"
2367
  dependencies = [
2368
  "combine",
2369
  "itoa 1.0.9",
2370
  "percent-encoding 2.3.0",
2371
  "ryu",
2372
  "sha1_smol",
2373
- "socket2",
2374
  "url 2.4.0",
2375
  ]
2376
 
@@ -2479,7 +2479,7 @@ dependencies = [
2479
  "serde",
2480
  "serde_json",
2481
  "serde_urlencoded 0.7.1",
2482
- "tokio 1.29.1",
2483
  "tokio-native-tls",
2484
  "tower-service",
2485
  "url 2.4.0",
@@ -2539,11 +2539,11 @@ dependencies = [
2539
 
2540
  [[package]]
2541
  name = "rustix"
2542
- version = "0.38.7"
2543
  source = "registry+https://github.com/rust-lang/crates.io-index"
2544
- checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399"
2545
  dependencies = [
2546
- "bitflags 2.3.3",
2547
  "errno",
2548
  "libc",
2549
  "linux-raw-sys",
@@ -2648,7 +2648,7 @@ version = "0.25.0"
2648
  source = "registry+https://github.com/rust-lang/crates.io-index"
2649
  checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06"
2650
  dependencies = [
2651
- "bitflags 2.3.3",
2652
  "cssparser",
2653
  "derive_more",
2654
  "fxhash",
@@ -2684,29 +2684,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
2684
 
2685
  [[package]]
2686
  name = "serde"
2687
- version = "1.0.182"
2688
  source = "registry+https://github.com/rust-lang/crates.io-index"
2689
- checksum = "bdb30a74471f5b7a1fa299f40b4bf1be93af61116df95465b2b5fc419331e430"
2690
  dependencies = [
2691
  "serde_derive",
2692
  ]
2693
 
2694
  [[package]]
2695
  name = "serde_derive"
2696
- version = "1.0.182"
2697
  source = "registry+https://github.com/rust-lang/crates.io-index"
2698
- checksum = "6f4c2c6ea4bc09b5c419012eafcdb0fcef1d9119d626c8f3a0708a5b92d38a70"
2699
  dependencies = [
2700
  "proc-macro2 1.0.66",
2701
- "quote 1.0.32",
2702
- "syn 2.0.28",
2703
  ]
2704
 
2705
  [[package]]
2706
  name = "serde_json"
2707
- version = "1.0.104"
2708
  source = "registry+https://github.com/rust-lang/crates.io-index"
2709
- checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
2710
  dependencies = [
2711
  "itoa 1.0.9",
2712
  "ryu",
@@ -2829,6 +2829,16 @@ dependencies = [
2829
  "winapi 0.3.9",
2830
  ]
2831
 
 
 
 
 
 
 
 
 
 
 
2832
  [[package]]
2833
  name = "stable_deref_trait"
2834
  version = "1.2.0"
@@ -2882,7 +2892,7 @@ dependencies = [
2882
  "phf_generator 0.7.24",
2883
  "phf_shared 0.7.24",
2884
  "proc-macro2 1.0.66",
2885
- "quote 1.0.32",
2886
  "string_cache_shared",
2887
  ]
2888
 
@@ -2895,7 +2905,7 @@ dependencies = [
2895
  "phf_generator 0.10.0",
2896
  "phf_shared 0.10.0",
2897
  "proc-macro2 1.0.66",
2898
- "quote 1.0.32",
2899
  ]
2900
 
2901
  [[package]]
@@ -2922,18 +2932,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2922
  checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
2923
  dependencies = [
2924
  "proc-macro2 1.0.66",
2925
- "quote 1.0.32",
2926
  "unicode-ident",
2927
  ]
2928
 
2929
  [[package]]
2930
  name = "syn"
2931
- version = "2.0.28"
2932
  source = "registry+https://github.com/rust-lang/crates.io-index"
2933
- checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
2934
  dependencies = [
2935
  "proc-macro2 1.0.66",
2936
- "quote 1.0.32",
2937
  "unicode-ident",
2938
  ]
2939
 
@@ -2944,16 +2954,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2944
  checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
2945
  dependencies = [
2946
  "proc-macro2 1.0.66",
2947
- "quote 1.0.32",
2948
  "syn 1.0.109",
2949
  "unicode-xid 0.2.4",
2950
  ]
2951
 
2952
  [[package]]
2953
  name = "tempfile"
2954
- version = "3.7.0"
2955
  source = "registry+https://github.com/rust-lang/crates.io-index"
2956
- checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998"
2957
  dependencies = [
2958
  "cfg-if 1.0.0",
2959
  "fastrand",
@@ -2984,22 +2994,22 @@ dependencies = [
2984
 
2985
  [[package]]
2986
  name = "thiserror"
2987
- version = "1.0.44"
2988
  source = "registry+https://github.com/rust-lang/crates.io-index"
2989
- checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
2990
  dependencies = [
2991
  "thiserror-impl",
2992
  ]
2993
 
2994
  [[package]]
2995
  name = "thiserror-impl"
2996
- version = "1.0.44"
2997
  source = "registry+https://github.com/rust-lang/crates.io-index"
2998
- checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
2999
  dependencies = [
3000
  "proc-macro2 1.0.66",
3001
- "quote 1.0.32",
3002
- "syn 2.0.28",
3003
  ]
3004
 
3005
  [[package]]
@@ -3087,11 +3097,10 @@ dependencies = [
3087
 
3088
  [[package]]
3089
  name = "tokio"
3090
- version = "1.29.1"
3091
  source = "registry+https://github.com/rust-lang/crates.io-index"
3092
- checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
3093
  dependencies = [
3094
- "autocfg 1.1.0",
3095
  "backtrace",
3096
  "bytes 1.4.0",
3097
  "libc",
@@ -3100,7 +3109,7 @@ dependencies = [
3100
  "parking_lot 0.12.1",
3101
  "pin-project-lite",
3102
  "signal-hook-registry",
3103
- "socket2",
3104
  "tokio-macros",
3105
  "windows-sys",
3106
  ]
@@ -3154,8 +3163,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
3154
  checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
3155
  dependencies = [
3156
  "proc-macro2 1.0.66",
3157
- "quote 1.0.32",
3158
- "syn 2.0.28",
3159
  ]
3160
 
3161
  [[package]]
@@ -3165,7 +3174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
3165
  checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
3166
  dependencies = [
3167
  "native-tls",
3168
- "tokio 1.29.1",
3169
  ]
3170
 
3171
  [[package]]
@@ -3250,7 +3259,7 @@ dependencies = [
3250
  "futures-core",
3251
  "futures-sink",
3252
  "pin-project-lite",
3253
- "tokio 1.29.1",
3254
  "tracing",
3255
  ]
3256
 
@@ -3476,8 +3485,8 @@ dependencies = [
3476
  "log",
3477
  "once_cell",
3478
  "proc-macro2 1.0.66",
3479
- "quote 1.0.32",
3480
- "syn 2.0.28",
3481
  "wasm-bindgen-shared",
3482
  ]
3483
 
@@ -3499,7 +3508,7 @@ version = "0.2.87"
3499
  source = "registry+https://github.com/rust-lang/crates.io-index"
3500
  checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
3501
  dependencies = [
3502
- "quote 1.0.32",
3503
  "wasm-bindgen-macro-support",
3504
  ]
3505
 
@@ -3510,8 +3519,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
3510
  checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
3511
  dependencies = [
3512
  "proc-macro2 1.0.66",
3513
- "quote 1.0.32",
3514
- "syn 2.0.28",
3515
  "wasm-bindgen-backend",
3516
  "wasm-bindgen-shared",
3517
  ]
@@ -3534,7 +3543,7 @@ dependencies = [
3534
 
3535
  [[package]]
3536
  name = "websurfx"
3537
- version = "0.16.4"
3538
  dependencies = [
3539
  "actix-cors",
3540
  "actix-files",
@@ -3556,7 +3565,7 @@ dependencies = [
3556
  "scraper",
3557
  "serde",
3558
  "serde_json",
3559
- "tokio 1.29.1",
3560
  ]
3561
 
3562
  [[package]]
@@ -3613,9 +3622,9 @@ dependencies = [
3613
 
3614
  [[package]]
3615
  name = "windows-targets"
3616
- version = "0.48.1"
3617
  source = "registry+https://github.com/rust-lang/crates.io-index"
3618
- checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
3619
  dependencies = [
3620
  "windows_aarch64_gnullvm",
3621
  "windows_aarch64_msvc",
@@ -3628,45 +3637,45 @@ dependencies = [
3628
 
3629
  [[package]]
3630
  name = "windows_aarch64_gnullvm"
3631
- version = "0.48.0"
3632
  source = "registry+https://github.com/rust-lang/crates.io-index"
3633
- checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
3634
 
3635
  [[package]]
3636
  name = "windows_aarch64_msvc"
3637
- version = "0.48.0"
3638
  source = "registry+https://github.com/rust-lang/crates.io-index"
3639
- checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
3640
 
3641
  [[package]]
3642
  name = "windows_i686_gnu"
3643
- version = "0.48.0"
3644
  source = "registry+https://github.com/rust-lang/crates.io-index"
3645
- checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
3646
 
3647
  [[package]]
3648
  name = "windows_i686_msvc"
3649
- version = "0.48.0"
3650
  source = "registry+https://github.com/rust-lang/crates.io-index"
3651
- checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
3652
 
3653
  [[package]]
3654
  name = "windows_x86_64_gnu"
3655
- version = "0.48.0"
3656
  source = "registry+https://github.com/rust-lang/crates.io-index"
3657
- checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
3658
 
3659
  [[package]]
3660
  name = "windows_x86_64_gnullvm"
3661
- version = "0.48.0"
3662
  source = "registry+https://github.com/rust-lang/crates.io-index"
3663
- checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
3664
 
3665
  [[package]]
3666
  name = "windows_x86_64_msvc"
3667
- version = "0.48.0"
3668
  source = "registry+https://github.com/rust-lang/crates.io-index"
3669
- checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
3670
 
3671
  [[package]]
3672
  name = "winreg"
 
14
  "futures-sink",
15
  "memchr",
16
  "pin-project-lite",
17
+ "tokio 1.32.0",
18
  "tokio-util",
19
  "tracing",
20
  ]
 
90
  "rand 0.8.5",
91
  "sha1",
92
  "smallvec 1.11.0",
93
+ "tokio 1.32.0",
94
  "tokio-util",
95
  "tracing",
96
  "zstd",
 
102
  source = "registry+https://github.com/rust-lang/crates.io-index"
103
  checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
104
  dependencies = [
105
+ "quote 1.0.33",
106
+ "syn 2.0.29",
107
  ]
108
 
109
  [[package]]
 
126
  checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e"
127
  dependencies = [
128
  "futures-core",
129
+ "tokio 1.32.0",
130
  ]
131
 
132
  [[package]]
 
142
  "futures-util",
143
  "mio 0.8.8",
144
  "num_cpus",
145
+ "socket2 0.4.9",
146
+ "tokio 1.32.0",
147
  "tracing",
148
  ]
149
 
 
204
  "serde_json",
205
  "serde_urlencoded 0.7.1",
206
  "smallvec 1.11.0",
207
+ "socket2 0.4.9",
208
  "time 0.3.25",
209
  "url 2.4.0",
210
  ]
 
217
  dependencies = [
218
  "actix-router",
219
  "proc-macro2 1.0.66",
220
+ "quote 1.0.33",
221
  "syn 1.0.109",
222
  ]
223
 
 
261
 
262
  [[package]]
263
  name = "aho-corasick"
264
+ version = "1.0.4"
265
  source = "registry+https://github.com/rust-lang/crates.io-index"
266
+ checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
267
  dependencies = [
268
  "memchr",
269
  ]
 
297
 
298
  [[package]]
299
  name = "anyhow"
300
+ version = "1.0.75"
301
  source = "registry+https://github.com/rust-lang/crates.io-index"
302
+ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
303
 
304
  [[package]]
305
  name = "askama_escape"
 
309
 
310
  [[package]]
311
  name = "async-trait"
312
+ version = "0.1.73"
313
  source = "registry+https://github.com/rust-lang/crates.io-index"
314
+ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
315
  dependencies = [
316
  "proc-macro2 1.0.66",
317
+ "quote 1.0.33",
318
+ "syn 2.0.29",
319
  ]
320
 
321
  [[package]]
 
386
 
387
  [[package]]
388
  name = "bitflags"
389
+ version = "2.4.0"
390
  source = "registry+https://github.com/rust-lang/crates.io-index"
391
+ checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
392
 
393
  [[package]]
394
  name = "block-buffer"
 
475
 
476
  [[package]]
477
  name = "cc"
478
+ version = "1.0.82"
479
  source = "registry+https://github.com/rust-lang/crates.io-index"
480
+ checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
481
  dependencies = [
482
  "jobserver",
483
  "libc",
 
533
 
534
  [[package]]
535
  name = "clap"
536
+ version = "4.3.23"
537
  source = "registry+https://github.com/rust-lang/crates.io-index"
538
+ checksum = "03aef18ddf7d879c15ce20f04826ef8418101c7e528014c3eeea13321047dca3"
539
  dependencies = [
540
  "clap_builder",
541
  ]
542
 
543
  [[package]]
544
  name = "clap_builder"
545
+ version = "4.3.23"
546
  source = "registry+https://github.com/rust-lang/crates.io-index"
547
+ checksum = "f8ce6fffb678c9b80a70b6b6de0aad31df727623a70fd9a842c30cd573e2fa98"
548
  dependencies = [
549
  "anstyle",
550
  "clap_lex",
 
810
  source = "registry+https://github.com/rust-lang/crates.io-index"
811
  checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
812
  dependencies = [
813
+ "quote 1.0.33",
814
+ "syn 2.0.29",
815
  ]
816
 
817
  [[package]]
 
828
  dependencies = [
829
  "convert_case",
830
  "proc-macro2 1.0.66",
831
+ "quote 1.0.33",
832
  "rustc_version 0.4.0",
833
  "syn 1.0.109",
834
  ]
 
956
  checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
957
  dependencies = [
958
  "proc-macro2 1.0.66",
959
+ "quote 1.0.33",
960
  "syn 1.0.109",
961
  "synstructure",
962
  ]
 
980
 
981
  [[package]]
982
  name = "flate2"
983
+ version = "1.0.27"
984
  source = "registry+https://github.com/rust-lang/crates.io-index"
985
+ checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
986
  dependencies = [
987
  "crc32fast",
988
  "miniz_oxide",
 
1188
  "http 0.2.9",
1189
  "indexmap",
1190
  "slab",
1191
+ "tokio 1.32.0",
1192
  "tokio-util",
1193
  "tracing",
1194
  ]
 
1250
  "mac",
1251
  "markup5ever 0.11.0",
1252
  "proc-macro2 1.0.66",
1253
+ "quote 1.0.33",
1254
  "syn 1.0.109",
1255
  ]
1256
 
 
1313
 
1314
  [[package]]
1315
  name = "httpdate"
1316
+ version = "1.0.3"
1317
  source = "registry+https://github.com/rust-lang/crates.io-index"
1318
+ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
1319
 
1320
  [[package]]
1321
  name = "humantime"
 
1370
  "httpdate",
1371
  "itoa 1.0.9",
1372
  "pin-project-lite",
1373
+ "socket2 0.4.9",
1374
+ "tokio 1.32.0",
1375
  "tower-service",
1376
  "tracing",
1377
  "want 0.3.1",
 
1399
  "bytes 1.4.0",
1400
  "hyper 0.14.27",
1401
  "native-tls",
1402
+ "tokio 1.32.0",
1403
  "tokio-native-tls",
1404
  ]
1405
 
 
1583
 
1584
  [[package]]
1585
  name = "log"
1586
+ version = "0.4.20"
1587
  source = "registry+https://github.com/rust-lang/crates.io-index"
1588
+ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
1589
 
1590
  [[package]]
1591
  name = "mac"
 
1817
 
1818
  [[package]]
1819
  name = "openssl"
1820
+ version = "0.10.56"
1821
  source = "registry+https://github.com/rust-lang/crates.io-index"
1822
+ checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e"
1823
  dependencies = [
1824
  "bitflags 1.3.2",
1825
  "cfg-if 1.0.0",
 
1837
  checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
1838
  dependencies = [
1839
  "proc-macro2 1.0.66",
1840
+ "quote 1.0.33",
1841
+ "syn 2.0.29",
1842
  ]
1843
 
1844
  [[package]]
 
1849
 
1850
  [[package]]
1851
  name = "openssl-sys"
1852
+ version = "0.9.91"
1853
  source = "registry+https://github.com/rust-lang/crates.io-index"
1854
+ checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac"
1855
  dependencies = [
1856
  "cc",
1857
  "libc",
 
1955
  "pest",
1956
  "pest_meta",
1957
  "proc-macro2 1.0.66",
1958
+ "quote 1.0.33",
1959
+ "syn 2.0.29",
1960
  ]
1961
 
1962
  [[package]]
 
2057
  "phf_generator 0.11.2",
2058
  "phf_shared 0.11.2",
2059
  "proc-macro2 1.0.66",
2060
+ "quote 1.0.33",
2061
+ "syn 2.0.29",
2062
  ]
2063
 
2064
  [[package]]
 
2090
 
2091
  [[package]]
2092
  name = "pin-project-lite"
2093
+ version = "0.2.12"
2094
  source = "registry+https://github.com/rust-lang/crates.io-index"
2095
+ checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
2096
 
2097
  [[package]]
2098
  name = "pin-utils"
 
2185
 
2186
  [[package]]
2187
  name = "quote"
2188
+ version = "1.0.33"
2189
  source = "registry+https://github.com/rust-lang/crates.io-index"
2190
+ checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
2191
  dependencies = [
2192
  "proc-macro2 1.0.66",
2193
  ]
 
2361
 
2362
  [[package]]
2363
  name = "redis"
2364
+ version = "0.23.2"
2365
  source = "registry+https://github.com/rust-lang/crates.io-index"
2366
+ checksum = "ffd6543a7bc6428396845f6854ccf3d1ae8823816592e2cbe74f20f50f209d02"
2367
  dependencies = [
2368
  "combine",
2369
  "itoa 1.0.9",
2370
  "percent-encoding 2.3.0",
2371
  "ryu",
2372
  "sha1_smol",
2373
+ "socket2 0.4.9",
2374
  "url 2.4.0",
2375
  ]
2376
 
 
2479
  "serde",
2480
  "serde_json",
2481
  "serde_urlencoded 0.7.1",
2482
+ "tokio 1.32.0",
2483
  "tokio-native-tls",
2484
  "tower-service",
2485
  "url 2.4.0",
 
2539
 
2540
  [[package]]
2541
  name = "rustix"
2542
+ version = "0.38.8"
2543
  source = "registry+https://github.com/rust-lang/crates.io-index"
2544
+ checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
2545
  dependencies = [
2546
+ "bitflags 2.4.0",
2547
  "errno",
2548
  "libc",
2549
  "linux-raw-sys",
 
2648
  source = "registry+https://github.com/rust-lang/crates.io-index"
2649
  checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06"
2650
  dependencies = [
2651
+ "bitflags 2.4.0",
2652
  "cssparser",
2653
  "derive_more",
2654
  "fxhash",
 
2684
 
2685
  [[package]]
2686
  name = "serde"
2687
+ version = "1.0.183"
2688
  source = "registry+https://github.com/rust-lang/crates.io-index"
2689
+ checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
2690
  dependencies = [
2691
  "serde_derive",
2692
  ]
2693
 
2694
  [[package]]
2695
  name = "serde_derive"
2696
+ version = "1.0.183"
2697
  source = "registry+https://github.com/rust-lang/crates.io-index"
2698
+ checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
2699
  dependencies = [
2700
  "proc-macro2 1.0.66",
2701
+ "quote 1.0.33",
2702
+ "syn 2.0.29",
2703
  ]
2704
 
2705
  [[package]]
2706
  name = "serde_json"
2707
+ version = "1.0.105"
2708
  source = "registry+https://github.com/rust-lang/crates.io-index"
2709
+ checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
2710
  dependencies = [
2711
  "itoa 1.0.9",
2712
  "ryu",
 
2829
  "winapi 0.3.9",
2830
  ]
2831
 
2832
+ [[package]]
2833
+ name = "socket2"
2834
+ version = "0.5.3"
2835
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2836
+ checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
2837
+ dependencies = [
2838
+ "libc",
2839
+ "windows-sys",
2840
+ ]
2841
+
2842
  [[package]]
2843
  name = "stable_deref_trait"
2844
  version = "1.2.0"
 
2892
  "phf_generator 0.7.24",
2893
  "phf_shared 0.7.24",
2894
  "proc-macro2 1.0.66",
2895
+ "quote 1.0.33",
2896
  "string_cache_shared",
2897
  ]
2898
 
 
2905
  "phf_generator 0.10.0",
2906
  "phf_shared 0.10.0",
2907
  "proc-macro2 1.0.66",
2908
+ "quote 1.0.33",
2909
  ]
2910
 
2911
  [[package]]
 
2932
  checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
2933
  dependencies = [
2934
  "proc-macro2 1.0.66",
2935
+ "quote 1.0.33",
2936
  "unicode-ident",
2937
  ]
2938
 
2939
  [[package]]
2940
  name = "syn"
2941
+ version = "2.0.29"
2942
  source = "registry+https://github.com/rust-lang/crates.io-index"
2943
+ checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
2944
  dependencies = [
2945
  "proc-macro2 1.0.66",
2946
+ "quote 1.0.33",
2947
  "unicode-ident",
2948
  ]
2949
 
 
2954
  checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
2955
  dependencies = [
2956
  "proc-macro2 1.0.66",
2957
+ "quote 1.0.33",
2958
  "syn 1.0.109",
2959
  "unicode-xid 0.2.4",
2960
  ]
2961
 
2962
  [[package]]
2963
  name = "tempfile"
2964
+ version = "3.8.0"
2965
  source = "registry+https://github.com/rust-lang/crates.io-index"
2966
+ checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
2967
  dependencies = [
2968
  "cfg-if 1.0.0",
2969
  "fastrand",
 
2994
 
2995
  [[package]]
2996
  name = "thiserror"
2997
+ version = "1.0.47"
2998
  source = "registry+https://github.com/rust-lang/crates.io-index"
2999
+ checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
3000
  dependencies = [
3001
  "thiserror-impl",
3002
  ]
3003
 
3004
  [[package]]
3005
  name = "thiserror-impl"
3006
+ version = "1.0.47"
3007
  source = "registry+https://github.com/rust-lang/crates.io-index"
3008
+ checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
3009
  dependencies = [
3010
  "proc-macro2 1.0.66",
3011
+ "quote 1.0.33",
3012
+ "syn 2.0.29",
3013
  ]
3014
 
3015
  [[package]]
 
3097
 
3098
  [[package]]
3099
  name = "tokio"
3100
+ version = "1.32.0"
3101
  source = "registry+https://github.com/rust-lang/crates.io-index"
3102
+ checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
3103
  dependencies = [
 
3104
  "backtrace",
3105
  "bytes 1.4.0",
3106
  "libc",
 
3109
  "parking_lot 0.12.1",
3110
  "pin-project-lite",
3111
  "signal-hook-registry",
3112
+ "socket2 0.5.3",
3113
  "tokio-macros",
3114
  "windows-sys",
3115
  ]
 
3163
  checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
3164
  dependencies = [
3165
  "proc-macro2 1.0.66",
3166
+ "quote 1.0.33",
3167
+ "syn 2.0.29",
3168
  ]
3169
 
3170
  [[package]]
 
3174
  checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
3175
  dependencies = [
3176
  "native-tls",
3177
+ "tokio 1.32.0",
3178
  ]
3179
 
3180
  [[package]]
 
3259
  "futures-core",
3260
  "futures-sink",
3261
  "pin-project-lite",
3262
+ "tokio 1.32.0",
3263
  "tracing",
3264
  ]
3265
 
 
3485
  "log",
3486
  "once_cell",
3487
  "proc-macro2 1.0.66",
3488
+ "quote 1.0.33",
3489
+ "syn 2.0.29",
3490
  "wasm-bindgen-shared",
3491
  ]
3492
 
 
3508
  source = "registry+https://github.com/rust-lang/crates.io-index"
3509
  checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
3510
  dependencies = [
3511
+ "quote 1.0.33",
3512
  "wasm-bindgen-macro-support",
3513
  ]
3514
 
 
3519
  checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
3520
  dependencies = [
3521
  "proc-macro2 1.0.66",
3522
+ "quote 1.0.33",
3523
+ "syn 2.0.29",
3524
  "wasm-bindgen-backend",
3525
  "wasm-bindgen-shared",
3526
  ]
 
3543
 
3544
  [[package]]
3545
  name = "websurfx"
3546
+ version = "0.17.0"
3547
  dependencies = [
3548
  "actix-cors",
3549
  "actix-files",
 
3565
  "scraper",
3566
  "serde",
3567
  "serde_json",
3568
+ "tokio 1.32.0",
3569
  ]
3570
 
3571
  [[package]]
 
3622
 
3623
  [[package]]
3624
  name = "windows-targets"
3625
+ version = "0.48.5"
3626
  source = "registry+https://github.com/rust-lang/crates.io-index"
3627
+ checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
3628
  dependencies = [
3629
  "windows_aarch64_gnullvm",
3630
  "windows_aarch64_msvc",
 
3637
 
3638
  [[package]]
3639
  name = "windows_aarch64_gnullvm"
3640
+ version = "0.48.5"
3641
  source = "registry+https://github.com/rust-lang/crates.io-index"
3642
+ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
3643
 
3644
  [[package]]
3645
  name = "windows_aarch64_msvc"
3646
+ version = "0.48.5"
3647
  source = "registry+https://github.com/rust-lang/crates.io-index"
3648
+ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
3649
 
3650
  [[package]]
3651
  name = "windows_i686_gnu"
3652
+ version = "0.48.5"
3653
  source = "registry+https://github.com/rust-lang/crates.io-index"
3654
+ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
3655
 
3656
  [[package]]
3657
  name = "windows_i686_msvc"
3658
+ version = "0.48.5"
3659
  source = "registry+https://github.com/rust-lang/crates.io-index"
3660
+ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
3661
 
3662
  [[package]]
3663
  name = "windows_x86_64_gnu"
3664
+ version = "0.48.5"
3665
  source = "registry+https://github.com/rust-lang/crates.io-index"
3666
+ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
3667
 
3668
  [[package]]
3669
  name = "windows_x86_64_gnullvm"
3670
+ version = "0.48.5"
3671
  source = "registry+https://github.com/rust-lang/crates.io-index"
3672
+ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
3673
 
3674
  [[package]]
3675
  name = "windows_x86_64_msvc"
3676
+ version = "0.48.5"
3677
  source = "registry+https://github.com/rust-lang/crates.io-index"
3678
+ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
3679
 
3680
  [[package]]
3681
  name = "winreg"
Cargo.toml CHANGED
@@ -1,31 +1,31 @@
1
  [package]
2
  name = "websurfx"
3
- version = "0.16.4"
4
  edition = "2021"
5
  description = "An open-source alternative to Searx that provides clean, ad-free, and organic results with incredible speed while keeping privacy and security in mind."
6
  repository = "https://github.com/neon-mmd/websurfx"
7
  license = "AGPL-3.0"
8
 
9
  [dependencies]
10
- reqwest = {version="*",features=["json"]}
11
- tokio = {version="*",features=["full"]}
12
- serde = {version="*",features=["derive"]}
13
- handlebars = { version = "4.3.6", features = ["dir_source"] }
14
- scraper = {version="*"}
15
  actix-web = {version="4.3.1", features = ["cookies"]}
16
  actix-files = {version="0.6.2"}
17
  actix-cors = {version="0.6.4"}
18
- serde_json = {version="*"}
19
- fake-useragent = {version="*"}
20
  env_logger = {version="0.10.0"}
21
- log = {version="0.4.17"}
22
- rlua = {version="*"}
23
- redis = {version="*"}
24
- md5 = {version="*"}
25
- rand={version="*"}
26
- once_cell = {version="*"}
27
  error-stack = {version="0.3.1"}
28
- async-trait = {version="*"}
29
 
30
  [dev-dependencies]
31
  rusty-hook = "^0.11.2"
 
1
  [package]
2
  name = "websurfx"
3
+ version = "0.17.0"
4
  edition = "2021"
5
  description = "An open-source alternative to Searx that provides clean, ad-free, and organic results with incredible speed while keeping privacy and security in mind."
6
  repository = "https://github.com/neon-mmd/websurfx"
7
  license = "AGPL-3.0"
8
 
9
  [dependencies]
10
+ reqwest = {version="0.11.18",features=["json"]}
11
+ tokio = {version="1.32.0",features=["full"]}
12
+ serde = {version="1.0.183",features=["derive"]}
13
+ handlebars = { version = "4.3.7", features = ["dir_source"] }
14
+ scraper = {version="0.17.1"}
15
  actix-web = {version="4.3.1", features = ["cookies"]}
16
  actix-files = {version="0.6.2"}
17
  actix-cors = {version="0.6.4"}
18
+ serde_json = {version="1.0.105"}
19
+ fake-useragent = {version="0.1.3"}
20
  env_logger = {version="0.10.0"}
21
+ log = {version="0.4.20"}
22
+ rlua = {version="0.19.7"}
23
+ redis = {version="0.23.2"}
24
+ md5 = {version="0.7.0"}
25
+ rand={version="0.8.5"}
26
+ once_cell = {version="1.18.0"}
27
  error-stack = {version="0.3.1"}
28
+ async-trait = {version="0.1.73"}
29
 
30
  [dev-dependencies]
31
  rusty-hook = "^0.11.2"
public/templates/search.html CHANGED
@@ -4,7 +4,7 @@
4
  <div class="results_aggregated">
5
  {{#if results}} {{#each results}}
6
  <div class="result">
7
- <h1><a href="{{{this.visitingUrl}}}">{{{this.title}}}</a></h1>
8
  <small>{{{this.url}}}</small>
9
  <p>{{{this.description}}}</p>
10
  <div class="upstream_engines">
 
4
  <div class="results_aggregated">
5
  {{#if results}} {{#each results}}
6
  <div class="result">
7
+ <h1><a href="{{{this.url}}}">{{{this.title}}}</a></h1>
8
  <small>{{{this.url}}}</small>
9
  <p>{{{this.description}}}</p>
10
  <div class="upstream_engines">
src/bin/websurfx.rs CHANGED
@@ -15,7 +15,7 @@ use websurfx::{config::parser::Config, run};
15
  #[actix_web::main]
16
  async fn main() -> std::io::Result<()> {
17
  // Initialize the parsed config file.
18
- let config = Config::parse(true).unwrap();
19
 
20
  log::info!(
21
  "started server on port {} and IP {}",
 
15
  #[actix_web::main]
16
  async fn main() -> std::io::Result<()> {
17
  // Initialize the parsed config file.
18
+ let config = Config::parse(false).unwrap();
19
 
20
  log::info!(
21
  "started server on port {} and IP {}",
src/config/parser.rs CHANGED
@@ -34,7 +34,7 @@ pub struct Config {
34
  pub aggregator: AggregatorConfig,
35
  pub logging: bool,
36
  pub debug: bool,
37
- pub upstream_search_engines: Vec<String>,
38
  pub request_timeout: u8,
39
  pub threads: u8,
40
  }
@@ -57,7 +57,7 @@ impl Config {
57
  /// # Arguments
58
  ///
59
  /// * `logging_initialized` - It takes a boolean which ensures that the logging doesn't get
60
- /// initialized twice.
61
  ///
62
  /// # Error
63
  ///
@@ -77,22 +77,8 @@ impl Config {
77
  let debug: bool = globals.get::<_, bool>("debug")?;
78
  let logging:bool= globals.get::<_, bool>("logging")?;
79
 
80
- // Check whether logging has not been initialized before.
81
- if logging_initialized {
82
- if let Ok(pkg_env_var) = std::env::var("PKG_ENV"){
83
- if pkg_env_var.to_lowercase() == "dev" {
84
- env_logger::Builder::new().filter(None, LevelFilter::Trace).init();
85
- }
86
- } else {
87
- // Initializing logging middleware with level set to default or info.
88
- let mut log_level: LevelFilter = LevelFilter::Error;
89
- if logging && debug == false {
90
- log_level = LevelFilter::Info;
91
- } else if debug {
92
- log_level = LevelFilter::Debug;
93
- };
94
- env_logger::Builder::new().filter(None, log_level).init();
95
- }
96
  }
97
 
98
  let threads: u8 = if parsed_threads == 0 {
@@ -121,12 +107,14 @@ impl Config {
121
  .get::<_, HashMap<String, bool>>("upstream_search_engines")?
122
  .into_iter()
123
  .filter_map(|(key, value)| value.then_some(key))
 
124
  .collect(),
125
  request_timeout: globals.get::<_, u8>("request_timeout")?,
126
  threads,
127
  })
128
  })
129
  }
 
130
  /// A helper function which returns an appropriate config file path checking if the config
131
  /// file exists on that path.
132
  ///
@@ -173,3 +161,25 @@ impl Config {
173
  Err("Config file not found!!".to_string().into())
174
  }
175
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  pub aggregator: AggregatorConfig,
35
  pub logging: bool,
36
  pub debug: bool,
37
+ pub upstream_search_engines: Vec<crate::engines::engine_models::EngineHandler>,
38
  pub request_timeout: u8,
39
  pub threads: u8,
40
  }
 
57
  /// # Arguments
58
  ///
59
  /// * `logging_initialized` - It takes a boolean which ensures that the logging doesn't get
60
+ /// initialized twice. Pass false if the logger has not yet been initialized.
61
  ///
62
  /// # Error
63
  ///
 
77
  let debug: bool = globals.get::<_, bool>("debug")?;
78
  let logging:bool= globals.get::<_, bool>("logging")?;
79
 
80
+ if !logging_initialized {
81
+ set_logging_level(debug, logging);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
 
84
  let threads: u8 = if parsed_threads == 0 {
 
107
  .get::<_, HashMap<String, bool>>("upstream_search_engines")?
108
  .into_iter()
109
  .filter_map(|(key, value)| value.then_some(key))
110
+ .filter_map(|engine| crate::engines::engine_models::EngineHandler::new(&engine))
111
  .collect(),
112
  request_timeout: globals.get::<_, u8>("request_timeout")?,
113
  threads,
114
  })
115
  })
116
  }
117
+
118
  /// A helper function which returns an appropriate config file path checking if the config
119
  /// file exists on that path.
120
  ///
 
161
  Err("Config file not found!!".to_string().into())
162
  }
163
  }
164
+
165
+ /// a helper function that sets the proper logging level
166
+ fn set_logging_level(debug: bool, logging: bool) {
167
+ if let Ok(pkg_env_var) = std::env::var("PKG_ENV") {
168
+ if pkg_env_var.to_lowercase() == "dev" {
169
+ env_logger::Builder::new()
170
+ .filter(None, LevelFilter::Trace)
171
+ .init();
172
+ return;
173
+ }
174
+ }
175
+
176
+ // Initializing logging middleware with level set to default or info.
177
+ let log_level = match (debug, logging) {
178
+ (true, true) => LevelFilter::Debug,
179
+ (true, false) => LevelFilter::Debug,
180
+ (false, true) => LevelFilter::Info,
181
+ (false, false) => LevelFilter::Error,
182
+ };
183
+
184
+ env_logger::Builder::new().filter(None, log_level).init();
185
+ }
src/engines/duckduckgo.rs CHANGED
@@ -7,7 +7,7 @@ use std::collections::HashMap;
7
  use reqwest::header::{HeaderMap, CONTENT_TYPE, COOKIE, REFERER, USER_AGENT};
8
  use scraper::{Html, Selector};
9
 
10
- use crate::results::aggregation_models::RawSearchResult;
11
 
12
  use super::engine_models::{EngineError, SearchEngine};
13
 
@@ -43,7 +43,7 @@ impl SearchEngine for DuckDuckGo {
43
  page: u32,
44
  user_agent: String,
45
  request_timeout: u8,
46
- ) -> Result<HashMap<String, RawSearchResult>, EngineError> {
47
  // Page number can be missing or empty string and so appropriate handling is required
48
  // so that upstream server recieves valid page number.
49
  let url: String = match page {
@@ -120,7 +120,7 @@ impl SearchEngine for DuckDuckGo {
120
  Ok(document
121
  .select(&results)
122
  .map(|result| {
123
- RawSearchResult::new(
124
  result
125
  .select(&result_title)
126
  .next()
@@ -147,7 +147,7 @@ impl SearchEngine for DuckDuckGo {
147
  vec!["duckduckgo".to_string()],
148
  )
149
  })
150
- .map(|search_result| (search_result.visiting_url.clone(), search_result))
151
  .collect())
152
  }
153
  }
 
7
  use reqwest::header::{HeaderMap, CONTENT_TYPE, COOKIE, REFERER, USER_AGENT};
8
  use scraper::{Html, Selector};
9
 
10
+ use crate::results::aggregation_models::SearchResult;
11
 
12
  use super::engine_models::{EngineError, SearchEngine};
13
 
 
43
  page: u32,
44
  user_agent: String,
45
  request_timeout: u8,
46
+ ) -> Result<HashMap<String, SearchResult>, EngineError> {
47
  // Page number can be missing or empty string and so appropriate handling is required
48
  // so that upstream server recieves valid page number.
49
  let url: String = match page {
 
120
  Ok(document
121
  .select(&results)
122
  .map(|result| {
123
+ SearchResult::new(
124
  result
125
  .select(&result_title)
126
  .next()
 
147
  vec!["duckduckgo".to_string()],
148
  )
149
  })
150
+ .map(|search_result| (search_result.url.clone(), search_result))
151
  .collect())
152
  }
153
  }
src/engines/engine_models.rs CHANGED
@@ -1,7 +1,7 @@
1
  //! This module provides the error enum to handle different errors associated while requesting data from
2
  //! the upstream search engines with the search query provided by the user.
3
 
4
- use crate::results::aggregation_models::RawSearchResult;
5
  use error_stack::{IntoReport, Result, ResultExt};
6
  use std::{collections::HashMap, fmt, time::Duration};
7
 
@@ -43,9 +43,9 @@ impl fmt::Display for EngineError {
43
 
44
  impl error_stack::Context for EngineError {}
45
 
46
- /// A trait to define common behaviour for all search engines.
47
  #[async_trait::async_trait]
48
- pub trait SearchEngine {
49
  async fn fetch_html_from_upstream(
50
  &self,
51
  url: String,
@@ -56,7 +56,7 @@ pub trait SearchEngine {
56
  Ok(reqwest::Client::new()
57
  .get(url)
58
  .timeout(Duration::from_secs(request_timeout as u64)) // Add timeout to request to avoid DDOSing the server
59
- .headers(header_map) // add spoofed headers to emulate human behaviour
60
  .send()
61
  .await
62
  .into_report()
@@ -73,5 +73,37 @@ pub trait SearchEngine {
73
  page: u32,
74
  user_agent: String,
75
  request_timeout: u8,
76
- ) -> Result<HashMap<String, RawSearchResult>, EngineError>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
 
1
  //! This module provides the error enum to handle different errors associated while requesting data from
2
  //! the upstream search engines with the search query provided by the user.
3
 
4
+ use crate::results::aggregation_models::SearchResult;
5
  use error_stack::{IntoReport, Result, ResultExt};
6
  use std::{collections::HashMap, fmt, time::Duration};
7
 
 
43
 
44
  impl error_stack::Context for EngineError {}
45
 
46
+ /// A trait to define common behavior for all search engines.
47
  #[async_trait::async_trait]
48
+ pub trait SearchEngine: Sync + Send {
49
  async fn fetch_html_from_upstream(
50
  &self,
51
  url: String,
 
56
  Ok(reqwest::Client::new()
57
  .get(url)
58
  .timeout(Duration::from_secs(request_timeout as u64)) // Add timeout to request to avoid DDOSing the server
59
+ .headers(header_map) // add spoofed headers to emulate human behavior
60
  .send()
61
  .await
62
  .into_report()
 
73
  page: u32,
74
  user_agent: String,
75
  request_timeout: u8,
76
+ ) -> Result<HashMap<String, SearchResult>, EngineError>;
77
+ }
78
+
79
+ pub struct EngineHandler {
80
+ engine: Box<dyn SearchEngine>,
81
+ name: &'static str,
82
+ }
83
+
84
+ impl Clone for EngineHandler {
85
+ fn clone(&self) -> Self {
86
+ Self::new(self.name).unwrap()
87
+ }
88
+ }
89
+
90
+ impl EngineHandler {
91
+ /// parses an engine name into an engine handler, returns none if the engine is unknown
92
+ pub fn new(engine_name: &str) -> Option<Self> {
93
+ let engine: (&'static str, Box<dyn SearchEngine>) =
94
+ match engine_name.to_lowercase().as_str() {
95
+ "duckduckgo" => ("duckduckgo", Box::new(super::duckduckgo::DuckDuckGo)),
96
+ "searx" => ("searx", Box::new(super::searx::Searx)),
97
+ _ => return None,
98
+ };
99
+
100
+ Some(Self {
101
+ engine: engine.1,
102
+ name: engine.0,
103
+ })
104
+ }
105
+
106
+ pub fn into_name_engine(self) -> (&'static str, Box<dyn SearchEngine>) {
107
+ (self.name, self.engine)
108
+ }
109
  }
src/engines/searx.rs CHANGED
@@ -6,7 +6,7 @@ use reqwest::header::{HeaderMap, CONTENT_TYPE, COOKIE, REFERER, USER_AGENT};
6
  use scraper::{Html, Selector};
7
  use std::collections::HashMap;
8
 
9
- use crate::results::aggregation_models::RawSearchResult;
10
 
11
  use super::engine_models::{EngineError, SearchEngine};
12
  use error_stack::{IntoReport, Report, Result, ResultExt};
@@ -42,7 +42,7 @@ impl SearchEngine for Searx {
42
  page: u32,
43
  user_agent: String,
44
  request_timeout: u8,
45
- ) -> Result<HashMap<String, RawSearchResult>, EngineError> {
46
  // Page number can be missing or empty string and so appropriate handling is required
47
  // so that upstream server recieves valid page number.
48
  let url: String = match page {
@@ -111,7 +111,7 @@ impl SearchEngine for Searx {
111
  Ok(document
112
  .select(&results)
113
  .map(|result| {
114
- RawSearchResult::new(
115
  result
116
  .select(&result_title)
117
  .next()
@@ -137,7 +137,7 @@ impl SearchEngine for Searx {
137
  vec!["searx".to_string()],
138
  )
139
  })
140
- .map(|search_result| (search_result.visiting_url.clone(), search_result))
141
  .collect())
142
  }
143
  }
 
6
  use scraper::{Html, Selector};
7
  use std::collections::HashMap;
8
 
9
+ use crate::results::aggregation_models::SearchResult;
10
 
11
  use super::engine_models::{EngineError, SearchEngine};
12
  use error_stack::{IntoReport, Report, Result, ResultExt};
 
42
  page: u32,
43
  user_agent: String,
44
  request_timeout: u8,
45
+ ) -> Result<HashMap<String, SearchResult>, EngineError> {
46
  // Page number can be missing or empty string and so appropriate handling is required
47
  // so that upstream server recieves valid page number.
48
  let url: String = match page {
 
111
  Ok(document
112
  .select(&results)
113
  .map(|result| {
114
+ SearchResult::new(
115
  result
116
  .select(&result_title)
117
  .next()
 
137
  vec!["searx".to_string()],
138
  )
139
  })
140
+ .map(|search_result| (search_result.url.clone(), search_result))
141
  .collect())
142
  }
143
  }
src/results/aggregation_models.rs CHANGED
@@ -5,97 +5,44 @@ use serde::{Deserialize, Serialize};
5
 
6
  use crate::{config::parser_models::Style, engines::engine_models::EngineError};
7
 
8
- /// A named struct to store, serialize and deserializes the individual search result from all the
9
- /// scraped and aggregated search results from the upstream search engines.
 
10
  ///
11
  /// # Fields
12
  ///
13
  /// * `title` - The title of the search result.
14
- /// * `visiting_url` - The url which is accessed when clicked on it (href url in html in simple
15
- /// words).
16
- /// * `url` - The url to be displayed below the search result title in html.
17
  /// * `description` - The description of the search result.
18
  /// * `engine` - The names of the upstream engines from which this results were provided.
19
- #[derive(Serialize, Deserialize)]
20
  #[serde(rename_all = "camelCase")]
21
  pub struct SearchResult {
22
  pub title: String,
23
- pub visiting_url: String,
24
  pub url: String,
25
  pub description: String,
26
  pub engine: Vec<String>,
27
  }
28
 
29
  impl SearchResult {
30
- /// Constructs a new `SearchResult` with the given arguments needed for the struct.
31
  ///
32
  /// # Arguments
33
  ///
34
  /// * `title` - The title of the search result.
35
- /// * `visiting_url` - The url which is accessed when clicked on it
36
  /// (href url in html in simple words).
37
- /// * `url` - The url to be displayed below the search result title in html.
38
  /// * `description` - The description of the search result.
39
  /// * `engine` - The names of the upstream engines from which this results were provided.
40
- pub fn new(
41
- title: String,
42
- visiting_url: String,
43
- url: String,
44
- description: String,
45
- engine: Vec<String>,
46
- ) -> Self {
47
  SearchResult {
48
  title,
49
- visiting_url,
50
  url,
51
  description,
52
  engine,
53
  }
54
  }
55
- }
56
-
57
- /// A named struct to store the raw scraped search results scraped search results from the
58
- /// upstream search engines before aggregating it.It derives the Clone trait which is needed
59
- /// to write idiomatic rust using `Iterators`.
60
- ///
61
- /// # Fields
62
- ///
63
- /// * `title` - The title of the search result.
64
- /// * `visiting_url` - The url which is accessed when clicked on it
65
- /// (href url in html in simple words).
66
- /// * `description` - The description of the search result.
67
- /// * `engine` - The names of the upstream engines from which this results were provided.
68
- #[derive(Clone)]
69
- pub struct RawSearchResult {
70
- pub title: String,
71
- pub visiting_url: String,
72
- pub description: String,
73
- pub engine: Vec<String>,
74
- }
75
-
76
- impl RawSearchResult {
77
- /// Constructs a new `RawSearchResult` with the given arguments needed for the struct.
78
- ///
79
- /// # Arguments
80
- ///
81
- /// * `title` - The title of the search result.
82
- /// * `visiting_url` - The url which is accessed when clicked on it
83
- /// (href url in html in simple words).
84
- /// * `description` - The description of the search result.
85
- /// * `engine` - The names of the upstream engines from which this results were provided.
86
- pub fn new(
87
- title: String,
88
- visiting_url: String,
89
- description: String,
90
- engine: Vec<String>,
91
- ) -> Self {
92
- RawSearchResult {
93
- title,
94
- visiting_url,
95
- description,
96
- engine,
97
- }
98
- }
99
 
100
  /// A function which adds the engine name provided as a string into a vector of strings.
101
  ///
 
5
 
6
  use crate::{config::parser_models::Style, engines::engine_models::EngineError};
7
 
8
+ /// A named struct to store the raw scraped search results scraped search results from the
9
+ /// upstream search engines before aggregating it.It derives the Clone trait which is needed
10
+ /// to write idiomatic rust using `Iterators`.
11
  ///
12
  /// # Fields
13
  ///
14
  /// * `title` - The title of the search result.
15
+ /// * `url` - The url which is accessed when clicked on it
16
+ /// (href url in html in simple words).
 
17
  /// * `description` - The description of the search result.
18
  /// * `engine` - The names of the upstream engines from which this results were provided.
19
+ #[derive(Clone, Serialize, Deserialize)]
20
  #[serde(rename_all = "camelCase")]
21
  pub struct SearchResult {
22
  pub title: String,
 
23
  pub url: String,
24
  pub description: String,
25
  pub engine: Vec<String>,
26
  }
27
 
28
  impl SearchResult {
29
+ /// Constructs a new `RawSearchResult` with the given arguments needed for the struct.
30
  ///
31
  /// # Arguments
32
  ///
33
  /// * `title` - The title of the search result.
34
+ /// * `url` - The url which is accessed when clicked on it
35
  /// (href url in html in simple words).
 
36
  /// * `description` - The description of the search result.
37
  /// * `engine` - The names of the upstream engines from which this results were provided.
38
+ pub fn new(title: String, url: String, description: String, engine: Vec<String>) -> Self {
 
 
 
 
 
 
39
  SearchResult {
40
  title,
 
41
  url,
42
  description,
43
  engine,
44
  }
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  /// A function which adds the engine name provided as a string into a vector of strings.
48
  ///
src/results/aggregator.rs CHANGED
@@ -8,18 +8,14 @@ use rand::Rng;
8
  use tokio::task::JoinHandle;
9
 
10
  use super::{
11
- aggregation_models::{EngineErrorInfo, RawSearchResult, SearchResult, SearchResults},
12
  user_agent::random_user_agent,
13
  };
14
 
15
- use crate::engines::{
16
- duckduckgo,
17
- engine_models::{EngineError, SearchEngine},
18
- searx,
19
- };
20
 
21
  /// Aliases for long type annotations
22
- type FutureVec = Vec<JoinHandle<Result<HashMap<String, RawSearchResult>, Report<EngineError>>>>;
23
 
24
  /// The function aggregates the scraped results from the user-selected upstream search engines.
25
  /// These engines can be chosen either from the user interface (UI) or from the configuration file.
@@ -64,139 +60,93 @@ pub async fn aggregate(
64
  page: u32,
65
  random_delay: bool,
66
  debug: bool,
67
- upstream_search_engines: Vec<String>,
68
  request_timeout: u8,
69
  ) -> Result<SearchResults, Box<dyn std::error::Error>> {
70
  let user_agent: String = random_user_agent();
71
- let mut result_map: HashMap<String, RawSearchResult> = HashMap::new();
72
 
73
  // Add a random delay before making the request.
74
  if random_delay || !debug {
75
  let mut rng = rand::thread_rng();
76
  let delay_secs = rng.gen_range(1..10);
77
- std::thread::sleep(Duration::from_secs(delay_secs));
78
  }
79
 
80
- // fetch results from upstream search engines simultaneously/concurrently.
81
- let search_engines: Vec<Box<dyn SearchEngine + Send + Sync>> = upstream_search_engines
82
- .iter()
83
- .map(|engine| match engine.to_lowercase().as_str() {
84
- "duckduckgo" => Box::new(duckduckgo::DuckDuckGo) as Box<dyn SearchEngine + Send + Sync>,
85
- "searx" => Box::new(searx::Searx) as Box<dyn SearchEngine + Send + Sync>,
86
- &_ => panic!("Config Error: Incorrect config file option provided"),
87
- })
88
- .collect();
89
-
90
- let task_capacity: usize = search_engines.len();
91
-
92
- let tasks: FutureVec = search_engines
93
- .into_iter()
94
- .map(|search_engine| {
95
- let query: String = query.clone();
96
- let user_agent: String = user_agent.clone();
97
- tokio::spawn(async move {
98
- search_engine
99
- .results(query, page, user_agent.clone(), request_timeout)
100
- .await
101
- })
102
- })
103
- .collect();
104
-
105
- let mut outputs = Vec::with_capacity(task_capacity);
106
 
107
  for task in tasks {
108
  if let Ok(result) = task.await {
109
- outputs.push(result)
110
  }
111
  }
112
 
 
 
113
  let mut engine_errors_info: Vec<EngineErrorInfo> = Vec::new();
114
 
115
- // The code block `outputs.iter()` determines whether it is the first time the code is being run.
116
- // It does this by checking the initial flag. If it is the first time, the code selects the first
117
- // engine from which results are fetched and adds or extends them into the `result_map`. If the
118
- // initially selected engine fails, the code automatically selects another engine to map or extend
119
- // into the `result_map`. On the other hand, if an engine selected for the first time successfully
120
- // fetches results and maps them into the `result_map`, the initial flag is set to false. Subsequently,
121
- // the code iterates through the remaining engines one by one. It compares the fetched results from each
122
- // engine with the results already present in the `result_map` to identify any duplicates. If duplicate
123
- // results are found, the code groups them together with the name of the engine from which they were
124
- // fetched, and automatically removes the duplicate results from the newly fetched data.
125
- //
126
- // Additionally, the code handles errors returned by the engines. It keeps track of which engines
127
- // encountered errors and stores this information in a vector of structures called `EngineErrorInfo`.
128
- // Each structure in this vector contains the name of the engine and the type of error it returned.
129
- // These structures will later be added to the final `SearchResults` structure. The `SearchResults`
130
- // structure is used to display an error box in the UI containing the relevant information from
131
- // the `EngineErrorInfo` structure.
132
- //
133
- // In summary, this code block manages the selection of engines, handling of duplicate results, and tracking
134
- // of errors in order to populate the `result_map` and provide informative feedback to the user through the
135
- // `SearchResults` structure.
136
- let mut initial: bool = true;
137
- let mut counter: usize = 0;
138
- outputs.iter().for_each(|results| {
139
- if initial {
140
- match results {
141
- Ok(result) => {
142
- result_map.extend(result.clone());
143
- counter += 1;
144
- initial = false
145
  }
146
- Err(error_type) => {
147
- log::error!("Engine Error: {:?}", error_type);
148
- engine_errors_info.push(EngineErrorInfo::new(
149
- error_type.downcast_ref::<EngineError>().unwrap(),
150
- upstream_search_engines[counter].clone(),
151
- ));
152
- counter += 1
153
  }
154
  }
155
- } else {
156
- match results {
157
- Ok(result) => {
158
- result.clone().into_iter().for_each(|(key, value)| {
159
- result_map
160
- .entry(key)
161
- .and_modify(|result| {
162
- result.add_engines(value.clone().engine());
163
- })
164
- .or_insert_with(|| -> RawSearchResult {
165
- RawSearchResult::new(
166
- value.title.clone(),
167
- value.visiting_url.clone(),
168
- value.description.clone(),
169
- value.engine.clone(),
170
- )
171
- });
172
- });
173
- counter += 1
174
- }
175
- Err(error_type) => {
176
- log::error!("Engine Error: {:?}", error_type);
177
- engine_errors_info.push(EngineErrorInfo::new(
178
- error_type.downcast_ref::<EngineError>().unwrap(),
179
- upstream_search_engines[counter].clone(),
180
- ));
181
- counter += 1
182
- }
183
  }
184
  }
185
- });
 
 
186
 
187
  Ok(SearchResults::new(
188
- result_map
189
- .into_iter()
190
- .map(|(key, value)| {
191
- SearchResult::new(
192
- value.title,
193
- value.visiting_url,
194
- key,
195
- value.description,
196
- value.engine,
197
- )
198
- })
199
- .collect(),
200
  query.to_string(),
201
  engine_errors_info,
202
  ))
 
8
  use tokio::task::JoinHandle;
9
 
10
  use super::{
11
+ aggregation_models::{EngineErrorInfo, SearchResult, SearchResults},
12
  user_agent::random_user_agent,
13
  };
14
 
15
+ use crate::engines::engine_models::{EngineError, EngineHandler};
 
 
 
 
16
 
17
  /// Aliases for long type annotations
18
+ type FutureVec = Vec<JoinHandle<Result<HashMap<String, SearchResult>, Report<EngineError>>>>;
19
 
20
  /// The function aggregates the scraped results from the user-selected upstream search engines.
21
  /// These engines can be chosen either from the user interface (UI) or from the configuration file.
 
60
  page: u32,
61
  random_delay: bool,
62
  debug: bool,
63
+ upstream_search_engines: Vec<EngineHandler>,
64
  request_timeout: u8,
65
  ) -> Result<SearchResults, Box<dyn std::error::Error>> {
66
  let user_agent: String = random_user_agent();
 
67
 
68
  // Add a random delay before making the request.
69
  if random_delay || !debug {
70
  let mut rng = rand::thread_rng();
71
  let delay_secs = rng.gen_range(1..10);
72
+ tokio::time::sleep(Duration::from_secs(delay_secs)).await;
73
  }
74
 
75
+ let mut names: Vec<&str> = vec![];
76
+
77
+ // create tasks for upstream result fetching
78
+ let mut tasks: FutureVec = FutureVec::new();
79
+
80
+ for engine_handler in upstream_search_engines {
81
+ let (name, search_engine) = engine_handler.into_name_engine();
82
+ names.push(name);
83
+ let query: String = query.clone();
84
+ let user_agent: String = user_agent.clone();
85
+ tasks.push(tokio::spawn(async move {
86
+ search_engine
87
+ .results(query, page, user_agent.clone(), request_timeout)
88
+ .await
89
+ }));
90
+ }
91
+
92
+ // get upstream responses
93
+ let mut responses = Vec::with_capacity(tasks.len());
 
 
 
 
 
 
 
94
 
95
  for task in tasks {
96
  if let Ok(result) = task.await {
97
+ responses.push(result)
98
  }
99
  }
100
 
101
+ // aggregate search results, removing duplicates and handling errors the upstream engines returned
102
+ let mut result_map: HashMap<String, SearchResult> = HashMap::new();
103
  let mut engine_errors_info: Vec<EngineErrorInfo> = Vec::new();
104
 
105
+ let mut handle_error = |error: Report<EngineError>, engine_name: String| {
106
+ log::error!("Engine Error: {:?}", error);
107
+ engine_errors_info.push(EngineErrorInfo::new(
108
+ error.downcast_ref::<EngineError>().unwrap(),
109
+ engine_name.to_string(),
110
+ ));
111
+ };
112
+
113
+ for _ in 0..responses.len() {
114
+ let response = responses.pop().unwrap();
115
+ let engine = names.pop().unwrap().to_string();
116
+
117
+ if result_map.is_empty() {
118
+ match response {
119
+ Ok(results) => {
120
+ result_map = results.clone();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
+ Err(error) => {
123
+ handle_error(error, engine);
 
 
 
 
 
124
  }
125
  }
126
+ continue;
127
+ }
128
+
129
+ match response {
130
+ Ok(result) => {
131
+ result.into_iter().for_each(|(key, value)| {
132
+ result_map
133
+ .entry(key)
134
+ .and_modify(|result| {
135
+ result.add_engines(engine.clone());
136
+ })
137
+ .or_insert_with(|| -> SearchResult { value });
138
+ });
139
+ }
140
+ Err(error) => {
141
+ handle_error(error, engine);
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
  }
144
+ }
145
+
146
+ let results = result_map.into_values().collect();
147
 
148
  Ok(SearchResults::new(
149
+ results,
 
 
 
 
 
 
 
 
 
 
 
150
  query.to_string(),
151
  engine_errors_info,
152
  ))
src/server/routes.rs CHANGED
@@ -7,12 +7,14 @@ use std::fs::read_to_string;
7
  use crate::{
8
  cache::cacher::RedisCache,
9
  config::parser::Config,
 
10
  handler::public_paths::public_path,
11
  results::{aggregation_models::SearchResults, aggregator::aggregate},
12
  };
13
  use actix_web::{get, web, HttpRequest, HttpResponse};
14
  use handlebars::Handlebars;
15
  use serde::Deserialize;
 
16
 
17
  /// A named struct which deserializes all the user provided search parameters and stores them.
18
  ///
@@ -96,15 +98,49 @@ pub async fn search(
96
  }
97
  let page = match &params.page {
98
  Some(page) => *page,
99
- None => 0,
100
  };
101
 
102
- let url = format!(
103
- "http://{}:{}/search?q={}&page={}",
104
- config.binding_ip, config.port, query, page
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  );
106
- let results_json = results(url, &config, query.to_string(), page, req).await?;
107
- let page_content: String = hbs.render("search", &results_json)?;
108
  Ok(HttpResponse::Ok().body(page_content))
109
  }
110
  None => Ok(HttpResponse::Found()
@@ -140,12 +176,19 @@ async fn results(
140
  {
141
  Some(cookie_value) => {
142
  let cookie_value: Cookie = serde_json::from_str(cookie_value.name_value().1)?;
 
 
 
 
 
 
 
143
  aggregate(
144
  query,
145
  page,
146
  config.aggregator.random_delay,
147
  config.debug,
148
- cookie_value.engines,
149
  config.request_timeout,
150
  )
151
  .await?
 
7
  use crate::{
8
  cache::cacher::RedisCache,
9
  config::parser::Config,
10
+ engines::engine_models::EngineHandler,
11
  handler::public_paths::public_path,
12
  results::{aggregation_models::SearchResults, aggregator::aggregate},
13
  };
14
  use actix_web::{get, web, HttpRequest, HttpResponse};
15
  use handlebars::Handlebars;
16
  use serde::Deserialize;
17
+ use tokio::join;
18
 
19
  /// A named struct which deserializes all the user provided search parameters and stores them.
20
  ///
 
98
  }
99
  let page = match &params.page {
100
  Some(page) => *page,
101
+ None => 1,
102
  };
103
 
104
+ let (_, results, _) = join!(
105
+ results(
106
+ format!(
107
+ "http://{}:{}/search?q={}&page={}",
108
+ config.binding_ip,
109
+ config.port,
110
+ query,
111
+ page - 1
112
+ ),
113
+ &config,
114
+ query.to_string(),
115
+ page - 1,
116
+ req.clone(),
117
+ ),
118
+ results(
119
+ format!(
120
+ "http://{}:{}/search?q={}&page={}",
121
+ config.binding_ip, config.port, query, page
122
+ ),
123
+ &config,
124
+ query.to_string(),
125
+ page,
126
+ req.clone(),
127
+ ),
128
+ results(
129
+ format!(
130
+ "http://{}:{}/search?q={}&page={}",
131
+ config.binding_ip,
132
+ config.port,
133
+ query,
134
+ page + 1
135
+ ),
136
+ &config,
137
+ query.to_string(),
138
+ page + 1,
139
+ req.clone(),
140
+ )
141
  );
142
+
143
+ let page_content: String = hbs.render("search", &results?)?;
144
  Ok(HttpResponse::Ok().body(page_content))
145
  }
146
  None => Ok(HttpResponse::Found()
 
176
  {
177
  Some(cookie_value) => {
178
  let cookie_value: Cookie = serde_json::from_str(cookie_value.name_value().1)?;
179
+
180
+ let engines = cookie_value
181
+ .engines
182
+ .iter()
183
+ .filter_map(|name| EngineHandler::new(name))
184
+ .collect();
185
+
186
  aggregate(
187
  query,
188
  page,
189
  config.aggregator.random_delay,
190
  config.debug,
191
+ engines,
192
  config.request_timeout,
193
  )
194
  .await?
tests/index.rs CHANGED
@@ -8,7 +8,7 @@ fn spawn_app() -> String {
8
  // Binding to port 0 will trigger the OS to assign a port for us.
9
  let listener = TcpListener::bind("127.0.0.1:0").expect("Failed to bind random port");
10
  let port = listener.local_addr().unwrap().port();
11
- let config = Config::parse(true).unwrap();
12
  let server = run(listener, config).expect("Failed to bind address");
13
 
14
  tokio::spawn(server);
@@ -36,7 +36,7 @@ async fn test_index() {
36
  assert_eq!(res.status(), 200);
37
 
38
  let handlebars = handlebars();
39
- let config = Config::parse(false).unwrap();
40
  let template = handlebars.render("index", &config.style).unwrap();
41
  assert_eq!(res.text().await.unwrap(), template);
42
  }
 
8
  // Binding to port 0 will trigger the OS to assign a port for us.
9
  let listener = TcpListener::bind("127.0.0.1:0").expect("Failed to bind random port");
10
  let port = listener.local_addr().unwrap().port();
11
+ let config = Config::parse(false).unwrap();
12
  let server = run(listener, config).expect("Failed to bind address");
13
 
14
  tokio::spawn(server);
 
36
  assert_eq!(res.status(), 200);
37
 
38
  let handlebars = handlebars();
39
+ let config = Config::parse(true).unwrap();
40
  let template = handlebars.render("index", &config.style).unwrap();
41
  assert_eq!(res.text().await.unwrap(), template);
42
  }