Skip to content

defaultLink VS language specific resolution? #28

@Echsecutor

Description

@Echsecutor

Reproduction

Prepare a digital Link with a linkset like e.g.

curl -s -H "accept: application/linkset+json" https://id.gs1.de/01/04047111050247 | jq
{
  "linkset": [
    {
      "anchor": "https://id.gs1.de/01/04047111050247",
      "https://ref.gs1.org/voc/pip": [
        {
          "href": "https://gs1.de",
          "title": "test",
          "type": "text/html",
          "hreflang": [
            "en"
          ]
        },
        {
          "href": "https://www.eecc.de",
          "title": "test",
          "type": "text/html",
          "hreflang": [
            "de"
          ]
        }
      ],
      "https://gs1.org/voc/defaultLink": [
        {
          "href": "https://www.eecc.de",
          "title": "test",
          "type": "text/html",
          "hreflang": [
            "de"
          ]
        }
      ]
    }
  ]
}

The following resolutions are all correct, as far as I can see

curl -vs 'https://id.gs1.de/01/04047111050247' -H 'accept-language: de' 2>&1 | grep location
< location: https://www.eecc.de

 curl -vs 'https://id.gs1.de/01/04047111050247?linkType=gs1:pip' -H 'accept-language: en' 2>&1 | grep location
< location: https://gs1.de

curl -vs 'https://id.gs1.de/01/04047111050247?linkType=gs1:pip' 2>&1 | grep location
< location: https://www.eecc.de

curl -vs 'https://id.gs1.de/01/04047111050247' 2>&1 | grep location
< location: https://www.eecc.de

curl -vs 'https://id.gs1.de/01/04047111050247' -H 'accept-language: en' 2>&1 | grep location
< location: https://www.eecc.de

 curl -vs 'https://id.gs1.de/01/04047111050247?linkType=gs1:pip' -H 'accept-language: en' -H 'accept: text/html' 2>&1 | grep location
< location: https://gs1.de

curl -vs 'https://id.gs1.de/01/04047111050247?linkType=gs1:pip' -H 'accept-language: de' -H 'accept: text/html' 2>&1 | grep location
< location: https://www.eecc.de

Actual behavior

Image

the test backend response is

{
    "test": "getAllHeaders",
    "testVal": "https:\/\/id.gs1.de\/01\/04047111050247",
    "result": {
        "uri": "https:\/\/id.gs1.de\/01\/04047111050247",
        "httpCode": 302,
        "httpMsg": "server: nginx\r\ndate: Wed, 20 May 2026 20:42:20 GMT\r\ncontent-length: 0\r\nlocation: https:\/\/www.eecc.de\r\nvary: Origin\r\nvary: Access-Control-Request-Method\r\nvary: Access-Control-Request-Headers\r\naccess-control-allow-origin: https:\/\/ref.gs1.org\/test-suites\/resolver\/\r\naccess-control-allow-credentials: true\r\nlink: <https:\/\/id.gs1.de\/01\/04047111050247>; rel=\"linkset\"; type=\"application\/linkset+json\"\r\naccess-control-allow-methods: GET, HEAD, OPTIONS\r\nx-content-type-options: nosniff\r\nx-xss-protection: 0\r\ncache-control: no-cache, no-store, max-age=0, must-revalidate\r\npragma: no-cache\r\nexpires: 0\r\nstrict-transport-security: max-age=15724800; includeSubDomains\r\nx-frame-options: DENY",
        "requestURI": "\/test-suites\/resolver\/1.0.0\/tester.php?test=getAllHeaders&testVal=https%3A%2F%2Fid.gs1.de%2F01%2F04047111050247&linkType=gs1%3Apip&mediaType=text%2Fhtml&lang=en",
        "Requesting_User_Agent": "Mozilla\/5.0 (X11; Linux x86_64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/148.0.0.0 Safari\/537.36",
        "Requesting_Accept_Header": "*\/*",
        "Requesting_Accept_Language": "en-US,en;q=0.9,de;q=0.8",
        "0": "HTTP\/2 302 ",
        "server": "nginx",
        "date": "Wed, 20 May 2026 20:42:20 GMT",
        "content-length": "0",
        "location": "https:\/\/www.eecc.de",
        "vary": "Access-Control-Request-Headers",
        "access-control-allow-origin": "https:\/\/ref.gs1.org\/test-suites\/resolver\/",
        "access-control-allow-credentials": "true",
        "link": "<https:\/\/id.gs1.de\/01\/04047111050247>; rel=\"linkset\"; type=\"application\/linkset+json\"",
        "access-control-allow-methods": "GET, HEAD, OPTIONS",
        "x-content-type-options": "nosniff",
        "x-xss-protection": "0",
        "cache-control": "no-cache, no-store, max-age=0, must-revalidate",
        "pragma": "no-cache",
        "expires": "0",
        "strict-transport-security": "max-age=15724800; includeSubDomains",
        "x-frame-options": "DENY",
        "1": "Origin: https:\/\/ref.gs1.org\/test-suites\/resolver\/",
        "2": "Accept: text\/html",
        "3": "Accept-Language: en"
    }
}

Expected

curl -vs 'https://id.gs1.de/01/04047111050247?linkType=gs1:pip' -H 'accept-language: en' -H 'accept: text/html' 2>&1 | grep location
< location: https://gs1.de

curl -vs 'https://id.gs1.de/01/04047111050247&linkType=gs1:pip&mediaType=text/html&lang=en' 2>&1 | grep location
< location: https://gs1.de

curl -vs 'https://id.gs1.de/01/04047111050247&linkType=gs1:pip&mediaType=text/html&lang=en' -H 'accept-language: en-US,en;q=0.9,de;q=0.8' -H 'accept: */*' 2>&1 | grep location
< location: https://gs1.de

is resolved correctly. The error message is unclear. What exactly did not work according to the test expectation?

According to GS1-Conformant Resolver Standard - Resolving GS1 identification keys to one or more sources of related information and/or services - Release 1.2.0, Ratified, Jan 2026, see
https://ref.gs1.org/standards/resolver/1.2.0/GS1_Conformant_Resolver_standard_i1.2-r-2026-01-19

Section 2.6.3 Matching request parameters with link attributes

  1. If no link type is set in the query the choice is only between links with the gs1:defaultLink and
    gs1:defaultLinkMulti link types.

  2. If there are no links typed as gs1:defaultLinkMulti, redirect to the gs1:defaultLink.

This means, in the above Example

curl -vs 'https://id.gs1.de/01/04047111050247' -H 'accept-language: en' 2>&1 | grep location
< location: https://www.eecc.de

is correctly resolved according to the standard, though maybe unexpected for the user.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions