[{"data":1,"prerenderedAt":2178},["ShallowReactive",2],{"navigation_docs":3,"-core-context":172,"-core-context-surround":2173},[4,26,67,98,124,140,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Core","i-lucide-box","\u002Fcore","2.core",[32,37,42,47,52,57,62],{"title":33,"path":34,"stem":35,"icon":36},"Routing","\u002Fcore\u002Frouting","2.core\u002F1.routing","i-lucide-route",{"title":38,"path":39,"stem":40,"icon":41},"Handlers","\u002Fcore\u002Fhandlers","2.core\u002F2.handlers","i-lucide-braces",{"title":43,"path":44,"stem":45,"icon":46},"Request Binding","\u002Fcore\u002Frequest-binding","2.core\u002F3.request-binding","i-lucide-tags",{"title":48,"path":49,"stem":50,"icon":51},"Validation","\u002Fcore\u002Fvalidation","2.core\u002F4.validation","i-lucide-check-check",{"title":53,"path":54,"stem":55,"icon":56},"Context","\u002Fcore\u002Fcontext","2.core\u002F5.context","i-lucide-file-input",{"title":58,"path":59,"stem":60,"icon":61},"Errors","\u002Fcore\u002Ferrors","2.core\u002F6.errors","i-lucide-triangle-alert",{"title":63,"path":64,"stem":65,"icon":66},"Middleware","\u002Fcore\u002Fmiddleware","2.core\u002F7.middleware","i-lucide-layers",{"title":68,"icon":69,"path":70,"stem":71,"children":72,"page":25},"Auth","i-lucide-shield-check","\u002Fauth","3.auth",[73,78,83,88,93],{"title":74,"path":75,"stem":76,"icon":77},"Overview","\u002Fauth\u002Foverview","3.auth\u002F1.overview","i-lucide-shield",{"title":79,"path":80,"stem":81,"icon":82},"Auth Rules","\u002Fauth\u002Fauth-rules","3.auth\u002F2.auth-rules","i-lucide-lock",{"title":84,"path":85,"stem":86,"icon":87},"JWT Providers","\u002Fauth\u002Fjwt-providers","3.auth\u002F3.jwt-providers","i-lucide-key",{"title":89,"path":90,"stem":91,"icon":92},"Roles & Permissions","\u002Fauth\u002Froles-and-permissions","3.auth\u002F4.roles-and-permissions","i-lucide-users",{"title":94,"path":95,"stem":96,"icon":97},"Audit Logging","\u002Fauth\u002Faudit-logging","3.auth\u002F5.audit-logging","i-lucide-scroll-text",{"title":99,"icon":100,"path":101,"stem":102,"children":103,"page":25},"GoTrue","i-lucide-key-round","\u002Fgotrue","4.gotrue",[104,109,114,119],{"title":105,"path":106,"stem":107,"icon":108},"Proxy","\u002Fgotrue\u002Fproxy","4.gotrue\u002F1.proxy","i-lucide-shuffle",{"title":110,"path":111,"stem":112,"icon":113},"Endpoints","\u002Fgotrue\u002Fendpoints","4.gotrue\u002F2.endpoints","i-lucide-list",{"title":115,"path":116,"stem":117,"icon":118},"Client IP & Rate Limits","\u002Fgotrue\u002Fclient-ip-and-rate-limits","4.gotrue\u002F3.client-ip-and-rate-limits","i-lucide-network",{"title":120,"path":121,"stem":122,"icon":123},"Deployment","\u002Fgotrue\u002Fdeployment","4.gotrue\u002F4.deployment","i-lucide-server",{"title":125,"icon":126,"path":127,"stem":128,"children":129,"page":25},"API Docs","i-lucide-file-text","\u002Fapi-docs","5.api-docs",[130,135],{"title":131,"path":132,"stem":133,"icon":134},"OpenAPI","\u002Fapi-docs\u002Fopenapi","5.api-docs\u002F1.openapi","i-lucide-file-json",{"title":136,"path":137,"stem":138,"icon":139},"Scalar UI","\u002Fapi-docs\u002Fscalar","5.api-docs\u002F2.scalar","i-lucide-book-open-text",{"title":141,"icon":142,"path":143,"stem":144,"children":145,"page":25},"Guides","i-lucide-compass","\u002Fguides","6.guides",[146,151,156],{"title":147,"path":148,"stem":149,"icon":150},"Testing","\u002Fguides\u002Ftesting","6.guides\u002F1.testing","i-lucide-flask-conical",{"title":152,"path":153,"stem":154,"icon":155},"Performance","\u002Fguides\u002Fperformance","6.guides\u002F2.performance","i-lucide-gauge",{"title":157,"path":158,"stem":159,"icon":160},"Releasing","\u002Fguides\u002Freleasing","6.guides\u002F3.releasing","i-lucide-tag",{"title":162,"icon":163,"path":164,"stem":165,"children":166,"page":25},"Reference","i-lucide-code","\u002Freference","7.reference",[167],{"title":168,"path":169,"stem":170,"icon":171},"API Reference","\u002Freference\u002Fapi-reference","7.reference\u002F1.api-reference","i-lucide-list-tree",{"id":173,"title":53,"body":174,"description":2166,"extension":2167,"links":2168,"meta":2169,"navigation":2170,"path":54,"seo":2171,"stem":55,"__hash__":2172},"docs\u002F2.core\u002F5.context.md",{"type":175,"value":176,"toc":2156},"minimark",[177,190,295,305,353,358,361,456,554,567,571,653,656,852,859,863,988,991,1243,1261,1265,1271,1581,1620,1627,1631,1676,1679,1851,1860,1864,1867,1954,1967,1971,2128,2134,2138,2152],[178,179,180,181,185,186,189],"p",{},"Every handler receives an ",[182,183,184],"code",{},"*ezz.Context",". It embeds ",[182,187,188],{},"context.Context",", holds the request and response writer, and caches the metadata most services end up reading on every request.",[191,192,197],"pre",{"className":193,"code":194,"language":195,"meta":196,"style":196},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type Context struct {\n    context.Context\n\n    Request   *http.Request\n    Response  http.ResponseWriter\n    StartTime time.Time\n    \u002F\u002F ...\n}\n","go","",[182,198,199,218,230,237,255,268,282,289],{"__ignoreMap":196},[200,201,204,208,212,215],"span",{"class":202,"line":203},"line",1,[200,205,207],{"class":206},"sMK4o","type",[200,209,211],{"class":210},"sBMFI"," Context",[200,213,214],{"class":206}," struct",[200,216,217],{"class":206}," {\n",[200,219,221,224,227],{"class":202,"line":220},2,[200,222,223],{"class":210},"    context",[200,225,226],{"class":206},".",[200,228,229],{"class":210},"Context\n",[200,231,233],{"class":202,"line":232},3,[200,234,236],{"emptyLinePlaceholder":235},true,"\n",[200,238,240,244,247,250,252],{"class":202,"line":239},4,[200,241,243],{"class":242},"sTEyZ","    Request   ",[200,245,246],{"class":206},"*",[200,248,249],{"class":210},"http",[200,251,226],{"class":206},[200,253,254],{"class":210},"Request\n",[200,256,258,261,263,265],{"class":202,"line":257},5,[200,259,260],{"class":242},"    Response  ",[200,262,249],{"class":210},[200,264,226],{"class":206},[200,266,267],{"class":210},"ResponseWriter\n",[200,269,271,274,277,279],{"class":202,"line":270},6,[200,272,273],{"class":242},"    StartTime ",[200,275,276],{"class":210},"time",[200,278,226],{"class":206},[200,280,281],{"class":210},"Time\n",[200,283,285],{"class":202,"line":284},7,[200,286,288],{"class":287},"sHwdD","    \u002F\u002F ...\n",[200,290,292],{"class":202,"line":291},8,[200,293,294],{"class":206},"}\n",[178,296,297,298,300,301,304],{},"Because it embeds ",[182,299,188],{},", you can pass ",[182,302,303],{},"ctx"," straight to anything expecting one:",[191,306,308],{"className":193,"code":307,"language":195,"meta":196,"style":196},"rows, err := db.QueryContext(ctx, \"SELECT ...\")\n",[182,309,310],{"__ignoreMap":196},[200,311,312,315,318,321,324,327,329,333,336,338,340,343,347,350],{"class":202,"line":203},[200,313,314],{"class":242},"rows",[200,316,317],{"class":206},",",[200,319,320],{"class":242}," err ",[200,322,323],{"class":206},":=",[200,325,326],{"class":242}," db",[200,328,226],{"class":206},[200,330,332],{"class":331},"s2Zo4","QueryContext",[200,334,335],{"class":206},"(",[200,337,303],{"class":242},[200,339,317],{"class":206},[200,341,342],{"class":206}," \"",[200,344,346],{"class":345},"sfazB","SELECT ...",[200,348,349],{"class":206},"\"",[200,351,352],{"class":206},")\n",[354,355,357],"h2",{"id":356},"read-request-metadata","Read request metadata",[178,359,360],{},"These are extracted once when the context is created, so calling them repeatedly costs nothing.",[362,363,364,377],"table",{},[365,366,367],"thead",{},[368,369,370,374],"tr",{},[371,372,373],"th",{},"Method",[371,375,376],{},"Source",[378,379,380,398,418,430,446],"tbody",{},[368,381,382,388],{},[383,384,385],"td",{},[182,386,387],{},"GetRequestID()",[383,389,390,393,394,397],{},[182,391,392],{},"X-Request-ID",", then ",[182,395,396],{},"X-Correlation-ID",", otherwise a generated value",[368,399,400,405],{},[383,401,402],{},[182,403,404],{},"GetClientIP()",[383,406,407,408,393,411,414,415],{},"First hop of ",[182,409,410],{},"X-Forwarded-For",[182,412,413],{},"X-Real-IP",", otherwise ",[182,416,417],{},"RemoteAddr",[368,419,420,425],{},[383,421,422],{},[182,423,424],{},"GetUserAgent()",[383,426,427],{},[182,428,429],{},"User-Agent",[368,431,432,437],{},[383,433,434],{},[182,435,436],{},"GetTraceID()",[383,438,439,393,442,445],{},[182,440,441],{},"X-Trace-ID",[182,443,444],{},"X-B3-TraceId",", otherwise empty",[368,447,448,453],{},[383,449,450],{},[182,451,452],{},"StartTime",[383,454,455],{},"When the context was created",[191,457,459],{"className":193,"code":458,"language":195,"meta":196,"style":196},"logger.InfoContext(ctx, \"processing order\",\n    \"request_id\", ctx.GetRequestID(),\n    \"trace_id\", ctx.GetTraceID(),\n    \"client_ip\", ctx.GetClientIP(),\n)\n",[182,460,461,487,510,530,550],{"__ignoreMap":196},[200,462,463,466,468,471,473,475,477,479,482,484],{"class":202,"line":203},[200,464,465],{"class":242},"logger",[200,467,226],{"class":206},[200,469,470],{"class":331},"InfoContext",[200,472,335],{"class":206},[200,474,303],{"class":242},[200,476,317],{"class":206},[200,478,342],{"class":206},[200,480,481],{"class":345},"processing order",[200,483,349],{"class":206},[200,485,486],{"class":206},",\n",[200,488,489,492,495,497,499,502,504,507],{"class":202,"line":220},[200,490,491],{"class":206},"    \"",[200,493,494],{"class":345},"request_id",[200,496,349],{"class":206},[200,498,317],{"class":206},[200,500,501],{"class":242}," ctx",[200,503,226],{"class":206},[200,505,506],{"class":331},"GetRequestID",[200,508,509],{"class":206},"(),\n",[200,511,512,514,517,519,521,523,525,528],{"class":202,"line":232},[200,513,491],{"class":206},[200,515,516],{"class":345},"trace_id",[200,518,349],{"class":206},[200,520,317],{"class":206},[200,522,501],{"class":242},[200,524,226],{"class":206},[200,526,527],{"class":331},"GetTraceID",[200,529,509],{"class":206},[200,531,532,534,537,539,541,543,545,548],{"class":202,"line":239},[200,533,491],{"class":206},[200,535,536],{"class":345},"client_ip",[200,538,349],{"class":206},[200,540,317],{"class":206},[200,542,501],{"class":242},[200,544,226],{"class":206},[200,546,547],{"class":331},"GetClientIP",[200,549,509],{"class":206},[200,551,552],{"class":202,"line":257},[200,553,352],{"class":206},[555,556,557,559,560,562,563,226],"warning",{},[182,558,547],{}," trusts ",[182,561,410],{}," unconditionally, so a direct client can set it to anything. Do not use it for rate limiting, lockouts, or audit records unless a proxy you control always overwrites the header. The GoTrue proxy resolves the client IP differently, walking only trusted hops; see ",[564,565,566],"a",{"href":116},"Client IP and rate limits",[354,568,570],{"id":569},"read-the-request","Read the request",[362,572,573,582],{},[365,574,575],{},[368,576,577,579],{},[371,578,373],{},[371,580,581],{},"Returns",[378,583,584,597,607,617,630,640],{},[368,585,586,591],{},[383,587,588],{},[182,589,590],{},"Param(name)",[383,592,593,594],{},"A path parameter, falling back to ",[182,595,596],{},"Request.PathValue",[368,598,599,604],{},[383,600,601],{},[182,602,603],{},"Query(name)",[383,605,606],{},"The first value of a query parameter",[368,608,609,614],{},[383,610,611],{},[182,612,613],{},"QueryValues(name)",[383,615,616],{},"All values of a query parameter",[368,618,619,624],{},[383,620,621],{},[182,622,623],{},"QueryAll()",[383,625,626,627],{},"The full ",[182,628,629],{},"url.Values",[368,631,632,637],{},[383,633,634],{},[182,635,636],{},"RequestHeader(name)",[383,638,639],{},"A request header value",[368,641,642,647],{},[383,643,644],{},[182,645,646],{},"Body()",[383,648,649,650],{},"The raw ",[182,651,652],{},"io.ReadCloser",[178,654,655],{},"The query string is parsed the first time you ask for it and cached for the rest of the request.",[191,657,659],{"className":193,"code":658,"language":195,"meta":196,"style":196},"app.GET(\"\u002Fsearch\", ezz.HFunc(func(ctx *ezz.Context) (*Results, error) {\n    term := ctx.Query(\"q\")\n    tags := ctx.QueryValues(\"tag\")\n    if term == \"\" {\n        return nil, ezz.BadRequest(\"q is required\")\n    }\n    return search(ctx, term, tags)\n}))\n",[182,660,661,725,750,775,792,818,823,847],{"__ignoreMap":196},[200,662,663,666,668,671,673,675,678,680,682,685,687,690,693,696,699,702,704,706,709,712,715,717,721,723],{"class":202,"line":203},[200,664,665],{"class":242},"app",[200,667,226],{"class":206},[200,669,670],{"class":331},"GET",[200,672,335],{"class":206},[200,674,349],{"class":206},[200,676,677],{"class":345},"\u002Fsearch",[200,679,349],{"class":206},[200,681,317],{"class":206},[200,683,684],{"class":242}," ezz",[200,686,226],{"class":206},[200,688,689],{"class":331},"HFunc",[200,691,692],{"class":206},"(func(",[200,694,303],{"class":695},"sHdIc",[200,697,698],{"class":206}," *",[200,700,701],{"class":210},"ezz",[200,703,226],{"class":206},[200,705,53],{"class":210},[200,707,708],{"class":206},")",[200,710,711],{"class":206}," (*",[200,713,714],{"class":210},"Results",[200,716,317],{"class":206},[200,718,720],{"class":719},"spNyl"," error",[200,722,708],{"class":206},[200,724,217],{"class":206},[200,726,727,730,732,734,736,739,741,743,746,748],{"class":202,"line":220},[200,728,729],{"class":242},"    term ",[200,731,323],{"class":206},[200,733,501],{"class":242},[200,735,226],{"class":206},[200,737,738],{"class":331},"Query",[200,740,335],{"class":206},[200,742,349],{"class":206},[200,744,745],{"class":345},"q",[200,747,349],{"class":206},[200,749,352],{"class":206},[200,751,752,755,757,759,761,764,766,768,771,773],{"class":202,"line":232},[200,753,754],{"class":242},"    tags ",[200,756,323],{"class":206},[200,758,501],{"class":242},[200,760,226],{"class":206},[200,762,763],{"class":331},"QueryValues",[200,765,335],{"class":206},[200,767,349],{"class":206},[200,769,770],{"class":345},"tag",[200,772,349],{"class":206},[200,774,352],{"class":206},[200,776,777,781,784,787,790],{"class":202,"line":239},[200,778,780],{"class":779},"s7zQu","    if",[200,782,783],{"class":242}," term ",[200,785,786],{"class":206},"==",[200,788,789],{"class":206}," \"\"",[200,791,217],{"class":206},[200,793,794,797,800,802,804,807,809,811,814,816],{"class":202,"line":257},[200,795,796],{"class":779},"        return",[200,798,799],{"class":206}," nil,",[200,801,684],{"class":242},[200,803,226],{"class":206},[200,805,806],{"class":331},"BadRequest",[200,808,335],{"class":206},[200,810,349],{"class":206},[200,812,813],{"class":345},"q is required",[200,815,349],{"class":206},[200,817,352],{"class":206},[200,819,820],{"class":202,"line":270},[200,821,822],{"class":206},"    }\n",[200,824,825,828,831,833,835,837,840,842,845],{"class":202,"line":284},[200,826,827],{"class":779},"    return",[200,829,830],{"class":331}," search",[200,832,335],{"class":206},[200,834,303],{"class":242},[200,836,317],{"class":206},[200,838,839],{"class":242}," term",[200,841,317],{"class":206},[200,843,844],{"class":242}," tags",[200,846,352],{"class":206},[200,848,849],{"class":202,"line":291},[200,850,851],{"class":206},"}))\n",[178,853,854,855,858],{},"For anything structured, prefer a request struct and let ",[564,856,857],{"href":44},"binding"," do this work.",[354,860,862],{"id":861},"write-a-response","Write a response",[362,864,865,874],{},[365,866,867],{},[368,868,869,871],{},[371,870,373],{},[371,872,873],{},"Behaviour",[378,875,876,893,903,913,926,939,951,965,975],{},[368,877,878,883],{},[383,879,880],{},[182,881,882],{},"JSON(status, data)",[383,884,885,886,889,890],{},"Sets ",[182,887,888],{},"Content-Type",", writes the status, encodes ",[182,891,892],{},"data",[368,894,895,900],{},[383,896,897],{},[182,898,899],{},"Status(code)",[383,901,902],{},"Writes the status header and nothing else",[368,904,905,910],{},[383,906,907],{},[182,908,909],{},"SetHeader(key, value)",[383,911,912],{},"Sets a response header, before the status is written",[368,914,915,920],{},[383,916,917],{},[182,918,919],{},"NoContent()",[383,921,922,925],{},[182,923,924],{},"204"," with no body",[368,927,928,933],{},[383,929,930],{},[182,931,932],{},"Redirect(url, status)",[383,934,935,936],{},"Delegates to ",[182,937,938],{},"http.Redirect",[368,940,941,946],{},[383,942,943],{},[182,944,945],{},"ServeFile(path)",[383,947,935,948],{},[182,949,950],{},"http.ServeFile",[368,952,953,958],{},[383,954,955],{},[182,956,957],{},"Error(err)",[383,959,960,961,964],{},"Writes an error response, mapping ",[182,962,963],{},"*HTTPError"," to its status",[368,966,967,972],{},[383,968,969],{},[182,970,971],{},"Written()",[383,973,974],{},"Whether a response has been written",[368,976,977,982],{},[383,978,979],{},[182,980,981],{},"StatusCode()",[383,983,984,985],{},"The status that was written, or ",[182,986,987],{},"0",[178,989,990],{},"Set headers before writing the status, since the status flushes the header map:",[191,992,994],{"className":193,"code":993,"language":195,"meta":196,"style":196},"app.GET(\"\u002Ffiles\u002F{name}\", ezz.H(func(ctx *ezz.Context, req FileRequest) (any, error) {\n    etag := etagFor(req.Name)\n    ctx.SetHeader(\"ETag\", etag)\n    ctx.SetHeader(\"Cache-Control\", \"max-age=300\")\n\n    if ctx.RequestHeader(\"If-None-Match\") == etag {\n        ctx.Status(http.StatusNotModified)\n        return nil, nil\n    }\n    return nil, ctx.ServeFile(\"\u002Fvar\u002Ffiles\u002F\" + req.Name)\n}))\n",[182,995,996,1058,1080,1106,1134,1138,1169,1190,1199,1204,1238],{"__ignoreMap":196},[200,997,998,1000,1002,1004,1006,1008,1011,1013,1015,1017,1019,1022,1024,1026,1028,1030,1032,1034,1036,1039,1042,1044,1047,1050,1052,1054,1056],{"class":202,"line":203},[200,999,665],{"class":242},[200,1001,226],{"class":206},[200,1003,670],{"class":331},[200,1005,335],{"class":206},[200,1007,349],{"class":206},[200,1009,1010],{"class":345},"\u002Ffiles\u002F{name}",[200,1012,349],{"class":206},[200,1014,317],{"class":206},[200,1016,684],{"class":242},[200,1018,226],{"class":206},[200,1020,1021],{"class":331},"H",[200,1023,692],{"class":206},[200,1025,303],{"class":695},[200,1027,698],{"class":206},[200,1029,701],{"class":210},[200,1031,226],{"class":206},[200,1033,53],{"class":210},[200,1035,317],{"class":206},[200,1037,1038],{"class":695}," req",[200,1040,1041],{"class":210}," FileRequest",[200,1043,708],{"class":206},[200,1045,1046],{"class":206}," (",[200,1048,1049],{"class":210},"any",[200,1051,317],{"class":206},[200,1053,720],{"class":719},[200,1055,708],{"class":206},[200,1057,217],{"class":206},[200,1059,1060,1063,1065,1068,1070,1073,1075,1078],{"class":202,"line":220},[200,1061,1062],{"class":242},"    etag ",[200,1064,323],{"class":206},[200,1066,1067],{"class":331}," etagFor",[200,1069,335],{"class":206},[200,1071,1072],{"class":242},"req",[200,1074,226],{"class":206},[200,1076,1077],{"class":242},"Name",[200,1079,352],{"class":206},[200,1081,1082,1085,1087,1090,1092,1094,1097,1099,1101,1104],{"class":202,"line":232},[200,1083,1084],{"class":242},"    ctx",[200,1086,226],{"class":206},[200,1088,1089],{"class":331},"SetHeader",[200,1091,335],{"class":206},[200,1093,349],{"class":206},[200,1095,1096],{"class":345},"ETag",[200,1098,349],{"class":206},[200,1100,317],{"class":206},[200,1102,1103],{"class":242}," etag",[200,1105,352],{"class":206},[200,1107,1108,1110,1112,1114,1116,1118,1121,1123,1125,1127,1130,1132],{"class":202,"line":239},[200,1109,1084],{"class":242},[200,1111,226],{"class":206},[200,1113,1089],{"class":331},[200,1115,335],{"class":206},[200,1117,349],{"class":206},[200,1119,1120],{"class":345},"Cache-Control",[200,1122,349],{"class":206},[200,1124,317],{"class":206},[200,1126,342],{"class":206},[200,1128,1129],{"class":345},"max-age=300",[200,1131,349],{"class":206},[200,1133,352],{"class":206},[200,1135,1136],{"class":202,"line":257},[200,1137,236],{"emptyLinePlaceholder":235},[200,1139,1140,1142,1144,1146,1149,1151,1153,1156,1158,1160,1163,1166],{"class":202,"line":270},[200,1141,780],{"class":779},[200,1143,501],{"class":242},[200,1145,226],{"class":206},[200,1147,1148],{"class":331},"RequestHeader",[200,1150,335],{"class":206},[200,1152,349],{"class":206},[200,1154,1155],{"class":345},"If-None-Match",[200,1157,349],{"class":206},[200,1159,708],{"class":206},[200,1161,1162],{"class":206}," ==",[200,1164,1165],{"class":242}," etag ",[200,1167,1168],{"class":206},"{\n",[200,1170,1171,1174,1176,1179,1181,1183,1185,1188],{"class":202,"line":284},[200,1172,1173],{"class":242},"        ctx",[200,1175,226],{"class":206},[200,1177,1178],{"class":331},"Status",[200,1180,335],{"class":206},[200,1182,249],{"class":242},[200,1184,226],{"class":206},[200,1186,1187],{"class":242},"StatusNotModified",[200,1189,352],{"class":206},[200,1191,1192,1194,1196],{"class":202,"line":291},[200,1193,796],{"class":779},[200,1195,799],{"class":206},[200,1197,1198],{"class":206}," nil\n",[200,1200,1202],{"class":202,"line":1201},9,[200,1203,822],{"class":206},[200,1205,1207,1209,1211,1213,1215,1218,1220,1222,1225,1227,1230,1232,1234,1236],{"class":202,"line":1206},10,[200,1208,827],{"class":779},[200,1210,799],{"class":206},[200,1212,501],{"class":242},[200,1214,226],{"class":206},[200,1216,1217],{"class":331},"ServeFile",[200,1219,335],{"class":206},[200,1221,349],{"class":206},[200,1223,1224],{"class":345},"\u002Fvar\u002Ffiles\u002F",[200,1226,349],{"class":206},[200,1228,1229],{"class":206}," +",[200,1231,1038],{"class":242},[200,1233,226],{"class":206},[200,1235,1077],{"class":242},[200,1237,352],{"class":206},[200,1239,1241],{"class":202,"line":1240},11,[200,1242,851],{"class":206},[178,1244,1245,1248,1249,1252,1253,1256,1257,1260],{},[182,1246,1247],{},"JSON"," encodes with HTML escaping turned off, so ",[182,1250,1251],{},"&",", ",[182,1254,1255],{},"\u003C",", and ",[182,1258,1259],{},">"," survive intact in strings.",[354,1262,1264],{"id":1263},"stream-server-sent-events","Stream server-sent events",[178,1266,1267,1270],{},[182,1268,1269],{},"Stream"," sets the streaming headers and hands back a small writer.",[191,1272,1274],{"className":193,"code":1273,"language":195,"meta":196,"style":196},"app.GET(\"\u002Fevents\", ezz.HFunc(func(ctx *ezz.Context) (any, error) {\n    stream := ctx.Stream(\"text\u002Fevent-stream\")\n\n    ticker := time.NewTicker(time.Second)\n    defer ticker.Stop()\n\n    for {\n        select {\n        case \u003C-ctx.Done():             \u002F\u002F client disconnected\n            return nil, nil\n        case t := \u003C-ticker.C:\n            if err := stream.WriteJSON(\"tick\", map[string]any{\"at\": t}); err != nil {\n                return nil, nil\n            }\n            stream.Flush()\n        }\n    }\n}))\n",[182,1275,1276,1327,1351,1355,1381,1397,1401,1408,1415,1436,1445,1467,1536,1546,1552,1565,1571,1576],{"__ignoreMap":196},[200,1277,1278,1280,1282,1284,1286,1288,1291,1293,1295,1297,1299,1301,1303,1305,1307,1309,1311,1313,1315,1317,1319,1321,1323,1325],{"class":202,"line":203},[200,1279,665],{"class":242},[200,1281,226],{"class":206},[200,1283,670],{"class":331},[200,1285,335],{"class":206},[200,1287,349],{"class":206},[200,1289,1290],{"class":345},"\u002Fevents",[200,1292,349],{"class":206},[200,1294,317],{"class":206},[200,1296,684],{"class":242},[200,1298,226],{"class":206},[200,1300,689],{"class":331},[200,1302,692],{"class":206},[200,1304,303],{"class":695},[200,1306,698],{"class":206},[200,1308,701],{"class":210},[200,1310,226],{"class":206},[200,1312,53],{"class":210},[200,1314,708],{"class":206},[200,1316,1046],{"class":206},[200,1318,1049],{"class":210},[200,1320,317],{"class":206},[200,1322,720],{"class":719},[200,1324,708],{"class":206},[200,1326,217],{"class":206},[200,1328,1329,1332,1334,1336,1338,1340,1342,1344,1347,1349],{"class":202,"line":220},[200,1330,1331],{"class":242},"    stream ",[200,1333,323],{"class":206},[200,1335,501],{"class":242},[200,1337,226],{"class":206},[200,1339,1269],{"class":331},[200,1341,335],{"class":206},[200,1343,349],{"class":206},[200,1345,1346],{"class":345},"text\u002Fevent-stream",[200,1348,349],{"class":206},[200,1350,352],{"class":206},[200,1352,1353],{"class":202,"line":232},[200,1354,236],{"emptyLinePlaceholder":235},[200,1356,1357,1360,1362,1365,1367,1370,1372,1374,1376,1379],{"class":202,"line":239},[200,1358,1359],{"class":242},"    ticker ",[200,1361,323],{"class":206},[200,1363,1364],{"class":242}," time",[200,1366,226],{"class":206},[200,1368,1369],{"class":331},"NewTicker",[200,1371,335],{"class":206},[200,1373,276],{"class":242},[200,1375,226],{"class":206},[200,1377,1378],{"class":242},"Second",[200,1380,352],{"class":206},[200,1382,1383,1386,1389,1391,1394],{"class":202,"line":257},[200,1384,1385],{"class":779},"    defer",[200,1387,1388],{"class":242}," ticker",[200,1390,226],{"class":206},[200,1392,1393],{"class":331},"Stop",[200,1395,1396],{"class":206},"()\n",[200,1398,1399],{"class":202,"line":270},[200,1400,236],{"emptyLinePlaceholder":235},[200,1402,1403,1406],{"class":202,"line":284},[200,1404,1405],{"class":779},"    for",[200,1407,217],{"class":206},[200,1409,1410,1413],{"class":202,"line":291},[200,1411,1412],{"class":779},"        select",[200,1414,217],{"class":206},[200,1416,1417,1420,1423,1425,1427,1430,1433],{"class":202,"line":1201},[200,1418,1419],{"class":779},"        case",[200,1421,1422],{"class":206}," \u003C-",[200,1424,303],{"class":242},[200,1426,226],{"class":206},[200,1428,1429],{"class":331},"Done",[200,1431,1432],{"class":206},"():",[200,1434,1435],{"class":287},"             \u002F\u002F client disconnected\n",[200,1437,1438,1441,1443],{"class":202,"line":1206},[200,1439,1440],{"class":779},"            return",[200,1442,799],{"class":206},[200,1444,1198],{"class":206},[200,1446,1447,1449,1452,1454,1456,1459,1461,1464],{"class":202,"line":1240},[200,1448,1419],{"class":779},[200,1450,1451],{"class":242}," t ",[200,1453,323],{"class":206},[200,1455,1422],{"class":206},[200,1457,1458],{"class":242},"ticker",[200,1460,226],{"class":206},[200,1462,1463],{"class":242},"C",[200,1465,1466],{"class":206},":\n",[200,1468,1470,1473,1475,1477,1480,1482,1485,1487,1489,1492,1494,1496,1499,1502,1505,1507,1510,1512,1515,1517,1520,1523,1526,1528,1531,1534],{"class":202,"line":1469},12,[200,1471,1472],{"class":779},"            if",[200,1474,320],{"class":242},[200,1476,323],{"class":206},[200,1478,1479],{"class":242}," stream",[200,1481,226],{"class":206},[200,1483,1484],{"class":331},"WriteJSON",[200,1486,335],{"class":206},[200,1488,349],{"class":206},[200,1490,1491],{"class":345},"tick",[200,1493,349],{"class":206},[200,1495,317],{"class":206},[200,1497,1498],{"class":206}," map[",[200,1500,1501],{"class":719},"string",[200,1503,1504],{"class":206},"]",[200,1506,1049],{"class":210},[200,1508,1509],{"class":206},"{",[200,1511,349],{"class":206},[200,1513,1514],{"class":345},"at",[200,1516,349],{"class":206},[200,1518,1519],{"class":206},":",[200,1521,1522],{"class":242}," t",[200,1524,1525],{"class":206},"});",[200,1527,320],{"class":242},[200,1529,1530],{"class":206},"!=",[200,1532,1533],{"class":206}," nil",[200,1535,217],{"class":206},[200,1537,1539,1542,1544],{"class":202,"line":1538},13,[200,1540,1541],{"class":779},"                return",[200,1543,799],{"class":206},[200,1545,1198],{"class":206},[200,1547,1549],{"class":202,"line":1548},14,[200,1550,1551],{"class":206},"            }\n",[200,1553,1555,1558,1560,1563],{"class":202,"line":1554},15,[200,1556,1557],{"class":242},"            stream",[200,1559,226],{"class":206},[200,1561,1562],{"class":331},"Flush",[200,1564,1396],{"class":206},[200,1566,1568],{"class":202,"line":1567},16,[200,1569,1570],{"class":206},"        }\n",[200,1572,1574],{"class":202,"line":1573},17,[200,1575,822],{"class":206},[200,1577,1579],{"class":202,"line":1578},18,[200,1580,851],{"class":206},[178,1582,1583,1585,1586,1588,1589,1592,1593,1596,1597,1600,1601,1252,1604,1252,1607,1252,1610,1256,1613,1616,1617,1619],{},[182,1584,1269],{}," sets ",[182,1587,888],{}," to the value you pass, plus ",[182,1590,1591],{},"Cache-Control: no-cache"," and ",[182,1594,1595],{},"Connection: keep-alive",", and marks the response as written. The returned ",[182,1598,1599],{},"*StreamWriter"," has ",[182,1602,1603],{},"WriteEvent(event, data)",[182,1605,1606],{},"WriteJSON(event, value)",[182,1608,1609],{},"Write(bytes)",[182,1611,1612],{},"Flush()",[182,1614,1615],{},"Close()",". Call ",[182,1618,1562],{}," after each message, otherwise events sit in the buffer.",[178,1621,1622,1623,1626],{},"Watch ",[182,1624,1625],{},"ctx.Done()"," so a disconnected client does not leave the handler spinning.",[354,1628,1630],{"id":1629},"reach-the-authenticated-user","Reach the authenticated user",[362,1632,1633,1641],{},[365,1634,1635],{},[368,1636,1637,1639],{},[371,1638,373],{},[371,1640,873],{},[378,1642,1643,1656,1666],{},[368,1644,1645,1650],{},[383,1646,1647],{},[182,1648,1649],{},"User()",[383,1651,1652,1653],{},"The user value from the auth provider, or ",[182,1654,1655],{},"nil",[368,1657,1658,1663],{},[383,1659,1660],{},[182,1661,1662],{},"MustUser()",[383,1664,1665],{},"The same value, panicking when there is none",[368,1667,1668,1673],{},[383,1669,1670],{},[182,1671,1672],{},"SetUser(user)",[383,1674,1675],{},"Replaces the user, mostly useful in tests",[178,1677,1678],{},"The value is whatever your auth provider returned, so assert it to the type you expect:",[191,1680,1682],{"className":193,"code":1681,"language":195,"meta":196,"style":196},"app.GET(\"\u002Fme\", ezz.HFunc(func(ctx *ezz.Context) (*Profile, error) {\n    user, ok := ctx.User().(auth.User)\n    if !ok {\n        return nil, ezz.Unauthorized(\"no user on request\")\n    }\n    claims := user.GetClaims()\n    return loadProfile(ctx, claims.Subject)\n}))\n",[182,1683,1684,1736,1767,1779,1803,1807,1824,1847],{"__ignoreMap":196},[200,1685,1686,1688,1690,1692,1694,1696,1699,1701,1703,1705,1707,1709,1711,1713,1715,1717,1719,1721,1723,1725,1728,1730,1732,1734],{"class":202,"line":203},[200,1687,665],{"class":242},[200,1689,226],{"class":206},[200,1691,670],{"class":331},[200,1693,335],{"class":206},[200,1695,349],{"class":206},[200,1697,1698],{"class":345},"\u002Fme",[200,1700,349],{"class":206},[200,1702,317],{"class":206},[200,1704,684],{"class":242},[200,1706,226],{"class":206},[200,1708,689],{"class":331},[200,1710,692],{"class":206},[200,1712,303],{"class":695},[200,1714,698],{"class":206},[200,1716,701],{"class":210},[200,1718,226],{"class":206},[200,1720,53],{"class":210},[200,1722,708],{"class":206},[200,1724,711],{"class":206},[200,1726,1727],{"class":210},"Profile",[200,1729,317],{"class":206},[200,1731,720],{"class":719},[200,1733,708],{"class":206},[200,1735,217],{"class":206},[200,1737,1738,1741,1743,1746,1748,1750,1752,1755,1758,1761,1763,1765],{"class":202,"line":220},[200,1739,1740],{"class":242},"    user",[200,1742,317],{"class":206},[200,1744,1745],{"class":242}," ok ",[200,1747,323],{"class":206},[200,1749,501],{"class":242},[200,1751,226],{"class":206},[200,1753,1754],{"class":331},"User",[200,1756,1757],{"class":206},"().(",[200,1759,1760],{"class":210},"auth",[200,1762,226],{"class":206},[200,1764,1754],{"class":210},[200,1766,352],{"class":206},[200,1768,1769,1771,1774,1777],{"class":202,"line":232},[200,1770,780],{"class":779},[200,1772,1773],{"class":206}," !",[200,1775,1776],{"class":242},"ok ",[200,1778,1168],{"class":206},[200,1780,1781,1783,1785,1787,1789,1792,1794,1796,1799,1801],{"class":202,"line":239},[200,1782,796],{"class":779},[200,1784,799],{"class":206},[200,1786,684],{"class":242},[200,1788,226],{"class":206},[200,1790,1791],{"class":331},"Unauthorized",[200,1793,335],{"class":206},[200,1795,349],{"class":206},[200,1797,1798],{"class":345},"no user on request",[200,1800,349],{"class":206},[200,1802,352],{"class":206},[200,1804,1805],{"class":202,"line":257},[200,1806,822],{"class":206},[200,1808,1809,1812,1814,1817,1819,1822],{"class":202,"line":270},[200,1810,1811],{"class":242},"    claims ",[200,1813,323],{"class":206},[200,1815,1816],{"class":242}," user",[200,1818,226],{"class":206},[200,1820,1821],{"class":331},"GetClaims",[200,1823,1396],{"class":206},[200,1825,1826,1828,1831,1833,1835,1837,1840,1842,1845],{"class":202,"line":284},[200,1827,827],{"class":779},[200,1829,1830],{"class":331}," loadProfile",[200,1832,335],{"class":206},[200,1834,303],{"class":242},[200,1836,317],{"class":206},[200,1838,1839],{"class":242}," claims",[200,1841,226],{"class":206},[200,1843,1844],{"class":242},"Subject",[200,1846,352],{"class":206},[200,1848,1849],{"class":202,"line":291},[200,1850,851],{"class":206},[178,1852,1853,1856,1857,1859],{},[182,1854,1855],{},"ezz.UserFromContext(ctx)"," reads the same value from a plain ",[182,1858,188],{},", which is handy inside middleware or a service layer that does not take the ezz context.",[354,1861,1863],{"id":1862},"respect-the-context-lifetime","Respect the context lifetime",[178,1865,1866],{},"Contexts are pooled. When your handler returns, the context is reset and put back for the next request, so a reference kept beyond that point will observe another request's data.",[191,1868,1870],{"className":193,"code":1869,"language":195,"meta":196,"style":196},"\u002F\u002F wrong: ctx is recycled as soon as the handler returns\ngo func() {\n    report(ctx.GetRequestID())\n}()\n\n\u002F\u002F right: copy what you need, and use a context that outlives the request\nrequestID := ctx.GetRequestID()\ngo func() {\n    report(requestID)\n}()\n",[182,1871,1872,1877,1886,1902,1907,1911,1916,1931,1939,1950],{"__ignoreMap":196},[200,1873,1874],{"class":202,"line":203},[200,1875,1876],{"class":287},"\u002F\u002F wrong: ctx is recycled as soon as the handler returns\n",[200,1878,1879,1881,1884],{"class":202,"line":220},[200,1880,195],{"class":779},[200,1882,1883],{"class":206}," func()",[200,1885,217],{"class":206},[200,1887,1888,1891,1893,1895,1897,1899],{"class":202,"line":232},[200,1889,1890],{"class":331},"    report",[200,1892,335],{"class":206},[200,1894,303],{"class":242},[200,1896,226],{"class":206},[200,1898,506],{"class":331},[200,1900,1901],{"class":206},"())\n",[200,1903,1904],{"class":202,"line":239},[200,1905,1906],{"class":206},"}()\n",[200,1908,1909],{"class":202,"line":257},[200,1910,236],{"emptyLinePlaceholder":235},[200,1912,1913],{"class":202,"line":270},[200,1914,1915],{"class":287},"\u002F\u002F right: copy what you need, and use a context that outlives the request\n",[200,1917,1918,1921,1923,1925,1927,1929],{"class":202,"line":284},[200,1919,1920],{"class":242},"requestID ",[200,1922,323],{"class":206},[200,1924,501],{"class":242},[200,1926,226],{"class":206},[200,1928,506],{"class":331},[200,1930,1396],{"class":206},[200,1932,1933,1935,1937],{"class":202,"line":291},[200,1934,195],{"class":779},[200,1936,1883],{"class":206},[200,1938,217],{"class":206},[200,1940,1941,1943,1945,1948],{"class":202,"line":1201},[200,1942,1890],{"class":331},[200,1944,335],{"class":206},[200,1946,1947],{"class":242},"requestID",[200,1949,352],{"class":206},[200,1951,1952],{"class":202,"line":1206},[200,1953,1906],{"class":206},[178,1955,1956,1957,1959,1960,1962,1963,1966],{},"The same applies to ",[182,1958,188],{}," cancellation: ",[182,1961,303],{}," is derived from the request, so it is cancelled when the response completes. Background work that must outlive the response needs ",[182,1964,1965],{},"context.WithoutCancel"," or a fresh context.",[354,1968,1970],{"id":1969},"build-a-context-in-tests","Build a context in tests",[191,1972,1974],{"className":193,"code":1973,"language":195,"meta":196,"style":196},"w := httptest.NewRecorder()\nr := httptest.NewRequest(\"GET\", \"\u002Fusers\u002F42\", nil)\nr.SetPathValue(\"id\", \"42\")\n\nctx := ezz.NewTestContext(w, r)\nresp, err := getUser(ctx, GetUserRequest{ID: \"42\"})\n",[182,1975,1976,1993,2029,2059,2063,2089],{"__ignoreMap":196},[200,1977,1978,1981,1983,1986,1988,1991],{"class":202,"line":203},[200,1979,1980],{"class":242},"w ",[200,1982,323],{"class":206},[200,1984,1985],{"class":242}," httptest",[200,1987,226],{"class":206},[200,1989,1990],{"class":331},"NewRecorder",[200,1992,1396],{"class":206},[200,1994,1995,1998,2000,2002,2004,2007,2009,2011,2013,2015,2017,2019,2022,2024,2026],{"class":202,"line":220},[200,1996,1997],{"class":242},"r ",[200,1999,323],{"class":206},[200,2001,1985],{"class":242},[200,2003,226],{"class":206},[200,2005,2006],{"class":331},"NewRequest",[200,2008,335],{"class":206},[200,2010,349],{"class":206},[200,2012,670],{"class":345},[200,2014,349],{"class":206},[200,2016,317],{"class":206},[200,2018,342],{"class":206},[200,2020,2021],{"class":345},"\u002Fusers\u002F42",[200,2023,349],{"class":206},[200,2025,317],{"class":206},[200,2027,2028],{"class":206}," nil)\n",[200,2030,2031,2034,2036,2039,2041,2043,2046,2048,2050,2052,2055,2057],{"class":202,"line":232},[200,2032,2033],{"class":242},"r",[200,2035,226],{"class":206},[200,2037,2038],{"class":331},"SetPathValue",[200,2040,335],{"class":206},[200,2042,349],{"class":206},[200,2044,2045],{"class":345},"id",[200,2047,349],{"class":206},[200,2049,317],{"class":206},[200,2051,342],{"class":206},[200,2053,2054],{"class":345},"42",[200,2056,349],{"class":206},[200,2058,352],{"class":206},[200,2060,2061],{"class":202,"line":239},[200,2062,236],{"emptyLinePlaceholder":235},[200,2064,2065,2068,2070,2072,2074,2077,2079,2082,2084,2087],{"class":202,"line":257},[200,2066,2067],{"class":242},"ctx ",[200,2069,323],{"class":206},[200,2071,684],{"class":242},[200,2073,226],{"class":206},[200,2075,2076],{"class":331},"NewTestContext",[200,2078,335],{"class":206},[200,2080,2081],{"class":242},"w",[200,2083,317],{"class":206},[200,2085,2086],{"class":242}," r",[200,2088,352],{"class":206},[200,2090,2091,2094,2096,2098,2100,2103,2105,2107,2109,2112,2114,2117,2119,2121,2123,2125],{"class":202,"line":270},[200,2092,2093],{"class":242},"resp",[200,2095,317],{"class":206},[200,2097,320],{"class":242},[200,2099,323],{"class":206},[200,2101,2102],{"class":331}," getUser",[200,2104,335],{"class":206},[200,2106,303],{"class":242},[200,2108,317],{"class":206},[200,2110,2111],{"class":210}," GetUserRequest",[200,2113,1509],{"class":206},[200,2115,2116],{"class":242},"ID",[200,2118,1519],{"class":206},[200,2120,342],{"class":206},[200,2122,2054],{"class":345},[200,2124,349],{"class":206},[200,2126,2127],{"class":206},"})\n",[178,2129,2130,2131,2133],{},"See ",[564,2132,147],{"href":148}," for the rest of the helpers.",[354,2135,2137],{"id":2136},"next-steps","Next steps",[2139,2140,2141,2147],"ul",{},[2142,2143,2144,2146],"li",{},[564,2145,58],{"href":59}," for how returned errors become responses.",[2142,2148,2149,2151],{},[564,2150,63],{"href":64}," for work that happens around the handler.",[2153,2154,2155],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":196,"searchDepth":220,"depth":220,"links":2157},[2158,2159,2160,2161,2162,2163,2164,2165],{"id":356,"depth":220,"text":357},{"id":569,"depth":220,"text":570},{"id":861,"depth":220,"text":862},{"id":1263,"depth":220,"text":1264},{"id":1629,"depth":220,"text":1630},{"id":1862,"depth":220,"text":1863},{"id":1969,"depth":220,"text":1970},{"id":2136,"depth":220,"text":2137},"Read request data, write responses, stream events, and reach the authenticated user.","md",null,{},{"icon":56},{"title":53,"description":2166},"43PSUziSJQTq7YSl4vknzlzKdwc3paXraKuSvZIVMHA",[2174,2176],{"title":48,"path":49,"stem":50,"description":2175,"icon":51,"children":-1},"Reject bad input with validate tags before your handler runs.",{"title":58,"path":59,"stem":60,"description":2177,"icon":61,"children":-1},"Map Go errors to status codes and control the error body.",1784970047281]