요청이 session.get()에서는 되지만 PreparedRequest로 다시 작성한 뒤 인증서 검증에 실패할 수 있습니다. 저수준 send 경로는 일반 request 메서드와 같은 환경 병합을 하지 않습니다.

import requests

with requests.Session() as session:
    request = requests.Request("GET", "https://example.com/")
    prepared = session.prepare_request(request)

    settings = session.merge_environment_settings(
        prepared.url, {}, None, None, None
    )
    response = session.send(
        prepared,
        timeout=(5, 15),
        **settings,
    )
    response.raise_for_status()
    print(response.status_code)

원하는 URL 변경을 마친 뒤 최종 준비된 URL로 병합하세요. 프록시와 우회 결정은 목적지에 따라 달라지므로 이전 URL로 얻은 설정이 실제 전송 요청에 맞지 않을 수 있습니다.

CA 설정은 놓치기 쉽습니다

일반 환경 신뢰가 켜져 있고 검증을 명시적으로 재정의하지 않았다면 병합은 REQUESTS_CA_BUNDLE와 대체 CURL_CA_BUNDLE를 고려합니다. 기본 verify로 send를 직접 호출하면 이 CA 조회를 하지 않습니다. 검증을 끄는 것은 차이를 감출 뿐 원하는 인증서 저장소를 제공하지 않습니다.

Session.prepare_request()는 세션의 준비 동작도 적용합니다. Request.prepare()로 요청을 직접 만드는 것은 별도 선택입니다. 세션 쿠키나 다른 세션 준비가 자동 적용될 것으로 기대하지 마세요.

프록시에는 더 구체적인 규칙이 있습니다

모든 PreparedRequest가 프록시 환경 변수를 무시한다는 말은 부정확합니다. Requests 2.34.2에서 send는 proxies 키워드 인수가 없을 때 기본 프록시를 결정합니다. send에 proxies={}를 주면 그 특정 기본값 결정 분기를 건너뜁니다.

merge_environment_settings에 전달하는 빈 딕셔너리는 역할이 다릅니다. 병합은 적용 가능한 환경 경로를 채운 뒤 send에 전달할 수 있습니다. 두 코드에서 빈 딕셔너리가 있다는 사실만 보면 이를 받는 메서드가 다르다는 점을 놓칩니다.

사용자 정의 요청 구성 코드에서 준비, 환경 병합, 전송을 함께 두세요. 앱이 의도적으로 trust_env=False를 쓰면 병합은 그 정책을 따릅니다. 환경 설정을 일부러 끈 클라이언트에 강제로 적용하는 수단이 아닙니다.

관련 글