github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/docs/guide/advanced/multi-services.html (about) 1 <!DOCTYPE html> 2 <html lang="en-US"> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width,initial-scale=1"> 6 <title>Multi-services | Goyave</title> 7 <meta name="generator" content="VuePress 1.5.3"> 8 <link rel="icon" type="image/png" sizes="16x16" href="/goyave/goyave_16.png"> 9 <link rel="icon" type="image/png" sizes="32x32" href="/goyave/goyave_32.png"> 10 <link rel="icon" type="image/png" sizes="64x64" href="/goyave/goyave_64.png"> 11 <link rel="icon" type="image/png" sizes="128x128" href="/goyave/goyave_128.png"> 12 <link rel="icon" type="image/png" sizes="256x256" href="/goyave/goyave_256.png"> 13 <link rel="icon" type="image/png" sizes="512x512" href="/goyave/goyave_512.png"> 14 <meta name="description" content="Goyave is a Golang web API framework aiming at cleanliness, fast development and power."> 15 <meta name="og:title" content="Multi-services - Goyave"> 16 <meta name="twitter:title" content="Multi-services - Goyave"> 17 <meta name="title" content="Multi-services - Goyave"> 18 <meta property="twitter:description" content="Goyave is a Golang web API framework aiming at cleanliness, fast development and power."> 19 <meta property="twitter:image:src" content="https://system-glitch.github.io/goyave/goyave_banner.png"> 20 <meta property="twitter:card" content="summary_large_image"> 21 <meta property="og:type" content="website"> 22 <meta property="og:description" content="Goyave is a Golang web API framework aiming at cleanliness, fast development and power."> 23 <meta property="og:image" content="https://system-glitch.github.io/goyave/goyave_banner.png"> 24 <meta property="og:site_name" content="Goyave"> 25 <link rel="preload" href="/goyave/assets/css/0.styles.589fd562.css" as="style"><link rel="preload" href="/goyave/assets/js/app.092490a7.js" as="script"><link rel="preload" href="/goyave/assets/js/4.75a9cc68.js" as="script"><link rel="preload" href="/goyave/assets/js/1.121dd9ed.js" as="script"><link rel="preload" href="/goyave/assets/js/13.770050f3.js" as="script"><link rel="preload" href="/goyave/assets/js/5.c83f1192.js" as="script"><link rel="prefetch" href="/goyave/assets/js/10.2f07bbf5.js"><link rel="prefetch" href="/goyave/assets/js/11.2d66fdef.js"><link rel="prefetch" href="/goyave/assets/js/12.63171b15.js"><link rel="prefetch" href="/goyave/assets/js/14.b933d8cf.js"><link rel="prefetch" href="/goyave/assets/js/15.36df2a66.js"><link rel="prefetch" href="/goyave/assets/js/16.ed66719e.js"><link rel="prefetch" href="/goyave/assets/js/17.7bef5f05.js"><link rel="prefetch" href="/goyave/assets/js/18.470b55ed.js"><link rel="prefetch" href="/goyave/assets/js/19.90e0dab8.js"><link rel="prefetch" href="/goyave/assets/js/20.3a300ca3.js"><link rel="prefetch" href="/goyave/assets/js/21.c3fd6053.js"><link rel="prefetch" href="/goyave/assets/js/22.d5569617.js"><link rel="prefetch" href="/goyave/assets/js/23.931b2034.js"><link rel="prefetch" href="/goyave/assets/js/24.1a4755e7.js"><link rel="prefetch" href="/goyave/assets/js/25.0d463913.js"><link rel="prefetch" href="/goyave/assets/js/26.3c173a7a.js"><link rel="prefetch" href="/goyave/assets/js/27.9c5b36f2.js"><link rel="prefetch" href="/goyave/assets/js/28.41e055b7.js"><link rel="prefetch" href="/goyave/assets/js/29.b87adf4a.js"><link rel="prefetch" href="/goyave/assets/js/3.ef71e77d.js"><link rel="prefetch" href="/goyave/assets/js/6.2336bf0c.js"><link rel="prefetch" href="/goyave/assets/js/7.d60e55c1.js"><link rel="prefetch" href="/goyave/assets/js/8.2ee33a42.js"><link rel="prefetch" href="/goyave/assets/js/9.8e043d60.js"> 26 <link rel="stylesheet" href="/goyave/assets/css/0.styles.589fd562.css"> 27 </head> 28 <body> 29 <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/goyave/" class="home-link router-link-active"><img src="/goyave/goyave_64.png" alt="Goyave" class="logo"> <span class="site-name can-hide">Goyave</span></a> <div class="links"><div class="user-settings"><a title="Dark theme" href="#" class="settings-button"><svg aria-hidden="true" data-prefix="fas" data-icon="cog" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg-inline--fa fa-cog fa-w-16 settings-icon"><path fill="currentColor" d="M8 0c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM8 15c-3.9 0-7-3.1-7-7 0-2.4 1.2-4.6 3.2-5.9-0.1 0.6-0.2 1.3-0.2 1.9 0 4.9 4 8.9 8.9 9-1.3 1.3-3 2-4.9 2z"></path></svg></a></div> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/goyave/guide/" class="nav-link router-link-active"> 30 Guide 31 </a></div><div class="nav-item"><a href="https://pkg.go.dev/github.com/System-Glitch/goyave/v2" target="_blank" rel="noopener noreferrer" class="nav-link external"> 32 pkg.go.dev 33 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <a href="https://github.com/System-Glitch/goyave" target="_blank" rel="noopener noreferrer" class="repo-link"> 34 GitHub 35 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/goyave/guide/" class="nav-link router-link-active"> 36 Guide 37 </a></div><div class="nav-item"><a href="https://pkg.go.dev/github.com/System-Glitch/goyave/v2" target="_blank" rel="noopener noreferrer" class="nav-link external"> 38 pkg.go.dev 39 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <a href="https://github.com/System-Glitch/goyave" target="_blank" rel="noopener noreferrer" class="repo-link"> 40 GitHub 41 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Guide</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>The Basics</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Advanced</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/goyave/guide/advanced/helpers.html" class="sidebar-link">Helpers</a></li><li><a href="/goyave/guide/advanced/authentication.html" class="sidebar-link">Authentication</a></li><li><a href="/goyave/guide/advanced/localization.html" class="sidebar-link">Localization</a></li><li><a href="/goyave/guide/advanced/testing.html" class="sidebar-link">Testing</a></li><li><a href="/goyave/guide/advanced/multi-services.html" aria-current="page" class="active sidebar-link">Multi-services</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/multi-services.html#introduction" class="sidebar-link">Introduction</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/multi-services.html#startup-hooks" class="sidebar-link">Startup hooks</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/multi-services.html#start-the-server" class="sidebar-link">Start the server</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/multi-services.html#stop-the-server" class="sidebar-link">Stop the server</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/multi-services.html#server-status" class="sidebar-link">Server status</a></li><li class="sidebar-sub-header"><a href="/goyave/guide/advanced/multi-services.html#maintenance-mode" class="sidebar-link">Maintenance mode</a></li></ul></li><li><a href="/goyave/guide/advanced/cors.html" class="sidebar-link">CORS</a></li><li><a href="/goyave/guide/advanced/status-handlers.html" class="sidebar-link">Status Handlers</a></li><li><a href="/goyave/guide/advanced/logging.html" class="sidebar-link">Logging</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="multi-services"><a href="#multi-services" class="header-anchor">#</a> Multi-services</h1> <p></p><div class="table-of-contents"><ul><li><a href="#introduction">Introduction</a></li><li><a href="#startup-hooks">Startup hooks</a></li><li><a href="#start-the-server">Start the server</a><ul><li><a href="#errors">Errors</a></li></ul></li><li><a href="#stop-the-server">Stop the server</a></li><li><a href="#server-status">Server status</a></li><li><a href="#maintenance-mode">Maintenance mode</a></li></ul></div><p></p> <h2 id="introduction"><a href="#introduction" class="header-anchor">#</a> Introduction</h2> <p>Sometimes you need to run several services in the same executable. For example if you are hosting a websocket server on top of your web API. Goyave can be run in a goroutine and stopped on-demand.</p> <p>All functions below are features that require the <code>goyave</code> package to be imported.</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"github.com/System-Glitch/goyave/v2"</span> 42 </code></pre></div><h2 id="startup-hooks"><a href="#startup-hooks" class="header-anchor">#</a> Startup hooks</h2> <p>Startup hooks are function executed in a goroutine after the server finished initializing. This is especially useful when you want to start other services or execute specific commands while being sure the server is up and running, ready to respond to incoming requests. Startup hooks must be registered <strong>before</strong> the <code>goyave.Start()</code> call.</p> <h4 id="goyave-registerstartuphook"><a href="#goyave-registerstartuphook" class="header-anchor">#</a> goyave.RegisterStartupHook</h4> <p>Register a startup hook to execute some code once the server is ready and running.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>hook func()</code></td> <td><code>void</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>goyave<span class="token punctuation">.</span><span class="token function">RegsiterStartupHook</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 43 goyave<span class="token punctuation">.</span>Logger<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Server ready."</span><span class="token punctuation">)</span> 44 <span class="token punctuation">}</span><span class="token punctuation">)</span> 45 </code></pre></div><h4 id="goyave-clearstartuphooks"><a href="#goyave-clearstartuphooks" class="header-anchor">#</a> goyave.ClearStartupHooks</h4> <p>Clear all registered startup hooks. Useful when you are writing tests or developing a service able to restart your server multiple times.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>void</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>goyave<span class="token punctuation">.</span><span class="token function">ClearStartupHooks</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 46 </code></pre></div><h2 id="start-the-server"><a href="#start-the-server" class="header-anchor">#</a> Start the server</h2> <h4 id="goyave-start"><a href="#goyave-start" class="header-anchor">#</a> goyave.Start</h4> <p>Starts the server. This functions needs a route registrer function as a parameter. Learn more in the <a href="/goyave/guide/basics/routing.html">routing</a> section.<br> 47 The configuration is not reloaded if you call <code>Start</code> multiple times. You can still reload the configuration with <code>config.Load()</code> if you need it. 48 This operation is <strong>blocking</strong>. Triggers a panic if the server is already running. Errors returned can be safely type-asserted to <code>*goyave.Error</code>.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td><code>routeRegistrer func(*goyave.Router)</code></td> <td><code>error</code></td></tr></tbody></table> <p><strong>Examples:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> err <span class="token operator">:=</span> goyave<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span>route<span class="token punctuation">.</span>Register<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> 49 os<span class="token punctuation">.</span><span class="token function">Exit</span><span class="token punctuation">(</span>err<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>goyave<span class="token punctuation">.</span>Error<span class="token punctuation">)</span><span class="token punctuation">.</span>ExitCode<span class="token punctuation">)</span> 50 <span class="token punctuation">}</span> 51 </code></pre></div><p><strong>Running the server in the background:</strong></p> <p>You can start the server in a goroutine. However, if you do this and the main goroutine terminates, the server will not shutdown gracefully and the program will exit right away. Be sure to call <code>goyave.Stop()</code> to stop the server gracefully before exiting. Learn more in the next section.</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span> goyave<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span>route<span class="token punctuation">.</span>Register<span class="token punctuation">)</span> 52 <span class="token comment">//...</span> 53 goyave<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 54 </code></pre></div><h3 id="errors"><a href="#errors" class="header-anchor">#</a> Errors</h3> <p>Errors generated byt the server itself (when calling <code>Start()</code>) are wrapped into an instance of <code>*goyave.Error</code>. This struct contains an exit code and the original error.</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Error <span class="token keyword">struct</span> <span class="token punctuation">{</span> 55 ExitCode <span class="token builtin">int</span> 56 Err <span class="token builtin">error</span> 57 <span class="token punctuation">}</span> 58 </code></pre></div><p><strong>Exit codes:</strong></p> <ul><li><code>2</code>: Panic (server already running, error when loading language files, etc)</li> <li><code>3</code>: Configuration is invalid</li> <li><code>4</code>: An error occurred when opening network listener</li> <li><code>5</code>: An error occurred in the HTTP server</li></ul> <h2 id="stop-the-server"><a href="#stop-the-server" class="header-anchor">#</a> Stop the server</h2> <p>When the running process receives a <code>SIGINT</code> or a <code>SIGTERM</code> signal, for example when you press <code>CTRL+C</code> to interrupt the program, the server will shutdown gracefully, so you don't have to handle that yourself.</p> <p>However, if you start the server in a goroutine, you have the responsibility to shutdown properly. If you exit the program manually or if the main goroutine terminates, ensure that <code>goyave.Stop()</code> is called. If the program exits because of an interruption signal, the server will shutdown gracefully.</p> <h4 id="goyave-stop"><a href="#goyave-stop" class="header-anchor">#</a> goyave.Stop</h4> <p>Stop the server gracefully without interrupting any active connections. Make sure the program doesn't exit and waits instead for Stop to return.</p> <p>Stop does not attempt to close nor wait for hijacked connections such as WebSockets. The caller of <code>Stop</code> should separately notify such long-lived connections of shutdown and wait for them to close, if desired.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>void</code></td></tr></tbody></table> <p><strong>Examples:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>goyave<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 59 </code></pre></div><h2 id="server-status"><a href="#server-status" class="header-anchor">#</a> Server status</h2> <p>The <code>goyave.IsReady()</code> function lets you know if the server is running or not.</p> <p>This function should not be used to wait for the server to be ready. Use a startup hook instead.</p> <h4 id="goyave-isready"><a href="#goyave-isready" class="header-anchor">#</a> goyave.IsReady</h4> <p>Returns true if the server is ready to receive and serve incoming requests.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>bool</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> goyave<span class="token punctuation">.</span><span class="token function">IsReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 60 goyave<span class="token punctuation">.</span>Logger<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Server is ready"</span><span class="token punctuation">)</span> 61 <span class="token punctuation">}</span> 62 </code></pre></div><h2 id="maintenance-mode"><a href="#maintenance-mode" class="header-anchor">#</a> Maintenance mode</h2> <p><span class="badge tip" style="vertical-align:top;" data-v-15b7b770>Since v2.1.0</span></p> <p>On top of being able to start the server in maintenance mode using the <code>maintenance</code> configuration entry, you can enable and disable this mode at runtime.</p> <div class="table"><p><a href="#goyave-enablemaintenance">EnableMaintenance</a> <a href="#goyave-disablemaintenance">DisableMaintenance</a> <a href="#goyave-ismaintenanceenabled">IsMaintenanceEnabled</a></p></div><h4 id="goyave-enablemaintenance"><a href="#goyave-enablemaintenance" class="header-anchor">#</a> goyave.EnableMaintenance</h4> <p>Replace the main server handler with the "Service Unavailable" handler.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>void</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>goyave<span class="token punctuation">.</span><span class="token function">EnableMaintenance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 63 </code></pre></div><h4 id="goyave-disablemaintenance"><a href="#goyave-disablemaintenance" class="header-anchor">#</a> goyave.DisableMaintenance</h4> <p>Replace the main server handler with the original router.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>void</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>goyave<span class="token punctuation">.</span><span class="token function">DisableMaintenance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 64 </code></pre></div><h4 id="goyave-ismaintenanceenabled"><a href="#goyave-ismaintenanceenabled" class="header-anchor">#</a> goyave.IsMaintenanceEnabled</h4> <p>Returns true if the server is currently in maintenance mode.</p> <table><thead><tr><th>Parameters</th> <th>Return</th></tr></thead> <tbody><tr><td></td> <td><code>bool</code></td></tr></tbody></table> <p><strong>Example:</strong></p> <div class="language-go extra-class"><pre class="language-go"><code>fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>goyave<span class="token punctuation">.</span><span class="token function">IsMaintenanceEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// false</span> 65 </code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/System-Glitch/goyave/edit/master/docs_src/src/guide/advanced/multi-services.md" target="_blank" rel="noopener noreferrer">Edit this page on GitHub</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev"> 66 ← 67 <a href="/goyave/guide/advanced/testing.html" class="prev"> 68 Testing 69 </a></span> <span class="next"><a href="/goyave/guide/advanced/cors.html"> 70 CORS 71 </a> 72 → 73 </span></p></div> </main></div><div class="global-ui"><!----></div></div> 74 <script src="/goyave/assets/js/app.092490a7.js" defer></script><script src="/goyave/assets/js/4.75a9cc68.js" defer></script><script src="/goyave/assets/js/1.121dd9ed.js" defer></script><script src="/goyave/assets/js/13.770050f3.js" defer></script><script src="/goyave/assets/js/5.c83f1192.js" defer></script> 75 </body> 76 </html>