What happens
run_services_validators in src/mock_vws/_services_validators/__init__.py calls around thirty validators in sequence on every request, regardless of which endpoint was hit. Each validator then works out for itself whether it applies, by re-reading the body or by re-checking the path and method.
Two consequences.
The same work is repeated. For a single POST /targets, the request body is json.loadsed by validate_keys, the metadata validators, the active flag validator, the name validators, the width validator and each of the image validators. The image is base64-decoded and opened with PIL separately by validate_image_integrity, validate_image_format, validate_image_color_space and validate_image_size — four decodes and four Image.open calls of the same bytes, each with its own if not request_body: return and if image is None: return preamble.
The route table is rebuilt per request. validate_keys constructs eleven _Route objects on every call, at src/mock_vws/_services_validators/key_validators.py:57 onwards, then linearly matches the request against them.
Why it matters
Correctness first: Vuforia's error precedence — which of several simultaneous problems with a request is the one reported — is currently encoded implicitly as the order of the calls in this one function. That ordering is the product of a lot of verification against real Vuforia, and nothing states it or protects it. Reordering two lines silently changes which result code the mock returns, and only a test which sends a request that is wrong in two ways at once would notice.
Second, this is a mock whose whole point is to be faster than the real service, and the redundant decoding is on the hot path of the most commonly exercised endpoint.
Suggested resolution
Build the validator chains once, per route, at module level, so that each endpoint declares the validators which apply to it in the order they apply. That makes the precedence explicit and reviewable, removes the per-validator applicability guards, and stops validators which cannot apply from running at all.
Parsing the body once and passing the parsed form down the chain would remove the repeated decoding, but is a separate step and need not be done at the same time.
The route table in key_validators.py is a third copy of information already held in _requests_mock_server/mock_web_services_api.py and _flask_server/vws.py; a shared table would fall out of #3370.
What happens
run_services_validatorsinsrc/mock_vws/_services_validators/__init__.pycalls around thirty validators in sequence on every request, regardless of which endpoint was hit. Each validator then works out for itself whether it applies, by re-reading the body or by re-checking the path and method.Two consequences.
The same work is repeated. For a single
POST /targets, the request body isjson.loadsed byvalidate_keys, the metadata validators, the active flag validator, the name validators, the width validator and each of the image validators. The image is base64-decoded and opened with PIL separately byvalidate_image_integrity,validate_image_format,validate_image_color_spaceandvalidate_image_size— four decodes and fourImage.opencalls of the same bytes, each with its ownif not request_body: returnandif image is None: returnpreamble.The route table is rebuilt per request.
validate_keysconstructs eleven_Routeobjects on every call, atsrc/mock_vws/_services_validators/key_validators.py:57onwards, then linearly matches the request against them.Why it matters
Correctness first: Vuforia's error precedence — which of several simultaneous problems with a request is the one reported — is currently encoded implicitly as the order of the calls in this one function. That ordering is the product of a lot of verification against real Vuforia, and nothing states it or protects it. Reordering two lines silently changes which result code the mock returns, and only a test which sends a request that is wrong in two ways at once would notice.
Second, this is a mock whose whole point is to be faster than the real service, and the redundant decoding is on the hot path of the most commonly exercised endpoint.
Suggested resolution
Build the validator chains once, per route, at module level, so that each endpoint declares the validators which apply to it in the order they apply. That makes the precedence explicit and reviewable, removes the per-validator applicability guards, and stops validators which cannot apply from running at all.
Parsing the body once and passing the parsed form down the chain would remove the repeated decoding, but is a separate step and need not be done at the same time.
The route table in
key_validators.pyis a third copy of information already held in_requests_mock_server/mock_web_services_api.pyand_flask_server/vws.py; a shared table would fall out of #3370.