# StyloBot Release Series: Sidecar Architecture

*StyloBotin havaitsemismoottori on ASP.NET Core. Tämä selvitys selittää, miten moottori liitetään Go-portaaleihin , NodeM SK4js- sovelluksiin M SK5 ja mihin tahansa muuhun askeleeseen gRPC:n sivuauton välityksellä.*

[<img src="/articleimages/stylobot-logo.svg" alt="StyloBot" width="120" />](https://www.stylobot.net)

> **Euroopan unionin `github.com/scottgal/stylobot-go` SDK, `github.com/scottgal/caddy-stylobot` plugin, ja `Mostlylucid.BotDetection.Sidecar` kontti julkaistaan piakkoin** Everything below describes the surface they will expose.

> **StyloBot -sarja**
> 
> 1. [**Käytänne, Ei identiteettiä**](/blog/stylobot-fingerprint): miksi StyloBot mallistaa asiakkaita käytännöllisesti
> 2. [**Behaviour-Aware ASP.NET UI**](/blog/behaviour-aware-ux): serveri-renderoitu pinta .NET- sovelluksille
> 3. [**Pitkällä aikavälillä tapahtuvan -käynnissä olevan .NET-palvelujen rajaton kasvun löytäminen ja korjaaminen**](/blog/stylobot-release-reliability):, luotettavuuden kurinalaisuus, joka pitää moottorin tuskallisena tuotannossa
> 4. [**Behaviour-Aware TypeScript UI**](/blog/typescript-sdk): ExpressM SK1 Fastify, ja hakukonekomponentit
> 5. **Sidecar-arkkitehtuuri**: tämä artikkeli
> 6. [**Oppiminen nopeuttamaan**](/blog/stylobot-release-learning): mukautuva oppimisjärjestelmä, , neljä,- tasotasoinen muisti ja , tuomiovarasto
> 7. [**Todistuksen testaaminen, joka ei jää rauhaan**](/blog/stylobot-release-nondeterministic-testing): tarkastusta koskevat säännökset : yksi BDF-tietokanta hallinnoi regressiaa M SK2 lastausta, , ja kalibrointia
> 8. [**StyloExtract - paikallisen oppimisen HTML:n Markdown-muuttaja**](/blog/stylobot-release-styloextract): HTMLM SK1Markdown-laaja, joka on päällekkäinen tunnistajan kanssa , walkinger bug lucidVIEW caught, ja dogfood loop, joka teki siitä rehellisen

<!--category-- Architecture, Go, ASP.NET Core, StyloBot, gRPC -->
<datetime class="hidden">2026-06-01T10:30</datetime>

# Miksi sivuauto?

Päinvastoinen proxy on selvä paikka käyttää bot-tutkimusta: se on kaiken edessä , näkee jokaisen pyynnön, ja voi estää minkä tahansa sovelluskoodin käyttämisenM SK3 Tämä logiikka pysyy ennallaan, kunnes te kysytte, mitä hakemuksenne pitäisi tehdä *tehdä toisin* otetaan huomioon, kuka esittää pyynnön.

Puoliautomalli erottaa kaksi huolenaihetta. Portaali pysyy nopeana ja staattisena. Puolipyörä säilyttää istunnon tilanteen , archetypiset ankkurit M SK3 ajotilanteen , ja verdiktimusterin, jotka tekevät havaitsemisesta täsmällisen |(archetypinen ankkurimusteri MSC6ankkurimalli MST7 per-- sormenjälkien verdiktiomusterio | , ja neljään vaiheeseen kuuluvan koulutuksen järjestelmä on [Oppiminen nopeuttamaan](/blog/stylobot-release-learning)). Molemmat viestivät paikallisen verkon välityksellä.

Tämä ei ole uusi malli. [Envoy Proxy](https://www.envoyproxy.io/) tekee juuri tämän palvelun osalta-mesh-kysymykset (mTLSM SK2 retries, osien katkaiseminen [Dapr](https://dapr.io/) tehdäänkö se valtion ja pubin osalta [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) toimiiko se telemetrin osalta. Linkerd, Consul ConnectM SK2 ja AWS App Mesh kaikki noudattavat samaa mallia . Muodon esiintyminen jatkuu, koska se ratkaisee todellisen ongelman

[TOC]

## Miksi ei vain sisällytä sitä kirjastoon?

Vaihtoehtona on jäljittämistoimien kompilointi suoraan verkon kautta. Go:n osalta se merkitsee puhdasta-Go-yhdenmukaistamista tai CGo-libraariin sidottua komissiotaM SK2 Nodin osalta se tarkoittaa jäljittämisen suorittamista ohjelmien rinnalla prosessissa -

Mikään ei ole realistista tällaisen monimutkaisen moottorin kannalta. **aaltot** (Laajemmat aaltot toimivat vain silloin, kun aikaisempien signaalien perusteella se on todennäköistä. **Markov-ketjuvektorit** Markov-ketju on vain todennäköisyysmalli "ottaen huomioon tämän istunnon viimeiset toimet, , mitä seuraavaksi tulee,?", ja 129 mittasuhteet ottavat riittävän sivun, **Leidenin yhteisön havaitseminen** yli näihin vektoreihin: graafika-yhdentämisalgoritmi, joka yhdistää tilaisuudet, jotka käyttäytyvät samalla tavallaM SK2 mikä on StyloBotin tapa havaita bot-verkko jopa silloin, kun yksittäiset tilaisuutensa näyttävät hyvältä . Ja kaikki tämä säilyy SQLitessä pyyntöjen välisenä ajanjaksona–. Tämä valtio tarvitsee riippumattoman elinkaaren –. Se ei voi aloittaa uudelleen nodinprosessia tai joutua hajoamaan, kun verkon kautta lastataan uudelleen sen konfigurointi

sivuauto antaa jokaiselle osalle tehdä sen, mitä se on hyvä.

```mermaid
graph TD
    classDef input fill:none,stroke:#3b82f6,stroke-width:2px
    classDef async fill:none,stroke:#a855f7,stroke-width:2px
    classDef good fill:none,stroke:#22c55e,stroke-width:2px
    classDef store fill:none,stroke:#f59e0b,stroke-width:2px

    GW["Gateway<br/>Caddy / YARP / nginx"]:::input
    SD["StyloBot Sidecar · ASP.NET Core<br/>gRPC :5090 · REST :5091<br/>≤50ms per Detect RPC"]:::async
    APP["Upstream Application<br/>Node / Go / ASP.NET<br/>reads req.stylobot.verdict"]:::good
    DB[("SQLite<br/>sessions · signatures · reputation")]:::store

    GW --> SD
    SD <--> DB
    GW --> APP
```

Portaali kutsuu sivuautoa, sekoittaa tuloksen HTTP-otsakeiksi, ja mahdollisuuksien mukaan estääM SK2 Edellä oleva sovellus lukee otsikot ja toimii päätöksessäMSC3 sivuauto pysyy pyyntöjen välisessä tilassa . havaitsemisputki kulkee yhden gRPC-puhelun sisällä, ja sen tulos leviää yhdeksänä HTTP:n otsikoina

# Tylväauto

`Mostlylucid.BotDetection.Sidecar` on vähimmäis ASP.NET Core-prosessi. Se ei sisällä UI:täM SK2 ei static file servingiä , eikä routingia gRPC:n ja REST:n loppupisteiden ulkopuolelle . Se käynnistää täydellisen havaitsemismoottorin ja paljastaa kaksi porttia

- **:5090**: HTTP
- **:5091**: HTTP `/api/v1/*` loppukohdat

## gRPC

[gRPC](https://grpc.io/) on Googlessa kehitetty korkeatasoinen -tehokas etämenettelypuhelujärjestelmä, joka käyttää [Pöytäkirjapufferit](https://protobuf.dev/) (protobuf ) lankamuodossaan: compact binary encoding that is faster to serialise and smaller on the wire than JSONM SK3 gRPC runs over HTTPMSC4 which means it gets multiplexing SSK5multiple requests over one TCP connection

Yhteys on määritelty `.proto` file. Siihen peräisin olevasta filestäM SK1 koodigeneraattorit tuottavat typed-client ja server -stubit millä tahansa tuetuilla kielillä `.proto` asiakirjat, niin että kaikki kieli, jolla on gRPC-implementointi, voi kutsua sivuauton: Go, NodeM SK2 Python , RustMST4 JavaMSC5 ja monet muutMSV6

## gRPC-yhteys

Palvelussa on kolme RPC:tä:

```protobuf
service DetectionService {
  rpc Detect(DetectRequest)             returns (DetectResponse);
  rpc DetectBatch(DetectBatchRequest)   returns (DetectBatchResponse);
  rpc RenderWidget(RenderWidgetRequest) returns (RenderWidgetResponse);
}
```

**`Detect`** on per-pyynnön kuuma tie. Siirtää se menetelmäänM SK2 tie , otsikotMST4 etäisyydessä oleva IPMSC5 ja valinnaiset TLS-silmäjälkiä koskevat tiedot

**`DetectBatch`** suorittaa useita pyyntöjä johdonmukaisesti. Sovelletaan pöytäkirjan uudelleensovittamiseen ja offline-analyysiin , ei peri

**`RenderWidget`** hyväksyy nestemuodon mallin stringin, valinnaisen verdiktin , ja avaimen-lisämuutoksen arvokartanM SK3, joka sitten renderoi mallin serverinSSK4puolelle ja palauttaa HTML:nCSK5 Tämä on se tapa, jolla muut kuin NET-puheenjohtajat tuottavat bottaCSC7tietoista HTML:tä ilman erillisen renderointiprosessin käynnistämistä\; yksityiskohtaiset tiedot RenderWidget -osasta jäljempänä

## Mitä tapahtuu Detect-puhelussa

Lyhyt käännös ennen taulukkoa,, koska nämä nimet tulevat esiin

- **Tappi**: per-pyynnön avain, -arvokassi `request.ip.is_datacenter`, `detection.useragent.confidence`). Detektorit kirjoittavat sille signaaleja, ; seuraavat samaa laajuutta käyttävät detektorit lukevat ne,. Elättää vain yhden pyynnön ajan.
- **Synteettinen HttpContext**: `HttpContext` gRPC-palvelu rakentuu protopyynnön alueilta. havaitsemismoottori on suunniteltu ASP:lle.NETin keskiteollisuudelle ja odottaa, että se lukee `HttpContext`; synteesing one lets the same engine run unchanged inside a gRPC call
- **Tunnusvaikutukset** / **Yhdennetyttodisteet**:detektorin outputs (signaali kirjoittaa SSK2luottamus deltat) ja niiden yhdistetty tulosM SK4

```mermaid
sequenceDiagram
    participant GW as Gateway (Caddy)
    participant SD as gRPC Service
    participant ORC as BlackboardOrchestrator
    participant DET as Detectors (up to 49, 4 waves)
    participant DB as SQLite

    GW->>SD: Detect RPC { method, path, headers, remoteIp }
    SD->>ORC: DetectAsync(syntheticHttpContext)
    ORC->>DET: Wave 0 - Identity + ContentSequence
    ORC->>DET: Wave 1 - Fast path <1ms: UA, Header, IP, Heuristic ...
    ORC->>DET: Wave 2 - Session vectors, Behavioural waveform
    ORC->>DET: Wave 3 - Slow path: DNS, advanced fingerprinting
    DET-->>ORC: DetectionContributions (signals, confidence deltas)
    ORC->>DB: update session vector and reputation score
    DB-->>ORC: ok
    ORC-->>SD: AggregatedEvidence { botProbability, riskBand, ... }
    SD-->>GW: DetectResponse { isBot, riskBand, recommendedAction, ... }
```

Koko putki kulkee yhtenäisen gRPC-puhelun sisällä. Vastauksen palauttamisen jälkeen ei ole async-työtä

# Go SDK

Go:n Gateway-koodi ei voi importoida ASP:ta.NETin sivuautoa . Se voi kutsua sitä gRPC:stä. Go SDK:sta M SK3`github.com/scottgal/stylobot-go`) tarjoaa typed-interfacen, joka salaa luodut protobufin-tyypit kokonaan soittajilta.

### Miksi SDK kätkee protobufin tyypit

Protobuf-generated code is verbose and has an unusual API .`RISK_BAND_HIGH`, ei `"High"`). Alojen nimet ovat kammelCase joissakin generaattoreissa ja snake _case toisissaM SK2 Avoimen API:n prototyyppien estäminen tarkoittaa, että puhelijoiden on ymmärrettävä kaikki tämä

SDK käännöstää kerran rajalla (protoenumit kanonaalisiksi stringeiksi ,protorakenteet yksinkertaisiin Go-rakenteisiinM SK2 ja kutsujat eivät koskaan näe niitä.

```go
// the only interface you depend on: no proto imports required
type Client interface {
    Detect(ctx context.Context, req DetectRequest) (*Verdict, error)
    DetectBatch(ctx context.Context, reqs []DetectRequest) ([]*Verdict, error)
    RenderWidget(ctx context.Context, req RenderRequest) (*RenderResponse, error)
    Close() error
}
```

`DetectRequest` ja `Verdict` ovat yksinkertaisia Go-rakenteita:

```go
type DetectRequest struct {
    Method   string
    Path     string
    Headers  map[string]string
    RemoteIP string
    Protocol string  // "http" or "https"; defaults to "https" if empty
    TLS      *TLSInfo
}

type Verdict struct {
    IsBot             bool
    BotProbability    float32
    Confidence        float32
    BotType           string   // "AiBot", "Scraper", "GoodBot", ...
    BotName           string
    RiskBand          string   // "VeryLow", "Low", "Elevated", "Medium", "High", "VeryHigh"
    RecommendedAction string   // "Allow", "Throttle", "Challenge", "Block"
    ThreatScore       float32
    ThreatBand        string
    ProcessingTimeMs  float32
    DetectorsRun      int32
    Reasons           []Reason
}
```

Clientin luominen ja havaitsemisen suorittaminen:

```go
import (
    stylobot "github.com/scottgal/stylobot-go"
    "context"
    "time"
)

client, err := stylobot.NewClient(
    "localhost:5090",
    stylobot.WithTimeout(50 * time.Millisecond),
    stylobot.WithAPIKey(os.Getenv("SB_API_KEY")),
)
if err != nil {
    log.Fatal(err)
}
defer client.Close()

verdict, err := client.Detect(ctx, stylobot.DetectRequest{
    Method:   r.Method,
    Path:     r.URL.RequestURI(),
    RemoteIP: r.RemoteAddr,
    Headers:  extractHeaders(r),
    Protocol: "https",
})
if err != nil {
    // fail open: log and continue
    log.Printf("stylobot detect failed: %v", err)
    return next(w, r)
}

if verdict.RecommendedAction == "Block" {
    http.Error(w, "Forbidden", http.StatusForbidden)
    return
}
```

### Liiallinen yhteys ja käynnistysturva

`grpc.NewClient` luodaan asiakaskanava, mutta ei välittömästi perustaa TCP-yhteyttä. Yhteys tapahtuu ensimmäisessä RPC-puhelussa. Tämä tarkoittaa sitä, että verkonkäytäväprosessi alkaa menestyksekkäästi, vaikka sivuauto ei olekaan vielä aloittanut toimintaansa.

Tämä on erilainen kuin HTTP-clientit,, joissa tavallisesti yhdistetään luomisen yhteydessä. [gRPC Go -asiakirja](https://pkg.go.dev/google.golang.org/grpc#NewClient) kattaa elinkaaren yksityiskohtaisesti.

### Timeout-interaktion

`WithTimeout` liikkeellä `NewClient` asettaa kutakin call-aikaa koskevan perimmäismääräyksen, joka on sovellettu kussakin `Detect` call. Jos puhelinkoodenne ( tai Caddyn pluginin kaltaiset välineet ovat jo lähtöisin määräajasta, - saapuvan pyynnön rajoittuneesta kontekstista,, SDK soveltaa sitä määräaikaa, joka päättyy ensimmäisenä. `WithTimeout` peräisin `NewClient` ja antaa pluginin valvoa sitä. yksinkäyttöön (Handler, joka kutsuu suoraan SDK:ta `NewClient` Kuten edellä on osoitettu.

# Caddy- plugin

[Caddy](https://caddyserver.com/) on Go-pohjainen web-serveri ja käänneproxy automaattisesti HTTPS:n kanssa. [xcaddy](https://github.com/caddyserver/xcaddy) laatia tilapäinen Caddy-binaari, johon sisältyvät pluginit,, joka tuottaa yhden itsenM SK1contained binary with no runtime dependency on shared libraries. Tämä eroaa nginx ' dynaamisen modulaarisen järjestelmän kanssa`.so` Laadittu runtimessa). StyloBotin plugin (`github.com/scottgal/caddy-stylobot`) rekisteröi middleware-käsittelijän, joka kutsuu Go SDK:n jokaiseen pyyntöön

Caddyfile-configuration:

```caddy
{
    order stylobot before respond
}

:80 {
    stylobot {
        endpoint localhost:5090   # gRPC host:port of the sidecar
        timeout   50ms            # per-request deadline; fails open on expiry
        # on_block 503            # optional: change the block status code (default: 403)
    }
    reverse_proxy upstream:3000
}
```

Plugin siirtää yhdeksän tuomion otsikkoa jokaiseen esitettyyn pyyntöön:

| Otsake | Lähdealue SSK2
|---|---|
| `X-StyloBot-IsBot` | `isBot` (bool) |
| `X-StyloBot-Probability` | `botProbability` (0.0-1.0) |
| `X-StyloBot-Confidence` | `confidence` (0.0-1.0) |
| `X-StyloBot-BotType` | eM SK1g . `AiBot`, `Scraper`, `GoodBot` |
| `X-StyloBot-BotName` | eM SK1g . `GPTBot`, `Googlebot` |
| `X-StyloBot-RiskBand` | `VeryLow` ... `VeryHigh` |
| `X-StyloBot-Action` | `Allow` / `Throttle` / `Challenge` / `Block` |
| `X-StyloBot-ThreatScore` | lukumääräinen  |
| `X-StyloBot-ThreatBand` | `None` ... `Critical` |

Pyytää, missä `isBot=true` ja `Action=Block` pysäytetään ottamalla käyttöön 403 ja ei koskaan päästä uppstreamin alueelleM SK1 Kaikki muu ( mukaan lukien robotit, joilla on `Throttle` tai `Challenge` suositus) siirretään eteenpäin ja kaikki yhdeksän otsikkoa on säilytetty ennallaan . Tämä on suunniteltu jakautuminenM SK2 portti käsittää kovat lohkot; etuvirta käsittää vivahteet

`on_block` muutetaan asemaa koskevaa koodia, jota käytetään, kun portaali sulkee (defaultM SK1 403). Olot `on_block 503` supistaa uudelleentryynnin logiikka romuttajille, jotka pitävät 403 uudelleentryytävänä

## Mitä middleware tekee jokaisessa pyynnössä

```mermaid
flowchart TD
    classDef input fill:none,stroke:#3b82f6,stroke-width:2px
    classDef async fill:none,stroke:#a855f7,stroke-width:2px
    classDef good fill:none,stroke:#22c55e,stroke-width:2px

    A["1. Strip inbound X-StyloBot-* headers"]:::input
    B["2. context.WithTimeout(r.Context(), 50ms)"]:::input
    C["3. sbClient.Detect(ctx, DetectRequest)"]:::async
    D{error?}
    E["log warn - fail open<br/>forward unchanged"]:::good
    F["4. injectHeaders<br/>X-StyloBot-IsBot, Probability, Confidence,<br/>BotType, BotName, RiskBand, Action,<br/>ThreatScore, ThreatBand"]:::input
    I["next.ServeHTTP - forward to upstream<br/>with all verdict headers injected"]:::good

    A --> B --> C --> D
    D -->|yes| E --> I
    D -->|no| F --> I
```

**Menettely 1, lipun sisällytettävät otsikotM SK1** Asiakkaat, jotka tietävät `X-StyloBot-*` header names could self-inject a favourable verdict and have it survive the fail

**Askel 2, asiasisältöjen määräaika** Keskeytys on johdettu `r.Context()` käyttämällä `context.WithTimeout` (, joka kestää suhteellisen ajan `context.WithDeadline` otetaan absoluuttinen aika; ne ovat samanarvoisia ). peräisin `r.Context()` mieluummin kuin `context.Background()` on keskeinen kohta: jos klienti katkaistaan ennen gRPC-puhelun loppuunsaattamista , peruuttaminen leviää läpi ja sivuauto lopettaa käsittelyn varhaisessa vaiheessa

**Menettelyt 3 ja 4, havaitsevat ja syövät** Niistä yhdeksästä tuomioalueesta tulee yhdeksän `X-StyloBot-*` headers. Headerit on asetettu ennen lohkotarkastusta ,, joten etuvirta lukee ne `styloBotMiddleware({ mode: 'headers' })` kaikille muille kuin -blokoiduille pyyntöille. Pyynnöille, joissa `isBot=true` ja `recommendedAction=Block` palaavat 403 ottamalla vastaan ovet ; kaikki muu etenee täysmääräisen tuomion otsikoilla

täytäntöönpano

```go
// from sdk/caddy/stylobot.go
func (s *StyloBot) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
    for _, name := range stylobotHeaders {
        r.Header.Del(name)
    }

    ctx, cancel := context.WithTimeout(r.Context(), s.timeout)
    defer cancel()

    verdict, err := s.sbClient.Detect(ctx, sb.DetectRequest{
        Method:   r.Method,
        Path:     r.URL.RequestURI(),
        RemoteIP: ExtractIP(r),
        Protocol: r.Proto,
        Headers:  ExtractHeaders(r),
    })
    if err != nil {
        s.logger.Warn("stylobot detect failed, failing open", zap.Error(err))
        return next.ServeHTTP(w, r)
    }

    injectHeaders(r, verdict)

    if verdict.IsBot && s.OnBlock > 0 && verdict.RecommendedAction == "Block" {
        http.Error(w, "Forbidden", s.OnBlock)
        return nil
    }
    return next.ServeHTTP(w, r)
}
```

## Rakenne xcaddyn avulla

Caddy- pluginit on koottava binääriin käyttäen [xcaddy](https://github.com/caddyserver/xcaddy). Integraatiotestissä oleva Dockerfile osoittaa mallin

```dockerfile
# from tests/integration/caddy-sidecar/Dockerfile
FROM caddy:2-builder AS builder

WORKDIR /build
COPY sdk/caddy/ caddy-plugin/
COPY sdk/go/    go/

WORKDIR /build/caddy-plugin

RUN xcaddy build \
    --with github.com/scottgal/caddy-stylobot=/build/caddy-plugin \
    --with github.com/scottgal/stylobot-go=/build/go

FROM caddy:2
COPY --from=builder /build/caddy-plugin/caddy /usr/bin/caddy
COPY tests/integration/caddy-sidecar/Caddyfile /etc/caddy/Caddyfile
```

### xcaddy korvaa direktiivin

Plugin's `go.mod` sisältää:

```
replace github.com/scottgal/stylobot-go => ../go
```

Tämä kertoo Go-työkaluketjulle ", kun näette `stylobot-go`, käyttää paikallista luetteloa sen sijaan, että vetäisiin modulen proxysta `go build` ja `go test` plugin-hakemuksessa.

xcaddy luo uuden tilapäisen Go-modulin rakennukselleen. Tämä moduli ei periä `replace` pluginin ohjeet's `go.mod`. Ilman toista `--with` argument, xcaddy yrittää ladata `stylobot-go` peräisin `pkg.go.dev` (jotka se ei ole vielä julkaistu

Euroopan unionin `--with module=path` argumentti on xcaddy's native equivalent of a `replace` direktiivi: se kartoittaa moduulien etenemissuunnitelman paikalliseen luetteloon rakentamisajankohtana . Molemmat paikalliset moduulidit on nimettävä nimenomaisesti

# RenderWidget: nestemuodon mallit gRPC:stä

`RenderWidget` on sivuautossa oleva gRPC RPC, joka hyväksyy nestemuodon mallin stringin, renderoi sen havaitsemista koskevalla kontekstilla, ja palauttaa HTML:nM SK2 Tämä mahdollistaa sen, että kukin kutsuja (Jäyttää proxy-osoitteeseenMSC4Node SSR-layerinSSK5kiintiöputkenlaajatuksenMST6 tuottaa bottaMSR7tietoinen HTML ilman erillisen renderointiprosessin runningtiaMSL8

### Tekiiviesitykset

[Hiili](https://shopify.github.io/liquid/) on Shopifyn luoma templointikieli,, jota käyttävät Shopify-aiheet, JekyllM SK2 GitHub Pages , ja monet muut järjestelmätMSC4 Sen keskeiset ominaispiirteet [Fluidit.Kore](https://github.com/sebastienros/fluid), korkeat -tehokkuus .Netin täytäntöönpano Liquidiin, mallin renderointia varten

Auton sivuajoneuvojen käyttöönotto:

```csharp
// from src/Mostlylucid.BotDetection.Sidecar/Services/DetectionGrpcService.cs
private static readonly FluidParser Parser = new();  // static, shared, compiled templates cached

public override async Task<Proto.RenderWidgetResponse> RenderWidget(
    Proto.RenderWidgetRequest request, ServerCallContext context)
{
    if (!Parser.TryParse(request.Template, out var template, out var error))
        return new Proto.RenderWidgetResponse { Success = false, Error = error };

    var ctx = new TemplateContext();
    if (request.Verdict is { } v)
    {
        ctx.SetValue("isBot",             v.IsBot);
        ctx.SetValue("botProbability",    (double)v.BotProbability);
        ctx.SetValue("botType",           v.BotType);
        ctx.SetValue("botName",           v.BotName);
        ctx.SetValue("riskBand",          v.RiskBand.ToString());
        ctx.SetValue("recommendedAction", v.RecommendedAction.ToString());
        ctx.SetValue("threatScore",       (double)v.ThreatScore);
        ctx.SetValue("threatBand",        v.ThreatBand.ToString());
    }
    foreach (var kv in request.Vars)
        ctx.SetValue(kv.Key, kv.Value);

    var html = await template.RenderAsync(ctx);
    return new Proto.RenderWidgetResponse { Html = html, Success = true };
}
```

Fluid.Core ylläpitää sisäistä koottua mallivarastoa. Samaa mallia koskevat toistuvat esittelyt siirretään uudelleen `FluidParser` on statinen ja yhteinen kaikissa gRPC-puheluissa.

Yhdyskunta `StyloBotGrpcClient.renderWidget()` esimerkki ja koko mallin muuttuva viite ovat [TypeScriptin SDK-artikkeli](/blog/typescript-sdk).

Puhutaan siitä Gosta:

```go
rendered, err := client.RenderWidget(ctx, stylobot.RenderRequest{
    Template: `{% if isBot %}<p class="warning">Bot: {{ botType }}</p>{% endif %}`,
    Verdict:  verdict,
    Vars:     map[string]string{"locale": "en-GB"},
})
if err == nil && rendered.Success {
    fmt.Fprint(w, rendered.HTML)
}
```

mallin syntaksi on sama, jos kutsutte `RenderWidget` Go, Node, tai käyttä `<sb-widget>` sama nestemoottori, samat muuttuvat nimetM SK2 sama renderointitie

# Tuotantojärjestelmä

```mermaid
graph LR
    classDef input fill:none,stroke:#3b82f6,stroke-width:2px
    classDef async fill:none,stroke:#a855f7,stroke-width:2px
    classDef good fill:none,stroke:#22c55e,stroke-width:2px
    classDef store fill:none,stroke:#f59e0b,stroke-width:2px

    INT([Internet])
    CF["Cloudflare<br/>Tunnel / CDN"]
    CA["Caddy<br/>+ caddy-stylobot"]:::input
    SD["StyloBot Sidecar<br/>:5090 gRPC  ·  :5091 REST"]:::async
    WEB["Upstream App<br/>Node / Go / ASP.NET"]:::good
    DB[("SQLite<br/>sessions · reputation")]:::store

    INT --> CF --> CA
    CA -->|"gRPC Detect<br/>≤50ms"| SD
    SD <-->|"persist"| DB
    CA -->|"X-StyloBot-* headers"| WEB
    WEB -->|"/_stylobot/partials/render<br/>(widget rendering)"| SD
```

Edellä olevassa sovelluksessa kutsutaan sivuautoa suoraan widget rendering-tarkoituksiin, gatewayn ohittaminenM SK1 Widget rendering tarvitsee koko verdictin kontekstin ja tapahtuu sen jälkeen, kun pyyntö on jo ohittanut gateway detekoinnin, joten detection duplicationa ei ole

## Fail- avataan jokaisella tasolla

Caddy plugin, Node middleware, ja Go SDK kaikki epäonnistuvat avaamiseenM SK2 sivuauton tauko tai virheestä tulee varoituspäiväkirja ja salliva tyhjentävä tuomio , ei MSSK4xxMSC5 Caddyn määräaika on kylmäMST7käynnin turvallisuusmarginaali*MST8 vakaaMTSK9lämpöyhteyksissä pysyvät kustannukset ovat

Tämä merkitsee, että kaupankäynti – - – estää laillisen liikenteen, koska jäljittäminen ei ole käytettävissä, mikä on huonompaa kuin bot-liikenteen puuttuminen sivuautojen katkeamisen aikana.

---


Release-sarja jatkuu. Lisää postia havaitsemista koskevista sisäisistä osistaM SK1 käyttöönottomallit , havainnollisuuteen liittyvää toimintaan liittyvää toimintatapoja sekä kaupallista topologiaa on vielä käsiteltävänä.

- [Käytänne, Ei identiteettiä](/blog/stylobot-fingerprint): miksi havaitsemisen on oltava käyttäytymiseen perustuvaa , ei identiteettiin perustuvaa
- [Behaviour-Aware ASP.NET UI](/blog/behaviour-aware-ux): päätöksen muuttaminen Razor-päätökseksi / valvojapolitiikka
- [Pitkällä aikavälillä tapahtuvan -käynnissä olevan .NET-palvelujen rajaton kasvun löytäminen ja korjaaminen](/blog/stylobot-release-reliability): luotettavuutta koskeva kurinalaisuus, joka pitää moottorin hitaana kestävässä liikenteessä
- [Behaviour-Aware TypeScript UI](/blog/typescript-sdk): sama tuomio ilmeni ExpressissaM SK1 Fastify, ja hakukoneessa
- **Sidecar-arkkitehtuuri** ( tämä artikla ): se, miten moottori liitetään mihin tahansa askeleeseen gRPC:n kautta

Lähde täytäntöönpanosta: [github.com/scottgalM SK2stylobot](https://github.com/scottgal/stylobot). Elävä moottoriM SK1 Dashboard , ja kaupalliset valvontalaitteet [stylobot.net](https://www.stylobot.net).