1+ import os
2+ import urllib .request
3+ import logging
4+ from cfenv import AppEnv
5+ from oauth2 import OAuth2Client
6+ import py_eureka_client .eureka_client as eureka_client
7+ import py_eureka_client .http_client as http_client
8+ from urllib .error import URLError
9+ from typing import Union
10+
11+ logger = logging .getLogger (__name__ )
12+
13+ class _OAuth2HttpClient (http_client .HttpClient ):
14+ """
15+ A custom http client that uses OAuth2 to authenticate requests.
16+ """
17+
18+ def __init__ (self , credentials : dict ):
19+ self .oauth_client = OAuth2Client (
20+ client_id = credentials ['client_id' ],
21+ client_secret = credentials ['client_secret' ],
22+ access_token_uri = credentials ['access_token_uri' ]
23+ )
24+
25+ async def urlopen (self , request : Union [str , http_client .HttpRequest ] = None ,
26+ data : bytes = None , timeout : float = None ) -> http_client .HttpResponse :
27+ if isinstance (request , http_client .HttpRequest ):
28+ req = request
29+ elif isinstance (request , str ):
30+ req = http_client .HttpRequest (request , headers = {'Accept-Encoding' : 'gzip' })
31+ else :
32+ raise URLError ("Invalid URL" )
33+
34+ req = req ._to_urllib_request ()
35+ req .add_header ("Connection" , "close" )
36+ req .add_header ("Authorization" , f"Bearer { self .oauth_client .get_access_token ()} " )
37+ res = urllib .request .urlopen (req , data = data , timeout = timeout )
38+ return http_client .HttpResponse (res )
39+
40+ def _on_err (err_type : str , err : Exception ):
41+ logger .error (f"Eureka client error - Type: { err_type } , Error: { err } " )
42+ if err_type in (eureka_client .ERROR_REGISTER , eureka_client .ERROR_DISCOVER ):
43+ eureka_client .stop ()
44+
45+ def init_client ():
46+ """
47+ Initializes the eureka client.
48+ """
49+
50+ env = AppEnv ()
51+
52+ service_registry = env .get_service (label = "p.service-registry" )
53+ if not service_registry :
54+ raise ValueError ("No 'p.service-registry' service instance found." )
55+
56+ credentials = service_registry .credentials
57+
58+ http_client .set_http_client (_OAuth2HttpClient (credentials ))
59+
60+ eureka_client .init (
61+ app_name = env .name ,
62+ instance_host = env .uris [0 ],
63+ instance_ip = os .getenv ('CF_INSTANCE_INTERNAL_IP' ),
64+ instance_id = f"{ env .uris [0 ]} :{ env .app .get ('instance_id' ) or '0' } " ,
65+ instance_unsecure_port_enabled = True ,
66+ instance_port = 80 ,
67+ instance_secure_port_enabled = True ,
68+ instance_secure_port = 443 ,
69+ vip_adr = 'UNKNOWN' ,
70+ secure_vip_addr = 'UNKNOWN' ,
71+ eureka_server = credentials ['uri' ],
72+ on_error = _on_err
73+ )
74+
75+ def call_service (name : str , path : str ):
76+ """
77+ Calls a service with the given name and path.
78+ """
79+ try :
80+ return eureka_client .do_service (app_name = name , service = path , prefer_https = True )
81+ except urllib .request .HTTPError as e :
82+ logger .error (f"Error calling service { name } at { path } : { e } " )
83+ raise e
0 commit comments