diff --git a/src/flaresolverr_service.py b/src/flaresolverr_service.py
index 890d8ad..ad21504 100644
--- a/src/flaresolverr_service.py
+++ b/src/flaresolverr_service.py
@@ -242,7 +242,7 @@ def _resolve_challenge(req: V1RequestBase, method: str) -> ChallengeResolutionT:
except FunctionTimedOut:
raise Exception(f'Error solving the challenge. Timeout after {timeout} seconds.')
except Exception as e:
- raise Exception('Error solving the challenge. ' + str(e))
+ raise Exception('Error solving the challenge. ' + str(e).replace('\n', '\\n'))
finally:
if not req.session and driver is not None:
driver.quit()
diff --git a/src/sessions.py b/src/sessions.py
index d80607a..1a635e0 100644
--- a/src/sessions.py
+++ b/src/sessions.py
@@ -25,7 +25,8 @@ class SessionsStorage:
def __init__(self):
self.sessions = {}
- def create(self, session_id: Optional[str] = None, proxyconf: Optional[dict] = None, force_new: Optional[bool] = False) -> Tuple[Session, bool]:
+ def create(self, session_id: Optional[str] = None, proxy: Optional[dict] = None,
+ force_new: Optional[bool] = False) -> Tuple[Session, bool]:
"""create creates new instance of WebDriver if necessary,
assign defined (or newly generated) session_id to the instance
and returns the session object. If a new session has been created
@@ -44,7 +45,7 @@ class SessionsStorage:
if self.exists(session_id):
return self.sessions[session_id], False
- driver = utils.get_webdriver(proxyconf=proxyconf)
+ driver = utils.get_webdriver(proxy)
created_at = datetime.now()
session = Session(session_id, driver, created_at)
diff --git a/src/tests.py b/src/tests.py
index 0f6d974..6e31435 100644
--- a/src/tests.py
+++ b/src/tests.py
@@ -1,4 +1,5 @@
import unittest
+from typing import Optional
from webtest import TestApp
@@ -7,7 +8,7 @@ import flaresolverr
import utils
-def _find_obj_by_key(key: str, value: str, _list: list) -> dict | None:
+def _find_obj_by_key(key: str, value: str, _list: list) -> Optional[dict]:
for obj in _list:
if obj[key] == value:
return obj
@@ -28,6 +29,8 @@ class TestFlareSolverr(unittest.TestCase):
cloudflare_blocked_url = "https://cpasbiens3.fr/index.php?do=search&subaction=search"
app = TestApp(flaresolverr.app)
+ # wait until the server is ready
+ app.get('/')
def test_wrong_endpoint(self):
res = self.app.get('/wrong', status=404)
@@ -261,10 +264,88 @@ class TestFlareSolverr(unittest.TestCase):
self.assertGreater(len(solution.cookies), 0)
self.assertIn("Chrome/", solution.userAgent)
- # todo: test Cmd 'request.get' should return OK with HTTP 'proxy' param
- # todo: test Cmd 'request.get' should return OK with HTTP 'proxy' param with credentials
- # todo: test Cmd 'request.get' should return OK with SOCKSv5 'proxy' param
- # todo: test Cmd 'request.get' should fail with wrong 'proxy' param
+ def test_v1_endpoint_request_get_proxy_http_param(self):
+ """
+ To configure TinyProxy in local:
+ * sudo vim /etc/tinyproxy/tinyproxy.conf
+ * edit => LogFile "/tmp/tinyproxy.log"
+ * edit => Syslog Off
+ * sudo tinyproxy -d
+ * sudo tail -f /tmp/tinyproxy.log
+ """
+ res = self.app.post_json('/v1', {
+ "cmd": "request.get",
+ "url": self.google_url,
+ "proxy": {
+ "url": self.proxy_url
+ }
+ })
+ self.assertEqual(res.status_code, 200)
+
+ body = V1ResponseBase(res.json)
+ self.assertEqual(STATUS_OK, body.status)
+ self.assertEqual("Challenge not detected!", body.message)
+ self.assertGreater(body.startTimestamp, 10000)
+ self.assertGreaterEqual(body.endTimestamp, body.startTimestamp)
+ self.assertEqual(utils.get_flaresolverr_version(), body.version)
+
+ solution = body.solution
+ self.assertIn(self.google_url, solution.url)
+ self.assertEqual(solution.status, 200)
+ self.assertIs(len(solution.headers), 0)
+ self.assertIn("
Google", solution.response)
+ self.assertGreater(len(solution.cookies), 0)
+ self.assertIn("Chrome/", solution.userAgent)
+
+ def test_v1_endpoint_request_get_proxy_socks_param(self):
+ """
+ To configure Dante in local:
+ * https://linuxhint.com/set-up-a-socks5-proxy-on-ubuntu-with-dante/
+ * sudo vim /etc/sockd.conf
+ * sudo systemctl restart sockd.service
+ * curl --socks5 socks5://127.0.0.1:1080 https://www.google.com
+ """
+ res = self.app.post_json('/v1', {
+ "cmd": "request.get",
+ "url": self.google_url,
+ "proxy": {
+ "url": self.proxy_socks_url
+ }
+ })
+ self.assertEqual(res.status_code, 200)
+
+ body = V1ResponseBase(res.json)
+ self.assertEqual(STATUS_OK, body.status)
+ self.assertEqual("Challenge not detected!", body.message)
+ self.assertGreater(body.startTimestamp, 10000)
+ self.assertGreaterEqual(body.endTimestamp, body.startTimestamp)
+ self.assertEqual(utils.get_flaresolverr_version(), body.version)
+
+ solution = body.solution
+ self.assertIn(self.google_url, solution.url)
+ self.assertEqual(solution.status, 200)
+ self.assertIs(len(solution.headers), 0)
+ self.assertIn("Google", solution.response)
+ self.assertGreater(len(solution.cookies), 0)
+ self.assertIn("Chrome/", solution.userAgent)
+
+ def test_v1_endpoint_request_get_proxy_wrong_param(self):
+ res = self.app.post_json('/v1', {
+ "cmd": "request.get",
+ "url": self.google_url,
+ "proxy": {
+ "url": "http://127.0.0.1:43210"
+ }
+ }, status=500)
+ self.assertEqual(res.status_code, 500)
+
+ body = V1ResponseBase(res.json)
+ self.assertEqual(STATUS_ERROR, body.status)
+ self.assertIn("Error: Error solving the challenge. Message: unknown error: net::ERR_PROXY_CONNECTION_FAILED",
+ body.message)
+ self.assertGreater(body.startTimestamp, 10000)
+ self.assertGreaterEqual(body.endTimestamp, body.startTimestamp)
+ self.assertEqual(utils.get_flaresolverr_version(), body.version)
def test_v1_endpoint_request_get_fail_timeout(self):
res = self.app.post_json('/v1', {
@@ -401,6 +482,20 @@ class TestFlareSolverr(unittest.TestCase):
self.assertEqual("Session created successfully.", body.message)
self.assertEqual(body.session, "test_create_session")
+ def test_v1_endpoint_sessions_create_with_proxy(self):
+ res = self.app.post_json('/v1', {
+ "cmd": "sessions.create",
+ "proxy": {
+ "url": self.proxy_url
+ }
+ })
+ self.assertEqual(res.status_code, 200)
+
+ body = V1ResponseBase(res.json)
+ self.assertEqual(STATUS_OK, body.status)
+ self.assertEqual("Session created successfully.", body.message)
+ self.assertIsNotNone(body.session)
+
def test_v1_endpoint_sessions_list(self):
self.app.post_json('/v1', {
"cmd": "sessions.create",
diff --git a/src/tests_sites.py b/src/tests_sites.py
index a29369c..aa7dcbc 100644
--- a/src/tests_sites.py
+++ b/src/tests_sites.py
@@ -39,6 +39,8 @@ def asset_cloudflare_solution(self, res, site_url, site_text):
class TestFlareSolverr(unittest.TestCase):
app = TestApp(flaresolverr.app)
+ # wait until the server is ready
+ app.get('/')
def test_v1_endpoint_request_get_cloudflare(self):
sites_get = [
diff --git a/src/utils.py b/src/utils.py
index 31c1fdd..b2a01df 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -36,7 +36,7 @@ def get_flaresolverr_version() -> str:
return FLARESOLVERR_VERSION
-def get_webdriver(proxyconf: dict=None) -> WebDriver:
+def get_webdriver(proxy: dict = None) -> WebDriver:
global PATCHED_DRIVER_PATH
logging.debug('Launching web browser...')
@@ -55,8 +55,8 @@ def get_webdriver(proxyconf: dict=None) -> WebDriver:
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
- if proxyconf:
- proxy_url = proxyconf['url']
+ if proxy and 'url' in proxy:
+ proxy_url = proxy['url']
logging.debug("Using webdriver proxy: %s", proxy_url)
options.add_argument('--proxy-server=%s' % proxy_url)