class
Analyzer::Fsharp::Giraffe
- Analyzer::Fsharp::Giraffe
- Analyzer
- Reference
- Object
Overview
Giraffe is a functional web framework on top of ASP.NET Core. Routes
are HttpHandler values composed via the >=> Kleisli operator and
collected with choose [...]. Common combinators surfaced here:
route "/path"— exact path matchrouteCi "/path"— case-insensitive variantroutex "regex"— regex variant (path is reported verbatim)routef "/users/%i/%s"— typed parameterssubRoute "/prefix" handlerand friends — mount nested routes
HTTP method filters (GET, POST, etc.) appearing on the same
textual line as a route are honored; lines without an explicit
method default to a fallback set.
Defined in:
analyzer/analyzers/fsharp/giraffe.crConstant Summary
-
FALLBACK_METHODS =
["GET", "POST", "PUT", "DELETE", "PATCH"] -
HTTP_METHODS =
["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] of ::String -
METHOD_WORD_PATTERNS =
HTTP_METHODS.map do |m| {m, /\b#{m}\b/} end -
NO_UTF_CHECK =
Regex::MatchOptions::NO_UTF_CHECK -
PCRE2 (Crystal's regex backend) re-validates UTF-8 encoding of the subject on every
match_at_byte_indexcall by default -- an O(remaining-length) pass, since our scan loop calls it at every character position that O(n²) rather than O(n).content(andcleaned, built from it) is always sourced throughAnalyzer#read_file_content, which reads withinvalid: :skip, so both are guaranteed structurally valid UTF-8 already -- the same invariantString#scanin the standard library relies on when it sets this same option after its first match. Confirmed empirically: a 4x-larger synthetic file went from ~16.7s to ~0.014s once this was applied to the combinator matchers below (~1000x). -
ROUTE_BIND_RE =
/\GrouteBind(?:\s*<[^>\n]*>)?\s+"([^"]+)"/ -
ROUTE_COMBINATOR =
/(?:route(?:Bind|Ci[fx]?|xp?|f)?|subRoute(?:Ci|f)?)\b/ -
Crystal recompiles an interpolated regex literal on every evaluation (a full PCRE2 JIT compile). Both the stop-line matcher and the per-verb window probes interpolate only fixed patterns, so precompile them once at load time.
-
ROUTE_CONST_RE =
/\G(?:routeCix|routexp|routeCi|routex|route)\s+([A-Za-z_][A-Za-z0-9_']*(?:\.[A-Za-z_][A-Za-z0-9_']*)*)/ -
ROUTE_HANDLER_STOP_RE =
/\A(?:(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\b.*\b#{ROUTE_COMBINATOR}|#{ROUTE_COMBINATOR})/ -
ROUTE_RE =
/\G(?:routeCix|routexp|routeCi|routex|route)\s+"([^"]+)"/ -
ROUTEF_PARAM_TYPES =
{'i' => "int", 'd' => "int64", 'b' => "bool", 'c' => "char", 's' => "string", 'f' => "float", 'O' => "guid", 'u' => "uint64"} -
Mapping of routef format specifiers to noir path-param types.
-
ROUTEF_RE =
/\G(?:routef|routeCif)\s+"([^"]+)"/ -
SUB_ROUTE_RE =
/\G(subRoute(?:Ci|f)?)\s+"([^"]+)"\s*([\(\[])/ -
Combinator matchers for the main scan loop below.
\G(rather than\A) anchors each match to the exact byte offset passed toRegex#match_at_byte_index, mirroring what\Adid against a freshly slicedcleaned[i..]remainder -- but without the slice. -
VERB_CHOOSE_RE =
/\G(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*>=>\s*choose\s*\[/ -
VERB_LIST_RE =
/\G(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*\[/