[{"data":1,"prerenderedAt":2101},["ShallowReactive",2],{"navigation_docs":3,"-core-handlers":172,"-core-handlers-surround":2096},[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":38,"body":174,"description":2089,"extension":2090,"links":2091,"meta":2092,"navigation":2093,"path":39,"seo":2094,"stem":40,"__hash__":2095},"docs\u002F2.core\u002F2.handlers.md",{"type":175,"value":176,"toc":2078},"minimark",[177,181,243,257,262,552,562,566,573,666,682,686,689,736,739,850,857,965,969,980,1267,1271,1279,1433,1437,1442,1582,1586,1589,1819,1822,1969,1973,1981,2040,2047,2051,2074],[178,179,180],"p",{},"A handler is a function with this shape:",[182,183,188],"pre",{"className":184,"code":185,"language":186,"meta":187,"style":187},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","func(ctx *ezz.Context, req Req) (Resp, error)\n","go","",[189,190,191],"code",{"__ignoreMap":187},[192,193,196,200,204,207,211,214,216,219,222,225,228,231,234,236,240],"span",{"class":194,"line":195},"line",1,[192,197,199],{"class":198},"sMK4o","func(",[192,201,203],{"class":202},"sHdIc","ctx ",[192,205,206],{"class":198},"*",[192,208,210],{"class":209},"sBMFI","ezz",[192,212,213],{"class":198},".",[192,215,53],{"class":209},[192,217,218],{"class":198},",",[192,220,221],{"class":202}," req ",[192,223,224],{"class":209},"Req",[192,226,227],{"class":198},")",[192,229,230],{"class":198}," (",[192,232,233],{"class":209},"Resp",[192,235,218],{"class":198},[192,237,239],{"class":238},"spNyl"," error",[192,241,242],{"class":198},")\n",[178,244,245,248,249,252,253,256],{},[189,246,247],{},"ezz.H"," wraps it into a ",[189,250,251],{},"*Handler[Req, Resp]",", which implements ",[189,254,255],{},"http.Handler"," and reports its own request and response types so the OpenAPI generator can document it.",[258,259,261],"h2",{"id":260},"write-a-handler-with-a-request-type","Write a handler with a request type",[182,263,265],{"className":184,"code":264,"language":186,"meta":187,"style":187},"type GetUserRequest struct {\n    ID     string `path:\"id\" validate:\"required\"`\n    Expand bool   `query:\"expand\"`\n}\n\napp.GET(\"\u002Fusers\u002F{id}\", ezz.H(func(ctx *ezz.Context, req GetUserRequest) (*User, error) {\n    user, ok := store[req.ID]\n    if !ok {\n        return nil, ezz.NotFound(\"user not found\")\n    }\n    if req.Expand {\n        user.Orders = loadOrders(ctx, user.ID)\n    }\n    return user, nil\n}))\n",[189,266,267,281,301,318,324,331,402,433,449,476,482,496,528,533,546],{"__ignoreMap":187},[192,268,269,272,275,278],{"class":194,"line":195},[192,270,271],{"class":198},"type",[192,273,274],{"class":209}," GetUserRequest",[192,276,277],{"class":198}," struct",[192,279,280],{"class":198}," {\n",[192,282,284,288,291,294,298],{"class":194,"line":283},2,[192,285,287],{"class":286},"sTEyZ","    ID     ",[192,289,290],{"class":238},"string",[192,292,293],{"class":198}," `",[192,295,297],{"class":296},"sfazB","path:\"id\" validate:\"required\"",[192,299,300],{"class":198},"`\n",[192,302,304,307,310,313,316],{"class":194,"line":303},3,[192,305,306],{"class":286},"    Expand ",[192,308,309],{"class":238},"bool",[192,311,312],{"class":198},"   `",[192,314,315],{"class":296},"query:\"expand\"",[192,317,300],{"class":198},[192,319,321],{"class":194,"line":320},4,[192,322,323],{"class":198},"}\n",[192,325,327],{"class":194,"line":326},5,[192,328,330],{"emptyLinePlaceholder":329},true,"\n",[192,332,334,337,339,343,346,349,352,354,356,359,361,364,367,370,373,375,377,379,381,384,386,388,391,394,396,398,400],{"class":194,"line":333},6,[192,335,336],{"class":286},"app",[192,338,213],{"class":198},[192,340,342],{"class":341},"s2Zo4","GET",[192,344,345],{"class":198},"(",[192,347,348],{"class":198},"\"",[192,350,351],{"class":296},"\u002Fusers\u002F{id}",[192,353,348],{"class":198},[192,355,218],{"class":198},[192,357,358],{"class":286}," ezz",[192,360,213],{"class":198},[192,362,363],{"class":341},"H",[192,365,366],{"class":198},"(func(",[192,368,369],{"class":202},"ctx",[192,371,372],{"class":198}," *",[192,374,210],{"class":209},[192,376,213],{"class":198},[192,378,53],{"class":209},[192,380,218],{"class":198},[192,382,383],{"class":202}," req",[192,385,274],{"class":209},[192,387,227],{"class":198},[192,389,390],{"class":198}," (*",[192,392,393],{"class":209},"User",[192,395,218],{"class":198},[192,397,239],{"class":238},[192,399,227],{"class":198},[192,401,280],{"class":198},[192,403,405,408,410,413,416,419,422,425,427,430],{"class":194,"line":404},7,[192,406,407],{"class":286},"    user",[192,409,218],{"class":198},[192,411,412],{"class":286}," ok ",[192,414,415],{"class":198},":=",[192,417,418],{"class":286}," store",[192,420,421],{"class":198},"[",[192,423,424],{"class":286},"req",[192,426,213],{"class":198},[192,428,429],{"class":286},"ID",[192,431,432],{"class":198},"]\n",[192,434,436,440,443,446],{"class":194,"line":435},8,[192,437,439],{"class":438},"s7zQu","    if",[192,441,442],{"class":198}," !",[192,444,445],{"class":286},"ok ",[192,447,448],{"class":198},"{\n",[192,450,452,455,458,460,462,465,467,469,472,474],{"class":194,"line":451},9,[192,453,454],{"class":438},"        return",[192,456,457],{"class":198}," nil,",[192,459,358],{"class":286},[192,461,213],{"class":198},[192,463,464],{"class":341},"NotFound",[192,466,345],{"class":198},[192,468,348],{"class":198},[192,470,471],{"class":296},"user not found",[192,473,348],{"class":198},[192,475,242],{"class":198},[192,477,479],{"class":194,"line":478},10,[192,480,481],{"class":198},"    }\n",[192,483,485,487,489,491,494],{"class":194,"line":484},11,[192,486,439],{"class":438},[192,488,383],{"class":286},[192,490,213],{"class":198},[192,492,493],{"class":286},"Expand ",[192,495,448],{"class":198},[192,497,499,502,504,507,510,513,515,517,519,522,524,526],{"class":194,"line":498},12,[192,500,501],{"class":286},"        user",[192,503,213],{"class":198},[192,505,506],{"class":286},"Orders ",[192,508,509],{"class":198},"=",[192,511,512],{"class":341}," loadOrders",[192,514,345],{"class":198},[192,516,369],{"class":286},[192,518,218],{"class":198},[192,520,521],{"class":286}," user",[192,523,213],{"class":198},[192,525,429],{"class":286},[192,527,242],{"class":198},[192,529,531],{"class":194,"line":530},13,[192,532,481],{"class":198},[192,534,536,539,541,543],{"class":194,"line":535},14,[192,537,538],{"class":438},"    return",[192,540,521],{"class":286},[192,542,218],{"class":198},[192,544,545],{"class":198}," nil\n",[192,547,549],{"class":194,"line":548},15,[192,550,551],{"class":198},"}))\n",[178,553,554,555,557,558,561],{},"Before your function runs, ezz binds ",[189,556,424],{}," from the request and validates it. A binding or validation failure returns ",[189,559,560],{},"400"," and your function is never called.",[258,563,565],{"id":564},"write-a-handler-without-a-request-type","Write a handler without a request type",[178,567,568,569,572],{},"When there is nothing to bind, ",[189,570,571],{},"ezz.HFunc"," drops the second parameter:",[182,574,576],{"className":184,"code":575,"language":186,"meta":187,"style":187},"app.GET(\"\u002Fhealth\", ezz.HFunc(func(ctx *ezz.Context) (*HealthResponse, error) {\n    return &HealthResponse{Status: \"ok\"}, nil\n}))\n",[189,577,578,631,662],{"__ignoreMap":187},[192,579,580,582,584,586,588,590,593,595,597,599,601,604,606,608,610,612,614,616,618,620,623,625,627,629],{"class":194,"line":195},[192,581,336],{"class":286},[192,583,213],{"class":198},[192,585,342],{"class":341},[192,587,345],{"class":198},[192,589,348],{"class":198},[192,591,592],{"class":296},"\u002Fhealth",[192,594,348],{"class":198},[192,596,218],{"class":198},[192,598,358],{"class":286},[192,600,213],{"class":198},[192,602,603],{"class":341},"HFunc",[192,605,366],{"class":198},[192,607,369],{"class":202},[192,609,372],{"class":198},[192,611,210],{"class":209},[192,613,213],{"class":198},[192,615,53],{"class":209},[192,617,227],{"class":198},[192,619,390],{"class":198},[192,621,622],{"class":209},"HealthResponse",[192,624,218],{"class":198},[192,626,239],{"class":238},[192,628,227],{"class":198},[192,630,280],{"class":198},[192,632,633,635,638,640,643,646,649,652,655,657,660],{"class":194,"line":283},[192,634,538],{"class":438},[192,636,637],{"class":198}," &",[192,639,622],{"class":209},[192,641,642],{"class":198},"{",[192,644,645],{"class":286},"Status",[192,647,648],{"class":198},":",[192,650,651],{"class":198}," \"",[192,653,654],{"class":296},"ok",[192,656,348],{"class":198},[192,658,659],{"class":198},"},",[192,661,545],{"class":198},[192,663,664],{"class":194,"line":303},[192,665,551],{"class":198},[178,667,668,670,671,674,675,678,679,213],{},[189,669,247],{}," with a ",[189,672,673],{},"struct{}"," request type does the same thing, which is why ",[189,676,677],{},"ezz.HFunc(fn)"," has the type ",[189,680,681],{},"*Handler[struct{}, Resp]",[258,683,685],{"id":684},"understand-when-the-response-is-written","Understand when the response is written",[178,687,688],{},"After your function returns, ezz decides what to send:",[690,691,692,699,719,725],"ol",{},[693,694,695,696,213],"li",{},"If the function returned an error, the error is written and nothing else happens. See ",[697,698,58],"a",{"href":59},[693,700,701,702,705,706,705,709,705,712,705,715,718],{},"If you already wrote to the response yourself (",[189,703,704],{},"ctx.JSON",", ",[189,707,708],{},"ctx.Status",[189,710,711],{},"ctx.Redirect",[189,713,714],{},"ctx.ServeFile",[189,716,717],{},"ctx.Stream",", or a direct write), ezz leaves it alone.",[693,720,721,722,213],{},"Otherwise, if the returned value is not the zero value for its type, it is encoded as JSON with status ",[189,723,724],{},"200",[693,726,727,728,732,733,735],{},"If the returned value ",[729,730,731],"em",{},"is"," the zero value, nothing is written, and the server sends ",[189,734,724],{}," with an empty body.",[178,737,738],{},"That last rule is worth internalising:",[182,740,742],{"className":184,"code":741,"language":186,"meta":187,"style":187},"\u002F\u002F writes {\"status\":\"ok\"}\nreturn &HealthResponse{Status: \"ok\"}, nil\n\n\u002F\u002F writes {} because the pointer is non-nil\nreturn &HealthResponse{}, nil\n\n\u002F\u002F writes nothing: a nil pointer is the zero value\nvar h *HealthResponse\nreturn h, nil\n\n\u002F\u002F writes nothing: an empty struct value is the zero value\nreturn HealthResponse{}, nil\n",[189,743,744,750,775,779,784,797,801,806,819,830,834,839],{"__ignoreMap":187},[192,745,746],{"class":194,"line":195},[192,747,749],{"class":748},"sHwdD","\u002F\u002F writes {\"status\":\"ok\"}\n",[192,751,752,755,757,759,761,763,765,767,769,771,773],{"class":194,"line":283},[192,753,754],{"class":438},"return",[192,756,637],{"class":198},[192,758,622],{"class":209},[192,760,642],{"class":198},[192,762,645],{"class":286},[192,764,648],{"class":198},[192,766,651],{"class":198},[192,768,654],{"class":296},[192,770,348],{"class":198},[192,772,659],{"class":198},[192,774,545],{"class":198},[192,776,777],{"class":194,"line":303},[192,778,330],{"emptyLinePlaceholder":329},[192,780,781],{"class":194,"line":320},[192,782,783],{"class":748},"\u002F\u002F writes {} because the pointer is non-nil\n",[192,785,786,788,790,792,795],{"class":194,"line":326},[192,787,754],{"class":438},[192,789,637],{"class":198},[192,791,622],{"class":209},[192,793,794],{"class":198},"{},",[192,796,545],{"class":198},[192,798,799],{"class":194,"line":333},[192,800,330],{"emptyLinePlaceholder":329},[192,802,803],{"class":194,"line":404},[192,804,805],{"class":748},"\u002F\u002F writes nothing: a nil pointer is the zero value\n",[192,807,808,811,814,816],{"class":194,"line":435},[192,809,810],{"class":198},"var",[192,812,813],{"class":286}," h ",[192,815,206],{"class":198},[192,817,818],{"class":209},"HealthResponse\n",[192,820,821,823,826,828],{"class":194,"line":451},[192,822,754],{"class":438},[192,824,825],{"class":286}," h",[192,827,218],{"class":198},[192,829,545],{"class":198},[192,831,832],{"class":194,"line":478},[192,833,330],{"emptyLinePlaceholder":329},[192,835,836],{"class":194,"line":484},[192,837,838],{"class":748},"\u002F\u002F writes nothing: an empty struct value is the zero value\n",[192,840,841,843,846,848],{"class":194,"line":498},[192,842,754],{"class":438},[192,844,845],{"class":209}," HealthResponse",[192,847,794],{"class":198},[192,849,545],{"class":198},[178,851,852,853,856],{},"Prefer pointer response types (",[189,854,855],{},"*User",") or types that are never meaningfully empty. If you genuinely want an empty success, be explicit:",[182,858,860],{"className":184,"code":859,"language":186,"meta":187,"style":187},"app.DELETE(\"\u002Fusers\u002F{id}\", ezz.H(func(ctx *ezz.Context, req DeleteUserRequest) (any, error) {\n    store.Delete(req.ID)\n    return nil, ctx.NoContent()   \u002F\u002F 204, no body\n}))\n",[189,861,862,921,941,961],{"__ignoreMap":187},[192,863,864,866,868,871,873,875,877,879,881,883,885,887,889,891,893,895,897,899,901,903,906,908,910,913,915,917,919],{"class":194,"line":195},[192,865,336],{"class":286},[192,867,213],{"class":198},[192,869,870],{"class":341},"DELETE",[192,872,345],{"class":198},[192,874,348],{"class":198},[192,876,351],{"class":296},[192,878,348],{"class":198},[192,880,218],{"class":198},[192,882,358],{"class":286},[192,884,213],{"class":198},[192,886,363],{"class":341},[192,888,366],{"class":198},[192,890,369],{"class":202},[192,892,372],{"class":198},[192,894,210],{"class":209},[192,896,213],{"class":198},[192,898,53],{"class":209},[192,900,218],{"class":198},[192,902,383],{"class":202},[192,904,905],{"class":209}," DeleteUserRequest",[192,907,227],{"class":198},[192,909,230],{"class":198},[192,911,912],{"class":209},"any",[192,914,218],{"class":198},[192,916,239],{"class":238},[192,918,227],{"class":198},[192,920,280],{"class":198},[192,922,923,926,928,931,933,935,937,939],{"class":194,"line":283},[192,924,925],{"class":286},"    store",[192,927,213],{"class":198},[192,929,930],{"class":341},"Delete",[192,932,345],{"class":198},[192,934,424],{"class":286},[192,936,213],{"class":198},[192,938,429],{"class":286},[192,940,242],{"class":198},[192,942,943,945,947,950,952,955,958],{"class":194,"line":303},[192,944,538],{"class":438},[192,946,457],{"class":198},[192,948,949],{"class":286}," ctx",[192,951,213],{"class":198},[192,953,954],{"class":341},"NoContent",[192,956,957],{"class":198},"()",[192,959,960],{"class":748},"   \u002F\u002F 204, no body\n",[192,962,963],{"class":194,"line":320},[192,964,551],{"class":198},[258,966,968],{"id":967},"take-over-the-response","Take over the response",[178,970,971,972,975,976,979],{},"The context gives you the raw ",[189,973,974],{},"http.ResponseWriter",", so a handler can write anything. Return ",[189,977,978],{},"nil"," afterwards and ezz will not touch the response.",[182,981,983],{"className":184,"code":982,"language":186,"meta":187,"style":187},"app.GET(\"\u002Freports\u002F{id}.csv\", ezz.H(func(ctx *ezz.Context, req ReportRequest) (any, error) {\n    ctx.SetHeader(\"Content-Type\", \"text\u002Fcsv\")\n    ctx.SetHeader(\"Content-Disposition\", `attachment; filename=\"report.csv\"`)\n    ctx.Status(http.StatusOK)\n\n    w := csv.NewWriter(ctx.Response)\n    defer w.Flush()\n    for _, row := range rows(req.ID) {\n        if err := w.Write(row); err != nil {\n            return nil, err\n        }\n    }\n    return nil, nil\n}))\n",[189,984,985,1043,1073,1102,1122,1126,1152,1168,1201,1236,1246,1251,1255,1263],{"__ignoreMap":187},[192,986,987,989,991,993,995,997,1000,1002,1004,1006,1008,1010,1012,1014,1016,1018,1020,1022,1024,1026,1029,1031,1033,1035,1037,1039,1041],{"class":194,"line":195},[192,988,336],{"class":286},[192,990,213],{"class":198},[192,992,342],{"class":341},[192,994,345],{"class":198},[192,996,348],{"class":198},[192,998,999],{"class":296},"\u002Freports\u002F{id}.csv",[192,1001,348],{"class":198},[192,1003,218],{"class":198},[192,1005,358],{"class":286},[192,1007,213],{"class":198},[192,1009,363],{"class":341},[192,1011,366],{"class":198},[192,1013,369],{"class":202},[192,1015,372],{"class":198},[192,1017,210],{"class":209},[192,1019,213],{"class":198},[192,1021,53],{"class":209},[192,1023,218],{"class":198},[192,1025,383],{"class":202},[192,1027,1028],{"class":209}," ReportRequest",[192,1030,227],{"class":198},[192,1032,230],{"class":198},[192,1034,912],{"class":209},[192,1036,218],{"class":198},[192,1038,239],{"class":238},[192,1040,227],{"class":198},[192,1042,280],{"class":198},[192,1044,1045,1048,1050,1053,1055,1057,1060,1062,1064,1066,1069,1071],{"class":194,"line":283},[192,1046,1047],{"class":286},"    ctx",[192,1049,213],{"class":198},[192,1051,1052],{"class":341},"SetHeader",[192,1054,345],{"class":198},[192,1056,348],{"class":198},[192,1058,1059],{"class":296},"Content-Type",[192,1061,348],{"class":198},[192,1063,218],{"class":198},[192,1065,651],{"class":198},[192,1067,1068],{"class":296},"text\u002Fcsv",[192,1070,348],{"class":198},[192,1072,242],{"class":198},[192,1074,1075,1077,1079,1081,1083,1085,1088,1090,1092,1094,1097,1100],{"class":194,"line":303},[192,1076,1047],{"class":286},[192,1078,213],{"class":198},[192,1080,1052],{"class":341},[192,1082,345],{"class":198},[192,1084,348],{"class":198},[192,1086,1087],{"class":296},"Content-Disposition",[192,1089,348],{"class":198},[192,1091,218],{"class":198},[192,1093,293],{"class":198},[192,1095,1096],{"class":296},"attachment; filename=\"report.csv\"",[192,1098,1099],{"class":198},"`",[192,1101,242],{"class":198},[192,1103,1104,1106,1108,1110,1112,1115,1117,1120],{"class":194,"line":320},[192,1105,1047],{"class":286},[192,1107,213],{"class":198},[192,1109,645],{"class":341},[192,1111,345],{"class":198},[192,1113,1114],{"class":286},"http",[192,1116,213],{"class":198},[192,1118,1119],{"class":286},"StatusOK",[192,1121,242],{"class":198},[192,1123,1124],{"class":194,"line":326},[192,1125,330],{"emptyLinePlaceholder":329},[192,1127,1128,1131,1133,1136,1138,1141,1143,1145,1147,1150],{"class":194,"line":333},[192,1129,1130],{"class":286},"    w ",[192,1132,415],{"class":198},[192,1134,1135],{"class":286}," csv",[192,1137,213],{"class":198},[192,1139,1140],{"class":341},"NewWriter",[192,1142,345],{"class":198},[192,1144,369],{"class":286},[192,1146,213],{"class":198},[192,1148,1149],{"class":286},"Response",[192,1151,242],{"class":198},[192,1153,1154,1157,1160,1162,1165],{"class":194,"line":404},[192,1155,1156],{"class":438},"    defer",[192,1158,1159],{"class":286}," w",[192,1161,213],{"class":198},[192,1163,1164],{"class":341},"Flush",[192,1166,1167],{"class":198},"()\n",[192,1169,1170,1173,1176,1178,1181,1183,1186,1189,1191,1193,1195,1197,1199],{"class":194,"line":435},[192,1171,1172],{"class":438},"    for",[192,1174,1175],{"class":286}," _",[192,1177,218],{"class":198},[192,1179,1180],{"class":286}," row ",[192,1182,415],{"class":198},[192,1184,1185],{"class":438}," range",[192,1187,1188],{"class":341}," rows",[192,1190,345],{"class":198},[192,1192,424],{"class":286},[192,1194,213],{"class":198},[192,1196,429],{"class":286},[192,1198,227],{"class":198},[192,1200,280],{"class":198},[192,1202,1203,1206,1209,1211,1213,1215,1218,1220,1223,1226,1228,1231,1234],{"class":194,"line":451},[192,1204,1205],{"class":438},"        if",[192,1207,1208],{"class":286}," err ",[192,1210,415],{"class":198},[192,1212,1159],{"class":286},[192,1214,213],{"class":198},[192,1216,1217],{"class":341},"Write",[192,1219,345],{"class":198},[192,1221,1222],{"class":286},"row",[192,1224,1225],{"class":198},");",[192,1227,1208],{"class":286},[192,1229,1230],{"class":198},"!=",[192,1232,1233],{"class":198}," nil",[192,1235,280],{"class":198},[192,1237,1238,1241,1243],{"class":194,"line":478},[192,1239,1240],{"class":438},"            return",[192,1242,457],{"class":198},[192,1244,1245],{"class":286}," err\n",[192,1247,1248],{"class":194,"line":484},[192,1249,1250],{"class":198},"        }\n",[192,1252,1253],{"class":194,"line":498},[192,1254,481],{"class":198},[192,1256,1257,1259,1261],{"class":194,"line":530},[192,1258,538],{"class":438},[192,1260,457],{"class":198},[192,1262,545],{"class":198},[192,1264,1265],{"class":194,"line":535},[192,1266,551],{"class":198},[258,1268,1270],{"id":1269},"choose-a-response-status-other-than-200","Choose a response status other than 200",[178,1272,1273,1274,1276,1277,648],{},"Call ",[189,1275,704],{}," with the status you want, then return ",[189,1278,978],{},[182,1280,1282],{"className":184,"code":1281,"language":186,"meta":187,"style":187},"app.POST(\"\u002Fusers\", ezz.H(func(ctx *ezz.Context, req CreateUserRequest) (any, error) {\n    user := store.Create(req)\n    ctx.SetHeader(\"Location\", \"\u002Fusers\u002F\"+user.ID)\n    return nil, ctx.JSON(http.StatusCreated, user)\n}))\n",[189,1283,1284,1343,1363,1401,1429],{"__ignoreMap":187},[192,1285,1286,1288,1290,1293,1295,1297,1300,1302,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1326,1329,1331,1333,1335,1337,1339,1341],{"class":194,"line":195},[192,1287,336],{"class":286},[192,1289,213],{"class":198},[192,1291,1292],{"class":341},"POST",[192,1294,345],{"class":198},[192,1296,348],{"class":198},[192,1298,1299],{"class":296},"\u002Fusers",[192,1301,348],{"class":198},[192,1303,218],{"class":198},[192,1305,358],{"class":286},[192,1307,213],{"class":198},[192,1309,363],{"class":341},[192,1311,366],{"class":198},[192,1313,369],{"class":202},[192,1315,372],{"class":198},[192,1317,210],{"class":209},[192,1319,213],{"class":198},[192,1321,53],{"class":209},[192,1323,218],{"class":198},[192,1325,383],{"class":202},[192,1327,1328],{"class":209}," CreateUserRequest",[192,1330,227],{"class":198},[192,1332,230],{"class":198},[192,1334,912],{"class":209},[192,1336,218],{"class":198},[192,1338,239],{"class":238},[192,1340,227],{"class":198},[192,1342,280],{"class":198},[192,1344,1345,1348,1350,1352,1354,1357,1359,1361],{"class":194,"line":283},[192,1346,1347],{"class":286},"    user ",[192,1349,415],{"class":198},[192,1351,418],{"class":286},[192,1353,213],{"class":198},[192,1355,1356],{"class":341},"Create",[192,1358,345],{"class":198},[192,1360,424],{"class":286},[192,1362,242],{"class":198},[192,1364,1365,1367,1369,1371,1373,1375,1378,1380,1382,1384,1387,1389,1392,1395,1397,1399],{"class":194,"line":303},[192,1366,1047],{"class":286},[192,1368,213],{"class":198},[192,1370,1052],{"class":341},[192,1372,345],{"class":198},[192,1374,348],{"class":198},[192,1376,1377],{"class":296},"Location",[192,1379,348],{"class":198},[192,1381,218],{"class":198},[192,1383,651],{"class":198},[192,1385,1386],{"class":296},"\u002Fusers\u002F",[192,1388,348],{"class":198},[192,1390,1391],{"class":198},"+",[192,1393,1394],{"class":286},"user",[192,1396,213],{"class":198},[192,1398,429],{"class":286},[192,1400,242],{"class":198},[192,1402,1403,1405,1407,1409,1411,1414,1416,1418,1420,1423,1425,1427],{"class":194,"line":320},[192,1404,538],{"class":438},[192,1406,457],{"class":198},[192,1408,949],{"class":286},[192,1410,213],{"class":198},[192,1412,1413],{"class":341},"JSON",[192,1415,345],{"class":198},[192,1417,1114],{"class":286},[192,1419,213],{"class":198},[192,1421,1422],{"class":286},"StatusCreated",[192,1424,218],{"class":198},[192,1426,521],{"class":286},[192,1428,242],{"class":198},[192,1430,1431],{"class":194,"line":326},[192,1432,551],{"class":198},[258,1434,1436],{"id":1435},"build-handlers-once-at-startup","Build handlers once, at startup",[178,1438,1439,1441],{},[189,1440,247],{}," inspects the request type and compiles a binder and a validator when you call it. Do that at registration time, which is what the examples above do, and the request path stays reflection-free.",[182,1443,1445],{"className":184,"code":1444,"language":186,"meta":187,"style":187},"\u002F\u002F good: compiled once at startup\napp.POST(\"\u002Fusers\", ezz.H(createUser))\n\n\u002F\u002F bad: builds a new binder and validator on every request\napp.POST(\"\u002Fusers\", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n    ezz.H(createUser).ServeHTTP(w, r)\n}))\n",[189,1446,1447,1452,1484,1488,1493,1549,1578],{"__ignoreMap":187},[192,1448,1449],{"class":194,"line":195},[192,1450,1451],{"class":748},"\u002F\u002F good: compiled once at startup\n",[192,1453,1454,1456,1458,1460,1462,1464,1466,1468,1470,1472,1474,1476,1478,1481],{"class":194,"line":283},[192,1455,336],{"class":286},[192,1457,213],{"class":198},[192,1459,1292],{"class":341},[192,1461,345],{"class":198},[192,1463,348],{"class":198},[192,1465,1299],{"class":296},[192,1467,348],{"class":198},[192,1469,218],{"class":198},[192,1471,358],{"class":286},[192,1473,213],{"class":198},[192,1475,363],{"class":341},[192,1477,345],{"class":198},[192,1479,1480],{"class":286},"createUser",[192,1482,1483],{"class":198},"))\n",[192,1485,1486],{"class":194,"line":303},[192,1487,330],{"emptyLinePlaceholder":329},[192,1489,1490],{"class":194,"line":320},[192,1491,1492],{"class":748},"\u002F\u002F bad: builds a new binder and validator on every request\n",[192,1494,1495,1497,1499,1501,1503,1505,1507,1509,1511,1514,1516,1519,1521,1524,1526,1528,1531,1533,1536,1538,1540,1542,1545,1547],{"class":194,"line":326},[192,1496,336],{"class":286},[192,1498,213],{"class":198},[192,1500,1292],{"class":341},[192,1502,345],{"class":198},[192,1504,348],{"class":198},[192,1506,1299],{"class":296},[192,1508,348],{"class":198},[192,1510,218],{"class":198},[192,1512,1513],{"class":286}," http",[192,1515,213],{"class":198},[192,1517,1518],{"class":341},"HandlerFunc",[192,1520,366],{"class":198},[192,1522,1523],{"class":202},"w",[192,1525,1513],{"class":209},[192,1527,213],{"class":198},[192,1529,1530],{"class":209},"ResponseWriter",[192,1532,218],{"class":198},[192,1534,1535],{"class":202}," r",[192,1537,372],{"class":198},[192,1539,1114],{"class":209},[192,1541,213],{"class":198},[192,1543,1544],{"class":209},"Request",[192,1546,227],{"class":198},[192,1548,280],{"class":198},[192,1550,1551,1554,1556,1558,1560,1562,1565,1568,1570,1572,1574,1576],{"class":194,"line":333},[192,1552,1553],{"class":286},"    ezz",[192,1555,213],{"class":198},[192,1557,363],{"class":341},[192,1559,345],{"class":198},[192,1561,1480],{"class":286},[192,1563,1564],{"class":198},").",[192,1566,1567],{"class":341},"ServeHTTP",[192,1569,345],{"class":198},[192,1571,1523],{"class":286},[192,1573,218],{"class":198},[192,1575,1535],{"class":286},[192,1577,242],{"class":198},[192,1579,1580],{"class":194,"line":404},[192,1581,551],{"class":198},[258,1583,1585],{"id":1584},"reuse-handler-functions","Reuse handler functions",[178,1587,1588],{},"Handlers are ordinary functions, so the usual Go patterns apply. Closures are the simplest way to inject dependencies:",[182,1590,1592],{"className":184,"code":1591,"language":186,"meta":187,"style":187},"func getUser(store *Store) func(*ezz.Context, GetUserRequest) (*User, error) {\n    return func(ctx *ezz.Context, req GetUserRequest) (*User, error) {\n        user, err := store.Find(ctx, req.ID)\n        if errors.Is(err, ErrNotFound) {\n            return nil, ezz.NotFound(\"user not found\")\n        }\n        return user, err\n    }\n}\n\napp.GET(\"\u002Fusers\u002F{id}\", ezz.H(getUser(store)))\n",[189,1593,1594,1641,1678,1709,1735,1757,1761,1771,1775,1779,1783],{"__ignoreMap":187},[192,1595,1596,1599,1602,1604,1607,1609,1612,1614,1617,1619,1621,1623,1625,1627,1629,1631,1633,1635,1637,1639],{"class":194,"line":195},[192,1597,1598],{"class":198},"func",[192,1600,1601],{"class":341}," getUser",[192,1603,345],{"class":198},[192,1605,1606],{"class":202},"store",[192,1608,372],{"class":198},[192,1610,1611],{"class":209},"Store",[192,1613,227],{"class":198},[192,1615,1616],{"class":198}," func(*",[192,1618,210],{"class":209},[192,1620,213],{"class":198},[192,1622,53],{"class":209},[192,1624,218],{"class":198},[192,1626,274],{"class":209},[192,1628,227],{"class":198},[192,1630,390],{"class":198},[192,1632,393],{"class":209},[192,1634,218],{"class":198},[192,1636,239],{"class":238},[192,1638,227],{"class":198},[192,1640,280],{"class":198},[192,1642,1643,1645,1648,1650,1652,1654,1656,1658,1660,1662,1664,1666,1668,1670,1672,1674,1676],{"class":194,"line":283},[192,1644,538],{"class":438},[192,1646,1647],{"class":198}," func(",[192,1649,369],{"class":202},[192,1651,372],{"class":198},[192,1653,210],{"class":209},[192,1655,213],{"class":198},[192,1657,53],{"class":209},[192,1659,218],{"class":198},[192,1661,383],{"class":202},[192,1663,274],{"class":209},[192,1665,227],{"class":198},[192,1667,390],{"class":198},[192,1669,393],{"class":209},[192,1671,218],{"class":198},[192,1673,239],{"class":238},[192,1675,227],{"class":198},[192,1677,280],{"class":198},[192,1679,1680,1682,1684,1686,1688,1690,1692,1695,1697,1699,1701,1703,1705,1707],{"class":194,"line":303},[192,1681,501],{"class":286},[192,1683,218],{"class":198},[192,1685,1208],{"class":286},[192,1687,415],{"class":198},[192,1689,418],{"class":286},[192,1691,213],{"class":198},[192,1693,1694],{"class":341},"Find",[192,1696,345],{"class":198},[192,1698,369],{"class":286},[192,1700,218],{"class":198},[192,1702,383],{"class":286},[192,1704,213],{"class":198},[192,1706,429],{"class":286},[192,1708,242],{"class":198},[192,1710,1711,1713,1716,1718,1721,1723,1726,1728,1731,1733],{"class":194,"line":320},[192,1712,1205],{"class":438},[192,1714,1715],{"class":286}," errors",[192,1717,213],{"class":198},[192,1719,1720],{"class":341},"Is",[192,1722,345],{"class":198},[192,1724,1725],{"class":286},"err",[192,1727,218],{"class":198},[192,1729,1730],{"class":286}," ErrNotFound",[192,1732,227],{"class":198},[192,1734,280],{"class":198},[192,1736,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755],{"class":194,"line":326},[192,1738,1240],{"class":438},[192,1740,457],{"class":198},[192,1742,358],{"class":286},[192,1744,213],{"class":198},[192,1746,464],{"class":341},[192,1748,345],{"class":198},[192,1750,348],{"class":198},[192,1752,471],{"class":296},[192,1754,348],{"class":198},[192,1756,242],{"class":198},[192,1758,1759],{"class":194,"line":333},[192,1760,1250],{"class":198},[192,1762,1763,1765,1767,1769],{"class":194,"line":404},[192,1764,454],{"class":438},[192,1766,521],{"class":286},[192,1768,218],{"class":198},[192,1770,1245],{"class":286},[192,1772,1773],{"class":194,"line":435},[192,1774,481],{"class":198},[192,1776,1777],{"class":194,"line":451},[192,1778,323],{"class":198},[192,1780,1781],{"class":194,"line":478},[192,1782,330],{"emptyLinePlaceholder":329},[192,1784,1785,1787,1789,1791,1793,1795,1797,1799,1801,1803,1805,1807,1809,1812,1814,1816],{"class":194,"line":484},[192,1786,336],{"class":286},[192,1788,213],{"class":198},[192,1790,342],{"class":341},[192,1792,345],{"class":198},[192,1794,348],{"class":198},[192,1796,351],{"class":296},[192,1798,348],{"class":198},[192,1800,218],{"class":198},[192,1802,358],{"class":209},[192,1804,213],{"class":198},[192,1806,363],{"class":209},[192,1808,345],{"class":198},[192,1810,1811],{"class":209},"getUser",[192,1813,345],{"class":198},[192,1815,1606],{"class":209},[192,1817,1818],{"class":198},")))\n",[178,1820,1821],{},"Methods on a service struct work equally well:",[182,1823,1825],{"className":184,"code":1824,"language":186,"meta":187,"style":187},"type UserAPI struct{ store *Store }\n\nfunc (a *UserAPI) Get(ctx *ezz.Context, req GetUserRequest) (*User, error) { ... }\n\napi := &UserAPI{store: store}\napp.GET(\"\u002Fusers\u002F{id}\", ezz.H(api.Get))\n",[189,1826,1827,1847,1851,1908,1912,1933],{"__ignoreMap":187},[192,1828,1829,1831,1834,1837,1840,1842,1844],{"class":194,"line":195},[192,1830,271],{"class":198},[192,1832,1833],{"class":209}," UserAPI",[192,1835,1836],{"class":198}," struct{",[192,1838,1839],{"class":286}," store ",[192,1841,206],{"class":198},[192,1843,1611],{"class":209},[192,1845,1846],{"class":198}," }\n",[192,1848,1849],{"class":194,"line":283},[192,1850,330],{"emptyLinePlaceholder":329},[192,1852,1853,1855,1857,1860,1862,1865,1867,1870,1872,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896,1898,1900,1903,1906],{"class":194,"line":303},[192,1854,1598],{"class":198},[192,1856,230],{"class":198},[192,1858,1859],{"class":202},"a ",[192,1861,206],{"class":198},[192,1863,1864],{"class":209},"UserAPI",[192,1866,227],{"class":198},[192,1868,1869],{"class":341}," Get",[192,1871,345],{"class":198},[192,1873,369],{"class":202},[192,1875,372],{"class":198},[192,1877,210],{"class":209},[192,1879,213],{"class":198},[192,1881,53],{"class":209},[192,1883,218],{"class":198},[192,1885,383],{"class":202},[192,1887,274],{"class":209},[192,1889,227],{"class":198},[192,1891,390],{"class":198},[192,1893,393],{"class":209},[192,1895,218],{"class":198},[192,1897,239],{"class":238},[192,1899,227],{"class":198},[192,1901,1902],{"class":198}," {",[192,1904,1905],{"class":198}," ...",[192,1907,1846],{"class":198},[192,1909,1910],{"class":194,"line":320},[192,1911,330],{"emptyLinePlaceholder":329},[192,1913,1914,1917,1919,1921,1923,1925,1927,1929,1931],{"class":194,"line":326},[192,1915,1916],{"class":286},"api ",[192,1918,415],{"class":198},[192,1920,637],{"class":198},[192,1922,1864],{"class":209},[192,1924,642],{"class":198},[192,1926,1606],{"class":286},[192,1928,648],{"class":198},[192,1930,418],{"class":286},[192,1932,323],{"class":198},[192,1934,1935,1937,1939,1941,1943,1945,1947,1949,1951,1953,1955,1957,1959,1962,1964,1967],{"class":194,"line":333},[192,1936,336],{"class":286},[192,1938,213],{"class":198},[192,1940,342],{"class":341},[192,1942,345],{"class":198},[192,1944,348],{"class":198},[192,1946,351],{"class":296},[192,1948,348],{"class":198},[192,1950,218],{"class":198},[192,1952,358],{"class":286},[192,1954,213],{"class":198},[192,1956,363],{"class":341},[192,1958,345],{"class":198},[192,1960,1961],{"class":286},"api",[192,1963,213],{"class":198},[192,1965,1966],{"class":286},"Get",[192,1968,1483],{"class":198},[258,1970,1972],{"id":1971},"inspect-a-handlers-types","Inspect a handler's types",[178,1974,1975,1977,1978,648],{},[189,1976,251],{}," satisfies ",[189,1979,1980],{},"ezz.TypedHandler",[182,1982,1984],{"className":184,"code":1983,"language":186,"meta":187,"style":187},"type TypedHandler interface {\n    http.Handler\n    RequestType() reflect.Type\n    ResponseType() reflect.Type\n}\n",[189,1985,1986,1998,2008,2023,2036],{"__ignoreMap":187},[192,1987,1988,1990,1993,1996],{"class":194,"line":195},[192,1989,271],{"class":198},[192,1991,1992],{"class":209}," TypedHandler",[192,1994,1995],{"class":198}," interface",[192,1997,280],{"class":198},[192,1999,2000,2003,2005],{"class":194,"line":283},[192,2001,2002],{"class":209},"    http",[192,2004,213],{"class":198},[192,2006,2007],{"class":209},"Handler\n",[192,2009,2010,2013,2015,2018,2020],{"class":194,"line":303},[192,2011,2012],{"class":341},"    RequestType",[192,2014,957],{"class":198},[192,2016,2017],{"class":209}," reflect",[192,2019,213],{"class":198},[192,2021,2022],{"class":209},"Type\n",[192,2024,2025,2028,2030,2032,2034],{"class":194,"line":320},[192,2026,2027],{"class":341},"    ResponseType",[192,2029,957],{"class":198},[192,2031,2017],{"class":209},[192,2033,213],{"class":198},[192,2035,2022],{"class":209},[192,2037,2038],{"class":194,"line":326},[192,2039,323],{"class":198},[178,2041,2042,2043,2046],{},"The app calls this at registration and stores the result on the route, which is how ",[189,2044,2045],{},"\u002Fopenapi.json"," learns your schemas without any code generation.",[258,2048,2050],{"id":2049},"next-steps","Next steps",[2052,2053,2054,2062,2067],"ul",{},[693,2055,2056,2059,2060,213],{},[697,2057,2058],{"href":44},"Request binding"," for the tags that fill ",[189,2061,424],{},[693,2063,2064,2066],{},[697,2065,48],{"href":49}," for the rules that guard it.",[693,2068,2069,2071,2072,213],{},[697,2070,53],{"href":54}," for everything on ",[189,2073,369],{},[2075,2076,2077],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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}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}",{"title":187,"searchDepth":283,"depth":283,"links":2079},[2080,2081,2082,2083,2084,2085,2086,2087,2088],{"id":260,"depth":283,"text":261},{"id":564,"depth":283,"text":565},{"id":684,"depth":283,"text":685},{"id":967,"depth":283,"text":968},{"id":1269,"depth":283,"text":1270},{"id":1435,"depth":283,"text":1436},{"id":1584,"depth":283,"text":1585},{"id":1971,"depth":283,"text":1972},{"id":2049,"depth":283,"text":2050},"Write typed handlers with ezz.H and ezz.HFunc, and control how responses are written.","md",null,{},{"icon":41},{"title":38,"description":2089},"mqJVkzTvu9LPE481L8byHH-qX5i1QOMNfx300N_nnME",[2097,2099],{"title":33,"path":34,"stem":35,"description":2098,"icon":36,"children":-1},"Register routes, use path patterns, group them, and attach metadata.",{"title":43,"path":44,"stem":45,"description":2100,"icon":46,"children":-1},"Fill your request struct from the path, query string, headers, form fields, and JSON body.",1784970045269]