Skip to content

Commit

Permalink
Retry getting the crumb in case of post failure.
Browse files Browse the repository at this point in the history
  • Loading branch information
lhupfeldt committed Feb 22, 2019
1 parent 80e7392 commit 6574db4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 22 deletions.
4 changes: 4 additions & 0 deletions api_base.py
Expand Up @@ -27,6 +27,10 @@ class AuthError(Exception):
pass


class ClientError(AuthError):
pass


class UnknownJobException(Exception):
def __init__(self, job_url, api_ex=None):
super(UnknownJobException, self).__init__("Job not found: " + job_url + (", " + repr(api_ex) if api_ex is not None else ""))
Expand Down
43 changes: 24 additions & 19 deletions jenkins_api.py
Expand Up @@ -6,7 +6,7 @@
import sys, os, tempfile, time
from collections import OrderedDict

from .api_base import BuildResult, Progress, AuthError, UnknownJobException, ApiInvocationMixin
from .api_base import BuildResult, Progress, AuthError, ClientError, UnknownJobException, ApiInvocationMixin
from .speed import Speed
from .rest_api_wrapper import ResourceNotFound, RequestsRestApi
from .jenkins_cli_protocol import CliProtocol
Expand Down Expand Up @@ -71,18 +71,14 @@ def __init__(self, direct_uri, job_prefix_filter=None, username=None, password=N
self.csrf = csrf
self._crumb = None

def _get_crumb(self):
def _get_fresh_crumb(self):
"""Get the CSRF crumb to be put on subsequent requests"""
if self._crumb:
try:
crumb = self.rest_api.get_content('/crumbIssuer/api/xml', xpath='concat(//crumbRequestField,":",//crumb)').split(b':')
self._crumb = {crumb[0]: crumb[1]}
return self._crumb

if self.csrf:
try:
crumb = self.rest_api.get_content('/crumbIssuer/api/xml', xpath='concat(//crumbRequestField,":",//crumb)').split(b':')
self._crumb = {crumb[0]: crumb[1]}
return self._crumb
except ResourceNotFound:
self.csrf = False
except ResourceNotFound:
self.csrf = False

def get_content(self, url, **params):
return self.rest_api.get_content(url, **params)
Expand All @@ -99,14 +95,23 @@ def get_json(self, url="", **params):
time.sleep(0.1)

def post(self, url, payload=None, headers=None, **params):
crumb = self._get_crumb()
if crumb:
if headers:
headers = headers.copy()
headers.update(crumb)
else:
headers = crumb
return self.rest_api.post(url, payload, headers, **params)
for crumb_attempt in (0, 1):
if self._crumb:
if headers:
headers = headers.copy()
headers.update(self._crumb)
else:
headers = self._crumb

try:
return self.rest_api.post(url, payload, headers, **params)
except ClientError as ex:
if crumb_attempt:
raise
if self.csrf:
if self._crumb:
print("INFO: getting new crumb:", ex)
self._get_fresh_crumb()

def headers(self):
return self.rest_api.headers()
Expand Down
8 changes: 5 additions & 3 deletions rest_api_wrapper.py
@@ -1,6 +1,6 @@
import sys

from .api_base import AuthError
from .api_base import AuthError, ClientError


major_version = sys.version_info.major
Expand Down Expand Up @@ -49,11 +49,13 @@ def _check_response(response, good_responses=(200,)):
except Exception as ex:
if response.status_code == 404:
raise ResourceNotFound(ex)
if response.status_code in (401, 403):
if response.status_code == 401:
raise AuthError(ex)
if response.status_code == 403:
raise ClientError(ex)
raise

# TODO: This is dubious, maybe we shoud raise here instead.
# TODO: This is dubious, maybe we should raise here instead.
return response

def _get(self, url, params):
Expand Down

0 comments on commit 6574db4

Please sign in to comment.