1- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1+ # ========= Copyright 2023-2025 @ CAMEL-AI.org. All Rights Reserved. =========
22# Licensed under the Apache License, Version 2.0 (the "License");
33# you may not use this file except in compliance with the License.
44# You may obtain a copy of the License at
1010# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1111# See the License for the specific language governing permissions and
1212# limitations under the License.
13- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
13+ # ========= Copyright 2023-2025 @ CAMEL-AI.org. All Rights Reserved. =========
1414
1515import asyncio
1616import json
1717import os
1818import time
19- from http .server import BaseHTTPRequestHandler
19+ from http .server import BaseHTTPRequestHandler , HTTPServer
2020from pathlib import Path
21- from typing import Any , Dict , List , Optional
21+ from typing import Any , Dict , List , Optional , cast
2222
2323import requests
2424from dotenv import load_dotenv
3232logger = get_logger (__name__ )
3333
3434
35+ class OAuthHTTPServer (HTTPServer ):
36+ code : Optional [str ] = None
37+
38+
3539class RedirectHandler (BaseHTTPRequestHandler ):
3640 """Handler for OAuth redirect requests."""
3741
@@ -42,14 +46,14 @@ def do_GET(self):
4246 try :
4347 query = parse_qs (urlparse (self .path ).query )
4448 code = query .get ("code" , [None ])[0 ]
45- self .server .code = code
49+ cast ( OAuthHTTPServer , self .server ) .code = code
4650 self .send_response (200 )
4751 self .end_headers ()
4852 self .wfile .write (
4953 b"Authentication complete. You can close this window."
5054 )
5155 except Exception as e :
52- self .server .code = None
56+ cast ( OAuthHTTPServer , self .server ) .code = None
5357 self .send_response (500 )
5458 self .end_headers ()
5559 self .wfile .write (
@@ -496,12 +500,19 @@ def _get_authorization_code_via_browser(self, auth_url: str) -> str:
496500 ValueError: If the authorization code cannot be captured.
497501 """
498502 import webbrowser
499- from http .server import HTTPServer
500503 from urllib .parse import urlparse
501504
502505 parsed_uri = urlparse (self .redirect_uri )
503- server_address = (parsed_uri .hostname , parsed_uri .port )
504- server = HTTPServer (server_address , RedirectHandler )
506+ hostname = parsed_uri .hostname
507+ port = parsed_uri .port
508+ if not hostname or not port :
509+ raise ValueError (
510+ f"Invalid redirect_uri, expected host and port: "
511+ f"{ self .redirect_uri } "
512+ )
513+
514+ server_address = (hostname , port )
515+ server = OAuthHTTPServer (server_address , RedirectHandler )
505516 server .code = None
506517
507518 logger .info (f"Opening browser for authentication: { auth_url } " )
@@ -510,9 +521,10 @@ def _get_authorization_code_via_browser(self, auth_url: str) -> str:
510521 server .handle_request ()
511522 server .server_close ()
512523
513- if not server .code :
524+ authorization_code = server .code
525+ if not authorization_code :
514526 raise ValueError ("Failed to get authorization code" )
515- return server . code
527+ return authorization_code
516528
517529 def _exchange_authorization_code_for_tokens (
518530 self , authorization_code : str , scope : List [str ]
0 commit comments