返回提交历史
Modified
g4f/gui/server/backend_api.py
+12
-9
Modified
g4f/requests/__init__.py
+14
-4
XFEstudio/gpt4free
Fix stop_browser, update secret validation
a30908ae
代码差异
2 个文件
+26
-13
@@ -87,12 +87,12 @@ class Backend_Api(Api):
87
87
format=serialization.PublicFormat.SubjectPublicKeyInfo
88
88
)
89
89
90
def decrypt_data(encrypted_data: str):
90
def decrypt_data(encrypted_data: str) -> str:
91
91
decrypted = private_key_obj.decrypt(
92
92
base64.b64decode(encrypted_data),
93
93
padding.PKCS1v15()
94
94
)
95
return decrypted.decode('utf-8')
95
return decrypted.decode()
96
96
97
97
def validate_secret(secret: str) -> bool:
98
98
"""
@@ -105,7 +105,7 @@ class Backend_Api(Api):
105
105
bool: True if the secret is valid, False otherwise.
106
106
"""
107
107
try:
108
decrypted_secret = decrypt_data(secret)
108
decrypted_secret = base64.b64decode(decrypt_data(secret).encode()).decode()
109
109
return int(decrypted_secret) >= time.time() - 2
110
110
except Exception as e:
111
111
logger.error(f"Secret validation failed: {e}")
@@ -114,7 +114,10 @@ class Backend_Api(Api):
114
114
@app.route('/backend-api/v2/public-key', methods=['GET'])
115
115
def get_public_key():
116
116
# Send the public key to the client for encryption
117
return jsonify({"public_key": public_key_pem.decode('utf-8'), "data": str(int(time.time()))})
117
return jsonify({
118
"public_key": public_key_pem.decode(),
119
"data": base64.b64encode(str(int(time.time())).encode()).decode()
120
})
118
121
119
122
@app.route('/backend-api/v2/models', methods=['GET'])
120
123
def jsonify_models(**kwargs):
@@ -282,7 +285,7 @@ class Backend_Api(Api):
282
285
},
283
286
}
284
287
285
@app.route('/backend-api/v2/create', methods=['GET', 'POST'])
288
@app.route('/backend-api/v2/create', methods=['GET'])
286
289
def create():
287
290
try:
288
291
tool_calls = []
@@ -335,7 +338,7 @@ class Backend_Api(Api):
335
338
if chunk:
336
339
yield chunk
337
340
return iter_response()
338
341
339
342
if cache_id:
340
343
cache_id = sha256(cache_id.encode() + json.dumps(parameters, sort_keys=True).encode()).hexdigest()
341
344
cache_dir = Path(get_cookies_dir()) / ".scrape_cache" / "create"
@@ -394,7 +397,7 @@ class Backend_Api(Api):
394
397
delete_files = request.args.get('delete_files', True)
395
398
refine_chunks_with_spacy = request.args.get('refine_chunks_with_spacy', False)
396
399
event_stream = 'text/event-stream' in request.headers.get('Accept', '')
397
mimetype = "text/event-stream" if event_stream else "text/plain";
400
mimetype = "text/event-stream" if event_stream else "text/plain"
398
401
return Response(get_streaming(bucket_dir, delete_files, refine_chunks_with_spacy, event_stream), mimetype=mimetype)
399
402
400
403
@self.app.route('/backend-api/v2/files/<bucket_id>', methods=['POST'])
@@ -413,14 +416,14 @@ class Backend_Api(Api):
413
416
suffix = os.path.splitext(filename)[1].lower()
414
417
copyfile = get_tempfile(file, suffix)
415
418
result = None
416
if has_markitdown and not filename.endswith((".md", ".json")):
419
if has_markitdown and not filename.endswith((".md", ".json", ".zip")):
417
420
try:
418
421
language = request.headers.get("x-recognition-language")
419
422
md = MarkItDown()
420
423
result = md.convert(copyfile, stream_info=StreamInfo(
421
424
extension=suffix,
422
425
mimetype=file.mimetype,
423
),recognition_language=language).text_content
426
), recognition_language=language).text_content
424
427
except Exception as e:
425
428
logger.exception(e)
426
429
is_media = is_allowed_extension(filename)
@@ -45,7 +45,9 @@ from ..typing import Cookies
45
45
from ..cookies import get_cookies_dir
46
46
from .defaults import DEFAULT_HEADERS, WEBVIEW_HAEDERS
47
47
48
BROWSER_EXECUTABLE_PATH = None
48
class BrowserConfig:
49
stop_browser = lambda: None
50
browser_executable_path: str = None
49
51
50
52
if not has_curl_cffi:
51
53
class Session:
@@ -141,7 +143,7 @@ def merge_cookies(cookies: Iterator[Morsel], response: Response) -> Cookies:
141
143
return cookies
142
144
143
145
def set_browser_executable_path(browser_executable_path: str):
144
BROWSER_EXECUTABLE_PATH = browser_executable_path
146
BrowserConfig.browser_executable_path = browser_executable_path
145
147
146
148
async def get_nodriver(
147
149
proxy: str = None,
@@ -154,7 +156,7 @@ async def get_nodriver(
154
156
raise MissingRequirementsError('Install "nodriver" and "platformdirs" package | pip install -U nodriver platformdirs')
155
157
user_data_dir = user_config_dir(f"g4f-{user_data_dir}") if has_platformdirs else None
156
158
if browser_executable_path is None:
157
browser_executable_path = BROWSER_EXECUTABLE_PATH
159
browser_executable_path = BrowserConfig.browser_executable_path
158
160
if browser_executable_path is None:
159
161
try:
160
162
browser_executable_path = find_chrome_executable()
@@ -173,11 +175,18 @@ async def get_nodriver(
173
175
if timeout * 2 > time_open:
174
176
debug.log(f"Nodriver: Browser is already in use since {time_open} secs.")
175
177
debug.log("Lock file:", lock_file)
176
for _ in range(timeout):
178
for idx in range(timeout):
177
179
if lock_file.exists():
178
180
await asyncio.sleep(1)
179
181
else:
180
182
break
183
if idx == timeout - 1:
184
debug.log("Timeout reached, nodriver is still in use.")
185
raise TimeoutError("Nodriver is already in use, please try again later.")
186
else:
187
debug.log(f"Nodriver: Browser was opened {time_open} secs ago, closing it.")
188
BrowserConfig.stop_browser()
189
lock_file.unlink(missing_ok=True)
181
190
lock_file.write_text(str(time.time()))
182
191
debug.log(f"Open nodriver with user_dir: {user_data_dir}")
183
192
try:
@@ -200,6 +209,7 @@ async def get_nodriver(
200
209
browser.stop()
201
210
finally:
202
211
lock_file.unlink(missing_ok=True)
212
BrowserConfig.stop_browser = on_stop
203
213
return browser, on_stop
204
214
205
215
async def see_stream(iter_lines: Iterator[bytes]) -> AsyncIterator[dict]: