| <!doctype html> |
| <html class="docs-version-current" lang="en" dir="ltr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <meta name="ahrefs-site-verification" content="c2f7370ecf46173f4fb25f114e74c97e0a2976d4f02f61c9b00a9d7d34e34698"> |
| <meta name="generator" content="Docusaurus v2.0.0-beta.6"> |
| <link rel="search" type="application/opensearchdescription+xml" title="Apache APISIX® -- Cloud-Native API Gateway and AI Gateway" href="/opensearch.xml"> |
| <script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"Apache APISIX","url":"https://apisix.apache.org"}</script> |
| <script src="https://widget.kapa.ai/kapa-widget.bundle.js" data-website-id="24b59d9a-682e-4c3d-9e83-bf2ee85cdc19" data-project-name="APISIX" data-project-color="#E8442E" data-project-logo="https://static.apiseven.com/202202/apache-apisix.png" data-modal-disclaimer="This is a custom LLM for APISIX with access to all developer documentation, GitHub issues and discussions." data-modal-example-questions="How to set up canary release in APISIX?,How to develop a custom APISIX plugin?,How to use custom NGINX configuration in APISIX?,How to configure mTLS between clients and APISIX?,How to only allow a specific APISIX consumer to access special services or routes?" async></script><title data-react-helmet="true">Getting started | Apache APISIX® -- Cloud-Native API Gateway and AI Gateway</title><meta data-react-helmet="true" property="og:image" content="https://static.apiseven.com/202202/apache-apisix.png"><meta data-react-helmet="true" name="twitter:image" content="https://static.apiseven.com/202202/apache-apisix.png"><meta data-react-helmet="true" property="og:url" content="https://apisix.apache.org/docs/go-plugin-runner/next/getting-started/"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="current"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-docs-apisix-go-plugin-runner-current"><meta data-react-helmet="true" name="robots" content="index,follow"><meta data-react-helmet="true" name="twitter:card" content="summary"><meta data-react-helmet="true" property="og:title" content="Getting started | Apache APISIX® -- Cloud-Native API Gateway and AI Gateway"><meta data-react-helmet="true" name="description" content="Go (>= 1.15)"><meta data-react-helmet="true" property="og:description" content="Go (>= 1.15)"><link data-react-helmet="true" rel="shortcut icon" href="https://static.apiseven.com/202202/favicon.png"><link data-react-helmet="true" rel="canonical" href="https://apisix.apache.org/docs/go-plugin-runner/next/getting-started/"><link data-react-helmet="true" rel="alternate" href="https://apisix.apache.org/docs/go-plugin-runner/next/getting-started/" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://apisix.apache.org/zh/docs/go-plugin-runner/next/getting-started/" hreflang="zh"><link data-react-helmet="true" rel="alternate" href="https://apisix.apache.org/docs/go-plugin-runner/next/getting-started/" hreflang="x-default"><link data-react-helmet="true" rel="preconnect" href="https://38VC84A2WJ-dsn.algolia.net" crossorigin="anonymous"><link rel="preload" href="https://static.apiseven.com/202202/MaisonNeue-Medium.otf" as="font" type="font/otf" crossorigin> |
| <link rel="preload" href="https://static.apiseven.com/202202/MaisonNeue-Bold.otf" as="font" type="font/otf" crossorigin> |
| <link rel="preload" href="https://static.apiseven.com/202202/MaisonNeue-Light.otf" as="font" type="font/otf" crossorigin> |
| <link rel="preload" href="https://static.apiseven.com/202202/MaisonNeue-Demi.otf" as="font" type="font/otf" crossorigin> |
| <link rel="preload" href="https://static.apiseven.com/202202/MaisonNeue-ExtraBold.otf" as="font" type="font/otf" crossorigin> |
| <link rel="preload" href="https://apisix-website-static.apiseven.com/assets/js/runtime~main.e29fe45b.js" as="script"> |
| <link rel="preload" href="https://apisix-website-static.apiseven.com/assets/js/main.e360d437.js" as="script"> |
| <link rel="stylesheet" href="https://apisix-website-static.apiseven.com/assets/css/styles.8de0825e.css"> |
| |
| <script>var _paq=window._paq=window._paq||[];_paq.push(["disableCookies"]),_paq.push(["trackPageView"]),_paq.push(["enableLinkTracking"]),function(){var a="https://analytics.apache.org/";_paq.push(["setTrackerUrl",a+"matomo.php"]),_paq.push(["setSiteId","17"]);var e=document,p=e.createElement("script"),t=e.getElementsByTagName("script")[0];p.async=!0,p.src=a+"matomo.js",t.parentNode.insertBefore(p,t)}()</script> |
| |
| </head> |
| <body> |
| <script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())</script><div id="__docusaurus"> |
| <div><a href="#" class="skipToContent_OuoZ">Skip to main content</a></div><div class="announcementBar_axC9" style="background-color:#e8433e;color:white" role="banner"><div class="announcementBarPlaceholder_xYHE"></div><div class="announcementBarContent_6uhP">🤔 Introducing APISIX AI Gateway – Built for LLMs and AI workloads. <a target="_blank" rel="noopener noreferrer" href="/ai-gateway/"> Learn More</a></div><button type="button" class="clean-btn close announcementBarClose_A3A1" aria-label="Close"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor"><path d="M24 20.188l-8.315-8.209 8.2-8.282-3.697-3.697-8.212 8.318-8.31-8.203-3.666 3.666 8.321 8.24-8.206 8.313 3.666 3.666 8.237-8.318 8.285 8.203z"></path></svg></button></div><nav class="navbar navbar--fixed-top navbarHideable_RReh"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a target="_parent" class="navbar__brand" href="/"><img src="/img/logo2.svg" alt="Apache APISIX®" class="themedImage_TMUO themedImage--light_4Vu1 navbar__logo"><img src="/img/logo2.svg" alt="Apache APISIX®" class="themedImage_TMUO themedImage--dark_uzRr navbar__logo"><b class="navbar__title">Apache APISIX®</b></a></div><div class="navbar__items navbar__items--right"><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a aria-current="page" class="navbar__link" target="_parent" href="/docs/">Docs</a><ul class="dropdown__menu"><li><a class="dropdown__link" target="_parent" href="/docs/apisix/getting-started/">Apache APISIX®️</a></li><li><a class="dropdown__link" target="_parent" href="/docs/apisix/next/dashboard/">Apache APISIX®️ Dashboard</a></li><li><a class="dropdown__link" target="_parent" href="/docs/ingress-controller/overview/">Apache APISIX®️ Ingress Controller</a></li><li><a class="dropdown__link" target="_parent" href="/docs/helm-chart/apisix/">Apache APISIX®️ Helm Charts</a></li><li><a class="dropdown__link" target="_parent" href="/docs/docker/build/">Apache APISIX®️ Docker</a></li><li><a class="dropdown__link" target="_parent" href="/docs/java-plugin-runner/development/">Apache APISIX®️ Java Plugin Runner</a></li><li><a class="dropdown__link" target="_parent" href="/docs/go-plugin-runner/getting-started/">Apache APISIX®️ Go Plugin Runner</a></li><li><a class="dropdown__link" target="_parent" href="/docs/python-plugin-runner/getting-started/">Apache APISIX®️ Python Plugin Runner</a></li><li><a class="dropdown__link" target="_parent" href="/docs/general/join/">General</a></li></ul></div><a class="navbar__item navbar__link" target="_parent" href="/blog/">Blog</a><a class="navbar__item navbar__link" target="_parent" href="/blog/tags/case-studies/">Case Studies</a><a class="navbar__item navbar__link" target="_parent" href="/downloads/">Downloads</a><a class="navbar__item navbar__link" target="_parent" href="/help/">Help</a><a class="navbar__item navbar__link" target="_parent" href="/team/">Team</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a class="navbar__link">Resources</a><ul class="dropdown__menu"><li><a class="dropdown__link" target="_parent" href="/showcase/">Showcase</a></li><li><a class="dropdown__link" target="_parent" href="/docs/general/code-samples/">Code Samples</a></li><li><a class="dropdown__link" target="_parent" href="/plugins/">PluginHub</a></li><li><a class="dropdown__link" target="_parent" href="/docs/general/join/">Community</a></li><li><a class="dropdown__link" target="_parent" href="/docs/general/events/">Events</a></li><li><a href="https://github.com/apache/apisix/milestones" target="_parent" rel="noopener noreferrer" class="dropdown__link">Roadmap</a></li></ul></div><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a href="#" class="navbar__link"><span><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" class="iconLanguage_zID8"><path fill="currentColor" d="M19.753 10.909c-.624-1.707-2.366-2.726-4.661-2.726-.09 0-.176.002-.262.006l-.016-2.063 3.525-.607c.115-.019.133-.119.109-.231-.023-.111-.167-.883-.188-.976-.027-.131-.102-.127-.207-.109-.104.018-3.25.461-3.25.461l-.013-2.078c-.001-.125-.069-.158-.194-.156l-1.025.016c-.105.002-.164.049-.162.148l.033 2.307s-3.061.527-3.144.543c-.084.014-.17.053-.151.143.019.09.19 1.094.208 1.172.018.08.072.129.188.107l2.924-.504.035 2.018c-1.077.281-1.801.824-2.256 1.303-.768.807-1.207 1.887-1.207 2.963 0 1.586.971 2.529 2.328 2.695 3.162.387 5.119-3.06 5.769-4.715 1.097 1.506.256 4.354-2.094 5.98-.043.029-.098.129-.033.207l.619.756c.08.096.206.059.256.023 2.51-1.73 3.661-4.515 2.869-6.683zm-7.386 3.188c-.966-.121-.944-.914-.944-1.453 0-.773.327-1.58.876-2.156a3.21 3.21 0 011.229-.799l.082 4.277a2.773 2.773 0 01-1.243.131zm2.427-.553l.046-4.109c.084-.004.166-.01.252-.01.773 0 1.494.145 1.885.361.391.217-1.023 2.713-2.183 3.758zm-8.95-7.668a.196.196 0 00-.196-.145h-1.95a.194.194 0 00-.194.144L.008 16.916c-.017.051-.011.076.062.076h1.733c.075 0 .099-.023.114-.072l1.008-3.318h3.496l1.008 3.318c.016.049.039.072.113.072h1.734c.072 0 .078-.025.062-.076-.014-.05-3.083-9.741-3.494-11.04zm-2.618 6.318l1.447-5.25 1.447 5.25H3.226z"></path></svg><span>English</span></span></a><ul class="dropdown__menu"><li><a href="/docs/go-plugin-runner/next/getting-started/" target="_self" rel="noopener noreferrer" class="dropdown__link dropdown__link--active" style="text-transform:capitalize">English</a></li><li><a href="/zh/docs/go-plugin-runner/next/getting-started/" target="_self" rel="noopener noreferrer" class="dropdown__link" style="text-transform:capitalize">简体中文</a></li></ul></div><div class="react-toggle toggle_2i4l react-toggle--disabled"><div class="react-toggle-track" role="button" tabindex="-1"><div class="react-toggle-track-check"><span class="toggle_iYfV">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_iYfV">🌞</span></div><div class="react-toggle-thumb"></div></div><input type="checkbox" class="react-toggle-screenreader-only" aria-label="Switch between dark and light mode"></div><div class="searchBox_fBfG"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper docs-doc-page"><div class="docPage_GMj9"><button class="clean-btn backToTopButton_i9tI" type="button"><svg viewBox="0 0 24 24" width="28"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="currentColor"></path></svg></button><aside class="docSidebarContainer_k0Pq"><div class="sidebar_LIo8 sidebarWithHideableNavbar_CMI-"><a target="_parent" tabindex="-1" class="sidebarLogo_P87M" href="/"><img src="/img/logo2.svg" alt="Apache APISIX®" class="themedImage_TMUO themedImage--light_4Vu1"><img src="/img/logo2.svg" alt="Apache APISIX®" class="themedImage_TMUO themedImage--dark_uzRr"><b>Apache APISIX®</b></a><div class="sidebarVersionSwitch_0QIZ">Version:<div class="navbar__item dropdown dropdown--hoverable"><a aria-current="page" class="navbar__link" href="/docs/go-plugin-runner/next/getting-started/">Next</a><ul class="dropdown__menu"><li><a aria-current="page" class="dropdown__link dropdown__link--active" href="/docs/go-plugin-runner/next/getting-started/"><div>Next</div></a></li><li><a class="dropdown__link" href="/docs/go-plugin-runner/getting-started/"><div>0.5.0<div class="badge_6FVu Latest_oyqS">Latest</div></div></a></li><li><a class="dropdown__link" href="/docs/go-plugin-runner/0.4.0/getting-started/"><div>0.4.0</div></a></li><li><a class="dropdown__link" href="/docs/go-plugin-runner/0.3.0/getting-started/"><div>0.3.0</div></a></li><li><a class="dropdown__link" href="/docs/go-plugin-runner/0.2.0/getting-started/"><div>0.2.0</div></a></li><li><a class="dropdown__link" href="/docs/go-plugin-runner/0.1.0/getting-started/"><div>0.1.0</div></a></li></ul></div></div><nav class="menu thin-scrollbar menu_oAhv menuWithAnnouncementBar_IVfW"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link menu__link--active" aria-current="page" href="/docs/go-plugin-runner/next/getting-started/">Getting started</a></li><li class="theme-doc-sidebar-item-link menu__list-item"><a class="menu__link" href="/docs/go-plugin-runner/next/developer-guide/">Developer Guide</a></li></ul></nav><button type="button" title="Collapse sidebar" aria-label="Collapse sidebar" class="button button--secondary button--outline collapseSidebarButton_EBxv"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_AF9Q"><g fill="#7a7a7a"><path d="M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"></path><path d="M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"></path></g></svg></button></div></aside><main class="docMainContainer_Q970"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_zHA2"><div class="theme-doc-version-banner alert alert--warning margin-bottom--md" role="alert"><div>This is unreleased documentation for Apache APISIX® -- Cloud-Native API Gateway and AI Gateway <b>Next</b> version.</div><div class="margin-top--md">For up-to-date documentation, see the <b><a href="/docs/go-plugin-runner/getting-started/">latest version</a></b> (0.5.0).</div></div><div class="docItemContainer_oiyr"><article><span class="theme-doc-version-badge badge badge--secondary">Version: Next</span><div class="tocCollapsible_aw-L theme-doc-toc-mobile tocMobile_Tx6Y"><button type="button" class="clean-btn tocCollapsibleButton_zr6a">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Getting started</h1></header><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3ly5" id="prerequisites"></a>Prerequisites<a class="hash-link" href="#prerequisites" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3ly5" id="compatibility-with-golang"></a>Compatibility with Golang<a class="hash-link" href="#compatibility-with-golang" title="Direct link to heading">#</a></h3><ul><li>Go (>= 1.15)</li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3ly5" id="compatibility-with-apache-apisix"></a>Compatibility with Apache APISIX<a class="hash-link" href="#compatibility-with-apache-apisix" title="Direct link to heading">#</a></h3><p>The following table describes the compatibility between apisix-go-plugin-runner and |
| <a href="https://apisix.apache.org" target="_blank" rel="noopener noreferrer">Apache APISIX</a>.</p><table><thead><tr><th align="right">apisix-go-plugin-runner</th><th align="right">Apache APISIX</th></tr></thead><tbody><tr><td align="right"><code>master</code></td><td align="right"><code>master</code> is recommended.</td></tr><tr><td align="right"><code>0.5.0</code></td><td align="right"><code>>= 3.0.0</code>, <code>3.0.0</code> is recommended.</td></tr><tr><td align="right"><code>0.4.0</code></td><td align="right"><code>>= 2.14.1</code>, <code>2.14.1</code> is recommended.</td></tr><tr><td align="right"><code>0.3.0</code></td><td align="right"><code>>= 2.13.0</code>, <code>2.13.0</code> is recommended.</td></tr><tr><td align="right"><code>0.2.0</code></td><td align="right"><code>>= 2.9.0</code>, <code>2.9.0</code> is recommended.</td></tr><tr><td align="right"><code>0.1.0</code></td><td align="right"><code>>= 2.7.0</code>, <code>2.7.0</code> is recommended.</td></tr></tbody></table><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3ly5" id="installation"></a>Installation<a class="hash-link" href="#installation" title="Direct link to heading">#</a></h2><p>For now, we need to use Go Runner as a library. <code>cmd/go-runner</code> in this project is an official example showing how to use the Go Runner SDK. |
| We will also support loading pre-compiled plugins through the Go Plugin mechanism later.</p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3ly5" id="development"></a>Development<a class="hash-link" href="#development" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3ly5" id="developing-with-the-go-runner-sdk"></a>Developing with the Go Runner SDK<a class="hash-link" href="#developing-with-the-go-runner-sdk" title="Direct link to heading">#</a></h3><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">$ tree cmd/go-runner</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cmd/go-runner</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── main.go</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── main_test.go</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── plugins</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ ├── say.go</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│ └── say_test.go</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── version.go</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>Above is the directory structure of the official example. <code>main.go</code> is the entry point, where the most critical part is:</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 go"><pre tabindex="0" class="prism-code language-go codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">cfg </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> runner</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">RunnerConfig</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">runner</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p><code>RunnerConfig</code> can be used to control the log level and log output location.</p><p><code>runner.Run</code> will make the application listen to the target socket path, receive requests and execute the registered plugins. The application will remain in this state until it exits.</p><p>Then let's look at the plugin implementation.</p><p>Open <code>plugins/say.go</code>.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 go"><pre tabindex="0" class="prism-code language-go codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">RegisterPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&</span><span class="token plain">Say</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Fatalf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"failed to register plugin say: %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>Since <code>main.go</code> imports the plugins package,</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 go"><pre tabindex="0" class="prism-code language-go codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"github.com/apache/apisix-go-plugin-runner/cmd/go-runner/plugins"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>in this way we register <code>Say</code> with <code>plugin.RegisterPlugin</code> before executing <code>runner.Run</code>.</p><p><code>Say</code> needs to implement the following methods:</p><p>The <code>Name</code> method returns the plugin name.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">func </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p *Say</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> Name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> string </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token builtin class-name">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"say"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p><code>ParseConf</code> will be called when the plugin configuration changes, parsing the configuration and returning the plugin specific configuration.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">func </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p *Say</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> ParseConf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">in </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">byte</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">, error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> conf :</span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> SayConf</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> err :</span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> json.Unmarshal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">in, </span><span class="token operator" style="color:#393A34">&</span><span class="token plain">conf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token builtin class-name">return</span><span class="token plain"> conf, err</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>The configuration of the plugin looks like this.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token builtin class-name">type</span><span class="token plain"> SayConf struct </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Body string </span><span class="token variable" style="color:#36acaa">`</span><span class="token variable" style="color:#36acaa">json: </span><span class="token variable string" style="color:#e3116c">"body"</span><span class="token variable" style="color:#36acaa">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p><code>RequestFilter</code> will be executed on every request with the say plugin configured.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">func </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p *Say</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> RequestFilter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conf interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">, w http.ResponseWriter, r pkgHTTP.Request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> body :</span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> conf.</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">SayConf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">.Body</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token builtin class-name">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> w.Header</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">.Add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"X-Resp-A6-Runner"</span><span class="token plain">, </span><span class="token string" style="color:#e3116c">"Go"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> _, err :</span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> w.Write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">))</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> nil </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> log.Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"failed to write: %s"</span><span class="token plain">, err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>We can see that the RequestFilter takes the value of the body set in the configuration as the response body. If we call <code>Write</code> or <code>WriteHeader</code> of the <code>http.ResponseWriter</code> |
| (respond directly in the plugin), it will response directly in the APISIX without touching the upstream. We can also set response headers in the plugin and touch the upstream |
| at the same time by set RespHeader in <code>pkgHTTP.Request</code>.</p><p><code>ResponseFilter</code> supports rewriting the response during the response phase, we can see an example of its use in the ResponseRewrite plugin:</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 go"><pre tabindex="0" class="prism-code language-go codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> RegexFilter </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Regex </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"regex"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Scope </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"scope"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Replace </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"replace"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> regexComplied </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">regexp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Regexp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> ResponseRewriteConf </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Status </span><span class="token builtin">int</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"status"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Headers </span><span class="token keyword" style="color:#00009f">map</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">]</span><span class="token builtin">string</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"headers"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Body </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"body"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> Filters </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">RegexFilter </span><span class="token string" style="color:#e3116c">`json:"filters"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">ResponseRewrite</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ResponseFilter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conf </span><span class="token keyword" style="color:#00009f">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> w pkgHTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> cfg </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> conf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ResponseRewriteConf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Status </span><span class="token operator" style="color:#393A34">></span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">WriteHeader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">200</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Header</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"X-Resp-A6-Runner"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Go"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Headers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">></span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> k</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">range</span><span class="token plain"> cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Headers </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Header</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">k</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> body </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Filters</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">></span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> originBody</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ReadBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">...</span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34"><</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Filters</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> f </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Filters</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> found </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">regexComplied</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originBody</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> found </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> matched </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Scope </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"once"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> originBody </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Replace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originBody</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> found</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Replace</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Scope </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"global"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> originBody </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ReplaceAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originBody</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> found</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Replace</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">...</span><span class="token operator" style="color:#393A34">...</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cfg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"failed to write: %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>We can see that <code>ResponseFilter</code> will rewrite the status, header, and response body of the response phase according to the configuration.</p><p>In addition, we can also get the status and headers in the original response through <code>pkgHTTP.Response</code>.</p><p>For the <code>pkgHTTP.Request</code> and <code>pkgHTTP.Response</code>, you can refer to the <a href="https://pkg.go.dev/github.com/apache/apisix-go-plugin-runner" rel="noopener noreferrer">API documentation</a> provided by the Go Runner SDK.</p><p>After building the application (<code>make build</code> in the example), we need to set some environment variables at runtime:</p><ul><li><code>APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock</code></li></ul><p>Like this:</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">APISIX_LISTEN_ADDRESS</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">unix:/tmp/runner.sock ./go-runner run</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>The application will listen to <code>/tmp/runner.sock</code> when it runs.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3ly5" id="setting-up-apisix-debugging"></a>Setting up APISIX (debugging)<a class="hash-link" href="#setting-up-apisix-debugging" title="Direct link to heading">#</a></h3><p>First you need to have APISIX on your machine, which needs to be on the same instance as Go Runner.</p><p><span class="lazy-load-image-background blur" style="color:transparent;display:inline-block"><div><noscript><img alt="runner-overview" src="https://raw.githubusercontent.com/apache/apisix-go-plugin-runner/master/docs/assets/images/runner-overview.png"></noscript><div style="width:500px;height:300px;border-radius:1rem;background-color:#d2d2d7"></div></div></span></p><p>The diagram above shows the workflow of APISIX on the left, while the plugin runner on the right is responsible for running external plugins written in different languages. apisix-go-plugin-runner is one such runner that supports Go.</p><p>When you configure a plugin runner in APISIX, APISIX will treat the plugin runner as a child process of its own. This sub-process belongs to the same user as the APISIX process. When we restart or reload APISIX, the plugin runner will also be restarted.</p><p>If you configure the ext-plugin-* plugin for a given route, a request to hit that route will trigger APISIX to make an RPC call to the plugin runner via a unix socket. The call is broken down into two phases.</p><ul><li>ext-plugin-pre-req: executed during handling the request, before most of the APISIX built-in plugins (Lua language plugins)</li><li>ext-plugin-post-req: executed during handling the request, after most of the APISIX built-in plugins (Lua language plugins)</li><li>ext-plugin-post-resp: executed during handling the response, after most of the APISIX built-in plugins (Lua language plugins)</li></ul><p>Configure the timing of plugin runner execution as needed.</p><p>The plugin runner handles the RPC calls, creates a mock request from it, then runs the plugins written in other languages and returns the results to APISIX.</p><p>The order of execution of these plugins is defined in the ext-plugin-* plugin configuration. Like other plugins, they can be enabled and disabled on the fly.</p><p>Let's go back to the examples. To show how to develop Go plugins, we first set APISIX into debug mode. Add the following configuration to config.yaml.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">ext-plugin:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> path_for_test: /tmp/runner.sock</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>This configuration means that after hitting a routing rule, APISIX will make an RPC request to /tmp/runner.sock.</p><p>Next, prepare the routing rule.</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> http://127.0.0.1:9080/apisix/admin/routes/1 -H </span><span class="token string" style="color:#e3116c">'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'</span><span class="token plain"> -X PUT -d </span><span class="token string" style="color:#e3116c">'</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "uri": "/get",</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "plugins": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "ext-plugin-pre-req": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "conf": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> { "name": "say", "value":"{\"body\":\"hello\"}"}</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> ]</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> },</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "upstream": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "type": "roundrobin",</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "nodes": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> "127.0.0.1:1980": 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c"> }</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">'</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>Note that the plugin name is configured in <code>name</code> and the plugin configuration (after JSON serialization) is placed in <code>value</code>.</p><p>If you see <code>refresh cache and try again</code> warning on APISIX side and <code>key not found</code> warning on Runner side during development, this is due to configuration cache inconsistency. Because the Runner is not managed by APISIX in the development state, the internal state may be inconsistent. Don't worry, APISIX will retry.</p><p>Then we request: curl 127.0.0.1:9080/get</p><p>We can see that the interface returns hello and does not access anything upstream.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3ly5" id="setting-up-apisix-running"></a>Setting up APISIX (running)<a class="hash-link" href="#setting-up-apisix-running" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3ly5" id="setting-up-directly"></a>Setting up directly<a class="hash-link" href="#setting-up-directly" title="Direct link to heading">#</a></h4><p>Here's an example of go-runner, you just need to configure the command line to run it inside ext-plugin:</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">ext-plugin:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># path_for_test: /tmp/runner.sock</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> cmd: </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"/path/to/apisix-go-plugin-runner/go-runner"</span><span class="token plain">, </span><span class="token string" style="color:#e3116c">"run"</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>APISIX will treat the plugin runner as a child process of its own, managing its entire lifecycle.</p><p>APISIX will automatically assign a unix socket address for the runner to listen to when it starts. environment variables do not need to be set manually.</p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3ly5" id="setting-up-in-container"></a>Setting up in container<a class="hash-link" href="#setting-up-in-container" title="Direct link to heading">#</a></h4><p>First you need to prepare the go-runner binary. Use this command:</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 shell"><pre tabindex="0" class="prism-code language-shell codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">make</span><span class="token plain"> build</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</h5></div><div class="admonition-content"><p>When you use a Linux distribution such as Alpine Linux that is not based on standard glibc, you must turn off Golang's CGO support via the <code>CGO_ENABLED=0</code> environment variable to avoid libc ABI incompatibilities. </p><p>If you want to use CGO, then you must build the binaries using the Go compiler and the C compiler in the same Linux distribution.</p></div></div><p>Then you need to rebuild the container image to include the go-runner binary. You can use the following Dockerfile:</p><div class="codeBlockContainer_EiTO"><div class="codeBlockContent_X2I6 bash"><pre tabindex="0" class="prism-code language-bash codeBlock_UxnK thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_W6UD"><span class="token-line" style="color:#393A34"><span class="token plain">FROM apache/apisix:2.15.0-debian</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">COPY ./go-runner /usr/local/apisix-go-plugin-runner/go-runner</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_V-PD clean-btn">Copy</button></div></div><p>Finally, you can push and run your custom image, just configure the binary path and commands in the configuration file via <code>ext-plugin.cmd</code> to start APISIX with go plugin runner.</p></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a href="/edit#https://github.com/apache/apisix-go-plugin-runner/edit/master/docs/en/latest/getting-started.md" target="_blank" rel="noreferrer noopener" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_mS5F" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_mt2f"></div></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/go-plugin-runner/next/developer-guide/"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Developer Guide »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_vrFS thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#prerequisites" class="table-of-contents__link">Prerequisites</a><ul><li><a href="#compatibility-with-golang" class="table-of-contents__link">Compatibility with Golang</a></li><li><a href="#compatibility-with-apache-apisix" class="table-of-contents__link">Compatibility with Apache APISIX</a></li></ul></li><li><a href="#installation" class="table-of-contents__link">Installation</a></li><li><a href="#development" class="table-of-contents__link">Development</a><ul><li><a href="#developing-with-the-go-runner-sdk" class="table-of-contents__link">Developing with the Go Runner SDK</a></li><li><a href="#setting-up-apisix-debugging" class="table-of-contents__link">Setting up APISIX (debugging)</a></li><li><a href="#setting-up-apisix-running" class="table-of-contents__link">Setting up APISIX (running)</a></li></ul></li></ul></div></div></div></div></main></div></div><footer class="container_MP5Z"><div class="linksRow_iwpv"><div class="linksCol_a1ec"><div>ASF</div><ul><li class="footer__item"><a href="https://www.apache.org/" target="_blank" rel="noopener noreferrer"><span></span><span>Foundation</span></a></li><li class="footer__item"><a href="https://www.apache.org/licenses/" target="_blank" rel="noopener noreferrer"><span></span><span>License</span></a></li><li class="footer__item"><a href="https://www.apache.org/events/" target="_blank" rel="noopener noreferrer"><span></span><span>Events</span></a></li><li class="footer__item"><a href="https://www.apache.org/security/" target="_blank" rel="noopener noreferrer"><span></span><span>Security</span></a></li><li class="footer__item"><a href="https://www.apache.org/foundation/sponsorship.html" target="_blank" rel="noopener noreferrer"><span></span><span>Sponsorship</span></a></li><li class="footer__item"><a href="https://www.apache.org/foundation/thanks.html" target="_blank" rel="noopener noreferrer"><span></span><span>Thanks</span></a></li></ul></div><div class="linksCol_a1ec"><div>Community</div><ul><li class="footer__item"><a href="https://github.com/apache/apisix/issues" target="_blank" rel="noopener noreferrer"><span></span><span>GitHub</span></a></li><li class="footer__item"><a href="/docs/general/join/"><span></span><span>Slack</span></a></li><li class="footer__item"><a href="https://twitter.com/ApacheAPISIX" target="_blank" rel="noopener noreferrer"><span></span><span>Twitter</span></a></li><li class="footer__item"><a href="https://www.youtube.com/channel/UCgPD18cMhOg5rmPVnQhAC8g" target="_blank" rel="noopener noreferrer"><span></span><span>YouTube</span></a></li></ul></div><div class="linksCol_a1ec"><div>More</div><ul><li class="footer__item"><a target="_parent" href="/blog/"><span></span><span>Blog</span></a></li><li class="footer__item"><a target="_parent" href="/showcase/"><span></span><span>Showcase</span></a></li><li class="footer__item"><a target="_parent" href="/plugins/"><span></span><span>Plugin Hub</span></a></li><li class="footer__item"><a href="https://github.com/apache/apisix/milestones" target="_parent" rel="noopener noreferrer"><span></span><span>Roadmap</span></a></li></ul></div></div><div class="copyright_ZfFh"><a href="https://www.apache.org/" target="_blank" rel="noopener noreferrer"><span style="display:inline-block;width:231.25px;height:40px"></span></a><div>Copyright © 2019-2025 The Apache Software Foundation. Apache APISIX, APISIX®, Apache, the Apache feather logo, and the Apache APISIX project logo are either registered trademarks or trademarks of the Apache Software Foundation.</div></div></footer></div> |
| <script src="https://apisix-website-static.apiseven.com/assets/js/runtime~main.e29fe45b.js"></script> |
| <script src="https://apisix-website-static.apiseven.com/assets/js/main.e360d437.js"></script> |
| </body> |
| </html> |