Mustermann Documentation

repository·main·Indexed 20 days ago

https://github.com/sinatra/mustermann

A powerful string matching library for Ruby providing various pattern types for parsing and generating strings, commonly used in web frameworks for routing. It supports multiple pattern types (e.g., :sinatra, :shell, :regexp), composite patterns via binary operators, and parameter extraction. Additional features include Mustermann::Set for routing tables, Mustermann::Mapper for string transformation, and a visualizer for inspecting pattern ASTs and syntax highlighting.

Tokens
27.1K
Snippets
96
Records
125
Agent score
71%

What's inside Mustermann

  1. Visualize Mustermann patterns

    main

    The mustermann-visualizer gem allows you to inspect the internal structure of Mustermann patterns. It supports:

    • Syntax highlighting: Generates highlighted versions of pattern objects using either HTML/CSS or ANSI color codes.
    • AST Tree visualization: Converts AST-based patterns into a tree structure represented with ANSI color codes.
  2. Overview of Mustermann pattern types

    main

    Mustermann supports various pattern types for string matching, ranging from exact identity matching to complex URI templates.

    Core Types (included in mustermann):

    • identity: Exact string matching with no parameter parsing.
    • regexp: Uses regular expressions (Oniguruma/Onigmo). Does not support expanding or generating templates.
    • sinatra: The default type. A superset of simple and a common subset of template and others.
    • rails: Compatible with Ruby on Rails, Hanami, and others.

    Extension Types (included in mustermann-contrib):

    • cake: CakePHP compatible.
    • express: Express.js and Pillar.js compatible.
    • flask: Flask and Werkzeug compatible.
    • pyramid: Pyramid and Pylons compatible.
    • shell: Unix Shell (bash, zsh) compatible. Does not support expanding or generating templates.
    • simple: Sinatra 1.x compatible. Does not support expanding or generating templates.
    • uri-template: RFC 6570 compliant. Can be generated from most other types.
  3. Use the `sinatra` pattern type

    main

    The sinatra pattern type is the default pattern type in Mustermann. If you do not specify a type option when creating a new pattern, Mustermann uses the sinatra implementation. It is designed for path-like matching and supports named captures, splats, and optional groups.

    Supported options for sinatra patterns:

    • capture
    • except
    • greedy
    • space_matches_plus
    • uri_decode
    • ignore_unknown_options
    require 'mustermann'
    
    # Uses the default 'sinatra' pattern type
    pattern = Mustermann.new('/:name')
    pattern === '/alice'      # => true
    pattern.params('/alice')  # => { "name" => "alice" }
  4. How Mustermann optimizes performance

    main

    Mustermann is designed to perform as much work as possible during object creation to ensure fast matching and expansion at runtime.

    Key Optimization Strategies

    • Pattern Caching: Mustermann.new may return the same instance for identical arguments. Do not rely on object identity.
    • AST-based Patterns: Patterns like sinatra, rails, hybrid, template, and flask use bounded character classes and negative look-ahead to avoid backtracking in the Oniguruma engine.
    • Trie-based Routing (Mustermann::Set): For large routing tables, Mustermann::Set uses a trie (prefix tree) to walk the input character by character. This is significantly faster than a linear scan. The switch to a trie occurs at a use_trie: threshold (default 50).
  5. Use Mustermann as a Regexp look-alike

    main

    Mustermann pattern objects implement methods from Ruby's Regexp class, including match, =~, ===, names, and named_captures. This allows them to be used in place of regular expressions in many contexts, such as case statements or Regexp.union.

    require 'mustermann'
    
    pattern = Mustermann.new('/:page')
    pattern.match('/')     # => nil
    pattern.match('/home') # => #<Mustermann::Match>
    pattern =~ '/home'    # => 0
    pattern === '/home'    # => true
    
    # Patterns (except :identity and :shell) convert to Regexp automatically
    union = Regexp.union(pattern, /^$/)
    union =~ "/foo" # => 0
  6. How Mustermann::Mapper works

    main

    A Mustermann::Mapper transforms input strings into output strings based on defined mappings. Each mapping pairs an input pattern (for parameter extraction) with one or more output patterns (for expansion). Mappings are applied in the order they are defined. You can also pass additional parameters during conversion to override or supplement captured values.

    require 'mustermann/mapper'
    
    # Initialize with a mapping hash
    mapper = Mustermann::Mapper.new("/:page(.:format)?" => ["/:page/view.:format", "/:page/view.html"])
    
    # Transform strings
    mapper['/foo']     # => "/foo/view.html"
    mapper['/foo.xml'] # => "/foo/view.xml"
    
    # Supplement parameters during conversion
    mapper = Mustermann::Mapper.new("/:example" => "(/:prefix)?/:example.html")
    mapper['/foo', prefix: 'en']  # => "/en/foo.html"
  7. Understand which pattern types use AST optimizations

    main

    Regex optimizations (like atomic groups and look-aheads) only apply to pattern types that compile from an Abstract Syntax Tree (AST).

    Supported AST types:

    • sinatra (default)
    • rails
    • hybrid
    • template
    • flask

    Non-AST types (no optimizations):

    • identity
    • shell
    • simple
    • regexp
  8. Combine patterns using Binary Operators

    main

    You can combine multiple patterns into a single composite pattern using binary operators. The resulting object is a fully functional pattern that supports methods like params and to_proc.

    • | (OR): Matches if at least one input pattern matches.
    • & (AND): Matches if all input patterns match.
    • ^ (XOR): Matches if exactly one input pattern matches.
    require 'mustermann'
    
    first  = Mustermann.new('/foo/:input')
    second = Mustermann.new('/:input/bar')
    
    first | second === "/foo/foo" # => true
    first | second === "/foo/bar" # => true
    
    first & second === "/foo/foo" # => false
    first & second === "/foo/bar" # => true
    
    first ^ second === "/foo/foo" # => true
    first ^ second === "/foo/bar" # => false
  9. Ensure thread safety when using Mustermann::Set

    main

    Matching and expansion on a Mustermann::Set are thread-safe once the set has been built. The internal trie and cache are read-only after construction.

    Important: Adding patterns is not thread-safe. You should populate your Mustermann::Set (or a Router built on top of it) during application startup before handling requests.

  10. Optimize pattern creation with Mustermann.new

    main

    Mustermann is designed to perform as much work as possible during object creation to keep matching and expansion fast at request time. To avoid redundant compilation, Mustermann.new may return the same instance for the same arguments if that instance has not been garbage collected.

    Warning: Do not rely on object identity (e.g., pattern1.equal?(pattern2)). The guarantee is that arguments producing equal patterns may reuse an existing object, but it is not strictly guaranteed.

    Mustermann.new("/:name").equal?(Mustermann.new("/:name")) # may be true
  11. How URI Template variable matching works

    main

    URI templates can be used in reverse to match a fully formed URI and extract named variables.

    Limitations: Variable matching works best when template expressions are delimited by the start/end of the URI or by characters that cannot be part of the expansion (like reserved characters surrounding a simple string expression). For complex variable matching, regular expressions may be more suitable.

    Example of complex matching: Using the explode modifier (*) allows capturing segments into an array.

    require 'mustermann'
    
    pattern = Mustermann.new("{/segments*}/{page}{.ext,cmpr:2}", type: :template)
    pattern.params("/a/b/c.tar.gz") 
    # => {"segments"=>["a","b"], "page"=>"c", "ext"=>"tar", "cmpr"=>"gz"}
  12. Use the Identity Pattern for fixed string matching

    main

    The Identity Pattern is the simplest pattern type in mustermann. It does not support special syntax or placeholders and is used to match exact, fixed strings. It is useful for simple equality checks or as a base for implementing custom pattern types.

    When using :identity, the pattern matches exactly the provided string or its URI-escaped version. It does not capture any parameters.

    require 'mustermann'
    
    pattern = Mustermann.new('/foo/bar', type: :identity)
    pattern === '/foo/bar' # => true
    pattern === '/foo/baz' # => false
    pattern.params('/foo/bar') # => {}