fix(harfanglab): retry transient API errors (1.7.3)
HarfangLab answers a 500 now and then on a call that passes when sent again. Each script's request() now retries up to three times (1, 2, 4 s): GET on 429/500/502/503/504, writes only on 429/502/503 so an isolation, a kill or a job is never sent twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,16 +1,35 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
def csv(v):
|
def csv(v):
|
||||||
return [x.strip() for x in str(v or "").split(",") if x.strip()]
|
return [x.strip() for x in str(v or "").split(",") if x.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def csv(v):
|
def csv(v):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
FIELD_TYPES = {
|
FIELD_TYPES = {
|
||||||
"name": 0, "path": 1, "username": 3, "commandline": 4,
|
"name": 0, "path": 1, "username": 3, "commandline": 4,
|
||||||
@@ -8,12 +8,31 @@ FIELD_TYPES = {
|
|||||||
OPERATORS = {"eq": 0, "not_eq": 1, "contains": 2, "not_contains": 3}
|
OPERATORS = {"eq": 0, "not_eq": 1, "contains": 2, "not_contains": 3}
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,13 +1,32 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
SEVERITIES = ["low", "medium", "high", "critical"]
|
SEVERITIES = ["low", "medium", "high", "critical"]
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers):
|
def request(method, url, headers):
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, headers=headers, method=method)
|
req = urllib.request.Request(url, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=90) as resp:
|
with urllib.request.urlopen(req, timeout=90) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,13 +1,32 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
SEVERITIES = ["low", "medium", "high", "critical"]
|
SEVERITIES = ["low", "medium", "high", "critical"]
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers):
|
def request(method, url, headers):
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, headers=headers, method=method)
|
req = urllib.request.Request(url, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=90) as resp:
|
with urllib.request.urlopen(req, timeout=90) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
FIELD_TYPES = {
|
FIELD_TYPES = {
|
||||||
"name": 0, "path": 1, "username": 3, "commandline": 4,
|
"name": 0, "path": 1, "username": 3, "commandline": 4,
|
||||||
@@ -8,12 +8,31 @@ FIELD_TYPES = {
|
|||||||
OPERATORS = {"eq": 0, "not_eq": 1, "contains": 2, "not_contains": 3}
|
OPERATORS = {"eq": 0, "not_eq": 1, "contains": 2, "not_contains": 3}
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,16 +1,35 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
def csv(v):
|
def csv(v):
|
||||||
return [x.strip() for x in str(v or "").split(",") if x.strip()]
|
return [x.strip() for x in str(v or "").split(",") if x.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,14 +1,33 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
PAGE = 500
|
PAGE = 500
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
@@ -1,16 +1,35 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
def csv(v):
|
def csv(v):
|
||||||
return [x.strip() for x in str(v or "").split(",") if x.strip()]
|
return [x.strip() for x in str(v or "").split(",") if x.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import json, os, sys, urllib.request, urllib.parse, urllib.error
|
import json, os, sys, time, urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
|
|
||||||
|
RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
|
def retryable(method, status):
|
||||||
|
# HarfangLab answers a 500 now and then on a call that passes when sent again.
|
||||||
|
# A read is safe to resend; a write only on an answer that says the action was
|
||||||
|
# not run (rate limit, gateway down), so an isolation or a job is never sent twice.
|
||||||
|
if status in (429, 502, 503):
|
||||||
|
return True
|
||||||
|
return method == "GET" and status in (500, 504)
|
||||||
|
|
||||||
|
|
||||||
def request(method, url, headers, body=None):
|
def request(method, url, headers, body=None):
|
||||||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||||||
|
for attempt in range(RETRIES + 1):
|
||||||
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
||||||
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||||
raw = resp.read()
|
raw = resp.read()
|
||||||
return json.loads(raw) if raw else {}
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if attempt == RETRIES or not retryable(method, e.code):
|
||||||
|
raise
|
||||||
|
e.close()
|
||||||
|
time.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
|
||||||
def qs(params):
|
def qs(params):
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user