-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.html
More file actions
173 lines (171 loc) · 125 KB
/
Copy pathproxy.html
File metadata and controls
173 lines (171 loc) · 125 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!DOCTYPE html>
<html lang="en-US" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Proxy Endpoints Guide | NpgsqlRest</title>
<meta name="description" content="Turn a PostgreSQL routine into a reverse-proxy endpoint with NpgsqlRest. Stream an upstream response straight through, or transform it in SQL — with header and claim forwarding, caching, and a complete AI-gateway example.">
<meta name="generator" content="VitePress v1.6.4">
<link rel="preload stylesheet" href="/assets/style.LpuNvTwL.css" as="style">
<link rel="preload stylesheet" href="/vp-icons.css" as="style">
<script type="module" src="/assets/app.VN9qkxsN.js"></script>
<link rel="preload" href="/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="modulepreload" href="/assets/chunks/theme.CbCjZi0Y.js">
<link rel="modulepreload" href="/assets/chunks/framework.CgT1UzWm.js">
<link rel="modulepreload" href="/assets/guide_proxy.md.DF7C5yHU.lean.js">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/favicon.ico">
<meta property="og:url" content="https://npgsqlrest.github.io">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="NpgsqlRest - Automatic PostgreSQL Web Server">
<meta name="twitter:description" content="Create REST APIs for PostgreSQL databases in minutes. Zero code, zero config, automatic endpoints from your database schema.">
<script defer data-id="101498393" src="//static.getclicky.com/js"></script>
<script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
<script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
<meta name="keywords" content="npgsqlrest proxy, reverse proxy postgresql, api gateway postgresql, proxy endpoint sql, transform upstream response, proxy_out">
<meta property="og:title" content="NpgsqlRest Proxy Endpoints Guide">
<meta property="og:description" content="Turn a PostgreSQL routine into a reverse-proxy endpoint — passthrough or transform.">
<meta property="og:type" content="article">
</head>
<body>
<div id="app"><div class="Layout" data-v-5d98c3a5><!--[--><!--]--><!--[--><span tabindex="-1" data-v-0b0ada53></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-0b0ada53>Skip to content</a><!--]--><!----><header class="VPNav" data-v-5d98c3a5 data-v-ae24b3ad><div class="VPNavBar" data-v-ae24b3ad data-v-6aa21345><div class="wrapper" data-v-6aa21345><div class="container" data-v-6aa21345><div class="title" data-v-6aa21345><div class="VPNavBarTitle has-sidebar" data-v-6aa21345 data-v-1168a8e4><a class="title" href="/" data-v-1168a8e4><!--[--><!--]--><!--[--><img class="VPImage logo" src="/favicon.ico" alt data-v-8426fc1a><!--]--><span data-v-1168a8e4>NpgsqlRest</span><!--[--><!--]--></a></div></div><div class="content" data-v-6aa21345><div class="content-body" data-v-6aa21345><!--[--><!--]--><div class="VPNavBarSearch search" data-v-6aa21345><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><span class="vp-icon DocSearch-Search-Icon"></span><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-6aa21345 data-v-dc692963><span id="main-nav-aria-label" class="visually-hidden" data-v-dc692963> Main Navigation </span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup active" data-v-dc692963 data-v-cf11d7a2><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-cf11d7a2><span class="text" data-v-cf11d7a2><!----><span data-v-cf11d7a2>Guide</span><span class="vpi-chevron-down text-icon" data-v-cf11d7a2></span></span></button><div class="menu" data-v-cf11d7a2><div class="VPMenu" data-v-cf11d7a2 data-v-b98bc113><div class="items" data-v-b98bc113><!--[--><!--[--><div class="VPMenuGroup" data-v-b98bc113 data-v-69e747b5><p class="title" data-v-69e747b5>Getting Started</p><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/" data-v-35975db6><!--[--><span data-v-35975db6>Overview</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/installation.html" data-v-35975db6><!--[--><span data-v-35975db6>Installation</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/quick-start.html" data-v-35975db6><!--[--><span data-v-35975db6>Quick Start</span><!--]--></a></div><!--]--><!--]--></div><!--]--><!--[--><div class="VPMenuGroup" data-v-b98bc113 data-v-69e747b5><p class="title" data-v-69e747b5>Topics</p><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/sql-files.html" data-v-35975db6><!--[--><span data-v-35975db6>SQL File Endpoints</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/configuration.html" data-v-35975db6><!--[--><span data-v-35975db6>Configuration Guide</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/annotations.html" data-v-35975db6><!--[--><span data-v-35975db6>Comment Annotations Guide</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/authentication.html" data-v-35975db6><!--[--><span data-v-35975db6>Authentication</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/sse.html" data-v-35975db6><!--[--><span data-v-35975db6>Server-Sent Events</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/http-types.html" data-v-35975db6><!--[--><span data-v-35975db6>HTTP Custom Types</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link active" href="/guide/proxy.html" data-v-35975db6><!--[--><span data-v-35975db6>Proxy Endpoints</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/testing.html" data-v-35975db6><!--[--><span data-v-35975db6>Testing</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/logging.html" data-v-35975db6><!--[--><span data-v-35975db6>Logging</span><!--]--></a></div><!--]--><!--]--></div><!--]--><!--[--><div class="VPMenuGroup" data-v-b98bc113 data-v-69e747b5><p class="title" data-v-69e747b5>Reference</p><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/faq.html" data-v-35975db6><!--[--><span data-v-35975db6>FAQ & Troubleshooting</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-35975db6><a class="VPLink link" href="/guide/changelog/" data-v-35975db6><!--[--><span data-v-35975db6>Changelog</span><!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/examples/" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>Examples</span><!--]--></a><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-dc692963 data-v-cf11d7a2><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-cf11d7a2><span class="text" data-v-cf11d7a2><!----><span data-v-cf11d7a2>Reference</span><span class="vpi-chevron-down text-icon" data-v-cf11d7a2></span></span></button><div class="menu" data-v-cf11d7a2><div class="VPMenu" data-v-cf11d7a2 data-v-b98bc113><div class="items" data-v-b98bc113><!--[--><!--[--><div class="VPMenuLink" data-v-b98bc113 data-v-35975db6><a class="VPLink link" href="/annotations/" data-v-35975db6><!--[--><span data-v-35975db6>Annotations</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-b98bc113 data-v-35975db6><a class="VPLink link" href="/config/" data-v-35975db6><!--[--><span data-v-35975db6>Configuration</span><!--]--></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/blog/" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>Blog</span><!--]--></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-6aa21345 data-v-6c893767><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-6c893767 data-v-5337faa4 data-v-1d5665e3><span class="check" data-v-1d5665e3><span class="icon" data-v-1d5665e3><!--[--><span class="vpi-sun sun" data-v-5337faa4></span><span class="vpi-moon moon" data-v-5337faa4></span><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-6aa21345 data-v-0394ad82 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/NpgsqlRest/NpgsqlRest" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><span class="vpi-social-github"></span></a><a class="VPSocialLink no-icon" href="https://patreon.com/vbconsulting" aria-label="Patreon" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M22.957 7.21c-.004-3.064-2.391-5.576-5.191-6.482-3.478-1.125-8.064-.962-11.384.604C2.357 3.231 1.093 7.391 1.046 11.54c-.039 3.411.302 7.463 3.097 9.746 2.602 2.124 6.19 2.078 9.402 1.836 1.883-.142 3.939-.358 5.477-1.528 1.564-1.19 1.873-3.298 1.972-5.151.134-2.51.187-5.016-.037-7.233zm-2.55 7.703c-.078 1.593-.383 3.473-1.795 4.334-1.351.824-3.151.973-4.686 1.083-2.891.207-6.063.276-8.514-1.399C3.106 17.39 2.924 14.34 2.95 11.67c.03-3.206.678-6.721 3.654-8.375 2.756-1.531 6.556-1.727 9.544-.872 2.339.669 4.351 2.678 4.355 5.217.007 2.583-.016 5.168-.095 7.273z"/><path d="M16.088 5.19c-1.008-.542-2.607-.48-3.441.388-.568.591-.773 1.389-.8 2.172-.034.993.068 2.013.361 2.953.307.985 1.034 1.848 2.077 2.012.878.138 1.83-.088 2.458-.732.7-.718.88-1.81.877-2.779-.003-.989-.084-1.99-.423-2.91-.268-.726-.654-1.328-1.109-1.104zm-.294 5.482c-.182.462-.581.771-1.091.696-.532-.078-.859-.533-1.04-1.005-.248-.647-.327-1.375-.312-2.06.01-.46.095-.939.371-1.313.345-.467.993-.447 1.426-.115.41.315.607.835.74 1.32.18.66.211 1.675-.094 2.477zM8.4 10.394c.233 1.084.755 2.299 1.907 2.579.934.227 1.993-.165 2.434-1.048.455-.91.346-1.995.166-2.972-.165-.893-.46-1.885-1.207-2.445-.745-.559-1.832-.457-2.479.192-.84.843-.958 2.138-.955 3.277.001.147.119.364.134.417zm1.363-2.808c.302-.321.805-.336 1.14-.054.445.375.618 1.015.75 1.558.131.54.212 1.156.082 1.703-.1.423-.378.821-.84.882-.469.062-.886-.306-1.088-.704-.326-.644-.401-1.426-.381-2.148.013-.465.104-.993.337-1.237z"/></svg></a><a class="VPSocialLink no-icon" href="https://buymeacoffee.com/vbilopavu" aria-label="Buy Me a Coffee" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364z"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-6aa21345 data-v-bb2aa2f0 data-v-cf11d7a2><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-cf11d7a2><span class="vpi-more-horizontal icon" data-v-cf11d7a2></span></button><div class="menu" data-v-cf11d7a2><div class="VPMenu" data-v-cf11d7a2 data-v-b98bc113><!----><!--[--><!--[--><!----><div class="group" data-v-bb2aa2f0><div class="item appearance" data-v-bb2aa2f0><p class="label" data-v-bb2aa2f0>Appearance</p><div class="appearance-action" data-v-bb2aa2f0><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-bb2aa2f0 data-v-5337faa4 data-v-1d5665e3><span class="check" data-v-1d5665e3><span class="icon" data-v-1d5665e3><!--[--><span class="vpi-sun sun" data-v-5337faa4></span><span class="vpi-moon moon" data-v-5337faa4></span><!--]--></span></span></button></div></div></div><div class="group" data-v-bb2aa2f0><div class="item social-links" data-v-bb2aa2f0><div class="VPSocialLinks social-links-list" data-v-bb2aa2f0 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/NpgsqlRest/NpgsqlRest" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><span class="vpi-social-github"></span></a><a class="VPSocialLink no-icon" href="https://patreon.com/vbconsulting" aria-label="Patreon" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M22.957 7.21c-.004-3.064-2.391-5.576-5.191-6.482-3.478-1.125-8.064-.962-11.384.604C2.357 3.231 1.093 7.391 1.046 11.54c-.039 3.411.302 7.463 3.097 9.746 2.602 2.124 6.19 2.078 9.402 1.836 1.883-.142 3.939-.358 5.477-1.528 1.564-1.19 1.873-3.298 1.972-5.151.134-2.51.187-5.016-.037-7.233zm-2.55 7.703c-.078 1.593-.383 3.473-1.795 4.334-1.351.824-3.151.973-4.686 1.083-2.891.207-6.063.276-8.514-1.399C3.106 17.39 2.924 14.34 2.95 11.67c.03-3.206.678-6.721 3.654-8.375 2.756-1.531 6.556-1.727 9.544-.872 2.339.669 4.351 2.678 4.355 5.217.007 2.583-.016 5.168-.095 7.273z"/><path d="M16.088 5.19c-1.008-.542-2.607-.48-3.441.388-.568.591-.773 1.389-.8 2.172-.034.993.068 2.013.361 2.953.307.985 1.034 1.848 2.077 2.012.878.138 1.83-.088 2.458-.732.7-.718.88-1.81.877-2.779-.003-.989-.084-1.99-.423-2.91-.268-.726-.654-1.328-1.109-1.104zm-.294 5.482c-.182.462-.581.771-1.091.696-.532-.078-.859-.533-1.04-1.005-.248-.647-.327-1.375-.312-2.06.01-.46.095-.939.371-1.313.345-.467.993-.447 1.426-.115.41.315.607.835.74 1.32.18.66.211 1.675-.094 2.477zM8.4 10.394c.233 1.084.755 2.299 1.907 2.579.934.227 1.993-.165 2.434-1.048.455-.91.346-1.995.166-2.972-.165-.893-.46-1.885-1.207-2.445-.745-.559-1.832-.457-2.479.192-.84.843-.958 2.138-.955 3.277.001.147.119.364.134.417zm1.363-2.808c.302-.321.805-.336 1.14-.054.445.375.618 1.015.75 1.558.131.54.212 1.156.082 1.703-.1.423-.378.821-.84.882-.469.062-.886-.306-1.088-.704-.326-.644-.401-1.426-.381-2.148.013-.465.104-.993.337-1.237z"/></svg></a><a class="VPSocialLink no-icon" href="https://buymeacoffee.com/vbilopavu" aria-label="Buy Me a Coffee" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364z"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-6aa21345 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><div class="divider" data-v-6aa21345><div class="divider-line" data-v-6aa21345></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-5d98c3a5 data-v-a6f0e41e><div class="container" data-v-a6f0e41e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-a6f0e41e><span class="vpi-align-left menu-icon" data-v-a6f0e41e></span><span class="menu-text" data-v-a6f0e41e>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-a6f0e41e data-v-8a42e2b4><button data-v-8a42e2b4>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-5d98c3a5 data-v-319d5ca6><div class="curtain" data-v-319d5ca6></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-319d5ca6><span class="visually-hidden" id="sidebar-aria-label" data-v-319d5ca6> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Getting Started</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Overview</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/installation.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Installation</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/quick-start.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Quick Start</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0 has-active" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Topics</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/sql-files.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>SQL File Endpoints</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/configuration.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Configuration Guide</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/annotations.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Comment Annotations Guide</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/authentication.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Authentication</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/sse.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Server-Sent Events</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/http-types.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>HTTP Custom Types</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/proxy.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Proxy Endpoints</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/testing.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Testing</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/logging.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Logging</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Reference</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/faq.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>FAQ & Troubleshooting</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guide/changelog/" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Changelog</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/examples/" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Examples</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/annotations/" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Annotations Reference</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/config/" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Configuration Reference</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-5d98c3a5 data-v-1428d186><div class="VPDoc has-sidebar has-aside" data-v-1428d186 data-v-39a288b8><!--[--><!--]--><div class="container" data-v-39a288b8><div class="aside" data-v-39a288b8><div class="aside-curtain" data-v-39a288b8></div><div class="aside-container" data-v-39a288b8><div class="aside-content" data-v-39a288b8><div class="VPDocAside" data-v-39a288b8 data-v-3f215769><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-3f215769 data-v-a5bbad30><div class="content" data-v-a5bbad30><div class="outline-marker" data-v-a5bbad30></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-a5bbad30>On this page</div><ul class="VPDocOutlineItem root" data-v-a5bbad30 data-v-b933a997><!--[--><!--]--></ul></div></nav><!--[--><!--[--><!--[--><!--[--><div class="comments-outline-link" data-v-6357a5e2><a href="#comments" class="outline-link" data-v-6357a5e2>Comments</a></div><!--]--><!--]--><!--]--><!--]--><div class="spacer" data-v-3f215769></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-39a288b8><div class="content-container" data-v-39a288b8><!--[--><!--]--><main class="main" data-v-39a288b8><div style="position:relative;" class="vp-doc _guide_proxy" data-v-39a288b8><div><h1 id="proxy-endpoints" tabindex="-1">Proxy Endpoints <a class="header-anchor" href="#proxy-endpoints" aria-label="Permalink to "Proxy Endpoints""></a></h1><p>A proxy endpoint forwards a request to an <strong>upstream service</strong> and returns its response. With NpgsqlRest you turn any routine into a reverse proxy by adding <a href="./../annotations/proxy.html"><code>@proxy</code></a> — and you choose whether to <strong>stream the upstream response straight through</strong> or <strong>run it through SQL first</strong> to cache, enrich, or reshape it. This makes PostgreSQL a lightweight API gateway that can add auth, caching, and database context to any backend.</p><p>This guide covers:</p><ol><li><a href="#how-it-works">How proxy endpoints work</a></li><li><a href="#enabling-the-proxy">Enabling the proxy</a></li><li><a href="#passthrough-mode">Passthrough mode</a></li><li><a href="#transform-mode">Transform mode</a></li><li><a href="#where-the-request-goes-target-url">Where the request goes: target URL</a></li><li><a href="#forwarding-headers-claims-and-ip">Forwarding headers, claims, and IP</a></li><li><a href="#forward-proxy-send-a-function-result-upstream">Forward proxy: send a function result upstream</a></li><li><a href="#configuration">Configuration</a></li><li><a href="#a-complete-example-cached-ai-gateway">A complete example: cached AI gateway</a></li></ol><div class="tip custom-block"><p class="custom-block-title">Reference pages</p><p>This is the conceptual walkthrough. For exact options see <a href="./../annotations/proxy.html"><code>@proxy</code></a>, <a href="./../annotations/proxy-out.html"><code>@proxy_out</code></a>, and <a href="./../config/proxy.html">Proxy configuration</a>.</p></div><h2 id="how-it-works" tabindex="-1">How it works <a class="header-anchor" href="#how-it-works" aria-label="Permalink to "How it works""></a></h2><p><code>@proxy</code> forwards the incoming request to an upstream host. What happens to the response depends on <strong>one thing</strong>: whether your routine declares the special <strong><code>_proxy_*</code> response parameters</strong>.</p><div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">flowchart TD</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> REQ["Client request"] --> NR["NpgsqlRest @proxy endpoint"]</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> NR -->|"forward (incoming path + query)"| UP["Upstream host"]</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> UP --> MODE{"routine declares</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_* params?"}</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> MODE -->|"no — passthrough"| OUT1["stream the upstream response</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> straight back; function body NOT run;</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> no DB connection opened"]</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> MODE -->|"yes — transform"| OUT2["bind response into _proxy_* params,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> run the function, return its result"]</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> OUT1 --> CL["Client"]</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> OUT2 --> CL</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><ul><li><strong>Passthrough</strong> — no <code>_proxy_*</code> parameters. NpgsqlRest streams the upstream response directly back to the client. The function body is <strong>never executed</strong> and <strong>no database connection is opened</strong>. This is a pure reverse proxy.</li><li><strong>Transform</strong> — the routine declares <code>_proxy_*</code> parameters. NpgsqlRest performs the upstream call, binds the response into those parameters, runs your function, and returns <strong>the function's</strong> result.</li></ul><h2 id="enabling-the-proxy" tabindex="-1">Enabling the proxy <a class="header-anchor" href="#enabling-the-proxy" aria-label="Permalink to "Enabling the proxy""></a></h2><details class="code-collapsible" open><summary>json</summary><div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">{</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">NpgsqlRest</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> {</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">ProxyOptions</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> {</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">Enabled</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#FE640B;--shiki-dark:#FAB387;"> true</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">,</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">Host</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> "http://localhost:3001"</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> }</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> }</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></details><p><code>Host</code> is the default upstream; an annotation can override it per endpoint (see <a href="#where-the-request-goes-target-url">target URL</a>).</p><h2 id="passthrough-mode" tabindex="-1">Passthrough mode <a class="header-anchor" href="#passthrough-mode" aria-label="Permalink to "Passthrough mode""></a></h2><p>The simplest proxy: forward and stream back. No <code>_proxy_*</code> parameters, so the body never runs.</p><div class="vp-code-group vp-adaptive-theme"><div class="tabs"><input type="radio" name="group-qo3Zy" id="tab-4FI8adQ" checked><label data-title="Function" for="tab-4FI8adQ">Function</label><input type="radio" name="group-qo3Zy" id="tab-cu6yQbs"><label data-title="SQL file" for="tab-cu6yQbs">SQL file</label></div><div class="blocks"><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">create</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> function</span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;"> service_status</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">()</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">returns</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> void</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">language</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> plpgsql</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">as</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> $$ </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">begin</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> end</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">; $$; </span><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">-- body is never executed in passthrough mode</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">comment on function service_status() is </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">HTTP GET /status</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@proxy http://internal-service:8080'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></details><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">-- sql/status.sql</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">/*</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">HTTP GET /status</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">@proxy http://internal-service:8080</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">*/</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">select</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">; </span><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">-- never executed; the endpoint just forwards</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div></details></div></div><p><code>GET /status</code> is forwarded to <code>http://internal-service:8080/status</code> and the upstream response is streamed back unchanged. Because no DB connection is opened, passthrough proxying is cheap — useful for putting NpgsqlRest's auth, CORS, rate limiting, or TLS in front of a plain internal service.</p><div class="warning custom-block"><p class="custom-block-title">Passthrough does not run your SQL</p><p>If you need the function body to execute (to log, cache, or reshape), you're in <strong>transform</strong> mode — you must declare at least one <code>_proxy_*</code> parameter. A passthrough endpoint's body is dead code.</p></div><h2 id="transform-mode" tabindex="-1">Transform mode <a class="header-anchor" href="#transform-mode" aria-label="Permalink to "Transform mode""></a></h2><p>Declare the response parameters and NpgsqlRest hands you the upstream response to do with as you like. All parameters are optional — declare only the ones you need:</p><div class="table-container"><div class="table-wrapper"><table tabindex="0"><thead><tr><th>Parameter</th><th>Type</th><th>Meaning</th></tr></thead><tbody><tr><td><code>_proxy_status_code</code></td><td><code>int</code> (or <code>text</code>)</td><td>Upstream HTTP status code.</td></tr><tr><td><code>_proxy_body</code></td><td><code>text</code></td><td>Response body (<code>null</code> if empty).</td></tr><tr><td><code>_proxy_headers</code></td><td><code>json</code></td><td>Response headers as JSON.</td></tr><tr><td><code>_proxy_content_type</code></td><td><code>text</code></td><td><code>Content-Type</code> of the response.</td></tr><tr><td><code>_proxy_success</code></td><td><code>boolean</code></td><td><code>true</code> for a <code>2xx</code> status.</td></tr><tr><td><code>_proxy_error_message</code></td><td><code>text</code></td><td>Set if the call failed (timeout, connection error); else <code>null</code>.</td></tr></tbody></table></div></div><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">create</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> function</span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;"> fetch_and_wrap</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">(</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_status_code </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">int</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_body </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_success </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">boolean</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_error_message </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">returns</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> json</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">language</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> plpgsql</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">as</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> $$</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">begin</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> if</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> not</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_success </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">then</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> return</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'error'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, </span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;">coalesce</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">(_proxy_error_message, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'upstream failed'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">),</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'status'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _proxy_status_code);</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> end</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> if</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> return</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'status'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _proxy_status_code, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'data'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _proxy_body::</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">json</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">);</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">end</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">$$;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">comment on function fetch_and_wrap(int, text, boolean, text) is </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">HTTP GET /wrapped</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@authorize</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@proxy https://api.example.com/data'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div></details><p>Here NpgsqlRest calls the upstream, fills the four parameters, runs <code>fetch_and_wrap</code>, and returns <em>its</em> JSON — letting you handle errors, cache the body in a table, or merge it with database data before responding. (The <code>_proxy_*</code> names are <a href="#configuration">configurable</a>.)</p><h2 id="where-the-request-goes-target-url" tabindex="-1">Where the request goes: target URL <a class="header-anchor" href="#where-the-request-goes-target-url" aria-label="Permalink to "Where the request goes: target URL""></a></h2><p>The upstream target is built as:</p><details class="code-collapsible" open><summary>code</summary><div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span>target = host + incoming request path + incoming query string</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details><p>The <strong>host</strong> comes from the annotation if present, otherwise from <code>ProxyOptions.Host</code>. A <strong>relative</strong> annotation path makes it a self-call:</p><div class="table-container"><div class="table-wrapper"><table tabindex="0"><thead><tr><th>Annotation</th><th><code>ProxyOptions.Host</code></th><th>Resolved target</th><th style="text-align:center;">Self-call?</th></tr></thead><tbody><tr><td><code>@proxy</code></td><td><code>https://api.example.com</code></td><td><code>https://api.example.com</code> + path + query</td><td style="text-align:center;">no</td></tr><tr><td><code>@proxy POST</code></td><td><code>https://api.example.com</code></td><td>same host, upstream method forced to <code>POST</code></td><td style="text-align:center;">no</td></tr><tr><td><code>@proxy https://other.com</code></td><td><code>https://api.example.com</code></td><td><code>https://other.com</code> + path + query</td><td style="text-align:center;">no</td></tr><tr><td><code>@proxy /api/data</code></td><td><em>(any)</em></td><td><code>/api/data</code> — internal call, no network</td><td style="text-align:center;"><strong>yes</strong></td></tr></tbody></table></div></div><p>The optional <code>[METHOD]</code> lets the upstream verb differ from the incoming one (e.g. accept a <code>GET</code> from clients but call the upstream with <code>POST</code>). A <strong>relative</strong> target (<code>@proxy /api/other</code>) is dispatched in-process to another of your endpoints with no HTTP round trip.</p><h2 id="forwarding-headers-claims-and-ip" tabindex="-1">Forwarding headers, claims, and IP <a class="header-anchor" href="#forwarding-headers-claims-and-ip" aria-label="Permalink to "Forwarding headers, claims, and IP""></a></h2><p>By default request and response headers are forwarded (minus a small exclude list). On top of that, NpgsqlRest can forward the <strong>authenticated identity</strong> to the upstream automatically — so the backend can trust who the caller is without re-doing auth:</p><ul><li><strong><a href="./../annotations/user-parameters.html"><code>@user_parameters</code></a></strong> — user claims, the client IP, HTTP-Custom-Type fields, and resolved-parameter values are forwarded in the endpoint's native shape: <strong>query-string parameters</strong> for <code>QueryString</code> endpoints, or <strong>merged into the JSON body</strong> for <code>BodyJson</code> endpoints.</li><li><strong><a href="./../annotations/user-context.html"><code>@user_context</code></a></strong> — the claims and client IP are forwarded as <strong>HTTP headers</strong> (one per <code>ContextKeyClaimsMapping</code> entry, plus a claims-JSON header and an IP header).</li></ul><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">create</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> function</span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;"> secure_gateway</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">(</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _user_id </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, </span><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">-- forwarded upstream as ?userId=…</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _user_name </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;"> -- forwarded upstream as ?userName=…</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">returns</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> void</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">language</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> plpgsql</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">as</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> $$ </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">begin</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> end</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">; $$;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">comment on function secure_gateway(text, text) is </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">HTTP GET /gateway</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@authorize</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@user_parameters</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@proxy https://internal-api/secure'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div></details><div class="info custom-block"><p class="custom-block-title">Long values are guarded</p><p>Automatic values appended to the upstream <strong>query string</strong> are capped by <code>MaxForwardedQueryParamLength</code> (default <code>2048</code>). A longer value is skipped with a warning rather than producing an unusable request line. Use a <code>BodyJson</code> endpoint if you must forward large values.</p></div><h2 id="forward-proxy-send-a-function-result-upstream" tabindex="-1">Forward proxy: send a function result upstream <a class="header-anchor" href="#forward-proxy-send-a-function-result-upstream" aria-label="Permalink to "Forward proxy: send a function result upstream""></a></h2><p><a href="./../annotations/proxy-out.html"><code>@proxy_out</code></a> (alias <code>@forward_proxy</code>) reverses the order: your function runs <strong>first</strong>, and <strong>its result is sent as the request body</strong> to the upstream, whose response is returned to the client. Use it to build a payload in SQL and hand it to a rendering/processing service:</p><div class="vp-code-group vp-adaptive-theme"><div class="tabs"><input type="radio" name="group-aDO0L" id="tab-j3czRf4" checked><label data-title="Function" for="tab-j3czRf4">Function</label><input type="radio" name="group-aDO0L" id="tab-isUkG4F"><label data-title="SQL file" for="tab-isUkG4F">SQL file</label></div><div class="blocks"><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">create</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> function</span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;"> generate_report</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">(_report_id </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">int</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">returns</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> json</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">language</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> sql</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">as</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> $$</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> select</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'title'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'Monthly Report'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'rows'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, (</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">select</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_agg(row_to_json(s)) </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">from</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> sales s </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">where</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> s.month </span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">=</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _report_id));</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">$$;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">comment on function generate_report(int) is </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">HTTP GET /report</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@proxy_out POST https://render-service.internal/render'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div></details><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">-- sql/report.sql</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">/*</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">HTTP GET /report</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">@proxy_out POST https://render-service.internal/render</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">@param $1 report_id</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">*/</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">select</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'title'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'Monthly Report'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'rows'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, (</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">select</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_agg(row_to_json(s)) </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">from</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> sales s </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">where</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> s.month </span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">=</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> $</span><span style="--shiki-light:#FE640B;--shiki-dark:#FAB387;">1</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">));</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></details></div></div><p><code>GET /report?reportId=3</code> runs <code>generate_report</code>, POSTs its JSON to the render service, and returns the rendered response. If the <strong>function</strong> fails, the error goes straight to the client and the upstream is never called; if the <strong>upstream</strong> fails, its status/body are forwarded (502 for connection errors, 504 for timeouts).</p><h2 id="configuration" tabindex="-1">Configuration <a class="header-anchor" href="#configuration" aria-label="Permalink to "Configuration""></a></h2><p>All under <code>NpgsqlRest.ProxyOptions</code>:</p><div class="table-container"><div class="table-wrapper"><table tabindex="0"><thead><tr><th>Setting</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><code>Enabled</code></td><td><code>false</code></td><td><strong>Must be <code>true</code></strong> for proxy annotations to work.</td></tr><tr><td><code>Host</code></td><td><code>null</code></td><td>Default upstream host. Used when an annotation has no URL; ignored when it specifies one.</td></tr><tr><td><code>DefaultTimeout</code></td><td><code>"00:00:30"</code></td><td>Per-request timeout (<code>HH:MM:SS</code> or interval format).</td></tr><tr><td><code>ForwardHeaders</code></td><td><code>true</code></td><td>Forward request headers upstream.</td></tr><tr><td><code>ExcludeHeaders</code></td><td><code>["Host", "Content-Length", "Transfer-Encoding"]</code></td><td>Request headers not forwarded.</td></tr><tr><td><code>ForwardResponseHeaders</code></td><td><code>true</code></td><td>Forward upstream response headers to the client.</td></tr><tr><td><code>ExcludeResponseHeaders</code></td><td><code>["Transfer-Encoding", "Content-Length"]</code></td><td>Response headers not forwarded.</td></tr><tr><td><code>ForwardUploadContent</code></td><td><code>false</code></td><td>Forward raw <code>multipart/form-data</code> upstream instead of processing it locally.</td></tr><tr><td><code>MaxForwardedQueryParamLength</code></td><td><code>2048</code></td><td>Max length of a single auto-forwarded query value (<code>0</code> disables the guard).</td></tr><tr><td><code>Response*Parameter</code></td><td><code>_proxy_status_code</code>, <code>_proxy_body</code>, <code>_proxy_headers</code>, <code>_proxy_content_type</code>, <code>_proxy_success</code>, <code>_proxy_error_message</code></td><td>Names of the transform-mode response parameters.</td></tr></tbody></table></div></div><details class="code-collapsible" open><summary>json</summary><div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">{</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">NpgsqlRest</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> {</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">ProxyOptions</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> {</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">Enabled</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#FE640B;--shiki-dark:#FAB387;"> true</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">,</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">Host</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> "http://localhost:3001"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">,</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">DefaultTimeout</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> "00:00:30"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">,</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">ForwardHeaders</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#FE640B;--shiki-dark:#FAB387;"> true</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">,</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> "</span><span style="--shiki-light:#1E66F5;--shiki-dark:#89B4FA;">ForwardResponseHeaders</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">"</span><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">:</span><span style="--shiki-light:#FE640B;--shiki-dark:#FAB387;"> true</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> }</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;"> }</span></span>
<span class="line"><span style="--shiki-light:#7C7F93;--shiki-dark:#9399B2;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div></details><h2 id="a-complete-example-cached-ai-gateway" tabindex="-1">A complete example: cached AI gateway <a class="header-anchor" href="#a-complete-example-cached-ai-gateway" aria-label="Permalink to "A complete example: cached AI gateway""></a></h2><p>This transform-mode endpoint proxies a request to an AI service, but <strong>caches</strong> each result in a table so repeated inputs never hit the upstream twice — a database-backed cache in front of a slow/expensive API.</p><details class="code-collapsible" open><summary>sql</summary><div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes catppuccin-latte catppuccin-mocha vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">create</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> function</span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;"> ai_sentiment</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">(</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _text </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_status_code </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">int</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_body </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_success </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">boolean</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_error_message </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> default</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> null</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">returns</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> json</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">language</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> plpgsql</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">as</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> $$</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">declare</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _hash </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">text</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> :</span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">=</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> md5(_text </span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">||</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> '::sentiment'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">);</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _cached record;</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _result </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">json</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">begin</span></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;"> -- 1. serve from the database cache when present</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> select</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> sentiment, sentiment_score </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">into</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _cached</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> from</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> analysis_cache </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">where</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> text_hash </span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">=</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _hash;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> if</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _cached.sentiment </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">is not null</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> then</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> return</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'sentiment'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _cached.sentiment,</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'score'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _cached.sentiment_score, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'cached'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, true);</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> end</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> if</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;"> -- 2. handle upstream failure</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> if</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> not</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_success </span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">then</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> return</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'error'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, </span><span style="--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic;">coalesce</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">(_proxy_error_message, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'AI service unavailable'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">),</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'status_code'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _proxy_status_code);</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> end</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> if</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;"> -- 3. cache the fresh result and return it</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _result :</span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">=</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> _proxy_body::</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">json</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> insert into</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> analysis_cache (text_hash, sentiment, sentiment_score)</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> values</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> (_hash, _result</span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">->></span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'sentiment'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, (_result</span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">->></span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'score'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)::</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">numeric</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> on</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> conflict (text_hash) do nothing;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;"> return</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;"> json_build_object(</span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'sentiment'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, _result</span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">->></span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'sentiment'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">,</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;"> 'score'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, (_result</span><span style="--shiki-light:#179299;--shiki-dark:#94E2D5;">->></span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'score'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">)::</span><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">numeric</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'cached'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">, false);</span></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">end</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">;</span></span>
<span class="line"><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">$$;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#8839EF;--shiki-dark:#CBA6F7;">comment on function ai_sentiment(text, int, text, boolean, text) is </span><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">'</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">HTTP POST /ai/sentiment</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@authorize</span></span>
<span class="line"><span style="--shiki-light:#40A02B;--shiki-dark:#A6E3A1;">@proxy POST'</span><span style="--shiki-light:#4C4F69;--shiki-dark:#CDD6F4;">; </span><span style="--shiki-light:#9CA0B0;--shiki-light-font-style:italic;--shiki-dark:#6C7086;--shiki-dark-font-style:italic;">-- no host → forwarded to ProxyOptions.Host</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br></div></div></details><p><code>POST /ai/sentiment</code> is forwarded to the configured AI service; the function then caches and shapes the result. Note that <strong>with caching, the upstream is still called every time</strong> (NpgsqlRest can't know the result is cached before the proxy runs) — to skip the call entirely on a cache hit, fetch with an <a href="./http-types.html">HTTP Custom Type</a> instead of <code>@proxy</code>, or split the lookup into a separate endpoint.</p><h2 id="see-it-in-the-examples" tabindex="-1">See it in the examples <a class="header-anchor" href="#see-it-in-the-examples" aria-label="Permalink to "See it in the examples""></a></h2><ul><li><a href="/examples/"><strong>Reverse Proxy & AI Service</strong></a> (<code>10_proxy_ai_service</code>) — transform-mode proxy with database-backed caching of AI responses. Tutorial: <a href="/blog/reverse-proxy-postgresql-ai-service-npgsqlrest.html">Reverse Proxy in PostgreSQL</a>.</li><li><a href="/examples/"><strong>Scraping Proxy</strong></a> (<code>18_scrap_proxy_demo</code>) — an <a href="./http-types.html">HTTP Custom Type</a> fetches a page, then <code>@proxy</code> forwards the scraped HTML to an upstream parser via <a href="./../annotations/body-parameter-name.html"><code>@body_parameter_name</code></a>.</li></ul><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to "Related""></a></h2><ul><li><a href="./../annotations/proxy.html"><code>@proxy</code></a> — reverse-proxy an endpoint (passthrough or transform)</li><li><a href="./../annotations/proxy-out.html"><code>@proxy_out</code></a> — forward a function result upstream</li><li><a href="./../config/proxy.html">Proxy configuration</a> — every <code>ProxyOptions</code> setting</li><li><a href="./http-types.html">HTTP Custom Types guide</a> — call an upstream and consume the response in SQL (skips on cache hit)</li><li><a href="./../annotations/user-parameters.html"><code>@user_parameters</code></a> / <a href="./../annotations/user-context.html"><code>@user_context</code></a> — forwarding the authenticated identity upstream</li></ul></div></div></main><footer class="VPDocFooter" data-v-39a288b8 data-v-e257564d><!--[--><!--]--><div class="edit-info" data-v-e257564d><div class="edit-link" data-v-e257564d><a class="VPLink link vp-external-link-icon no-icon edit-link-button" href="https://github.com/NpgsqlRest/npgsqlrest-docs/edit/main/docs/guide/proxy.md" target="_blank" rel="noreferrer" data-v-e257564d><!--[--><span class="vpi-square-pen edit-link-icon" data-v-e257564d></span> Edit this page on GitHub<!--]--></a></div><!----></div><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-e257564d><span class="visually-hidden" id="doc-footer-aria-label" data-v-e257564d>Pager</span><div class="pager" data-v-e257564d><a class="VPLink link pager-link prev" href="/guide/http-types.html" data-v-e257564d><!--[--><span class="desc" data-v-e257564d>Previous page</span><span class="title" data-v-e257564d>HTTP Custom Types</span><!--]--></a></div><div class="pager" data-v-e257564d><a class="VPLink link pager-link next" href="/guide/testing.html" data-v-e257564d><!--[--><span class="desc" data-v-e257564d>Next page</span><span class="title" data-v-e257564d>Testing</span><!--]--></a></div></nav></footer><!--[--><!--[--><!--[--><div id="comments" class="giscus-wrapper" data-v-5337483f><h2 class="comments-heading" data-v-5337483f>Comments</h2><!----></div><div class="sponsor-footer" data-v-b93f2dbd><div class="sponsor-footer-content" data-v-b93f2dbd><span class="sponsor-heart" data-v-b93f2dbd>❤️</span><span class="sponsor-text" data-v-b93f2dbd>Support this project:</span><a href="https://patreon.com/vbconsulting" target="_blank" class="sponsor-link" data-v-b93f2dbd><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" data-v-b93f2dbd><path d="M22.957 7.21c-.004-3.064-2.391-5.576-5.191-6.482-3.478-1.125-8.064-.962-11.384.604C2.357 3.231 1.093 7.391 1.046 11.54c-.039 3.411.302 7.463 3.097 9.746 2.602 2.124 6.19 2.078 9.402 1.836 1.883-.142 3.939-.358 5.477-1.528 1.564-1.19 1.873-3.298 1.972-5.151.134-2.51.187-5.016-.037-7.233zm-2.55 7.703c-.078 1.593-.383 3.473-1.795 4.334-1.351.824-3.151.973-4.686 1.083-2.891.207-6.063.276-8.514-1.399C3.106 17.39 2.924 14.34 2.95 11.67c.03-3.206.678-6.721 3.654-8.375 2.756-1.531 6.556-1.727 9.544-.872 2.339.669 4.351 2.678 4.355 5.217.007 2.583-.016 5.168-.095 7.273z" data-v-b93f2dbd></path><path d="M16.088 5.19c-1.008-.542-2.607-.48-3.441.388-.568.591-.773 1.389-.8 2.172-.034.993.068 2.013.361 2.953.307.985 1.034 1.848 2.077 2.012.878.138 1.83-.088 2.458-.732.7-.718.88-1.81.877-2.779-.003-.989-.084-1.99-.423-2.91-.268-.726-.654-1.328-1.109-1.104zm-.294 5.482c-.182.462-.581.771-1.091.696-.532-.078-.859-.533-1.04-1.005-.248-.647-.327-1.375-.312-2.06.01-.46.095-.939.371-1.313.345-.467.993-.447 1.426-.115.41.315.607.835.74 1.32.18.66.211 1.675-.094 2.477zM8.4 10.394c.233 1.084.755 2.299 1.907 2.579.934.227 1.993-.165 2.434-1.048.455-.91.346-1.995.166-2.972-.165-.893-.46-1.885-1.207-2.445-.745-.559-1.832-.457-2.479.192-.84.843-.958 2.138-.955 3.277.001.147.119.364.134.417zm1.363-2.808c.302-.321.805-.336 1.14-.054.445.375.618 1.015.75 1.558.131.54.212 1.156.082 1.703-.1.423-.378.821-.84.882-.469.062-.886-.306-1.088-.704-.326-.644-.401-1.426-.381-2.148.013-.465.104-.993.337-1.237z" data-v-b93f2dbd></path></svg> Patreon </a><span class="sponsor-separator" data-v-b93f2dbd>·</span><a href="https://buymeacoffee.com/vbilopavu" target="_blank" class="sponsor-link" data-v-b93f2dbd><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" data-v-b93f2dbd><path d="M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364z" data-v-b93f2dbd></path></svg> Buy Me a Coffee </a></div><div class="footer-license" data-v-b93f2dbd>Released under the MIT License.</div><div class="footer-copyright" data-v-b93f2dbd>Copyright © 2024-2026 VB Consulting</div></div><!--]--><!--]--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>
<script>window.__VP_HASH_MAP__=JSON.parse("{\"about.md\":\"DQcoTdts\",\"annotations_allow-anonymous.md\":\"B0UuFGg2\",\"annotations_authorize.md\":\"CK7v-SQu\",\"annotations_basic-auth-command.md\":\"Csb6mha2\",\"annotations_basic-auth-realm.md\":\"DsMX0SDT\",\"annotations_basic-auth.md\":\"ClrT2h43\",\"annotations_body-parameter-name.md\":\"BfhRegXI\",\"annotations_buffer-rows.md\":\"BrfXbHRV\",\"annotations_cache-expires-in.md\":\"BRoExkyw\",\"annotations_cache-profile.md\":\"YD0xPH6k\",\"annotations_cached.md\":\"Z17IaMQ8\",\"annotations_column-names.md\":\"BgCUEwzC\",\"annotations_command-timeout.md\":\"DGZAbOuK\",\"annotations_connection.md\":\"kVRk6UjZ\",\"annotations_custom-parameters.md\":\"C_JoJInz\",\"annotations_define-param.md\":\"BEpTOvZh\",\"annotations_disabled.md\":\"DLiSD84Q\",\"annotations_enabled.md\":\"w_f0uh0_\",\"annotations_encrypt-decrypt.md\":\"BVL3DPHk\",\"annotations_error-code-policy.md\":\"CcDC1Uqp\",\"annotations_http-type.md\":\"Yj3KYiqW\",\"annotations_http.md\":\"DPCDKDD2\",\"annotations_index.md\":\"DSU3OO0a\",\"annotations_internal.md\":\"yWqX_Gop\",\"annotations_interval-format.md\":\"qinH4egR\",\"annotations_login.md\":\"CNtMBAwP\",\"annotations_logout.md\":\"Cle7WE1K\",\"annotations_mcp.md\":\"CUGE4v1n\",\"annotations_nested.md\":\"G3R18jm5\",\"annotations_new-line.md\":\"9HsK47GA\",\"annotations_openapi.md\":\"CYi2hImP\",\"annotations_param.md\":\"DCLc58O5\",\"annotations_parameter-hash.md\":\"DAN4SbBB\",\"annotations_parameter-substitution.md\":\"BAnY-Etv\",\"annotations_path.md\":\"4EcrWuEH\",\"annotations_proxy-out.md\":\"C6XnOMaD\",\"annotations_proxy.md\":\"C1XKqZ1u\",\"annotations_query-string-null-handling.md\":\"bDnQmkU1\",\"annotations_rate-limiter-policy.md\":\"C6rNxcxq\",\"annotations_raw.md\":\"mVR52W_-\",\"annotations_request-headers-mode.md\":\"CiBM2WBe\",\"annotations_request-headers-parameter-name.md\":\"B1w65j2m\",\"annotations_request-param-type.md\":\"D2ADbicS\",\"annotations_resolved-parameters.md\":\"CtIRul_U\",\"annotations_response-headers.md\":\"BjZbt4Z0\",\"annotations_response-null-handling.md\":\"BXujxmf9\",\"annotations_result-name.md\":\"oSFavaHs\",\"annotations_retry-strategy.md\":\"DJkjr3eT\",\"annotations_returns.md\":\"BXcLtPWm\",\"annotations_security-sensitive.md\":\"iGNlRYXu\",\"annotations_separator.md\":\"Bh3F0ZIY\",\"annotations_single.md\":\"6tuGsQhF\",\"annotations_skip.md\":\"Dh_dVMzK\",\"annotations_sse-events-level.md\":\"BzejI_6s\",\"annotations_sse-events-scope.md\":\"DSBEdrmZ\",\"annotations_sse.md\":\"VtYFy1W4\",\"annotations_table-format.md\":\"BKXSdBmi\",\"annotations_tags.md\":\"DmTy6McN\",\"annotations_test-claim.md\":\"B8Axvirh\",\"annotations_test-connection.md\":\"CBXd7WXg\",\"annotations_test-response.md\":\"BIQYW_7j\",\"annotations_test-setup.md\":\"CEjyi1f2\",\"annotations_test-tag.md\":\"CzXuyAz7\",\"annotations_test-teardown.md\":\"DrTOzo2w\",\"annotations_tsclient.md\":\"BNgVXSoY\",\"annotations_upload.md\":\"BJPkIDDG\",\"annotations_user-context.md\":\"D9DNdqIU\",\"annotations_user-parameters.md\":\"RuNgxxKs\",\"annotations_validate.md\":\"BYjsje_G\",\"annotations_void.md\":\"CdJ8Ec9f\",\"blog_case-study-zero-backend-code.md\":\"C_RsDiAE\",\"blog_csv-excel-ingestion-postgresql-npgsqlrest.md\":\"DSyRNYor\",\"blog_custom-types-multiset-rest-api.md\":\"DCC_Eq7R\",\"blog_database-level-security-postgresql-authentication.md\":\"DOXBN62P\",\"blog_draft-anniversary-vietnam-of-computer-science.md\":\"pc601xHv\",\"blog_draft-npgsqlrest-vs-sqlpage.md\":\"DbSL1Z8X\",\"blog_end-to-end-static-type-checking-postgresql-typescript.md\":\"CfE5da_h\",\"blog_excel-export-table-format-postgresql-npgsqlrest.md\":\"BuWwG6CQ\",\"blog_external-api-calls-postgresql-http-types.md\":\"C9zYiqiX\",\"blog_index.md\":\"De5ptA_4\",\"blog_mcp-server-postgresql-ai-tools-npgsqlrest.md\":\"DvISemRM\",\"blog_multiple-auth-schemes-rbac-external-providers.md\":\"BbvFjCJf\",\"blog_npgsqlrest-3.13-production-patterns.md\":\"jTlztVH-\",\"blog_npgsqlrest-3.19-sql-test-runner-watch-mode.md\":\"Dc7T3KVb\",\"blog_npgsqlrest-vs-postgrest-supabase-comparison.md\":\"00RFbAF5\",\"blog_passkey-sql-auth.md\":\"BRkr8TRo\",\"blog_performance-scalability-high-availability-npgsqlrest.md\":\"C-bwVXtr\",\"blog_postgresql-bi-server-excel-csv-basic-auth.md\":\"C9mEJphA\",\"blog_postgresql-rest-api-benchmark-2024.md\":\"DwEQmIoA\",\"blog_postgresql-rest-api-benchmark-2025.md\":\"Tbw6Blag\",\"blog_postgresql-rest-api-benchmark-2026.md\":\"BnlvOVbX\",\"blog_real-time-chat-postgresql-sse-npgsqlrest.md\":\"DHt1C23t\",\"blog_reverse-proxy-postgresql-ai-service-npgsqlrest.md\":\"BtaYnMBE\",\"blog_secure-image-uploads-postgresql-typescript.md\":\"Cp-wJyj4\",\"blog_sql-file-source-rest-api-from-plain-sql.md\":\"czCJfcgj\",\"blog_sql-rest-api.md\":\"C3OYX-j7\",\"blog_the-backend-that-writes-itself-presentation.md\":\"gFR1Oe0-\",\"blog_the-power-of-simplicity.md\":\"Cs_l8y-q\",\"blog_typescript-codegen-walkthrough.md\":\"DU5mkobw\",\"blog_web-scraping-postgresql-http-types-xml.md\":\"CCovU_63\",\"blog_what-have-stored-procedures-ever-done-for-us.md\":\"DbQNwRp9\",\"config_antiforgery.md\":\"7miFkqvJ\",\"config_auth.md\":\"BTlaq10R\",\"config_authentication-options.md\":\"CzhPcVla\",\"config_basic-auth-config.md\":\"DZCrOE7U\",\"config_cache-options.md\":\"Cq5Q0JXd\",\"config_claims-mapping.md\":\"DxUSHFxx\",\"config_codegen.md\":\"opHl7x9x\",\"config_command-retry.md\":\"BgAKKMgf\",\"config_config-section.md\":\"CwHYEVn1\",\"config_connection.md\":\"OYNJshxp\",\"config_cors.md\":\"Cusa--1Y\",\"config_data-protection.md\":\"Djdf76Tb\",\"config_error-handling.md\":\"DjvdMMV4\",\"config_external-auth.md\":\"bAqNP7C3\",\"config_forwarded-headers.md\":\"CGTpUREz\",\"config_health-checks.md\":\"BpWdFu-y\",\"config_http-client.md\":\"dRXgMQQQ\",\"config_http-files.md\":\"B6K6vnkA\",\"config_index.md\":\"CXfhm2PI\",\"config_latest.md\":\"BHuOeOrq\",\"config_logging.md\":\"B2g4l4DC\",\"config_mcp.md\":\"D08gYjRL\",\"config_npgsqlrest.md\":\"CnfMgb40\",\"config_openapi.md\":\"BCg7CKgl\",\"config_passkey-auth.md\":\"DHQzx-GX\",\"config_proxy.md\":\"DOTosU06\",\"config_rate-limiter.md\":\"wLNPwvhE\",\"config_response-compression.md\":\"CMmom6qe\",\"config_routine-options.md\":\"VEEBtjYd\",\"config_security-headers.md\":\"D2EP-6xq\",\"config_server.md\":\"BCPr-8rO\",\"config_sql-file-source.md\":\"5_GwGm0C\",\"config_static-files.md\":\"CxiUeSZr\",\"config_stats.md\":\"CXkhOJdL\",\"config_table-format.md\":\"CKOmZ6yI\",\"config_test-runner.md\":\"D9PY_12B\",\"config_thread-pool.md\":\"CQCaprkR\",\"config_top-level.md\":\"F9S_nf2B\",\"config_uploads.md\":\"DoJGjd4G\",\"config_validation.md\":\"lHNUsfic\",\"config_watch.md\":\"B_iL-Wg4\",\"examples_index.md\":\"D4o4oSds\",\"guide_annotations.md\":\"DVRiz6k_\",\"guide_authentication.md\":\"BaKZBV2r\",\"guide_changelog_index.md\":\"B7c1xVM5\",\"guide_changelog_v3.0.0.md\":\"BCZYSJDP\",\"guide_changelog_v3.0.1.md\":\"C5QoKstF\",\"guide_changelog_v3.1.0.md\":\"Xl_94wGw\",\"guide_changelog_v3.1.1.md\":\"CP1dTmO5\",\"guide_changelog_v3.1.2.md\":\"DaCWRd65\",\"guide_changelog_v3.1.3.md\":\"BMixLZ4Y\",\"guide_changelog_v3.10.0.md\":\"CCimYYDV\",\"guide_changelog_v3.11.0.md\":\"yn587hBX\",\"guide_changelog_v3.11.1.md\":\"DxsV24Au\",\"guide_changelog_v3.12.0.md\":\"BDVbkMod\",\"guide_changelog_v3.13.0.md\":\"kmKD3jrx\",\"guide_changelog_v3.14.0.md\":\"DqJvVHhw\",\"guide_changelog_v3.15.0.md\":\"DiRcMMNc\",\"guide_changelog_v3.15.1.md\":\"EipfUUTu\",\"guide_changelog_v3.15.2.md\":\"B_9nMiuK\",\"guide_changelog_v3.16.0.md\":\"z16WdNnJ\",\"guide_changelog_v3.16.1.md\":\"twyBHeJH\",\"guide_changelog_v3.16.2.md\":\"DJyi_HNy\",\"guide_changelog_v3.16.3.md\":\"BaS-l5LJ\",\"guide_changelog_v3.17.0.md\":\"DCqJkXNp\",\"guide_changelog_v3.18.0.md\":\"DhzJiwQ7\",\"guide_changelog_v3.18.1.md\":\"BUjRzlAL\",\"guide_changelog_v3.18.2.md\":\"D9Kg93qi\",\"guide_changelog_v3.19.0.md\":\"CnLwz7zb\",\"guide_changelog_v3.2.0.md\":\"DqMIq3GM\",\"guide_changelog_v3.2.1.md\":\"jsATl_CJ\",\"guide_changelog_v3.2.2.md\":\"DCWOjWem\",\"guide_changelog_v3.2.3.md\":\"BU0QClul\",\"guide_changelog_v3.2.4.md\":\"DlHy9dKX\",\"guide_changelog_v3.2.6.md\":\"Be7WrEBG\",\"guide_changelog_v3.2.7.md\":\"DnOXNKXQ\",\"guide_changelog_v3.3.0.md\":\"D_74S82V\",\"guide_changelog_v3.3.1.md\":\"DBVEhTOX\",\"guide_changelog_v3.4.0.md\":\"DWaLq7jU\",\"guide_changelog_v3.4.1.md\":\"BjkyM2ol\",\"guide_changelog_v3.4.2.md\":\"CwgXLNC8\",\"guide_changelog_v3.4.3.md\":\"CwIJ6zQw\",\"guide_changelog_v3.4.4.md\":\"Dun3dnAP\",\"guide_changelog_v3.4.5.md\":\"CCdH9iK4\",\"guide_changelog_v3.4.6.md\":\"DfISyzwO\",\"guide_changelog_v3.4.7.md\":\"PS46_sBY\",\"guide_changelog_v3.4.8.md\":\"C6Us0ANY\",\"guide_changelog_v3.5.0.md\":\"COe0eWbp\",\"guide_changelog_v3.6.0.md\":\"p7Q-OsI9\",\"guide_changelog_v3.6.1.md\":\"CCDqHGJF\",\"guide_changelog_v3.6.2.md\":\"Lg_0h_OI\",\"guide_changelog_v3.6.3.md\":\"CcLrwLcH\",\"guide_changelog_v3.7.0.md\":\"BsBWtBOJ\",\"guide_changelog_v3.8.0.md\":\"D7bLiXbw\",\"guide_changelog_v3.9.0.md\":\"Cm0S1Ft1\",\"guide_configuration.md\":\"CAstKOPi\",\"guide_faq.md\":\"DzLvzPIX\",\"guide_http-types.md\":\"6rK6DntP\",\"guide_index.md\":\"C-0777ru\",\"guide_installation.md\":\"KDi2i5hY\",\"guide_logging.md\":\"CT7Uqiy7\",\"guide_proxy.md\":\"DF7C5yHU\",\"guide_quick-start.md\":\"DtKtFUQX\",\"guide_sql-files.md\":\"yAmqICyN\",\"guide_sse.md\":\"CCeiNuHG\",\"guide_testing.md\":\"Mc_wQPBP\",\"index.md\":\"WBf3vDSd\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"NpgsqlRest - Automatic PostgreSQL Web Server\",\"description\":\"Automatic PostgreSQL Web Server - Create REST APIs for PostgreSQL databases in minutes.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"logo\":\"/favicon.ico\",\"siteTitle\":\"NpgsqlRest\",\"nav\":[{\"text\":\"Guide\",\"items\":[{\"text\":\"Getting Started\",\"items\":[{\"text\":\"Overview\",\"link\":\"/guide/\"},{\"text\":\"Installation\",\"link\":\"/guide/installation\"},{\"text\":\"Quick Start\",\"link\":\"/guide/quick-start\"}]},{\"text\":\"Topics\",\"items\":[{\"text\":\"SQL File Endpoints\",\"link\":\"/guide/sql-files\"},{\"text\":\"Configuration Guide\",\"link\":\"/guide/configuration\"},{\"text\":\"Comment Annotations Guide\",\"link\":\"/guide/annotations\"},{\"text\":\"Authentication\",\"link\":\"/guide/authentication\"},{\"text\":\"Server-Sent Events\",\"link\":\"/guide/sse\"},{\"text\":\"HTTP Custom Types\",\"link\":\"/guide/http-types\"},{\"text\":\"Proxy Endpoints\",\"link\":\"/guide/proxy\"},{\"text\":\"Testing\",\"link\":\"/guide/testing\"},{\"text\":\"Logging\",\"link\":\"/guide/logging\"}]},{\"text\":\"Reference\",\"items\":[{\"text\":\"FAQ & Troubleshooting\",\"link\":\"/guide/faq\"},{\"text\":\"Changelog\",\"link\":\"/guide/changelog/\"}]}]},{\"text\":\"Examples\",\"link\":\"/examples/\"},{\"text\":\"Reference\",\"items\":[{\"text\":\"Annotations\",\"link\":\"/annotations/\"},{\"text\":\"Configuration\",\"link\":\"/config/\"}]},{\"text\":\"Blog\",\"link\":\"/blog/\"}],\"sidebar\":{\"/blog/\":[{\"text\":\"Tutorials\",\"collapsed\":false,\"items\":[{\"text\":\"Tests Are SQL Files Too\",\"link\":\"/blog/npgsqlrest-3.19-sql-test-runner-watch-mode\"},{\"text\":\"Case Study: 74 Endpoints, Zero Backend Code\",\"link\":\"/blog/case-study-zero-backend-code\"},{\"text\":\"TypeScript Code Generation Walkthrough\",\"link\":\"/blog/typescript-codegen-walkthrough\"},{\"text\":\"NpgsqlRest 3.13.0: Production Patterns\",\"link\":\"/blog/npgsqlrest-3.13-production-patterns\"},{\"text\":\"SQL REST API\",\"link\":\"/blog/sql-rest-api\"},{\"text\":\"SQL File Source\",\"link\":\"/blog/sql-file-source-rest-api-from-plain-sql\"},{\"text\":\"Database-Level Security\",\"link\":\"/blog/database-level-security-postgresql-authentication\"},{\"text\":\"Multiple Auth Schemes & RBAC\",\"link\":\"/blog/multiple-auth-schemes-rbac-external-providers\"},{\"text\":\"Passkey SQL Auth\",\"link\":\"/blog/passkey-sql-auth\"},{\"text\":\"End-to-End Type Checking\",\"link\":\"/blog/end-to-end-static-type-checking-postgresql-typescript\"},{\"text\":\"Real-Time Chat with SSE\",\"link\":\"/blog/real-time-chat-postgresql-sse-npgsqlrest\"},{\"text\":\"External API Calls\",\"link\":\"/blog/external-api-calls-postgresql-http-types\"},{\"text\":\"Web Scraping with HTTP Types\",\"link\":\"/blog/web-scraping-postgresql-http-types-xml\"},{\"text\":\"Reverse Proxy & AI Service\",\"link\":\"/blog/reverse-proxy-postgresql-ai-service-npgsqlrest\"},{\"text\":\"Secure Image Uploads\",\"link\":\"/blog/secure-image-uploads-postgresql-typescript\"},{\"text\":\"CSV & Excel Ingestion\",\"link\":\"/blog/csv-excel-ingestion-postgresql-npgsqlrest\"},{\"text\":\"PostgreSQL BI Server\",\"link\":\"/blog/postgresql-bi-server-excel-csv-basic-auth\"}]},{\"text\":\"Feature Deep Dives\",\"collapsed\":false,\"items\":[{\"text\":\"Excel Exports Done Right\",\"link\":\"/blog/excel-export-table-format-postgresql-npgsqlrest\"},{\"text\":\"Custom Types & Multiset\",\"link\":\"/blog/custom-types-multiset-rest-api\"},{\"text\":\"Performance & High Availability\",\"link\":\"/blog/performance-scalability-high-availability-npgsqlrest\"},{\"text\":\"What Have Stored Procedures Done for Us?\",\"link\":\"/blog/what-have-stored-procedures-ever-done-for-us\"},{\"text\":\"The Power of Simplicity\",\"link\":\"/blog/the-power-of-simplicity\"}]},{\"text\":\"Benchmarks & Comparisons\",\"collapsed\":false,\"items\":[{\"text\":\"Benchmark 2026\",\"link\":\"/blog/postgresql-rest-api-benchmark-2026\"},{\"text\":\"NpgsqlRest vs PostgREST vs Supabase\",\"link\":\"/blog/npgsqlrest-vs-postgrest-supabase-comparison\"}]},{\"text\":\"Other Links\",\"collapsed\":false,\"items\":[{\"text\":\"Guide\",\"link\":\"/guide/\"},{\"text\":\"Annotations Reference\",\"link\":\"/annotations/\"},{\"text\":\"Configuration Reference\",\"link\":\"/config/\"}]}],\"/guide/changelog/\":[{\"text\":\"Changelog\",\"items\":[{\"text\":\"Overview\",\"link\":\"/guide/changelog/\"},{\"text\":\"v3.19.0 (Latest)\",\"link\":\"/guide/changelog/v3.19.0\"},{\"text\":\"v3.18.2\",\"link\":\"/guide/changelog/v3.18.2\"},{\"text\":\"v3.18.1\",\"link\":\"/guide/changelog/v3.18.1\"},{\"text\":\"v3.18.0\",\"link\":\"/guide/changelog/v3.18.0\"},{\"text\":\"v3.17.0\",\"link\":\"/guide/changelog/v3.17.0\"},{\"text\":\"v3.16.3\",\"link\":\"/guide/changelog/v3.16.3\"},{\"text\":\"v3.16.2\",\"link\":\"/guide/changelog/v3.16.2\"},{\"text\":\"v3.16.1\",\"link\":\"/guide/changelog/v3.16.1\"},{\"text\":\"v3.16.0\",\"link\":\"/guide/changelog/v3.16.0\"},{\"text\":\"v3.15.2\",\"link\":\"/guide/changelog/v3.15.2\"},{\"text\":\"v3.15.1\",\"link\":\"/guide/changelog/v3.15.1\"},{\"text\":\"v3.15.0\",\"link\":\"/guide/changelog/v3.15.0\"},{\"text\":\"v3.14.0\",\"link\":\"/guide/changelog/v3.14.0\"},{\"text\":\"v3.13.0\",\"link\":\"/guide/changelog/v3.13.0\"},{\"text\":\"v3.12.0\",\"link\":\"/guide/changelog/v3.12.0\"},{\"text\":\"v3.11.1\",\"link\":\"/guide/changelog/v3.11.1\"},{\"text\":\"v3.11.0\",\"link\":\"/guide/changelog/v3.11.0\"},{\"text\":\"v3.10.0\",\"link\":\"/guide/changelog/v3.10.0\"},{\"text\":\"v3.9.0\",\"link\":\"/guide/changelog/v3.9.0\"},{\"text\":\"v3.8.0\",\"link\":\"/guide/changelog/v3.8.0\"},{\"text\":\"v3.7.0\",\"link\":\"/guide/changelog/v3.7.0\"},{\"text\":\"v3.6.3\",\"link\":\"/guide/changelog/v3.6.3\"},{\"text\":\"v3.6.2\",\"link\":\"/guide/changelog/v3.6.2\"},{\"text\":\"v3.6.1\",\"link\":\"/guide/changelog/v3.6.1\"},{\"text\":\"v3.6.0\",\"link\":\"/guide/changelog/v3.6.0\"},{\"text\":\"v3.5.0\",\"link\":\"/guide/changelog/v3.5.0\"},{\"text\":\"v3.4.8\",\"link\":\"/guide/changelog/v3.4.8\"},{\"text\":\"v3.4.7\",\"link\":\"/guide/changelog/v3.4.7\"},{\"text\":\"v3.4.6\",\"link\":\"/guide/changelog/v3.4.6\"},{\"text\":\"v3.4.5\",\"link\":\"/guide/changelog/v3.4.5\"},{\"text\":\"v3.4.4\",\"link\":\"/guide/changelog/v3.4.4\"},{\"text\":\"v3.4.3\",\"link\":\"/guide/changelog/v3.4.3\"},{\"text\":\"v3.4.2\",\"link\":\"/guide/changelog/v3.4.2\"},{\"text\":\"v3.4.1\",\"link\":\"/guide/changelog/v3.4.1\"},{\"text\":\"v3.4.0\",\"link\":\"/guide/changelog/v3.4.0\"},{\"text\":\"v3.3.1\",\"link\":\"/guide/changelog/v3.3.1\"},{\"text\":\"v3.3.0\",\"link\":\"/guide/changelog/v3.3.0\"},{\"text\":\"v3.2.7\",\"link\":\"/guide/changelog/v3.2.7\"},{\"text\":\"v3.2.6\",\"link\":\"/guide/changelog/v3.2.6\"},{\"text\":\"v3.2.4\",\"link\":\"/guide/changelog/v3.2.4\"},{\"text\":\"v3.2.3\",\"link\":\"/guide/changelog/v3.2.3\"},{\"text\":\"v3.2.2\",\"link\":\"/guide/changelog/v3.2.2\"},{\"text\":\"v3.2.1\",\"link\":\"/guide/changelog/v3.2.1\"},{\"text\":\"v3.2.0\",\"link\":\"/guide/changelog/v3.2.0\"},{\"text\":\"v3.1.3\",\"link\":\"/guide/changelog/v3.1.3\"},{\"text\":\"v3.1.2\",\"link\":\"/guide/changelog/v3.1.2\"},{\"text\":\"v3.1.1\",\"link\":\"/guide/changelog/v3.1.1\"},{\"text\":\"v3.1.0\",\"link\":\"/guide/changelog/v3.1.0\"},{\"text\":\"v3.0.1\",\"link\":\"/guide/changelog/v3.0.1\"},{\"text\":\"v3.0.0\",\"link\":\"/guide/changelog/v3.0.0\"}]},{\"text\":\"Other Links\",\"collapsed\":false,\"items\":[{\"text\":\"Guide\",\"link\":\"/guide/\"},{\"text\":\"Annotations Reference\",\"link\":\"/annotations/\"},{\"text\":\"Configuration Reference\",\"link\":\"/config/\"}]}],\"/examples/\":[{\"text\":\"Examples\",\"items\":[{\"text\":\"Overview\",\"link\":\"/examples/\"}]},{\"text\":\"Reference\",\"items\":[{\"text\":\"Guide\",\"link\":\"/guide/\"},{\"text\":\"Annotations Reference\",\"link\":\"/annotations/\"},{\"text\":\"Configuration Reference\",\"link\":\"/config/\"},{\"text\":\"Changelog\",\"link\":\"/guide/changelog/\"}]}],\"/guide/\":[{\"text\":\"Getting Started\",\"items\":[{\"text\":\"Overview\",\"link\":\"/guide/\"},{\"text\":\"Installation\",\"link\":\"/guide/installation\"},{\"text\":\"Quick Start\",\"link\":\"/guide/quick-start\"}]},{\"text\":\"Topics\",\"items\":[{\"text\":\"SQL File Endpoints\",\"link\":\"/guide/sql-files\"},{\"text\":\"Configuration Guide\",\"link\":\"/guide/configuration\"},{\"text\":\"Comment Annotations Guide\",\"link\":\"/guide/annotations\"},{\"text\":\"Authentication\",\"link\":\"/guide/authentication\"},{\"text\":\"Server-Sent Events\",\"link\":\"/guide/sse\"},{\"text\":\"HTTP Custom Types\",\"link\":\"/guide/http-types\"},{\"text\":\"Proxy Endpoints\",\"link\":\"/guide/proxy\"},{\"text\":\"Testing\",\"link\":\"/guide/testing\"},{\"text\":\"Logging\",\"link\":\"/guide/logging\"}]},{\"text\":\"Reference\",\"items\":[{\"text\":\"FAQ & Troubleshooting\",\"link\":\"/guide/faq\"},{\"text\":\"Changelog\",\"link\":\"/guide/changelog/\"},{\"text\":\"Examples\",\"link\":\"/examples/\"},{\"text\":\"Annotations Reference\",\"link\":\"/annotations/\"},{\"text\":\"Configuration Reference\",\"link\":\"/config/\"}]}],\"/annotations/\":[{\"text\":\"HTTP & Routing\",\"items\":[{\"text\":\"Overview\",\"link\":\"/annotations/\"},{\"text\":\"HTTP\",\"link\":\"/annotations/http\"},{\"text\":\"PATH\",\"link\":\"/annotations/path\"},{\"text\":\"PROXY\",\"link\":\"/annotations/proxy\"},{\"text\":\"PROXY_OUT\",\"link\":\"/annotations/proxy-out\"},{\"text\":\"INTERNAL\",\"link\":\"/annotations/internal\"},{\"text\":\"ENABLED\",\"link\":\"/annotations/enabled\"},{\"text\":\"DISABLED\",\"link\":\"/annotations/disabled\"},{\"text\":\"TAGS\",\"link\":\"/annotations/tags\"},{\"text\":\"OPENAPI\",\"link\":\"/annotations/openapi\"},{\"text\":\"MCP\",\"link\":\"/annotations/mcp\"},{\"text\":\"HTTP CUSTOM TYPES\",\"link\":\"/annotations/http-type\"}]},{\"text\":\"Authorization\",\"items\":[{\"text\":\"AUTHORIZE\",\"link\":\"/annotations/authorize\"},{\"text\":\"ALLOW_ANONYMOUS\",\"link\":\"/annotations/allow-anonymous\"},{\"text\":\"LOGIN\",\"link\":\"/annotations/login\"},{\"text\":\"LOGOUT\",\"link\":\"/annotations/logout\"},{\"text\":\"BASIC_AUTH\",\"link\":\"/annotations/basic-auth\"},{\"text\":\"BASIC_AUTH_REALM\",\"link\":\"/annotations/basic-auth-realm\"},{\"text\":\"BASIC_AUTH_COMMAND\",\"link\":\"/annotations/basic-auth-command\"}]},{\"text\":\"Request Configuration\",\"items\":[{\"text\":\"REQUEST_PARAM_TYPE\",\"link\":\"/annotations/request-param-type\"},{\"text\":\"REQUEST_HEADERS_MODE\",\"link\":\"/annotations/request-headers-mode\"},{\"text\":\"REQUEST_HEADERS_PARAMETER_NAME\",\"link\":\"/annotations/request-headers-parameter-name\"},{\"text\":\"BODY_PARAMETER_NAME\",\"link\":\"/annotations/body-parameter-name\"},{\"text\":\"QUERY_STRING_NULL_HANDLING\",\"link\":\"/annotations/query-string-null-handling\"},{\"text\":\"VALIDATE\",\"link\":\"/annotations/validate\"}]},{\"text\":\"Response Configuration\",\"items\":[{\"text\":\"Response Headers\",\"link\":\"/annotations/response-headers\"},{\"text\":\"RESPONSE_NULL_HANDLING\",\"link\":\"/annotations/response-null-handling\"},{\"text\":\"NESTED\",\"link\":\"/annotations/nested\"},{\"text\":\"SINGLE\",\"link\":\"/annotations/single\"},{\"text\":\"VOID\",\"link\":\"/annotations/void\"},{\"text\":\"RAW\",\"link\":\"/annotations/raw\"},{\"text\":\"SEPARATOR\",\"link\":\"/annotations/separator\"},{\"text\":\"NEW_LINE\",\"link\":\"/annotations/new-line\"},{\"text\":\"COLUMN_NAMES\",\"link\":\"/annotations/column-names\"}]},{\"text\":\"Caching & Performance\",\"items\":[{\"text\":\"CACHED\",\"link\":\"/annotations/cached\"},{\"text\":\"CACHE_EXPIRES_IN\",\"link\":\"/annotations/cache-expires-in\"},{\"text\":\"CACHE_PROFILE\",\"link\":\"/annotations/cache-profile\"},{\"text\":\"BUFFER_ROWS\",\"link\":\"/annotations/buffer-rows\"},{\"text\":\"COMMAND_TIMEOUT\",\"link\":\"/annotations/command-timeout\"},{\"text\":\"RETRY_STRATEGY\",\"link\":\"/annotations/retry-strategy\"},{\"text\":\"Interval Format\",\"link\":\"/annotations/interval-format\"}]},{\"text\":\"Server-Sent Events\",\"items\":[{\"text\":\"SSE\",\"link\":\"/annotations/sse\"},{\"text\":\"SSE_EVENTS_LEVEL\",\"link\":\"/annotations/sse-events-level\"},{\"text\":\"SSE_EVENTS_SCOPE\",\"link\":\"/annotations/sse-events-scope\"}]},{\"text\":\"Upload & Policies\",\"items\":[{\"text\":\"UPLOAD\",\"link\":\"/annotations/upload\"},{\"text\":\"ERROR_CODE_POLICY\",\"link\":\"/annotations/error-code-policy\"},{\"text\":\"RATE_LIMITER_POLICY\",\"link\":\"/annotations/rate-limiter-policy\"}]},{\"text\":\"Output & Code Generation\",\"items\":[{\"text\":\"TABLE_FORMAT\",\"link\":\"/annotations/table-format\"},{\"text\":\"TSCLIENT\",\"link\":\"/annotations/tsclient\"}]},{\"text\":\"Parameters\",\"items\":[{\"text\":\"PARAM\",\"link\":\"/annotations/param\"},{\"text\":\"PARAMETER_HASH\",\"link\":\"/annotations/parameter-hash\"},{\"text\":\"ENCRYPT / DECRYPT\",\"link\":\"/annotations/encrypt-decrypt\"},{\"text\":\"Parameter Value Substitution\",\"link\":\"/annotations/parameter-substitution\"},{\"text\":\"Resolved Parameters\",\"link\":\"/annotations/resolved-parameters\"}]},{\"text\":\"SQL File Annotations\",\"items\":[{\"text\":\"DEFINE_PARAM\",\"link\":\"/annotations/define-param\"},{\"text\":\"RESULT_NAME\",\"link\":\"/annotations/result-name\"},{\"text\":\"SKIP\",\"link\":\"/annotations/skip\"},{\"text\":\"RETURNS\",\"link\":\"/annotations/returns\"}]},{\"text\":\"Test Files (--test)\",\"items\":[{\"text\":\"TEST @setup\",\"link\":\"/annotations/test-setup\"},{\"text\":\"TEST @teardown\",\"link\":\"/annotations/test-teardown\"},{\"text\":\"TEST @connection\",\"link\":\"/annotations/test-connection\"},{\"text\":\"TEST @tag\",\"link\":\"/annotations/test-tag\"},{\"text\":\"TEST @claim\",\"link\":\"/annotations/test-claim\"},{\"text\":\"TEST @response\",\"link\":\"/annotations/test-response\"}]},{\"text\":\"Context & Security\",\"items\":[{\"text\":\"USER_CONTEXT\",\"link\":\"/annotations/user-context\"},{\"text\":\"USER_PARAMETERS\",\"link\":\"/annotations/user-parameters\"},{\"text\":\"CONNECTION\",\"link\":\"/annotations/connection\"},{\"text\":\"SECURITY_SENSITIVE\",\"link\":\"/annotations/security-sensitive\"},{\"text\":\"Custom Parameters\",\"link\":\"/annotations/custom-parameters\"}]},{\"text\":\"Other Links\",\"collapsed\":false,\"items\":[{\"text\":\"Guide\",\"link\":\"/guide/\"},{\"text\":\"Configuration Reference\",\"link\":\"/config/\"},{\"text\":\"Changelog\",\"link\":\"/guide/changelog/\"}]}],\"/config/\":[{\"text\":\"Core Settings\",\"items\":[{\"text\":\"Overview\",\"link\":\"/config/\"},{\"text\":\"Latest Default Configuration\",\"link\":\"/config/latest\"},{\"text\":\"Top-Level Settings\",\"link\":\"/config/top-level\"},{\"text\":\"Config Section\",\"link\":\"/config/config-section\"},{\"text\":\"NpgsqlRest Options\",\"link\":\"/config/npgsqlrest\"},{\"text\":\"Routine Options\",\"link\":\"/config/routine-options\"},{\"text\":\"Connection Settings\",\"link\":\"/config/connection\"},{\"text\":\"Server & SSL\",\"link\":\"/config/server\"}]},{\"text\":\"Security\",\"items\":[{\"text\":\"Authentication\",\"link\":\"/config/auth\"},{\"text\":\"External OAuth\",\"link\":\"/config/external-auth\"},{\"text\":\"Passkey Authentication\",\"link\":\"/config/passkey-auth\"},{\"text\":\"Authentication Options\",\"link\":\"/config/authentication-options\"},{\"text\":\"Claims Mapping\",\"link\":\"/config/claims-mapping\"},{\"text\":\"Basic Auth Config\",\"link\":\"/config/basic-auth-config\"},{\"text\":\"Validation\",\"link\":\"/config/validation\"},{\"text\":\"Antiforgery\",\"link\":\"/config/antiforgery\"},{\"text\":\"Data Protection\",\"link\":\"/config/data-protection\"},{\"text\":\"CORS\",\"link\":\"/config/cors\"},{\"text\":\"Security Headers\",\"link\":\"/config/security-headers\"},{\"text\":\"Forwarded Headers\",\"link\":\"/config/forwarded-headers\"}]},{\"text\":\"Features\",\"items\":[{\"text\":\"SQL File Source\",\"link\":\"/config/sql-file-source\"},{\"text\":\"Test Runner\",\"link\":\"/config/test-runner\"},{\"text\":\"Watch Mode\",\"link\":\"/config/watch\"},{\"text\":\"Proxy\",\"link\":\"/config/proxy\"},{\"text\":\"OpenAPI\",\"link\":\"/config/openapi\"},{\"text\":\"MCP\",\"link\":\"/config/mcp\"},{\"text\":\"HTTP Files\",\"link\":\"/config/http-files\"},{\"text\":\"Code Generation\",\"link\":\"/config/codegen\"},{\"text\":\"Upload Options\",\"link\":\"/config/uploads\"},{\"text\":\"Table Format\",\"link\":\"/config/table-format\"},{\"text\":\"HTTP Client\",\"link\":\"/config/http-client\"}]},{\"text\":\"Performance\",\"items\":[{\"text\":\"Response Compression\",\"link\":\"/config/response-compression\"},{\"text\":\"Cache Options\",\"link\":\"/config/cache-options\"},{\"text\":\"Rate Limiter\",\"link\":\"/config/rate-limiter\"},{\"text\":\"Command Retry\",\"link\":\"/config/command-retry\"},{\"text\":\"Thread Pool\",\"link\":\"/config/thread-pool\"}]},{\"text\":\"Infrastructure\",\"items\":[{\"text\":\"Logging\",\"link\":\"/config/logging\"},{\"text\":\"Static Files\",\"link\":\"/config/static-files\"},{\"text\":\"Error Handling\",\"link\":\"/config/error-handling\"},{\"text\":\"Health Checks\",\"link\":\"/config/health-checks\"},{\"text\":\"Stats\",\"link\":\"/config/stats\"}]},{\"text\":\"Other Links\",\"collapsed\":false,\"items\":[{\"text\":\"Guide\",\"link\":\"/guide/\"},{\"text\":\"Annotations Reference\",\"link\":\"/annotations/\"}]}]},\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/NpgsqlRest/NpgsqlRest\"},{\"icon\":{\"svg\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"currentColor\\\"><path d=\\\"M22.957 7.21c-.004-3.064-2.391-5.576-5.191-6.482-3.478-1.125-8.064-.962-11.384.604C2.357 3.231 1.093 7.391 1.046 11.54c-.039 3.411.302 7.463 3.097 9.746 2.602 2.124 6.19 2.078 9.402 1.836 1.883-.142 3.939-.358 5.477-1.528 1.564-1.19 1.873-3.298 1.972-5.151.134-2.51.187-5.016-.037-7.233zm-2.55 7.703c-.078 1.593-.383 3.473-1.795 4.334-1.351.824-3.151.973-4.686 1.083-2.891.207-6.063.276-8.514-1.399C3.106 17.39 2.924 14.34 2.95 11.67c.03-3.206.678-6.721 3.654-8.375 2.756-1.531 6.556-1.727 9.544-.872 2.339.669 4.351 2.678 4.355 5.217.007 2.583-.016 5.168-.095 7.273z\\\"/><path d=\\\"M16.088 5.19c-1.008-.542-2.607-.48-3.441.388-.568.591-.773 1.389-.8 2.172-.034.993.068 2.013.361 2.953.307.985 1.034 1.848 2.077 2.012.878.138 1.83-.088 2.458-.732.7-.718.88-1.81.877-2.779-.003-.989-.084-1.99-.423-2.91-.268-.726-.654-1.328-1.109-1.104zm-.294 5.482c-.182.462-.581.771-1.091.696-.532-.078-.859-.533-1.04-1.005-.248-.647-.327-1.375-.312-2.06.01-.46.095-.939.371-1.313.345-.467.993-.447 1.426-.115.41.315.607.835.74 1.32.18.66.211 1.675-.094 2.477zM8.4 10.394c.233 1.084.755 2.299 1.907 2.579.934.227 1.993-.165 2.434-1.048.455-.91.346-1.995.166-2.972-.165-.893-.46-1.885-1.207-2.445-.745-.559-1.832-.457-2.479.192-.84.843-.958 2.138-.955 3.277.001.147.119.364.134.417zm1.363-2.808c.302-.321.805-.336 1.14-.054.445.375.618 1.015.75 1.558.131.54.212 1.156.082 1.703-.1.423-.378.821-.84.882-.469.062-.886-.306-1.088-.704-.326-.644-.401-1.426-.381-2.148.013-.465.104-.993.337-1.237z\\\"/></svg>\"},\"link\":\"https://patreon.com/vbconsulting\",\"ariaLabel\":\"Patreon\"},{\"icon\":{\"svg\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"currentColor\\\"><path d=\\\"M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364z\\\"/></svg>\"},\"link\":\"https://buymeacoffee.com/vbilopavu\",\"ariaLabel\":\"Buy Me a Coffee\"}],\"editLink\":{\"pattern\":\"https://github.com/NpgsqlRest/npgsqlrest-docs/edit/main/docs/:path\",\"text\":\"Edit this page on GitHub\"},\"search\":{\"provider\":\"local\"}},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
</body>
</html>