Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Connection aborted ConnectionResetError 10054 while calling Jira using Python Requests library

rAJ August 14, 2025

I need help with below error,

Jira hosted on SSO Okta  and when I try to fetch JIra data using bearer token i see error below, Please i need urgent help with this

 

An error occurred during the request: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None

 

 

import requests
import json

# Replace with your Jira instance URL and the API endpoint
JIRA_BASE_URL = "https://jira.vtxxxxx.net"
API_ENDPOINT = "/rest/api/2/search"  # Example: fetching issues

# Replace with your generated Personal Access Token (PAT) or OAuth token
BEARER_TOKEN = "APITOKEN_HERE"

# Construct the full URL
url = f"{JIRA_BASE_URL}{API_ENDPOINT}"

# Set up the headers with the bearer token for authentication
headers = {
    "Authorization": f"Bearer {BEARER_TOKEN}",
    "Accept": "application/json"
}

try:
     response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()  # Raises an HTTPError for bad responses (4xx or 5xx)
    jira_data = response.json()

    if 'issues' in jira_data:
        print("Fetched Jira Issues:")
        for issue in jira_data['issues']:
            print(f"  - Key: {issue['key']}, Summary: {issue['fields']['summary']}")
    else:
        print("No issues found or unexpected response format.")

except requests.exceptions.RequestException as e:
    print(f"An error occurred during the request: {e}")
except json.JSONDecodeError:
    print("Failed to decode JSON response.")

1 answer

0 votes
Tuncay Senturk _Snapbytes_
Community Champion
August 15, 2025

Hi @rAJ 

It seems to be a network / TLS / proxy issue rather than an HTTP 401 or 403.

From the same host, you can simply run a curl command to https://jira.vtxxxxx.net/rest/api/2/serverInfo , if this also resets, it’s network/TLS/proxy, not your code.

rAJ August 15, 2025

hi @Tuncay Senturk _Snapbytes_ I was able to run curl command successfully, and also able to fetch Jira data using curl subprocess from Python script as well, But unable to fetch using requests library. I need it to work for prod env

Tuncay Senturk _Snapbytes_
Community Champion
August 15, 2025

Thanks—that narrows it down a lot. 

If curl works but requests not, it can be CA trust issue or proxy problem. You may need to import ca-bundle cert file for a hardened requests session.

 

rAJ August 15, 2025

@Tuncay Senturk _Snapbytes_ Tried CA bundle and proxy as well, below is script and now  i see ERROR:root:HTTPSConnectionPool(host='XXX.XXX.net', port=443): Max retries exceeded with url: /rest/api/2/issue/XXX-213207 (Caused by ProxyError('Unable to connect to proxy', OSError('Tunnel connection failed: 503 Service Unavailable'))

if I comment proxy , error is DEBUG:urllib3.connectionpool:Starting new HTTPS connection (6): xxx.xxx.net:443 ERROR:root:Connection reset (10054) — often WAF/TLS/UA/cipher mismatch: HTTPSConnectionPool(host='xx.xx.net', port=443): Max retries exceeded with url: /rest/api/2/issue/xx-213207 (Caused by ProtocolError('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))

 

import urllib.parse
import os, ssl, logging, requests
from requests.adapters import HTTPAdapter, DEFAULT_POOLBLOCK
from urllib3.util.retry import Retry
import urllib3
from urllib3.util.ssl_ import create_urllib3_context
import json
import urllib.parse


# Correct username with domain
proxy_username = "XXXX\\XXXX"

# Password with special characters
proxy_password = "XXXX

# Correctly encode the username and password
encoded_username = urllib.parse.quote_plus(proxy_username) # This will handle the backslash
encoded_password = urllib.parse.quote_plus(proxy_password)


# --- Verify Library Versions (for debugging) ---
print(f"Requests version: {requests.__version__}")
print(f"Urllib3 version: {urllib3.__version__}")
print(f"SSL module path: {ssl.__file__}")
print(f"HTTP_PROXY env var: {os.getenv('HTTP_PROXY')}")
print(f"HTTPS_PROXY env var: {os.getenv('HTTPS_PROXY')}")
print(f"http_proxy env var: {os.getenv('http_proxy')}")
print(f"https_proxy env var: {os.getenv('https_proxy')}")

# --- Configuration ---
JIRA_BASE = "https://xx.xxl.net"
URL = f"{JIRA_BASE}/rest/api/2/issue/XXXX-213207" 
TOKEN = "XXXXXX"

# Point this to your new file
CA_BUNDLE_PATH = r"C:\certs\ca-bundle.pem"

# No payload needed for GET request, so python_payload and payload_json_string are removed

# Make requests verbose for debugging (should already be set)
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)

# --- Custom Adapter for TLS 1.2 and Retries ---
class CustomTLSAdapter(HTTPAdapter):
    def __init__(self, **kwargs):
        self.ssl_context_override = kwargs.pop('ssl_context', None)
        super().__init__(**kwargs)

    def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs):
        ctx = create_urllib3_context()
        ctx.minimum_version = ssl.TLSVersion.TLSv1_2

        # Load custom CA bundle if provided
        if CA_BUNDLE_PATH:
            try:
                ctx.load_verify_locations(cafile=CA_BUNDLE_PATH)
                logging.info(f"Loaded custom CA bundle from: {CA_BUNDLE_PATH}")
            except Exception as e:
                logging.error(f"Failed to load CA bundle from {CA_BUNDLE_PATH}: {e}")
                pass

        pool_kwargs['ssl_context'] = ctx
        super().init_poolmanager(connections, maxsize, block, **pool_kwargs)

# --- TLS Adapter Configuration (using the custom adapter) ---
def tls_adapter_with_min_tls_1_2():
    retry_strategy = Retry(
        total=5,
        connect=5,
        read=5,
        backoff_factor=0.5,
        status_forcelist=[429, 500, 502, 503, 504],
        backoff_jitter=0.1
    )
    return CustomTLSAdapter(
        max_retries=retry_strategy,
        pool_connections=4, pool_maxsize=4,
    )

# --- Session Initialization ---
s = requests.Session()
s.mount("https://", tls_adapter_with_min_tls_1_2())


# Match curl-style headers from your command
s.headers.update({
    "Authorization": f"Bearer {TOKEN}",
   
    "Content-Type": "application/json", # Still acceptable for GET if server handles it, or remove
    "Accept": "application/json",
    #"User-Agent": "curl/7.88.1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Connection": "close"
})


# --- Proxy Configuration ---
s.proxies.update({"https": f"http://{encoded_username}:{encoded_password}@XXX.XXX.com:80"})


# --- Making the Request (using GET for Jira details) ---
try:
    logging.info(f"Attempting GET request to {URL}")
    # Use the session 's' for the GET request
    # Removed 'data' parameter as it's not needed for GET
    r = s.get(URL, timeout=(10, 600), verify=True, allow_redirects=False) # Keep verify=False for now

    print(f"Request Status: {r.status_code}")
    print("Response Body (first 400 chars):", r.text[:400])
    r.raise_for_status() # Raise HTTPError for bad status codes (4xx or 5xx)
   
    # If successful, parse and print JSON response
    logging.info("Successfully received response from JIRA API.")
    try:
        print("Parsed JSON Response:", r.json())
    except json.JSONDecodeError:
        logging.warning("Response was not valid JSON.")
        print("Raw Response Content:", r.text)

except requests.exceptions.SSLError as e:
    logging.error(f"TLS/Cert error — likely need corporate CA bundle: {e}")
except requests.exceptions.ProxyError as e:
    logging.error(f"Proxy error — align with how curl reaches Prod: {e}")
except requests.exceptions.ConnectionError as e:
    logging.error(f"Connection reset (10054) — often WAF/TLS/UA/cipher mismatch: {e}")
except requests.exceptions.RequestException as e:
    logging.error(f"An unexpected request error occurred: {e}")
except Exception as e:
    logging.error(f"An unexpected general error occurred: {e}")
Tuncay Senturk _Snapbytes_
Community Champion
August 15, 2025

Your logs tell something. Sorry if I'm misleading you though

With proxy, 503 service unavailable - the proxy is rejecting CONNECT to your Jira. Mostly, it needs enterprise authentication (Kerberos/NTLM) or the Jira host isn’t allowed.

Without proxy. 10054 Connection reset - something (WAF or load balancer) is closing the connection for Python's request (even though curl works)

So, I'd suggest bypassaing the corporate proxy for Jira and match crul's ca/tls settings (if that works :) )

Otherwise, if you must use the proxy, you may use Kerberos/NTLM auth instead of basic credentials.

rAJ August 15, 2025

final summary of what the most recent logs confirm about both options:

 

1. Bypass Proxy and Match curl's Settings

 

This option was successful in bypassing the proxy. The logs showed the proxy environment variables were None. However, the script failed with a ConnectionResetError,

 

2. Use Kerberos/NTLM Authentication

 

This option was never successfully tested in trials. causing the script to fail with a 503 Service Unavailable error before the Kerberos authentication could even be initiated. most recent logs show the correct behavior for bypassing the proxy, but not for Kerberos, as we never reached the point where that code would be executed successfully.

Suggest an answer

Log in or Sign up to answer