Retiring old mobile app versions
Goal: builds of your iOS app older than 4.2.0 call a field your API no longer serves well. Refuse them at the edge with a clear error, so the app can tell the user to update, and leave every newer build and every other client alone.
The rules for client profiles are on telling your clients apart; this recipe applies them to one case, a mobile app that already ships.
The running example is shop-api and its iOS app, built with Apollo iOS, which sends
apollographql-client-name: ios-app and apollographql-client-version on every request. The
build pipeline appends a build number to the version: build 118 of 4.2.0 sends 4.2.0-118.
What you need
Section titled “What you need”- A deployed service and its
gpilot.toml. - An app that sends its name and version on every request. Apollo iOS sends the two
apollographql-client-*headers; any other client can be set up to send them, orgp-client-nameandgp-client-version.
1. Declare the app and its floor
Section titled “1. Declare the app and its floor”[[client.profile]]name = "ios-app"when = "header:apollographql-client-name == 'ios-app'"version = "split(header:apollographql-client-version, '-', 0)"min_version = "4.2.0"version takes the part before the first -. That is not cosmetic: versions are compared as
semantic versions, where 4.2.0-118 is a prerelease of 4.2.0 and sorts below it. Without the
split, every build of 4.2.0 itself would be refused. With it, 4.2.0-118 is read as 4.2.0 and
clears the floor.
A request from the app below 4.2.0 is refused with 403 and CLIENT_VERSION_UNSUPPORTED, without
reaching your origin, with the required version in the message. A request that matches
no profile (your web app, a partner, a script) is not affected, because client.unknown stays at
"allow".
2. Deploy and try an old build
Section titled “2. Deploy and try an old build”curl -sS "https://$GRAPHPILOT_HOST/graphql" \ -H 'content-type: application/json' \ -H 'apollographql-client-name: ios-app' \ -H 'apollographql-client-version: 4.1.3-97' \ -d '{"query":"query ProductPage { product(id: \"p01\") { id name price } }"}'The answer is 403, and the body’s extensions.code is CLIENT_VERSION_UNSUPPORTED. Send
4.2.0-118 instead and the request is served as before.
Handle the code in the app: when a response carries CLIENT_VERSION_UNSUPPORTED, show the update
prompt instead of a generic error. The code is stable; the message text is for people.
3. Read it in Insights
Section titled “3. Read it in Insights”Before you raise the floor, look at who it would refuse. In Insights, each
request’s Client tab shows Recognized client ios-app and the version the profile read,
so 4.2.0 for build 4.2.0-118. From Jet (Starter), the request list can show client name and
version as columns, which is the quickest way to see which versions still call.
After the deployment, the refused requests are in the list with status 403. The Auth
failures preset (under Errors) lists requests answered 401 or 403.
Pitfalls
Section titled “Pitfalls”- Three-part versions only. A version the profile cannot parse as a semantic version is
refused, like one below the floor. An app that reports
4.2is refused; make it report4.2.0. Amin_versionthat does not parse refuses nothing and logsCLIENT_MIN_VERSION_UNREADABLE. - Never write the floor with
>=.header:apollographql-client-version >= '4.2.0'compares numbers, and a version is not one. Usemin_version, orsemver_gtein an expression; see versions. - A
+build suffix needs nosplit.4.2.0+118is build metadata, and4.2.0+118is the same release as4.2.0. Only a-suffix reads as a prerelease. - Raising the floor does not empty the cache. It refuses requests; the answers newer builds read stay cached as before.