Repository navigation
Rank Evidence prefixes in the order evidence.md lists them, and send one name once whatever its letter case - #75
Merged
Merged
Conversation
…hen other prefixes alphabetically, ignoring letter case
This was referenced Nov 11, 2026
Contributor
Author
|
Closing and reopening at once to start the checks again, because the runs queued during GitHub's Actions outage this evening never started. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rank Evidence prefixes in the order evidence.md lists them, and send one name once whatever its letter case
Problem
When one name is under more than one prefix, the Cloud Request Engine
should send it once, with the value of the prefix that ranks highest. The
engine ranks
server,fiftyoneandlocationalphabetically, where thespecification lists them in another order, and it sends one name given in
two letter cases twice.
getSelectedEvidencesorts the Evidence that is not query, header or cookieEvidence by the whole key, in reverse and in its exact letter case, with
Object.keys(selectedEvidence).sort().reverse()atline 677 of cloudRequestEngine.js on rc 5228a9f9,
and
getContentadds that group first, atline 544,
so the key added last wins. Four things follow.
fiftyonewins overlocation, which wins overserver, and any otherprefix that sorts before them, such as
apple, wins over all three.Location.bwins overfiftyone.b, because a capital letter sortsbefore a small one.
hasKeyPrefixatline 702
compares the prefix in its exact letter case, so
Header.dis not headerEvidence and
cookie.dwins over it, andQuery.nloses toheader.n.addQueryDatalooks for a name already added withhasOwn(queryData, suffix)atline 622,
in its exact letter case, so
header.User-Agentandquery.user-agentgo to the cloud as two fields,
User-Agentanduser-agent, rather thanone field with the query value.
What the specification says
evidence.md at d72eb074.
The Processing section of
cloud-request-engine.md at d72eb074
applies that order to the request.
So the order is query, header, cookie, server, fiftyone, location, then
every other prefix alphabetically, and the prefix's letter case does not
change its place. Because keys are case-insensitive,
header.User-Agentand
query.user-agenthold the same field once the prefix is removed, sothe order decides which one value is sent.
What the other languages do
ComparePrefixesatlines 234 to 273 of pipeline/core/evidence.go on rc be6088ae,
comparing the prefixes in lower case.
51degrees-java#107,
51degrees-python#99
and 51degrees-php#70
make the same changes in those languages, ranking the prefixes and
sending one name once whatever its letter case.
What changed
pipeline/fiftyone.pipeline.cloudrequestengine/cloudRequestEngine.js, andthe description of
getContentintypes/cloudRequestEngine.d.ts. Linenumbers in items 1 to 6 are at 9c3a115, the head before the two review
fixes, and item 7 is at the head, 616351a.
getSelectedEvidencesorts the other Evidence with a newcompareOtherKeys, lowest precedence first, atlines 689 to 695.
compareOtherKeysatlines 801 to 845
ranks the prefix by its place in
OTHER_PREFIX_PRECEDENCE,['server', 'fiftyone', 'location'], puts any other prefix after themordered by the prefix itself, and breaks a tie between two keys with the
same prefix on the whole key.
keyPrefixgives the text before the firstdot, or the whole key where there is none, in lower case, which is how
addQueryDataalready splits a key.hasKeyPrefixatline 715
compares the prefix ignoring letter case. A key still needs the dot to
have the prefix, as before.
line 639,
compares the prefix in lower case, so
Query.nreplacesheader.nwithout a warning, as
query.ndoes.addQueryDataatlines 623 to 666
looks for a name already added ignoring letter case. A later, higher
precedence value replaces it, name and value, so the name is sent once
and spelled as the winning key spells it. The conflict warning matches
keys and names ignoring letter case as well. This is what
51degrees-dotnet#136,
51degrees-java#107
and 51degrees-python#99
do.
getContent's description and the comment over the first group say theorder. The description no longer also says "'query.' evidence should
take precedence over all other evidence", which repeated its first
sentence, and keeps the sentence about the conflict warning
(lines 527 to 545 at 616351a).
types/cloudRequestEngine.d.tscarries the same description, so it nowmatches the source.
addQueryDatafinds a name already added through aMapfrom the namein lower case to the spelling added
(lines 611 to 682 at 616351a).
The map is built from
queryDataonce when the function starts, atline 614, read once for each value at line 640, and set for each value
added at line 680, on both the new name path and the replace path. It
was a walk of every name already added for each value, so the work
grew with the square of the number of values. .NET gets the same single
read from its case-insensitive dictionary. A
Mapis used ratherthan a plain object, so a name such as
constructorcannot find amember of the object prototype.
Nothing else calls
getSelectedEvidence,addQueryData,hasKeyPrefixor the new functions.
getDatacallsgetContentatline 425
on every data request, so the order applies to every request. No
signature changed.
Checks made
getSelectedEvidencehas one exit for each group,and only the other group's sort changed.
compareOtherKeysreturns on adifferent rank, then on a different prefix, then on the whole key, and
returns 0 only for two keys equal in lower case.
hasKeyPrefixhas oneexit.
addQueryDatahas three paths for each key, as before. A reservedname is skipped. A name not yet added, in any letter case, is added under
its own spelling. A name already added in any letter case is replaced,
name and value, after a warning where the key is not query Evidence and
another key holds the same name.
keyPrefixtakes the whole key as the prefix, asaddQueryDatatakes it as both prefix and name, andhasKeyPrefixstillneeds the dot, so such a key stays in the other group, as before.
Tests
tests/cloudEvidencePrecedence.test.js, six tests.each prefix wins over every later onegives one name for each of the 28pairs of query, header, cookie, server, fiftyone, location, apple and
zebra, the higher prefix added first so the order added cannot decide it,
and checks the higher prefix's value is sent for every pair.
a prefix ranks the same in any letter casechecksfiftyone.bwinsover
Location.b,SERVER.coverLocation.candHeader.dovercookie.d.a query key in any letter case replaces another without a warningchecks
Query.nwins overheader.nand logs nothing.other prefixes rank by the prefix alonechecksab.nwins overab-c.n, although the keyab-c.nsorts first because a hyphen sortsbefore a dot.
one name in two letter cases is sent once, from the higher prefixchecks
header.User-Agentandquery.user-agentgo as one field,user-agent, with the query value, andserver.X-Thingandfiftyone.x-thingas one field,X-Thing, with the server value.the names already added are read once, not once for each value(lines 140 to 169 at 616351a)
calls
addQueryDatawith forty header values and one query value thatreplaces one of them in other letters, on a
queryDatawhoseownKeystrap counts every read of its names, and checks the names were read at
most once, that forty names were added and that the query value won.
Commits.
rcmerge, takingrcat 1d7e024(#61,
#71 and
#33), with no
conflicts. Read and store evidence keys without regard to letter case #71 makes the Evidence store ignore letter case and keep a
key's first spelling, which leaves every key these tests add distinct.
rcmerge, takingrcat 1cab8de(#74,
#70 and
#72), with no
conflicts. Send the cloud every Evidence value apart from the reserved names #72 makes
getContentread the Evidence no element acceptsas well, a few lines above the lines this draft changes.
rcmerge, takingrcat f76d8b0(#62,
#55 and
#45), with no
conflicts. Accept no evidence in usage sharing, and share the web request it finds #45 changes
cloudRequestEngine.jsaway from the lines thisdraft changes.
Maplookup, and the repeated sentence cut fromgetContent's description.Runs, each with a temporary workflow on Node 22 running
cloudEvidencePrecedence.test.js,cloudRequestEngine.test.js,cloudRequestEngineCredentials.test.jsand ESLint on the changed files.run 43031388695
on 7164737. All four new tests fail. The pairs test lists
n-server-fiftyone sent fiftyone,n-server-location sent location,n-server-apple sent apple,n-fiftyone-apple sent appleandn-location-apple sent apple, the letter case test getslocationforfiftyone, the query test getsheaderforquery, and the prefix testgets
ab-cforab. The other two files pass, 36 tests.run 43031387763
on 0697802. The four new tests pass, the same 36 pass, and ESLint passes.
run 43055821037
on d321fc1. The new test fails, receiving
User-Agent,X-Thing,user-agentandx-thingwhere it expectsX-Thinganduser-agent.The other four pass, and the other two files pass, 37 tests.
run 43055821144
on 9c3a115. All five pass, the same 37 pass, and ESLint passes.
run 43056427316
on 9c3a115, the head before the review fixes, passed. Configure, the 6 build and test jobs (Ubuntu,
Ubuntu ARM and Windows, Node 22 and 24) and Complete succeeded, and the
2 Compare Performance jobs were skipped, as the full build turns them
off. Every one of the 7
Setting 'PullRequestSha'lines reads 9c3a115,and Configure printed "Left out 2 macOS entries". Earlier full builds
were on earlier heads,
run 43032151883
on 0697802, cancelled when
rctook Never send resource, license, licence or values from Evidence to the cloud #61 and Read and store evidence keys without regard to letter case #71,run 43034401232
on d323e23 and
run 43042464614
on 5a3c552, both of which passed.
Runs for the two review fixes, each a temporary workflow on Ubuntu with
Node 22 running
cloudEvidencePrecedence.test.js,cloudAllEvidence.test.jsandcloudRequestEngine.test.js, in a workflowfile named for its own branch. ESLint runs in the full build.
run 43111959654
on branch
tmp/node-75-red4, the test commit e5f9b9e. The new test failswith "Expected: <= 1, Received: 41", one read for each of the 41 values,
and the other 37 of 38 pass.
run 43111979404
on branch
tmp/node-75-green4, the head 616351a. All 38 pass.tmp/node-75-red3andtmp/node-75-green3,and a full build on
tmp/pr-matrix-75-f, were created during the GitHubActions outage of 11 November and never started, so they are not cited.
run 43111863074,
passed. Configure, the 6 build and test jobs (Ubuntu, Ubuntu ARM and
Windows, Node 22 and 24) and Complete succeeded, and the 2 Compare
Performance jobs were skipped, as the full build turns them off. Every
one of the 7
Setting 'PullRequestSha'lines reads616351a, and Configure printed "Left out
2 macOS entries". Each build and test job ran
eslint . --ext .js, gave1,227 passed and 2 skipped in the unit tests and 132 passed and 4 skipped
in the integration tests, and ran
cloudEvidencePrecedence.test.js.What remains
macOS was left out of this draft's full build under the 9 November decision.
The rc head is built with macOS before it merges into main.