Skip to content

fix(router): resolve deep links in both URL forms - #1092

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/deep-links-in-the-index-php-url-form
Sep 1, 2026
Merged

fix(router): resolve deep links in both URL forms#1092
rubenvdlinde merged 1 commit into
developmentfrom
fix/deep-links-in-the-index-php-url-form

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Nextcloud serves an app under both /apps/<id>/... and /index.php/apps/<id>/..., but generateUrl() returns only the form the instance is configured for. Used as the vue-router base, a visitor arriving on the other form has a pathname the router cannot strip its base from: no route matches, the catch-all takes over, and they land on the dashboard with no error.

I measured this on learniq, which had the identical base, against a live instance and all 282 of its routes:

URL lands on
/apps/learniq/courses Courses
/index.php/apps/learniq/courses dashboard

Every route behaved the same way. This is not one broken page, it is every deep link in that URL form, and it fails silently, which is what makes it expensive: a bookmark, an emailed link or an integration that hardcodes /index.php just quietly shows the wrong screen.

routerBase() derives the base from the pathname, so it always matches the URL the visitor actually arrived on. This is not a new idea in the fleet: openregister, opencatalogi, stackiq, larpinq, zaakafhandelapp, pipelinq and keepiq already do exactly this. This app is one of ten that were still on the naive form.

The change is the same in every one of them: add routerBase() and use it as the history base. generateUrl() stays as the fallback for the case where the pathname does not match at all.

Honest scope note. I verified the behaviour and the fix end to end on learniq (23 e2e cases passed, against 1 passed and 23 failed before). Here I have verified that the file parses and that the router base is the only thing that changed. The E2E job runs on the push to development rather than on this PR, so the suite verdict for this app arrives after merge.

Nextcloud serves an app under both /apps/decidiq/... and
/index.php/apps/decidiq/..., but generateUrl() returns only the form the
instance is configured for. Used as the vue-router base, that means a visitor
arriving on the other form has a pathname the router cannot strip its base
from. No route matches, the catch-all takes over, and they land on the
dashboard with no error at all.

Measured live on learniq, which had the identical base, across all 282 of its
routes: /apps/learniq/courses resolved to Courses, and
/index.php/apps/learniq/courses resolved to the dashboard. Not one broken page,
every deep link in that URL form.

routerBase() derives the base from the pathname, so it always matches the URL
the visitor actually arrived on. openregister, opencatalogi, stackiq, larpinq,
zaakafhandelapp, pipelinq and keepiq already do exactly this.
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/decidiq @ e932086

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-nav-ceiling
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 537/537
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development
Hydra gates

Quality workflow — 2026-09-01 17:05 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 1267cd8 into development Sep 1, 2026
49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant