uCalc API Version: 5.7.0-preview.1 Released: 7/30/2026

Warning

uCalc API Preview Release Notice:This preview documentation describes the intended behavior of the API. It is not fully accurate or complete.The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.Use of the preview version in your production code is not recommended.

Project: Developing a Basic Web Server Route Matcher

Product: 

Class: 

A step-by-step guide to building a simple web server route matcher using the uCalc Transformer's declarative patterns.

Remarks

💡 Project: Developing a Basic Web Server Route Matcher

A core task for any web server is routing: mapping an incoming URL path like /users/123 to the correct application logic (a "handler") and extracting any dynamic parameters (like the user ID 123). This project will guide you through building a simple but powerful route matcher using the declarative patterns of the uCalc Transformer.

The Goal: A Simple Routing DSL

We'll create a Domain-Specific Language (DSL) for defining routes that is common in modern web frameworks like Express.js or Flask. Placeholders for dynamic segments are enclosed in curly braces.

  • /users/{id}
  • /products/{category}/{id}

The Strategy: Transformer Rules

The core idea is to treat routing as a text transformation problem. We'll take an incoming URL path and transform it into a string that represents the action to take.

  • Input: /users/42
  • Rule: FromTo("/users/{id}", "Handler: UserProfile, id: {id}")
  • Output: "Handler: UserProfile, id: 42"

The application can then easily parse this output string to call the correct function with the extracted parameters.


Step 1: Setting Up the Transformer

First, we need a Transformer instance. This will be our router. We will define all our route patterns on this object.

csharp
using (var router = new uCalc.Transformer()) {
// ... rules will go here ...
}

Step 2: Defining the Routes

Each route is a FromTo rule. The pattern matches the URL structure, and the replacement string defines the output.

  • Static Route: A simple, fixed path.router.FromTo("/about", "Handler: AboutPage");

  • Dynamic Route: A path with one or more variable placeholders.router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}");

Step 3: Precedence Matters (LIFO)

What happens if you have two similar routes, like /users/new and /users/{id}? A request for /users/new could technically match both patterns. To resolve this, the Transformer uses a LIFO (Last-In, First-Out) precedence rule: the most recently defined rule is checked first.

Therefore, you must define your most specific rules last to give them higher priority.

## Step 4: Matching an Incoming URLTo process a request, simply call [Transform()](/reference/classes/ucalc.transformer/transform/) on the incoming URL string. If the result is different from the original URL, a match was found. If it's unchanged, it's a "404 Not Found."## ⚖️ Why uCalc? (Comparative Analysis)*   **vs. Regex**: Building a router with regular expressions is common but can be complex. Each route requires a carefully crafted regex, and managing their precedence can be tricky. uCalc's patterns are more readable (`/users/{id}` vs. `/users/(\w+)`), and the LIFO precedence is a clear, built-in system.*   **vs. Manual String Splitting**: Splitting the URL by `/` is brittle and doesn't handle complex patterns or constraints well.uCalc provides a declarative, token-aware, and extensible way to define a routing system that is both powerful and easy to maintain.

Examples

Defining one static and one dynamic route, then matching a URL against each.

ID: 1435

				
					using uCalcSoftware;

var uc = new uCalc();
using (var router = new uCalc.Transformer()) {
   // Define routes
   router.FromTo("/home", "Handler: HomePage");
   router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}");

   // Test routes
   Console.WriteLine($"Matching '/home': {router.Transform("/home")}");
   Console.WriteLine($"Matching '/users/42': {router.Transform("/users/42")}");
}
				
			
Matching '/home': Handler: HomePage
Matching '/users/42': Handler: UserProfile, id: 42
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   {
      uCalc::Transformer router;
      router.Owned(); // Causes router to be released when it goes out of scope
      // Define routes
      router.FromTo("/home", "Handler: HomePage");
      router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}");

      // Test routes
      cout << "Matching '/home': " << router.Transform("/home") << endl;
      cout << "Matching '/users/42': " << router.Transform("/users/42") << endl;
   }
}
				
			
Matching '/home': Handler: HomePage
Matching '/users/42': Handler: UserProfile, id: 42
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Using router As New uCalc.Transformer()
         '// Define routes
         router.FromTo("/home", "Handler: HomePage")
         router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}")
         
         '// Test routes
         Console.WriteLine($"Matching '/home': {router.Transform("/home")}")
         Console.WriteLine($"Matching '/users/42': {router.Transform("/users/42")}")
      End Using
   End Sub
End Module
				
			
Matching '/home': Handler: HomePage
Matching '/users/42': Handler: UserProfile, id: 42
A practical example of a router with multiple rules, demonstrating LIFO precedence and handling of a '404 Not Found' case.

ID: 1436

				
					using uCalcSoftware;

var uc = new uCalc();
using (var router = new uCalc.Transformer()) {
   // --- Define Routes ---
   // General rules first (lower precedence)
   router.FromTo("/products/{category}/{id}", "Handler: ProductDetail, category: {category}, id: {id}");
   router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}");

   // Specific rule last (higher precedence)
   router.FromTo("/users/new", "Handler: CreateUserPage");

   // --- Simulate Requests ---
   string[] urls = {"/users/123", "/users/new", "/products/electronics/567", "/contact"};

   foreach(var url in urls) {
      var originalUrl = url;
      var result = router.Transform(url);

      if (result.Text == originalUrl) {
         Console.WriteLine($"URL: {originalUrl} -> 404 Not Found");
      } else {
         Console.WriteLine($"URL: {originalUrl} -> {result}");
      }
   }
}
				
			
URL: /users/123 -> Handler: UserProfile, id: 123
URL: /users/new -> Handler: CreateUserPage
URL: /products/electronics/567 -> Handler: ProductDetail, category: electronics, id: 567
URL: /contact -> 404 Not Found
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   {
      uCalc::Transformer router;
      router.Owned(); // Causes router to be released when it goes out of scope
      // --- Define Routes ---
      // General rules first (lower precedence)
      router.FromTo("/products/{category}/{id}", "Handler: ProductDetail, category: {category}, id: {id}");
      router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}");

      // Specific rule last (higher precedence)
      router.FromTo("/users/new", "Handler: CreateUserPage");

      // --- Simulate Requests ---
      vector<string> urls = {"/users/123", "/users/new", "/products/electronics/567", "/contact"};

      for(auto url : urls) {
         auto originalUrl = url;
         auto result = router.Transform(url);

         if (result.Text() == originalUrl) {
            cout << "URL: " << originalUrl << " -> 404 Not Found" << endl;
         } else {
            cout << "URL: " << originalUrl << " -> " << result << endl;
         }
      }
   }
}
				
			
URL: /users/123 -> Handler: UserProfile, id: 123
URL: /users/new -> Handler: CreateUserPage
URL: /products/electronics/567 -> Handler: ProductDetail, category: electronics, id: 567
URL: /contact -> 404 Not Found
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Using router As New uCalc.Transformer()
         '// --- Define Routes ---
         '// General rules first (lower precedence)
         router.FromTo("/products/{category}/{id}", "Handler: ProductDetail, category: {category}, id: {id}")
         router.FromTo("/users/{id}", "Handler: UserProfile, id: {id}")
         
         '// Specific rule last (higher precedence)
         router.FromTo("/users/new", "Handler: CreateUserPage")
         
         '// --- Simulate Requests ---
         Dim urls() As String = {"/users/123", "/users/new", "/products/electronics/567", "/contact"}
         
         For Each url In urls
            Dim originalUrl = url
            Dim result = router.Transform(url)
            
            If result.Text = originalUrl Then
               Console.WriteLine($"URL: {originalUrl} -> 404 Not Found")
            Else
               Console.WriteLine($"URL: {originalUrl} -> {result}")
            End If
         Next
      End Using
   End Sub
End Module
				
			
URL: /users/123 -> Handler: UserProfile, id: 123
URL: /users/new -> Handler: CreateUserPage
URL: /products/electronics/567 -> Handler: ProductDetail, category: electronics, id: 567
URL: /contact -> 404 Not Found