Skip to content

Fix UTF-8 routing with wide Char and FPC Radix callbacks - #556

Open
Moonbot-Tech wants to merge 5 commits into
HashLoad:masterfrom
Moonbot-Tech:fix/utf8-routing-wide-char
Open

Fix UTF-8 routing with wide Char and FPC Radix callbacks#556
Moonbot-Tech wants to merge 5 commits into
HashLoad:masterfrom
Moonbot-Tech:fix/utf8-routing-wide-char

Conversation

@Moonbot-Tech

Copy link
Copy Markdown

Problem

Horse parses request paths into UTF-8 byte slices, but its registered literal routes were still compared as character strings. With a wide Char (SizeOf(Char) > 1), byte length and character length diverged and non-ASCII routes such as /ação/:id could not match /ação/42.

The optional Radix router had the same byte/character mismatch. Its FPC executor also stored the object method DoPreValidation as a plain procedure callback, which violates the callback ABI: the route could match, but invoking the callback corrupted execution.

Fix

  • encode populated request paths as UTF-8 whenever Char is wide;
  • cache UTF-8 bytes for literal RouterTree and Radix nodes and compare byte slices directly;
  • decode Radix byte spans through TEncoding.UTF8;
  • bridge the FPC Radix pre-validation method through a regular procedure instead of casting a method pointer;
  • add focused regressions for UTF-8 literal/parameter routes, byte-span decoding, and FPC Radix callback execution.

ASCII and single-byte Char paths keep their existing fast path.

Validation

The focused runtime matrix passes with:

  • Delphi 12.2 Win64;
  • MoonCompiler 1.0.0 on Win64 and Linux x86-64;
  • stock FPC 3.2.2 on Linux x86-64.

The matrix covers ASCII routes, UTF-8 literal and parameter routes, Radix static-route byte storage, byte-span decoding, and callback execution.

@regyssilveira

Copy link
Copy Markdown
Contributor

Obrigado pela correção e pela matriz de validação. A direção de trabalhar com bytes UTF-8 nos dois roteadores é coerente, e o bridge FPC elimina o cast de método incompatível. Antes da aprovação, porém, precisamos cobrir alguns pontos que os testes atuais — baseados principalmente em THorseRequest.Populate — não exercitam:

  1. Adicione testes em Tests.Integration.AdvancedRouting.pas, executados com THorseRouterTree e THorseRadixRouter, fazendo chamadas HTTP reais.
  2. Inclua uma URI enviada na forma percent-encoded, por exemplo /a%C3%A7%C3%A3o/42, além de qualquer caso com UTF-8 bruto. Clientes HTTP normalmente codificam caracteres não ASCII, portanto precisamos validar o valor que realmente atravessa o provider.
  3. Cubra segmentos UTF-8 em:
    • rota literal;
    • parâmetro;
    • middleware com path;
    • grupo/prefixo;
    • precedência entre rota literal e rota parametrizada.
  4. Adicione um caso para CaseSensitive := False, como rota /AÇÃO e requisição /ação, ou documente explicitamente que a comparação byte a byte faz folding apenas de ASCII e não oferece case folding Unicode.
  5. O bridge FPC usa GCurrentExecutor como threadvar. Em TRadixExecutor.Run, salve o valor anterior e restaure-o no finally, para que uma execução de roteamento aninhada no mesmo thread não deixe o callback externo apontando para o executor interno.
  6. Normalize as terminações de linha introduzidas em tests/src/Console.dpr.

Depois desses ajustes, poderemos validar novamente a compatibilidade Delphi/FPC e os dois roteadores para aprovação.

@Moonbot-Tech

Copy link
Copy Markdown
Author

Obrigado pela revisão detalhada. Apliquei todos os pontos:

  • adicionei testes HTTP reais em Tests.Integration.AdvancedRouting.pas para THorseRouterTree e THorseRadixRouter;
  • cobri rota literal, parâmetro, middleware com path, prefixo de grupo, precedência da rota literal e URI percent-encoded;
  • adicionei regressões para %2F dentro de um único parâmetro e para decodificação exata uma vez (%252F%2F);
  • TRadixExecutor.Run agora salva e restaura GCurrentExecutor e GCurrentNext, inclusive em roteamento aninhado por OnRequest e PreValidation;
  • documentei que CaseSensitive=False aplica folding apenas a ASCII;
  • normalizei as terminações de linha introduzidas em Console.dpr.

Validei os dois roteadores com chamadas HTTP reais no Delphi 12.2 e os caminhos Tree, Radix e nested routing no MoonCompiler/FPC.

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