'httpx' 모듈을 사용하여, 원격 서버에서 파일을 가져와 FastAPI에서 사용 중인데, SSL 인증서 확인이 안 됩니다.

'httpx' 모듈을 사용하여, 원격 서버에서 파일을 가져와 FastAPI에서 사용 중인데, SSL 인증서 확인이 안 됩니다.

QA

'httpx' 모듈을 사용하여, 원격 서버에서 파일을 가져와 FastAPI에서 사용 중인데, SSL 인증서 확인이 안 됩니다.

본문

안녕 하세요.

 

Apache를 리버스 프록시로 설정하여, FastAPI 애플리케이션을 Uvicorn으로 구동하는

 

그누보드6(6.0.4) 실서비스를 사용 중입니다.

 

'httpx' 모듈을 사용하여, 원격 서버에서 파일을 가져와 FastAPI에서 사용 중인데,


File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpx/_client.py", line 1661, in send response = await self._send_handling_auth( File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpx/_client.py", line 1689, in _send_handling_auth response = await self._send_handling_redirects( File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpx/_client.py", line 1726, in _send_handling_redirects response = await self._send_single_request(request) File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpx/_client.py", line 1763, in _send_single_request response = await transport.handle_async_request(request) File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpx/_transports/default.py", line 373, in handle_async_request resp = await self._pool.handle_async_request(req) File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_async/connection_pool.py", line 216, in handle_async_request raise exc from None File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_async/connection_pool.py", line 196, in handle_async_request response = await connection.handle_async_request( File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_async/connection.py", line 99, in handle_async_request raise exc File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_async/connection.py", line 76, in handle_async_request stream = await self._connect(request) File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_async/connection.py", line 154, in _connect stream = await stream.start_tls(**kwargs) File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_backends/anyio.py", line 80, in start_tls raise exc File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/httpcore/_backends/anyio.py", line 71, in start_tls ssl_stream = await anyio.streams.tls.TLSStream.wrap( File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/anyio/streams/tls.py", line 123, in wrap await wrapper._call_sslobject_method(ssl_object.do_handshake) File "/mnt/VOL1/base2/venv/lib/python3.9/site-packages/anyio/streams/tls.py", line 131, in _call_sslobject_method result = func(*args) File "/usr/lib/python3.9/ssl.py", line 944, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

 = = =("/mnt/VOL1/base2/")는 그누보드6 설치폴더 = = =

 

위와 같은 에러와 함께 SSL 인증서 확인_적용이 안 됩니다.

 

>>> 현재. SSL 검증을 비활성화 한 상태로 원격 서버의 이미지와 css를 FastAPI에 사용 중입니다.

 

여러모로 노력하였으나, 범인이 해결하기에는 문제가 있는 듯하여,

 

전문인의 조언을 듣고자 합니다.

.


.
import aiohttp
import ssl
import httpx
.

추가 모듈 등을 import하였고 ~

 

시스템 정보입니다.


root@HumanpcNAS:~# uname && uname -r
Linux
6.1.20-efm-standard
.
root@HumanpcNAS:~# python3 -V
Python 3.9.9
.
root@HumanpcNAS:~# cat requirements.txt
.
fastapi>=0.111.0 #그누보드(6.0.4) 설치시, 확인 됨
.
root@HumanpcNAS:~# httpd -v
Server version: Apache/2.4.52 (Unix)
.

 

Loaded Modules과 PHP 설정 ( https://glitter.kr/apm/ )

.

이 질문에 댓글 쓰기 :

답변 2

저도 궁금해서 출근전에 공부겸 찾아보고 있었습니다 하하.
ssl._create_default_https_context = ssl._create_unverified_context 문구가 계속 출현하긴 하네용.
http_context 관련해서는 거의 같은 대답을 하고 있는 듯 보입니다.

    ※ 필자는 다음과 같이 해결하였습니다.

 

  == main.py 수정 사항 ==

!. Server의 특정 디렉터리(/mnt/VOL1/hwi/)에 image, css, favicon, 등을 두고

그누보드의 특정 폴더(hwi)에 마운트 하고 robots.txt와 site_map.xml 등은 

  static  파일로 그누보드6에 마운트하는 방법을 사용하였다.

 

!. main.py에 추가된 소스 -


import httpx
import aiohttp
.
from ipaddress import ip_network, ip_address
.
from fastapi.responses import  PlainTextResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
.
.
.
.get("/hwi/{file_path:path}")
async def proxy_local_files(file_path: str, request: Request):
    base_directory = "/mnt/VOL1/hwi/"
    full_path = os.path.join(base_directory, file_path)
 
    if not os.path.exists(full_path):
        return Response(content="File not found", status_code=404)
 
    content_type = "application/octet-stream"
    if file_path.endswith(".css"):
        content_type = "text/css"
    elif file_path.endswith(".png"):
        content_type = "image/png"
    elif file_path.endswith(".jpg") or file_path.endswith(".jpeg"):
        content_type = "image/jpeg"
 
    with open(full_path, "rb") as file:
        content = file.read()
 
    return Response(content=content, media_type=content_type)
 
ROBOTS_TXT_PATH = "/mnt/VOL1/hwi/m.robots.txt"
M_GLITTER_SITEMAP_PATH = "/mnt/VOL1/hwi/m.glitter_sitemap.xml"
FAVICON_ICO_PATH = "/mnt/VOL1/hwi/gimg/favicon/favicon.ico"
 
async def fetch_local_file(path: str, response_class=PlainTextResponse):
    if os.path.exists(path):
        with open(path, "rb") as file:
            content = file.read()
        if response_class == PlainTextResponse:
            return response_class(content.decode("utf-8", errors="ignore"))
        elif response_class == StreamingResponse:
            return response_class(iter([content]), media_type="application/octet-stream")
    else:
        return PlainTextResponse(f"{path} file not found", status_code=404)
 
.get("/robots.txt", include_in_schema=False)
async def robots_txt():
    return await fetch_local_file(ROBOTS_TXT_PATH)
 
.get("/m.glitter_sitemap.xml", include_in_schema=False)
async def m_glitter_sitemap():
    return await fetch_local_file(M_GLITTER_SITEMAP_PATH)
 
.get("/", response_class=HTMLResponse)
async def read_root():
    return """
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
 
    </head>
    <body>
        <h1>그누보드6 본문</h1>
    </body>
    </html>+
    """
 
.get("/favicon.ico", include_in_schema=False)
async def favicon():
    return await fetch_local_file(FAVICON_ICO_PATH, response_class=StreamingResponse)

☆ import 코드 이외의 코드(함수 6개)는 main_middleware 함수의 아래에, 

    regist_core_middleware(app) 위에; 즉 사이에 놓아야 한다.

 

☆ /mnt/VOL1/hwi/,  /mnt/VOL1/hwi/gimg/favicon/ 이 폴더들은 사용자 특정 폴더임.

   -그누보드6은 /mnt/VOL1/base2/에 설치됨.

 

!. uvicorn server를 재시작 - 사용자를 root로 가정한 명령어 임.


cd  <누보드6 설치 디렉토리("/mnt/VOL1/base2")로 변경>
systemctl daemon-reload
python -m venv venv
source venv/bin/activate
uvicorn main:app --reload --host 0.0.0.0 --port 8000

 

!. http://사용자 IP(DNS)/robots.txt , 이 URL의 실행 확인 -

 

★ 필자의 "/mnt/VOL1/hwi/m.robots.txt"는 이렇게( https://m.glitter.kr/robots.txt ) 마운트 되었다.

 

※ 초보의 심정으로 ~~ 필자의 디렉터리 구조이다.


│
/mnt/VOL1/base2/ ( 그누보드6 설치 디렉터리 )
│   ├── .env
│   ├── . . .
│   └── main.py
│
/mnt/VOL1/hwi/ ( static 파일 디렉터리 )
│   ├── gimg/
│   │   ├── img/
│   │   └── favicon/
│   ├── css/
│   │   ├── glitter.css
│   │   ├── m.glitter_default.css
│   │   ├── . . .
│   │   └── policy.glitter_default.css
│   ├── robots.txt
│   ├── m.robots.txt
│   ├── policy.robots.txt
│   ├── . . .
│   ├── glitter_sitemap.xml
│   ├── m.glitter_sitemap.xml
│   ├── policy.glitter_sitemap.xml
│   └── site_map.xml
│
답변을 작성하시기 전에 로그인 해주세요.
전체 224
QA 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT