Skip to content

Add AdminUri to eSCL server advertisement and capabilities - #895

Merged
cyanfish merged 3 commits into
cyanfish:masterfrom
zomars:feature/escl-adminurl
Sep 7, 2026
Merged

cyanfish merged 3 commits into
cyanfish:masterfrom
zomars:feature/escl-adminurl

Conversation

@zomars

@zomars zomars commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

The eSCL spec requires an adminurl key in the _uscan/_uscans TXT records, and some clients depend on it. In particular, SwiftESCL-based apps (e.g. OpenAirScan on iOS) silently drop any discovery result whose TXT record has no adminurl (see LeoKlaus/SwiftESCL#10), so scanners shared by NAPS2 never show up there at all.

The server also always emitted an empty <scan:AdminURI> element in ScannerCapabilities. This PR fills both in with a real, functional URL.

Changes

  • MdnsAdvertiser: unconditionally emit adminurl=<protocol>://naps2-{uuid}.local.:{port}/eSCL/admin, in the same format as the existing representation (icon) key
  • EsclApiController: fill <scan:AdminURI> with the same URL instead of hardcoding "", and add a GET /eSCL/admin endpoint so the advertised URL actually resolves — it serves a basic status page (model, manufacturer, serial, UUID, active job count)
  • ClientServerTests: assert the advertised AdminURI and that the admin page responds

Testing

  • NAPS2.Escl.Tests pass (net10.0); NAPS2.Escl.Server builds clean for net8/netstandard2.0, NAPS2.Sdk/NAPS2.Lib build clean
  • TXT emission verified on a real network with a locally patched macOS build sharing an EPSON L3210: the _uscans TXT record carries adminurl (checked from another Mac via dns-sd -L), macOS Image Capture is unaffected, and OpenAirScan on iOS can then discover the shared scanner

Comment thread NAPS2.Escl.Server/MdnsAdvertiser.cs Resolved
Instead of letting the caller configure an admin URI, derive it from the
device like the icon URI, and add a /eSCL/admin endpoint with a basic
status page so the advertised URL actually resolves.
@zomars

zomars commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Updated in 1caa8cc per the review:

  • Dropped the caller-supplied AdminUri entirely — ScanServer.RegisterDevice, ScanServerDevice, SharedDevice and SharedDeviceManager are back to their original state
  • adminurl is now always advertised, derived from the device in the same format as the icon URL: http(s)://naps2-{uuid}.local.:{port}/eSCL/admin
  • <scan:AdminURI> in ScannerCapabilities uses that same URL
  • Added GET /eSCL/admin, which serves a basic status page (model, manufacturer, serial, UUID, active job count) so the advertised URL resolves to something useful
  • ClientServerTests now asserts the advertised URL and that the admin page responds

NAPS2.Escl.Tests pass, and NAPS2.Escl.Server / NAPS2.Sdk / NAPS2.Lib build clean. Ready for another look whenever you have time.

@cyanfish
cyanfish merged commit 6556235 into cyanfish:master Sep 7, 2026
5 of 6 checks passed
@zomars

zomars commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

CI on 1caa8cc failed to build on Windows — HttpClient in the test I added needs an explicit using System.Net.Http; for the net462 target (net10 gets it from implicit usings, which is why it passed on macOS/Ubuntu). Fixed in 6a7e6ac; I reproduced and verified it locally with dotnet build NAPS2.Escl.Tests -p:TargetFrameworks=net462 -f net462.

The follow-up run builds fine on all three OSes, but the Windows job then hit the 15-minute job timeout: NAPS2.Lib.Tests started at 06:34:34 and produced no further output before cancellation (it takes ~8s on master). That looks unrelated to this PR — the only changed files are in NAPS2.Escl.Server and NAPS2.Escl.Tests, NAPS2.Lib.Tests mocks ISharedDeviceManager rather than starting a server, and NAPS2.Escl.Tests isn't in the test scope at all. Could you re-run the Windows job when you get a chance? I don't have permission to re-run it myself.

@cyanfish

cyanfish commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Already re-ran and merged, CI passes on master.

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.

2 participants