Commit 5033a5e2 authored by Jerome Touvier's avatar Jerome Touvier

Merge branch 'update' into 'master'

fix error message

See merge request !6
parents 00af2d3f 41140634
Pipeline #48605 passed with stage
in 2 minutes and 3 seconds
......@@ -32,7 +32,7 @@ docker run --rm --name ws-resp -e RUNMODE=production ws-sacpz-resp start_resp:a
## RUNMODE builtin values
* `production`
* `production`
* `test`
* `local`
* other values map to :
......@@ -2,6 +2,7 @@ FDSN_CLIENT = "RESIF"
USER_AGENT_RESP = "resifws-resp"
USER_AGENT_SACPZ = "resifws-sacpz"
STATIONXML_CONVERTER = "java -jar stationxml-seed-converter-2.1.0.jar"
VERSION = "1.0.0"
# limitations
......@@ -15,9 +16,10 @@ STRING_FALSE = ("no", "false", "f", "n", "0")
class Error:
UNKNOWN_PARAM = "Unknown query parameter: "
MULTI_PARAM = " Multiple entries for query parameter: "
MULTI_PARAM = "Multiple entries for query parameter: "
VALID_PARAM = "Valid parameters."
START_LATER = "The starttime cannot be later than the endtime: "
TOO_LONG_DURATION = "Too many days requested (greater than "
UNSPECIFIED = "Error processing your request."
NODATA = "Your query doesn't match any available data."
TIMEOUT = f"Your query exceeds timeout ({TIMEOUT} seconds)."
......
......@@ -34,8 +34,8 @@ def get_inventory(params, user_agent):
def get_sacpz(params):
""" Builds the ws-sacpz response.
params: parameters """
"""Builds the ws-sacpz response.
params: parameters"""
try:
tic = time.time()
......@@ -69,8 +69,8 @@ def get_sacpz(params):
def get_resp(params):
""" Builds the ws-resp response.
params: parameters """
"""Builds the ws-resp response.
params: parameters"""
try:
tic = time.time()
......
VERSION = "1.0.0"
class Parameters:
def __init__(self):
self.network = None
......@@ -18,6 +15,14 @@ class Parameters:
self.time = None
self.nodata = "204"
self.constraints = {
"alias": [
("network", "net"),
("station", "sta"),
("location", "loc"),
("channel", "cha"),
("starttime", "start"),
("endtime", "end"),
],
"booleans": [],
"floats": [],
"not_none": [],
......@@ -25,13 +30,3 @@ class Parameters:
def todict(self):
return self.__dict__
ALIAS = [
("network", "net"),
("station", "sta"),
("location", "loc"),
("channel", "cha"),
("starttime", "start"),
("endtime", "end"),
]
......@@ -5,21 +5,20 @@ from multiprocessing import Process, Queue
from flask import request
from apps.constants import ALIAS
from apps.constants import Parameters
from apps.globals import Error
from apps.globals import HTTP
from apps.globals import TIMEOUT
from apps.output import get_resp
from apps.output import get_sacpz
from apps.parameters import Parameters
from apps.utils import check_base_parameters
from apps.utils import check_request
from apps.utils import currentutcday
from apps.utils import error_param
from apps.utils import error_request
from apps.utils import is_valid_starttime
from apps.utils import is_valid_datetime
from apps.utils import is_valid_nodata
from apps.utils import is_valid_starttime
def check_parameters(params):
......@@ -68,22 +67,9 @@ def checks_get():
params = Parameters().todict()
# check if the parameters are unknown
(p, result) = check_request(params, ALIAS)
(p, result) = check_request(params)
if result["code"] != 200:
return (p, result)
# determine selected features
params["request"] = tuple(request.args)
for key, val in params.items():
params[key] = request.args.get(key, val)
for key, alias in ALIAS:
if params[key] is None:
params[key] = request.args.get(alias, params[alias])
else:
params[alias] = params[key]
return check_parameters(params)
......
......@@ -4,34 +4,32 @@ import time
from difflib import SequenceMatcher
from datetime import datetime, timedelta
from flask import Response, request
from flask import request, Response
from apps.constants import VERSION
from apps.globals import Error
from apps.globals import HTTP
from apps.globals import NODATA_CODE
from apps.globals import STRING_FALSE
from apps.globals import STRING_TRUE
from apps.globals import VERSION
def is_valid_integer(dimension, mini=0, maxi=sys.maxsize):
# by default valid for positive integers
try:
dimension = int(dimension)
if mini <= dimension <= maxi:
return True
except Exception:
return False
return bool(mini <= dimension <= maxi)
def is_valid_float(dimension, mini=sys.float_info.epsilon, maxi=sys.float_info.max):
# by default valid for strictly positive floats
try:
dimension = float(dimension)
if mini <= dimension <= maxi:
return True
except Exception:
return False
return bool(mini <= dimension <= maxi)
def is_valid_datetime(date):
......@@ -95,7 +93,7 @@ def error_request(msg="", details="", code=500):
message_error = f"""Error {code}: {msg}\n
{details}\n
Request:
{request.url}\n
{request.full_path}\n
Request Submitted:
{request_date}\n
Service version:
......@@ -113,30 +111,38 @@ def error_500(dmesg):
return error_request(msg=HTTP._500_, details=dmesg, code=500)
# check request
def check_request(params, alias):
keys = list(params.keys())
def check_request(params):
# preliminary parameter checks
for key, val in request.args.items():
if key not in keys:
ratios = [SequenceMatcher(None, key, p).ratio() for p in keys]
guess = max([(v, keys[ind]) for ind, v in enumerate(ratios)])
# stops at the first unknown parameter meet:
if key not in params:
ratios = ((SequenceMatcher(None, key, p).ratio(), p) for p in params)
guess = max(ratios)
hint = ". Did you mean " + guess[1] + " ?" if guess[0] > 0.7 else ""
return error_param(keys, Error.UNKNOWN_PARAM + key + hint)
return error_param(params, Error.UNKNOWN_PARAM + key + hint)
# find nonword chars except :
# "," for lists "*?" for wildcards and ".:-" for date
if re.search(r"[^a-zA-Z0-9_,*?.:-]", val):
return error_param(keys, Error.CHAR + key)
return error_param(params, Error.CHAR + key)
for key in keys:
for key, val in params.items():
if len(request.args.getlist(key)) > 1:
return error_param(keys, Error.MULTI_PARAM + key)
for key in alias:
if len([v for v in key if v in request.args]) > 1:
return error_param(keys, Error.MULTI_PARAM + " and is shorthand ".join(key))
return error_param(params, Error.MULTI_PARAM + key)
params[key] = request.args.get(key, val)
for key, alias in params["constraints"]["alias"]:
if key in request.args and alias in request.args:
return error_param(
params, f"{Error.MULTI_PARAM}{key} (and is shorthand {alias})"
)
if params[key] is None or params[key] == "false":
params[key] = request.args.get(alias, params[alias])
else:
params[alias] = params[key]
return (keys, {"msg": HTTP._200_, "details": Error.VALID_PARAM, "code": 200})
return (params, {"msg": HTTP._200_, "details": Error.VALID_PARAM, "code": 200})
def check_base_parameters(params, max_days=None):
......
......@@ -43,7 +43,7 @@ The RESIF RESP web service returns response information of the selected instrume
## Date and time formats
YYYY-MM-DDThh:mm:ss[.ssssss] ex. 1997-01-31T12:04:32.123
YYYY-MM-DD ex. 1997-01-31 ( a time of 00:00:00 is assumed)
YYYY-MM-DD ex. 1997-01-31 (a time of 00:00:00 is assumed)
where:
......
......@@ -43,7 +43,7 @@ The RESIF SACPZ web service returns the poles and zeros of the selected instrume
## Date and time formats
YYYY-MM-DDThh:mm:ss[.ssssss] ex. 1997-01-31T12:04:32.123
YYYY-MM-DD ex. 1997-01-31 ( a time of 00:00:00 is assumed)
YYYY-MM-DD ex. 1997-01-31 (a time of 00:00:00 is assumed)
where:
......
......@@ -3,7 +3,7 @@ import os
from flask import Flask, make_response, render_template
from apps.constants import VERSION
from apps.globals import VERSION
from apps.root import output
app = Flask(__name__)
......
......@@ -3,7 +3,7 @@ import os
from flask import Flask, make_response, render_template
from apps.constants import VERSION
from apps.globals import VERSION
from apps.root import output
app = Flask(__name__)
......
......@@ -2,7 +2,7 @@ body {
margin: auto;
padding-right: 1em;
padding-left: 1em;
max-width: 75em;
max-width: 75em;
border-left: 1px solid black;
border-right: 1px solid black;
color: black;
......
......@@ -95,7 +95,7 @@ time-option :: [time=&lt;date&gt;] OR [starttime=&lt;date&gt;] &amp; [
</ul>
<h2 id="date-and-time-formats">Date and time formats</h2>
<pre><code>YYYY-MM-DDThh:mm:ss[.ssssss] ex. 1997-01-31T12:04:32.123
YYYY-MM-DD ex. 1997-01-31 ( a time of 00:00:00 is assumed)
YYYY-MM-DD ex. 1997-01-31 (a time of 00:00:00 is assumed)
where:
......
......@@ -23,7 +23,7 @@
<representation mediaType="application/xml"/>
</response>
</method>
</resource>
</resource>
<resource path="query">
<method href="#query"/>
</resource>
......
......@@ -95,7 +95,7 @@ time-option :: [time=&lt;date&gt;] OR [starttime=&lt;date&gt;] &amp; [
</ul>
<h2 id="date-and-time-formats">Date and time formats</h2>
<pre><code>YYYY-MM-DDThh:mm:ss[.ssssss] ex. 1997-01-31T12:04:32.123
YYYY-MM-DD ex. 1997-01-31 ( a time of 00:00:00 is assumed)
YYYY-MM-DD ex. 1997-01-31 (a time of 00:00:00 is assumed)
where:
......
......@@ -23,7 +23,7 @@
<representation mediaType="application/xml"/>
</response>
</method>
</resource>
</resource>
<resource path="query">
<method href="#query"/>
</resource>
......
......@@ -7,6 +7,7 @@ sys.path.append("../")
from apps.globals import Error
from apps.globals import HTTP
from apps.parameters import Parameters
from apps.root import check_parameters
from apps.utils import error_param
from apps.utils import is_valid_integer
......@@ -101,10 +102,7 @@ class MyTest(unittest.TestCase):
self.assertFalse(is_valid_bool_string("oui"))
def test_parameters(self):
self.maxDiff = None
# ?network=FR&channel=HHZ&timetime=2018-02-12T03:08:02&endtime=2018-02-12T03:10:00&station=CIEL
p1 = {}
p1 = Parameters().todict()
p1["network"] = "FR"
p1["station"] = "CIEL"
p1["location"] = "00"
......@@ -112,12 +110,6 @@ class MyTest(unittest.TestCase):
p1["start"] = None
p1["end"] = None
p1["time"] = "2018-02-12T04:08:02"
p1["nodata"] = "204"
p1["constraints"] = {
"booleans": [],
"floats": [],
"not_none": [],
}
valid_param = {"msg": HTTP._200_, "details": Error.VALID_PARAM, "code": 200}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment