| |
| <!DOCTYPE html> |
| |
| |
| <html lang="en" data-content_root="./" > |
| |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" /> |
| |
| <title>Writing your own Guacamole application — Apache Guacamole Manual v1.6.0</title> |
| |
| |
| |
| <script data-cfasync="false"> |
| document.documentElement.dataset.mode = localStorage.getItem("mode") || ""; |
| document.documentElement.dataset.theme = localStorage.getItem("theme") || ""; |
| </script> |
| |
| <!-- Loaded before other Sphinx assets --> |
| <link href="_static/styles/theme.css?digest=dfe6caa3a7d634c4db9b" rel="stylesheet" /> |
| <link href="_static/styles/bootstrap.css?digest=dfe6caa3a7d634c4db9b" rel="stylesheet" /> |
| <link href="_static/styles/pydata-sphinx-theme.css?digest=dfe6caa3a7d634c4db9b" rel="stylesheet" /> |
| |
| |
| <link href="_static/vendor/fontawesome/6.5.2/css/all.min.css?digest=dfe6caa3a7d634c4db9b" rel="stylesheet" /> |
| <link rel="preload" as="font" type="font/woff2" crossorigin href="_static/vendor/fontawesome/6.5.2/webfonts/fa-solid-900.woff2" /> |
| <link rel="preload" as="font" type="font/woff2" crossorigin href="_static/vendor/fontawesome/6.5.2/webfonts/fa-brands-400.woff2" /> |
| <link rel="preload" as="font" type="font/woff2" crossorigin href="_static/vendor/fontawesome/6.5.2/webfonts/fa-regular-400.woff2" /> |
| |
| <link rel="stylesheet" type="text/css" href="_static/pygments.css?v=8f2a1f02" /> |
| <link rel="stylesheet" type="text/css" href="_static/styles/sphinx-book-theme.css?v=eba8b062" /> |
| <link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" /> |
| <link rel="stylesheet" type="text/css" href="_static/tabs.css?v=4c969af8" /> |
| <link rel="stylesheet" type="text/css" href="_static/gug.css?v=475feb7f" /> |
| |
| <!-- Pre-loaded scripts that we'll load fully later --> |
| <link rel="preload" as="script" href="_static/scripts/bootstrap.js?digest=dfe6caa3a7d634c4db9b" /> |
| <link rel="preload" as="script" href="_static/scripts/pydata-sphinx-theme.js?digest=dfe6caa3a7d634c4db9b" /> |
| <script src="_static/vendor/fontawesome/6.5.2/js/all.min.js?digest=dfe6caa3a7d634c4db9b"></script> |
| |
| <script src="_static/documentation_options.js?v=9eb32ce0"></script> |
| <script src="_static/doctools.js?v=9bcbadda"></script> |
| <script src="_static/sphinx_highlight.js?v=dc90522c"></script> |
| <script src="_static/clipboard.min.js?v=a7894cd8"></script> |
| <script src="_static/copybutton.js?v=c136e461"></script> |
| <script src="_static/tabs.js?v=3ee01567"></script> |
| <script src="_static/scripts/sphinx-book-theme.js?v=887ef09a"></script> |
| <script>DOCUMENTATION_OPTIONS.pagename = 'writing-you-own-guacamole-app';</script> |
| <link rel="index" title="Index" href="genindex.html" /> |
| <link rel="search" title="Search" href="search.html" /> |
| <link rel="next" title="Guacamole protocol reference" href="protocol-reference.html" /> |
| <link rel="prev" title="Event listeners" href="event-listeners.html" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1"/> |
| <meta name="docsearch:language" content="en"/> |
| </head> |
| |
| |
| <body data-bs-spy="scroll" data-bs-target=".bd-toc-nav" data-offset="180" data-bs-root-margin="0px 0px -60%" data-default-mode=""> |
| |
| |
| |
| <div id="pst-skip-link" class="skip-link d-print-none"><a href="#main-content">Skip to main content</a></div> |
| |
| <div id="pst-scroll-pixel-helper"></div> |
| |
| <button type="button" class="btn rounded-pill" id="pst-back-to-top"> |
| <i class="fa-solid fa-arrow-up"></i>Back to top</button> |
| |
| |
| <input type="checkbox" |
| class="sidebar-toggle" |
| id="pst-primary-sidebar-checkbox"/> |
| <label class="overlay overlay-primary" for="pst-primary-sidebar-checkbox"></label> |
| |
| <input type="checkbox" |
| class="sidebar-toggle" |
| id="pst-secondary-sidebar-checkbox"/> |
| <label class="overlay overlay-secondary" for="pst-secondary-sidebar-checkbox"></label> |
| |
| <div class="search-button__wrapper"> |
| <div class="search-button__overlay"></div> |
| <div class="search-button__search-container"> |
| <form class="bd-search d-flex align-items-center" |
| action="search.html" |
| method="get"> |
| <i class="fa-solid fa-magnifying-glass"></i> |
| <input type="search" |
| class="form-control" |
| name="q" |
| id="search-input" |
| placeholder="Search..." |
| aria-label="Search..." |
| autocomplete="off" |
| autocorrect="off" |
| autocapitalize="off" |
| spellcheck="false"/> |
| <span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span> |
| </form></div> |
| </div> |
| |
| <div class="pst-async-banner-revealer d-none"> |
| <aside id="bd-header-version-warning" class="d-none d-print-none" aria-label="Version warning"></aside> |
| </div> |
| |
| |
| <header class="bd-header navbar navbar-expand-lg bd-navbar d-print-none"> |
| </header> |
| |
| |
| <div class="bd-container"> |
| <div class="bd-container__inner bd-page-width"> |
| |
| |
| |
| <div class="bd-sidebar-primary bd-sidebar"> |
| |
| |
| |
| <div class="sidebar-header-items sidebar-primary__section"> |
| |
| |
| |
| |
| </div> |
| |
| <div class="sidebar-primary-items__start sidebar-primary__section"> |
| <div class="sidebar-primary-item"> |
| |
| |
| |
| |
| |
| <a class="navbar-brand logo" href="index.html"> |
| |
| |
| |
| |
| |
| |
| <p class="title logo__title">Apache Guacamole Manual v1.6.0</p> |
| |
| </a></div> |
| <div class="sidebar-primary-item"> |
| |
| <script> |
| document.write(` |
| <button class="btn search-button-field search-button__button" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip"> |
| <i class="fa-solid fa-magnifying-glass"></i> |
| <span class="search-button__default-text">Search</span> |
| <span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span> |
| </button> |
| `); |
| </script></div> |
| <div class="sidebar-primary-item"><nav class="bd-links bd-docs-nav" aria-label="Main"> |
| <div class="bd-toc-item navbar-nav active"> |
| <p aria-level="2" class="caption" role="heading"><span class="caption-text">Getting Started</span></p> |
| <ul class="nav bd-sidenav"> |
| <li class="toctree-l1"><a class="reference internal" href="introduction.html">Introduction</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-architecture.html">Implementation and architecture</a></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="installing-guacamole.html">Installing Guacamole</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="guacamole-native.html">Native installation</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="guacamole-docker.html">Containerized (Docker) installation</a></li> |
| </ul> |
| </details></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="jdbc-auth.html">Database setup</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="mysql-auth.html">MariaDB / MySQL</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="postgresql-auth.html">PostgreSQL</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="sqlserver-auth.html">SQL Server</a></li> |
| </ul> |
| </details></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="security.html">Securing a Guacamole install</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="reverse-proxy.html">SSL termination</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="auth-ban.html">Blocking brute-force attacks</a></li> |
| </ul> |
| </details></li> |
| </ul> |
| <p aria-level="2" class="caption" role="heading"><span class="caption-text">Using Guacamole</span></p> |
| <ul class="nav bd-sidenav"> |
| <li class="toctree-l1"><a class="reference internal" href="configuring-guacamole.html">Configuration</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="using-guacamole.html">General usage</a></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="administration.html">Administration</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="batch-import.html">Importing connections</a></li> |
| </ul> |
| </details></li> |
| <li class="toctree-l1"><a class="reference internal" href="troubleshooting.html">Troubleshooting</a></li> |
| </ul> |
| <p aria-level="2" class="caption" role="heading"><span class="caption-text">Extensions</span></p> |
| <ul class="nav bd-sidenav"> |
| <li class="toctree-l1"><a class="reference internal" href="ldap-auth.html">Active Directory / LDAP</a></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="mfa.html">Multi-factor authentication</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="duo-auth.html">Duo</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="totp-auth.html">TOTP</a></li> |
| </ul> |
| </details></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="sso.html">Single sign-on</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="cas-auth.html">CAS</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="openid-auth.html">OpenID Connect</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="saml-auth.html">SAML</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="ssl-auth.html">Smart cards / Certificates</a></li> |
| </ul> |
| </details></li> |
| <li class="toctree-l1"><a class="reference internal" href="vault.html">Retrieving secrets from a vault</a></li> |
| <li class="toctree-l1 has-children"><a class="reference internal" href="external-auth.html">External authentication</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul> |
| <li class="toctree-l2"><a class="reference internal" href="json-auth.html">Encrypted, signed JSON</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="header-auth.html">HTTP header</a></li> |
| </ul> |
| </details></li> |
| <li class="toctree-l1"><a class="reference internal" href="radius-auth.html">RADIUS</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="adhoc-connections.html">Ad-hoc connections</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="auth-restrict.html">Login / Connection restrictions</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="recording-playback.html">Session recording player</a></li> |
| </ul> |
| <p aria-level="2" class="caption" role="heading"><span class="caption-text">Developer's Guide</span></p> |
| <ul class="current nav bd-sidenav"> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-protocol.html">The Guacamole protocol</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="libguac.html">libguac</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-common.html">guacamole-common</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-common-js.html">guacamole-common-js</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-ext.html">guacamole-ext</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="custom-protocols.html">Adding new protocols</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="custom-auth.html">Custom authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="event-listeners.html">Event listeners</a></li> |
| <li class="toctree-l1 current active"><a class="current reference internal" href="#">Writing your own Guacamole application</a></li> |
| </ul> |
| <p aria-level="2" class="caption" role="heading"><span class="caption-text">Appendices</span></p> |
| <ul class="nav bd-sidenav"> |
| <li class="toctree-l1"><a class="reference internal" href="protocol-reference.html">Guacamole protocol reference</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="jdbc-auth-schema.html">Database schema reference</a></li> |
| </ul> |
| |
| </div> |
| </nav></div> |
| </div> |
| |
| |
| <div class="sidebar-primary-items__end sidebar-primary__section"> |
| </div> |
| |
| <div id="rtd-footer-container"></div> |
| |
| |
| </div> |
| |
| <main id="main-content" class="bd-main" role="main"> |
| |
| |
| |
| <div class="sbt-scroll-pixel-helper"></div> |
| |
| <div class="bd-content"> |
| <div class="bd-article-container"> |
| |
| <div class="bd-header-article d-print-none"> |
| <div class="header-article-items header-article__inner"> |
| |
| <div class="header-article-items__start"> |
| |
| <div class="header-article-item"><button class="sidebar-toggle primary-toggle btn btn-sm" title="Toggle primary sidebar" data-bs-placement="bottom" data-bs-toggle="tooltip"> |
| <span class="fa-solid fa-bars"></span> |
| </button></div> |
| |
| </div> |
| |
| |
| <div class="header-article-items__end"> |
| |
| <div class="header-article-item"> |
| |
| <div class="article-header-buttons"> |
| |
| |
| |
| <button onclick="toggleFullScreen()" |
| class="btn btn-sm btn-fullscreen-button" |
| title="Fullscreen mode" |
| data-bs-placement="bottom" data-bs-toggle="tooltip" |
| > |
| |
| |
| <span class="btn__icon-container"> |
| <i class="fas fa-expand"></i> |
| </span> |
| |
| </button> |
| |
| |
| |
| <script> |
| document.write(` |
| <button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip"> |
| <i class="theme-switch fa-solid fa-sun fa-lg" data-mode="light"></i> |
| <i class="theme-switch fa-solid fa-moon fa-lg" data-mode="dark"></i> |
| <i class="theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode="auto"></i> |
| </button> |
| `); |
| </script> |
| |
| |
| <script> |
| document.write(` |
| <button class="btn btn-sm pst-navbar-icon search-button search-button__button" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip"> |
| <i class="fa-solid fa-magnifying-glass fa-lg"></i> |
| </button> |
| `); |
| </script> |
| <button class="sidebar-toggle secondary-toggle btn btn-sm" title="Toggle secondary sidebar" data-bs-placement="bottom" data-bs-toggle="tooltip"> |
| <span class="fa-solid fa-list"></span> |
| </button> |
| </div></div> |
| |
| </div> |
| |
| </div> |
| </div> |
| |
| |
| |
| <div id="jb-print-docs-body" class="onlyprint"> |
| <h1>Writing your own Guacamole application</h1> |
| <!-- Table of contents --> |
| <div id="print-main-content"> |
| <div id="jb-print-toc"> |
| |
| <div> |
| <h2> Contents </h2> |
| </div> |
| <nav aria-label="Page"> |
| <ul class="visible nav section-nav flex-column"> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#the-basics">The basics</a></li> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#web-application-skeleton">Web application skeleton</a><ul class="nav section-nav flex-column"> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#pom-xml"><code class="docutils literal notranslate"><span class="pre">pom.xml</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#web-inf-web-xml"><code class="docutils literal notranslate"><span class="pre">WEB-INF/web.xml</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#index-html"><code class="docutils literal notranslate"><span class="pre">index.html</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#building-the-skeleton">Building the skeleton</a></li> |
| </ul> |
| </li> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#adding-guacamole">Adding Guacamole</a><ul class="nav section-nav flex-column"> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#updating-pom-xml">Updating <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#the-simplest-tunnel-possible">The simplest tunnel possible</a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#adding-the-client">Adding the client</a></li> |
| </ul> |
| </li> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#where-to-go-from-here">Where to go from here</a></li> |
| </ul> |
| </nav> |
| </div> |
| </div> |
| </div> |
| |
| |
| |
| <div id="searchbox"></div> |
| <article class="bd-article"> |
| |
| <section id="writing-your-own-guacamole-application"> |
| <h1>Writing your own Guacamole application<a class="headerlink" href="#writing-your-own-guacamole-application" title="Link to this heading">#</a></h1> |
| <p>As Guacamole is an API, one of the best ways to put Guacamole to use is by |
| building your own Guacamole-driven web application, integrating HTML5 remote |
| desktop into whatever you think needs it.</p> |
| <p>The Guacamole project provides an example of doing this called |
| “guacamole-example”, but this example is already completed for you, and from a |
| quick glance at this example, it may not be obvious just how easy it is to |
| integrate remote access into a web application. This tutorial will walk you |
| through the basic steps of building an HTML5 remote desktop application using |
| the Guacamole API and Maven.</p> |
| <section id="the-basics"> |
| <span id="basic-guacamole-architecture"></span><h2>The basics<a class="headerlink" href="#the-basics" title="Link to this heading">#</a></h2> |
| <p>Guacamole’s architecture is made up of many components, but it’s actually |
| straightforward, especially from the perspective of the web application.</p> |
| <p>Guacamole has a proxy daemon, guacd, which handles communication using remote |
| desktop protocols, exposing those to whatever connects to it (in this case, the |
| web application) using the Guacamole protocol. From where the web application |
| is standing, it doesn’t really matter that guacd dynamically loads protocol |
| plugins or that it shares a common library allowing this; all that matters is |
| that the web application just has to connect to port 4822 (where guacd listens |
| by default) and use the Guacamole protocol. The architecture will take care of |
| the rest.</p> |
| <p>Thankfully, the Java side of the Guacamole API provides simple classes which |
| already implement the Guacamole protocol with the intent of tunneling it |
| between guacd and the JavaScript half of your web application. A typical web |
| application leveraging these classes needs |
| only the following:</p> |
| <ol class="arabic"> |
| <li><p>A class which extends <code class="docutils literal notranslate"><span class="pre">GuacamoleHTTPTunnelServlet</span></code>, providing the tunnel |
| between the JavaScript client (presumably using guacamole-common-js) and |
| guacd.</p> |
| <p><code class="docutils literal notranslate"><span class="pre">GuacamoleHTTPTunnelServlet</span></code> is an abstract class which is provided by the |
| Guacamole API and already implements a fully functional, HTTP-based tunnel |
| which the tunneling objects already part of guacamole-common-js are written |
| to connect to. This class exists to make it easy for you to use Guacamole’s |
| existing and robust HTTP tunnel implementation.</p> |
| <p>If you want to not use this class and instead use your own tunneling |
| mechanism, perhaps WebSocket, this is fine; the JavaScript object mentioned |
| above implements a common interface which you can also implement, and the |
| Guacamole JavaScript client which is also part of guacamole-common-js will |
| happily use your implementation as long as it provides that interface.</p> |
| </li> |
| <li><p>A web page which includes JavaScript files from guacamole-common-js and uses |
| the client and tunnel objects to connect back to the web application.</p> |
| <p>The JavaScript API provided by the Guacamole project includes a full |
| implementation of the Guacamole protocol as a client, implementations of |
| HTTP and WebSocket-based tunnels, and mouse/keyboard/touch input |
| abstraction. Again, as the Guacamole protocol and all parts of the |
| architecture are documented here, you don’t absolutely need to use these |
| objects, but it will make your life easier. Mouse and keyboard support in |
| JavaScript is finicky business, and the Guacamole client provided is |
| well-known to work with other components in the API, being the official |
| client of the project.</p> |
| </li> |
| </ol> |
| <p>That’s really all there is to it.</p> |
| <p>If you want authentication, the place to implement that would be in your |
| extended version of <code class="docutils literal notranslate"><span class="pre">GuacamoleHTTPTunnelServlet</span></code>; this is what the Guacamole |
| web application does. Besides authentication, there are many other things you |
| could wrap around your remote desktop application, but ultimately the base of |
| all this is simple: you have a tunnel which allows the JavaScript client to |
| communicate with guacd, and you have the JavaScript client itself, with the |
| hard part already provided within guacamole-common-js.</p> |
| </section> |
| <section id="web-application-skeleton"> |
| <span id="web-app-skeleton"></span><h2>Web application skeleton<a class="headerlink" href="#web-application-skeleton" title="Link to this heading">#</a></h2> |
| <p>As with most tutorials, this tutorial begins with creating a project skeleton |
| that establishes a minimal base for the tutorial to enhance in subsequent |
| steps.</p> |
| <p>This tutorial will use Maven, which is the same build system used by the |
| upstream Guacamole project. As the Guacamole project has a Maven repository for |
| both the Java and JavaScript APIs, writing a Guacamole-based application using |
| Maven is much easier; Maven will download and use the Guacamole API |
| automatically.</p> |
| <section id="pom-xml"> |
| <h3><code class="docutils literal notranslate"><span class="pre">pom.xml</span></code><a class="headerlink" href="#pom-xml" title="Link to this heading">#</a></h3> |
| <p>All Maven projects must have a project descriptor, the <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> file, in the |
| root directory of the project. This file describes project dependencies and |
| specific build requirements. Unlike other build tools like Apache Ant or GNU |
| Autotools, Maven chooses convention over configuration: files within the |
| project must be placed in specific locations, and the project dependencies must |
| be fully described in the pom.xml. If this is done, the build will be handled |
| automatically.</p> |
| <p>The basis of this Guacamole-driven web application will be a simple HTML file |
| which will ultimately become the client. While the finished product will have |
| an HTTP tunnel written in Java, we don’t need this yet for our skeleton. We |
| will create a very basic, barebones Maven project containing only <code class="docutils literal notranslate"><span class="pre">index.html</span></code> |
| and a web application descriptor file, <code class="docutils literal notranslate"><span class="pre">web.xml</span></code>. Once these files are in |
| place, the project can be packaged into a <code class="docutils literal notranslate"><span class="pre">.war</span></code> file which can be deployed to |
| your servlet container of choice (such as Apache Tomcat).</p> |
| <p>As this skeleton will contain no Java code, it has no dependencies, and |
| no build requirements beyond the metadata common to any Maven project. |
| The <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> is thus very simple for the time being: |
| i</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt"><project</span><span class="w"> </span><span class="na">xmlns=</span><span class="s">"http://maven.apache.org/POM/4.0.0"</span> |
| <span class="w"> </span><span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span> |
| <span class="w"> </span><span class="na">xsi:schemaLocation=</span><span class="s">"http://maven.apache.org/POM/4.0.0 </span> |
| <span class="s"> http://maven.apache.org/maven-v4_0_0.xsd"</span><span class="nt">></span> |
| |
| <span class="w"> </span><span class="nt"><modelVersion></span>4.0.0<span class="nt"></modelVersion></span> |
| <span class="w"> </span><span class="nt"><groupId></span>org.apache.guacamole<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>guacamole-tutorial<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><packaging></span>war<span class="nt"></packaging></span> |
| <span class="w"> </span><span class="nt"><version></span>1.6.0<span class="nt"></version></span> |
| <span class="w"> </span><span class="nt"><name></span>guacamole-tutorial<span class="nt"></name></span> |
| |
| <span class="w"> </span><span class="nt"><properties></span> |
| <span class="w"> </span><span class="nt"><project.build.sourceEncoding></span>UTF-8<span class="nt"></project.build.sourceEncoding></span> |
| <span class="w"> </span><span class="nt"></properties></span> |
| |
| <span class="nt"></project></span> |
| </pre></div> |
| </div> |
| </section> |
| <section id="web-inf-web-xml"> |
| <h3><code class="docutils literal notranslate"><span class="pre">WEB-INF/web.xml</span></code><a class="headerlink" href="#web-inf-web-xml" title="Link to this heading">#</a></h3> |
| <p>Before the project will build, there needs to be a web application deployment |
| descriptor, <code class="docutils literal notranslate"><span class="pre">web.xml</span></code>. This file is required by the Java EE standard for |
| building the <code class="docutils literal notranslate"><span class="pre">.war</span></code> file which will contain the web application, and will be |
| read by the servlet container when the application is actually deployed. For |
| Maven to find and use this file when building the <code class="docutils literal notranslate"><span class="pre">.war</span></code>, it must be placed in |
| the <code class="docutils literal notranslate"><span class="pre">src/main/webapp/WEB-INF/</span></code> directory.</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span> |
| |
| <span class="nt"><web-app</span><span class="w"> </span><span class="na">version=</span><span class="s">"2.5"</span> |
| <span class="w"> </span><span class="na">xmlns=</span><span class="s">"http://java.sun.com/xml/ns/javaee"</span> |
| <span class="w"> </span><span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span> |
| <span class="w"> </span><span class="na">xsi:schemaLocation=</span><span class="s">"http://java.sun.com/xml/ns/javaee </span> |
| <span class="s"> http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"</span><span class="nt">></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Basic config --></span> |
| <span class="w"> </span><span class="nt"><welcome-file-list></span> |
| <span class="w"> </span><span class="nt"><welcome-file></span>index.html<span class="nt"></welcome-file></span> |
| <span class="w"> </span><span class="nt"></welcome-file-list></span> |
| |
| <span class="nt"></web-app></span> |
| </pre></div> |
| </div> |
| </section> |
| <section id="index-html"> |
| <h3><code class="docutils literal notranslate"><span class="pre">index.html</span></code><a class="headerlink" href="#index-html" title="Link to this heading">#</a></h3> |
| <p>With the <code class="docutils literal notranslate"><span class="pre">web.xml</span></code> file in place and the skeleton <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> written, the web |
| application will now build successfully. However, as the <code class="docutils literal notranslate"><span class="pre">web.xml</span></code> refers to a |
| “welcome file” called <code class="docutils literal notranslate"><span class="pre">index.html</span></code> (which will ultimately contain our client), |
| we need to put this in place so the servlet container will have something to |
| serve. This file, as well as any other future static files, belongs within |
| <code class="docutils literal notranslate"><span class="pre">src/main/webapp</span></code>.</p> |
| <p>For now, this file can contain anything, since the other parts of our |
| Guacamole-driven web application are not written yet. It is a placeholder which |
| we will replace later:</p> |
| <div class="highlight-html notranslate"><div class="highlight"><pre><span></span><span class="cp"><!DOCTYPE HTML></span> |
| <span class="p"><</span><span class="nt">html</span><span class="p">></span> |
| |
| <span class="p"><</span><span class="nt">head</span><span class="p">></span> |
| <span class="p"><</span><span class="nt">title</span><span class="p">></span>Guacamole Tutorial<span class="p"></</span><span class="nt">title</span><span class="p">></span> |
| <span class="p"></</span><span class="nt">head</span><span class="p">></span> |
| |
| <span class="p"><</span><span class="nt">body</span><span class="p">></span> |
| <span class="p"><</span><span class="nt">p</span><span class="p">></span>Hello World<span class="p"></</span><span class="nt">p</span><span class="p">></span> |
| <span class="p"></</span><span class="nt">body</span><span class="p">></span> |
| |
| <span class="p"></</span><span class="nt">html</span><span class="p">></span> |
| </pre></div> |
| </div> |
| </section> |
| <section id="building-the-skeleton"> |
| <h3>Building the skeleton<a class="headerlink" href="#building-the-skeleton" title="Link to this heading">#</a></h3> |
| <p>Once all three of the above files are in place, the web application will build, |
| and can even be deployed to your servlet container. It won’t do anything yet |
| other than serve the <code class="docutils literal notranslate"><span class="pre">index.html</span></code> file, but it’s good to at least try building |
| the web application to make sure nothing is missing and all steps were followed |
| correctly before proceeding:</p> |
| <div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>mvn<span class="w"> </span>package |
| <span class="go">[INFO] Scanning for projects...</span> |
| <span class="go">[INFO] ------------------------------------------------------------------------</span> |
| <span class="go">[INFO] Building guacamole-tutorial</span> |
| <span class="go">[INFO] task-segment: [package]</span> |
| <span class="go">[INFO] ------------------------------------------------------------------------</span> |
| <span class="go">...</span> |
| <span class="go">[INFO] ------------------------------------------------------------------------</span> |
| <span class="go">[INFO] BUILD SUCCESSFUL</span> |
| <span class="go">[INFO] ------------------------------------------------------------------------</span> |
| <span class="go">[INFO] Total time: 4 seconds</span> |
| <span class="go">[INFO] Finished at: Fri Jan 11 13:04:11 PST 2013</span> |
| <span class="go">[INFO] Final Memory: 18M/128M</span> |
| <span class="go">[INFO] ------------------------------------------------------------------------</span> |
| <span class="gp">$</span> |
| </pre></div> |
| </div> |
| <p>Assuming you see the “<code class="docutils literal notranslate"><span class="pre">BUILD</span> <span class="pre">SUCCESSFUL</span></code>” message when you build the web |
| application, there will be a new file, <code class="docutils literal notranslate"><span class="pre">target/guacamole-tutorial-1.6.0.war</span></code>, |
| which can be deployed to your servlet container and tested. If you changed the |
| name or version of the project in the <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> file, the name of this new |
| <code class="docutils literal notranslate"><span class="pre">.war</span></code> file will be different, but it can still be found within <code class="docutils literal notranslate"><span class="pre">target/</span></code>.</p> |
| </section> |
| </section> |
| <section id="adding-guacamole"> |
| <span id="guacamole-skeleton"></span><h2>Adding Guacamole<a class="headerlink" href="#adding-guacamole" title="Link to this heading">#</a></h2> |
| <p>Once we have a functional web application built, the next step is to actually |
| add the references to the Guacamole API and integrate a Guacamole client into |
| the application.</p> |
| <section id="updating-pom-xml"> |
| <span id="adding-guac-to-pom"></span><h3>Updating <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code><a class="headerlink" href="#updating-pom-xml" title="Link to this heading">#</a></h3> |
| <p>Now that we’re adding Guacamole components to our project, we need to modify |
| <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> to specify which components are being used, and where they can be |
| obtained. With this information in place, Maven will automatically resolve |
| dependencies and download them as necessary during the build.</p> |
| <p>Regarding the build process itself, there are two main changes: we are now |
| going to be using Java, and we need the JavaScript files from |
| guacamole-common-js included automatically inside the <code class="docutils literal notranslate"><span class="pre">.war</span></code>.</p> |
| <p>Guacamole requires at least Java 8, thus we must add a section to the |
| <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> which describes the source and target Java versions:</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="w"> </span>... |
| |
| <span class="w"> </span><span class="nt"><build></span> |
| <span class="w"> </span><span class="nt"><plugins></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Compile using Java 8 --></span> |
| <span class="w"> </span><span class="nt"><plugin></span> |
| <span class="w"> </span><span class="nt"><groupId></span>org.apache.maven.plugins<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>maven-compiler-plugin<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><version></span>3.3<span class="nt"></version></span> |
| <span class="w"> </span><span class="nt"><configuration></span> |
| <span class="w"> </span><span class="nt"><source></span>1.8<span class="nt"></source></span> |
| <span class="w"> </span><span class="nt"><target></span>1.8<span class="nt"></target></span> |
| <span class="w"> </span><span class="nt"></configuration></span> |
| <span class="w"> </span><span class="nt"></plugin></span> |
| |
| <span class="w"> </span><span class="nt"></plugins></span> |
| |
| <span class="w"> </span><span class="nt"></build></span> |
| |
| <span class="w"> </span>... |
| </pre></div> |
| </div> |
| <p>Including the JavaScript files from an external project like |
| guacamole-common-js requires using a feature of the maven war plugin called |
| overlays. To add an overlay containing guacamole-common-js, we add a section |
| describing the configuration of the Maven war plugin, listing |
| guacamole-common-js as an overlay:</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="w"> </span>... |
| |
| <span class="w"> </span><span class="nt"><build></span> |
| <span class="w"> </span><span class="nt"><plugins></span> |
| |
| <span class="w"> </span>... |
| |
| <span class="w"> </span><span class="cm"><!-- Overlay guacamole-common-js (zip) --></span> |
| <span class="w"> </span><span class="nt"><plugin></span> |
| <span class="w"> </span><span class="nt"><groupId></span>org.apache.maven.plugins<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>maven-war-plugin<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><version></span>2.6<span class="nt"></version></span> |
| <span class="w"> </span><span class="nt"><configuration></span> |
| <span class="w"> </span><span class="nt"><overlays></span> |
| <span class="w"> </span><span class="nt"><overlay></span> |
| <span class="w"> </span><span class="nt"><groupId></span>org.apache.guacamole<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>guacamole-common-js<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><type></span>zip<span class="nt"></type></span> |
| <span class="w"> </span><span class="nt"></overlay></span> |
| <span class="w"> </span><span class="nt"></overlays></span> |
| <span class="w"> </span><span class="nt"></configuration></span> |
| <span class="w"> </span><span class="nt"></plugin></span> |
| |
| <span class="w"> </span><span class="nt"></plugins></span> |
| |
| <span class="w"> </span><span class="nt"></build></span> |
| |
| <span class="w"> </span>... |
| </pre></div> |
| </div> |
| <p>With the build now configured, we still need to add dependencies and list the |
| repositories those dependencies can be downloaded from.</p> |
| <p>As this is a web application which will use the Java Servlet API, we must |
| explicitly include this as a dependency, as well as the Guacamole Java and |
| JavaScript APIs:</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="w"> </span>... |
| |
| <span class="w"> </span><span class="nt"><dependencies></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Servlet API --></span> |
| <span class="w"> </span><span class="nt"><dependency></span> |
| <span class="w"> </span><span class="nt"><groupId></span>javax.servlet<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>servlet-api<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><version></span>2.5<span class="nt"></version></span> |
| <span class="w"> </span><span class="nt"><scope></span>provided<span class="nt"></scope></span> |
| <span class="w"> </span><span class="nt"></dependency></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Main Guacamole library --></span> |
| <span class="w"> </span><span class="nt"><dependency></span> |
| <span class="w"> </span><span class="nt"><groupId></span>org.apache.guacamole<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>guacamole-common<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><version></span>1.6.0<span class="nt"></version></span> |
| <span class="w"> </span><span class="nt"><scope></span>compile<span class="nt"></scope></span> |
| <span class="w"> </span><span class="nt"></dependency></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Guacamole JavaScript library --></span> |
| <span class="w"> </span><span class="nt"><dependency></span> |
| <span class="w"> </span><span class="nt"><groupId></span>org.apache.guacamole<span class="nt"></groupId></span> |
| <span class="w"> </span><span class="nt"><artifactId></span>guacamole-common-js<span class="nt"></artifactId></span> |
| <span class="w"> </span><span class="nt"><version></span>1.6.0<span class="nt"></version></span> |
| <span class="w"> </span><span class="nt"><type></span>zip<span class="nt"></type></span> |
| <span class="w"> </span><span class="nt"><scope></span>runtime<span class="nt"></scope></span> |
| <span class="w"> </span><span class="nt"></dependency></span> |
| |
| <span class="w"> </span><span class="nt"></dependencies></span> |
| |
| <span class="w"> </span>... |
| </pre></div> |
| </div> |
| <p>The Java Servlet API will be provided by your servlet container, so Maven does |
| not need to download it during the build, and it need not exist in any Maven |
| repository.</p> |
| <p>With these changes, the web application will still build at this point, even |
| though no Java code has been written yet. You may wish to verify that |
| everything still works.</p> |
| <p>If the <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code> was updated properly as described above, the web application |
| should build successfully, and the Guacamole JavaScript API should be |
| accessible in the <code class="docutils literal notranslate"><span class="pre">guacamole-common-js/</span></code> subdirectory of your web application |
| after it is deployed. A quick check that you can access |
| <code class="docutils literal notranslate"><span class="pre">/guacamole-tutorial-1.6.0/guacamole-common-js/all.min.js</span></code> is probably worth |
| the effort.</p> |
| </section> |
| <section id="the-simplest-tunnel-possible"> |
| <span id="simple-tunnel"></span><h3>The simplest tunnel possible<a class="headerlink" href="#the-simplest-tunnel-possible" title="Link to this heading">#</a></h3> |
| <p>As with the other tutorials in this book, we will keep this simple for the sake |
| of demonstrating the principles behind a Guacamole-based web application, and |
| to give developers a good idea of where to start looking when it’s time to |
| consult the API documentation.</p> |
| <p>It is the duty of the class extending <code class="docutils literal notranslate"><span class="pre">GuacamoleHTTPTunnelServlet</span></code> to implement |
| a function called <code class="docutils literal notranslate"><span class="pre">doConnect()</span></code>. This is the only function required to be |
| implemented, and in general it is the only function you should implement; the |
| other functions involved are already optimized for tunneling the Guacamole |
| protocol.</p> |
| <p>The <code class="docutils literal notranslate"><span class="pre">doConnect()</span></code> function returns a <code class="docutils literal notranslate"><span class="pre">GuacamoleTunnel</span></code>, which provides a |
| persistent communication channel for <code class="docutils literal notranslate"><span class="pre">GuacamoleHTTPTunnelServlet</span></code> to use when |
| talking with guacd and initiating a connection with some arbitrary remote |
| desktop using some arbitrary remote desktop protocol. In our simple tunnel, |
| this configuration will be hard-coded, and no authentication will be attempted. |
| Any user accessing this web application will be immediately given a functional |
| remote desktop, no questions asked.</p> |
| <p>Create a new file, <code class="docutils literal notranslate"><span class="pre">TutorialGuacamoleTunnelServlet.java</span></code>, defining a basic |
| implementation of a tunnel servlet class:</p> |
| <div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kn">package</span><span class="w"> </span><span class="nn">org.apache.guacamole.net.example</span><span class="p">;</span> |
| |
| <span class="kn">import</span><span class="w"> </span><span class="nn">javax.servlet.http.HttpServletRequest</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.GuacamoleException</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.net.GuacamoleSocket</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.net.GuacamoleTunnel</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.net.InetGuacamoleSocket</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.net.SimpleGuacamoleTunnel</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.protocol.ConfiguredGuacamoleSocket</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.protocol.GuacamoleConfiguration</span><span class="p">;</span> |
| <span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet</span><span class="p">;</span> |
| |
| <span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">TutorialGuacamoleTunnelServlet</span> |
| <span class="w"> </span><span class="kd">extends</span><span class="w"> </span><span class="n">GuacamoleHTTPTunnelServlet</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="nd">@Override</span> |
| <span class="w"> </span><span class="kd">protected</span><span class="w"> </span><span class="n">GuacamoleTunnel</span><span class="w"> </span><span class="nf">doConnect</span><span class="p">(</span><span class="n">HttpServletRequest</span><span class="w"> </span><span class="n">request</span><span class="p">)</span> |
| <span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">GuacamoleException</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="c1">// Create our configuration</span> |
| <span class="w"> </span><span class="n">GuacamoleConfiguration</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">GuacamoleConfiguration</span><span class="p">();</span> |
| <span class="w"> </span><span class="n">config</span><span class="p">.</span><span class="na">setProtocol</span><span class="p">(</span><span class="s">"vnc"</span><span class="p">);</span> |
| <span class="w"> </span><span class="n">config</span><span class="p">.</span><span class="na">setParameter</span><span class="p">(</span><span class="s">"hostname"</span><span class="p">,</span><span class="w"> </span><span class="s">"localhost"</span><span class="p">);</span> |
| <span class="w"> </span><span class="n">config</span><span class="p">.</span><span class="na">setParameter</span><span class="p">(</span><span class="s">"port"</span><span class="p">,</span><span class="w"> </span><span class="s">"5901"</span><span class="p">);</span> |
| <span class="w"> </span><span class="n">config</span><span class="p">.</span><span class="na">setParameter</span><span class="p">(</span><span class="s">"password"</span><span class="p">,</span><span class="w"> </span><span class="s">"potato"</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="c1">// Connect to guacd - everything is hard-coded here.</span> |
| <span class="w"> </span><span class="n">GuacamoleSocket</span><span class="w"> </span><span class="n">socket</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ConfiguredGuacamoleSocket</span><span class="p">(</span> |
| <span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">InetGuacamoleSocket</span><span class="p">(</span><span class="s">"localhost"</span><span class="p">,</span><span class="w"> </span><span class="mi">4822</span><span class="p">),</span> |
| <span class="w"> </span><span class="n">config</span> |
| <span class="w"> </span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="c1">// Return a new tunnel which uses the connected socket</span> |
| <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SimpleGuacamoleTunnel</span><span class="p">(</span><span class="n">socket</span><span class="p">);;</span> |
| |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| <p>Place this file in the <code class="docutils literal notranslate"><span class="pre">src/main/java/org/apache/guacamole/net/example</span></code> |
| subdirectory of the project. The initial part of this subdirectory, |
| <code class="docutils literal notranslate"><span class="pre">src/main/java</span></code>, is the path required by Maven, while the rest is the directory |
| required by Java based on the package associated with the class.</p> |
| <p>Once the class defining our tunnel is created, it must be added to the |
| <code class="docutils literal notranslate"><span class="pre">web.xml</span></code> such that the servlet container knows which URL maps to it. This URL |
| will later be given to the JavaScript client to establish the connection back |
| to the Guacamole server:</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="w"> </span>... |
| |
| <span class="w"> </span><span class="cm"><!-- Guacamole Tunnel Servlet --></span> |
| <span class="w"> </span><span class="nt"><servlet></span> |
| <span class="w"> </span><span class="nt"><description></span>Tunnel<span class="w"> </span>servlet.<span class="nt"></description></span> |
| <span class="w"> </span><span class="nt"><servlet-name></span>Tunnel<span class="nt"></servlet-name></span> |
| <span class="w"> </span><span class="nt"><servlet-class></span> |
| <span class="w"> </span>org.apache.guacamole.net.example.TutorialGuacamoleTunnelServlet |
| <span class="w"> </span><span class="nt"></servlet-class></span> |
| <span class="w"> </span><span class="nt"></servlet></span> |
| |
| <span class="w"> </span><span class="nt"><servlet-mapping></span> |
| <span class="w"> </span><span class="nt"><servlet-name></span>Tunnel<span class="nt"></servlet-name></span> |
| <span class="w"> </span><span class="nt"><url-pattern></span>/tunnel<span class="nt"></url-pattern></span> |
| <span class="w"> </span><span class="nt"></servlet-mapping></span> |
| |
| <span class="w"> </span>... |
| </pre></div> |
| </div> |
| <p>The first section assigns a unique name, “Tunnel”, to the servlet class we just |
| defined. The second section maps the servlet class by it’s servlet name |
| (“Tunnel”) to the URL we wish to use when making HTTP requests to the servlet: |
| <code class="docutils literal notranslate"><span class="pre">/tunnel</span></code>. This URL is relative to the context root of the web application. In |
| the case of this web application, the final absolute URL will be |
| <code class="docutils literal notranslate"><span class="pre">/guacamole-tutorial-1.6.0/tunnel</span></code>.</p> |
| </section> |
| <section id="adding-the-client"> |
| <span id="simple-client"></span><h3>Adding the client<a class="headerlink" href="#adding-the-client" title="Link to this heading">#</a></h3> |
| <p>As the Guacamole JavaScript API already provides functional client and tunnel |
| implementations, as well as mouse and keyboard input objects, the coding |
| required for the “web” side of the web application is very minimal.</p> |
| <p>We must create a <code class="docutils literal notranslate"><span class="pre">Guacamole.HTTPTunnel</span></code>, connect it to our |
| previously-implemented tunnel servlet, and pass that tunnel to a new |
| <code class="docutils literal notranslate"><span class="pre">Guacamole.Client</span></code>. Once that is done, and the <code class="docutils literal notranslate"><span class="pre">connect()</span></code> function of the |
| client is called, communication will immediately ensue, and your remote desktop |
| will be visible:</p> |
| <div class="highlight-html notranslate"><div class="highlight"><pre><span></span> ... |
| <span class="p"><</span><span class="nt">body</span><span class="p">></span> |
| |
| <span class="cm"><!-- Guacamole --></span> |
| <span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span> |
| <span class="na">src</span><span class="o">=</span><span class="s">"guacamole-common-js/all.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span> |
| |
| <span class="cm"><!-- Display --></span> |
| <span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"display"</span><span class="p">></</span><span class="nt">div</span><span class="p">></span> |
| |
| <span class="cm"><!-- Init --></span> |
| <span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span><span class="p">></span><span class="w"> </span><span class="cm">/* <![CDATA[ */</span> |
| |
| <span class="w"> </span><span class="c1">// Get display div from document</span> |
| <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">display</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"display"</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="c1">// Instantiate client, using an HTTP tunnel for communications.</span> |
| <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">guac</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Client</span><span class="p">(</span> |
| <span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">HTTPTunnel</span><span class="p">(</span><span class="s2">"tunnel"</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="c1">// Add client to display div</span> |
| <span class="w"> </span><span class="nx">display</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">guac</span><span class="p">.</span><span class="nx">getDisplay</span><span class="p">().</span><span class="nx">getElement</span><span class="p">());</span> |
| <span class="w"> </span> |
| <span class="w"> </span><span class="c1">// Error handler</span> |
| <span class="w"> </span><span class="nx">guac</span><span class="p">.</span><span class="nx">onerror</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nx">alert</span><span class="p">(</span><span class="nx">error</span><span class="p">);</span> |
| <span class="w"> </span><span class="p">};</span> |
| |
| <span class="w"> </span><span class="c1">// Connect</span> |
| <span class="w"> </span><span class="nx">guac</span><span class="p">.</span><span class="nx">connect</span><span class="p">();</span> |
| |
| <span class="w"> </span><span class="c1">// Disconnect on close</span> |
| <span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">onunload</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nx">guac</span><span class="p">.</span><span class="nx">disconnect</span><span class="p">();</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="cm">/* ]]> */</span><span class="w"> </span><span class="p"></</span><span class="nt">script</span><span class="p">></span> |
| |
| <span class="p"></</span><span class="nt">body</span><span class="p">></span> |
| ... |
| </pre></div> |
| </div> |
| <p>If you build and deploy the web application now, it will work, but mouse and |
| keyboard input will not. This is because input is not implemented by the client |
| directly. The <code class="docutils literal notranslate"><span class="pre">Guacamole.Client</span></code> object only decodes the Guacamole protocol and |
| handles the display, providing an element which you can add manually to the |
| DOM. While it will also send keyboard and mouse events for you, you need to |
| call the respective functions manually. The Guacamole API provides keyboard and |
| mouse abstraction objects which make this easy.</p> |
| <p>We need only create a <code class="docutils literal notranslate"><span class="pre">Guacamole.Mouse</span></code> and <code class="docutils literal notranslate"><span class="pre">Guacamole.Keyboard</span></code>, and add event |
| handlers to handle their corresponding input events, calling whichever function |
| of the Guacamole client is appropriate to send the input event through the |
| tunnel to guacd:</p> |
| <div class="highlight-html notranslate"><div class="highlight"><pre><span></span> ... |
| |
| <span class="cm"><!-- Init --></span> |
| <span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span><span class="p">></span><span class="w"> </span><span class="cm">/* <![CDATA[ */</span> |
| |
| <span class="w"> </span><span class="p">...</span> |
| |
| <span class="w"> </span><span class="c1">// Mouse</span> |
| <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">mouse</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Mouse</span><span class="p">(</span><span class="nx">guac</span><span class="p">.</span><span class="nx">getDisplay</span><span class="p">().</span><span class="nx">getElement</span><span class="p">());</span> |
| |
| <span class="w"> </span><span class="nx">mouse</span><span class="p">.</span><span class="nx">onmousedown</span><span class="w"> </span><span class="o">=</span><span class="w"> </span> |
| <span class="w"> </span><span class="nx">mouse</span><span class="p">.</span><span class="nx">onmouseup</span><span class="w"> </span><span class="o">=</span> |
| <span class="w"> </span><span class="nx">mouse</span><span class="p">.</span><span class="nx">onmousemove</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">mouseState</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nx">guac</span><span class="p">.</span><span class="nx">sendMouseState</span><span class="p">(</span><span class="nx">mouseState</span><span class="p">);</span> |
| <span class="w"> </span><span class="p">};</span> |
| |
| <span class="w"> </span><span class="c1">// Keyboard</span> |
| <span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Keyboard</span><span class="p">(</span><span class="nb">document</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="nx">keyboard</span><span class="p">.</span><span class="nx">onkeydown</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">keysym</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nx">guac</span><span class="p">.</span><span class="nx">sendKeyEvent</span><span class="p">(</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">keysym</span><span class="p">);</span> |
| <span class="w"> </span><span class="p">};</span> |
| |
| <span class="w"> </span><span class="nx">keyboard</span><span class="p">.</span><span class="nx">onkeyup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">keysym</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nx">guac</span><span class="p">.</span><span class="nx">sendKeyEvent</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">keysym</span><span class="p">);</span> |
| <span class="w"> </span><span class="p">};</span> |
| |
| <span class="w"> </span><span class="cm">/* ]]> */</span><span class="w"> </span><span class="p"></</span><span class="nt">script</span><span class="p">></span> |
| |
| ... |
| </pre></div> |
| </div> |
| </section> |
| </section> |
| <section id="where-to-go-from-here"> |
| <span id="next-steps"></span><h2>Where to go from here<a class="headerlink" href="#where-to-go-from-here" title="Link to this heading">#</a></h2> |
| <p>At this point, we now have a fully functional Guacamole-based web application. |
| This web application inherits all the core functionality present in the |
| official Guacamole web application, including sound and video, without very |
| much coding.</p> |
| <p>Extending this application to provide authentication, multiple connections per |
| user, or a spiffy interface which is compatible with mobile is not too much of |
| a stretch. This is exactly how the Guacamole web application is written. |
| Integrating Guacamole into an existing application would be similar.</p> |
| </section> |
| </section> |
| |
| |
| </article> |
| |
| |
| |
| |
| |
| |
| <footer class="prev-next-footer d-print-none"> |
| |
| <div class="prev-next-area"> |
| <a class="left-prev" |
| href="event-listeners.html" |
| title="previous page"> |
| <i class="fa-solid fa-angle-left"></i> |
| <div class="prev-next-info"> |
| <p class="prev-next-subtitle">previous</p> |
| <p class="prev-next-title">Event listeners</p> |
| </div> |
| </a> |
| <a class="right-next" |
| href="protocol-reference.html" |
| title="next page"> |
| <div class="prev-next-info"> |
| <p class="prev-next-subtitle">next</p> |
| <p class="prev-next-title">Guacamole protocol reference</p> |
| </div> |
| <i class="fa-solid fa-angle-right"></i> |
| </a> |
| </div> |
| </footer> |
| |
| </div> |
| |
| |
| |
| <div class="bd-sidebar-secondary bd-toc"><div class="sidebar-secondary-items sidebar-secondary__inner"> |
| |
| |
| <div class="sidebar-secondary-item"> |
| <div class="page-toc tocsection onthispage"> |
| <i class="fa-solid fa-list"></i> Contents |
| </div> |
| <nav class="bd-toc-nav page-toc"> |
| <ul class="visible nav section-nav flex-column"> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#the-basics">The basics</a></li> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#web-application-skeleton">Web application skeleton</a><ul class="nav section-nav flex-column"> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#pom-xml"><code class="docutils literal notranslate"><span class="pre">pom.xml</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#web-inf-web-xml"><code class="docutils literal notranslate"><span class="pre">WEB-INF/web.xml</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#index-html"><code class="docutils literal notranslate"><span class="pre">index.html</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#building-the-skeleton">Building the skeleton</a></li> |
| </ul> |
| </li> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#adding-guacamole">Adding Guacamole</a><ul class="nav section-nav flex-column"> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#updating-pom-xml">Updating <code class="docutils literal notranslate"><span class="pre">pom.xml</span></code></a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#the-simplest-tunnel-possible">The simplest tunnel possible</a></li> |
| <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#adding-the-client">Adding the client</a></li> |
| </ul> |
| </li> |
| <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#where-to-go-from-here">Where to go from here</a></li> |
| </ul> |
| </nav></div> |
| |
| </div></div> |
| |
| |
| </div> |
| <footer class="bd-footer-content"> |
| |
| <div class="bd-footer-content__inner container"> |
| |
| <div class="footer-item"> |
| |
| <p class="component-author"> |
| By The Apache Software Foundation |
| </p> |
| |
| </div> |
| |
| <div class="footer-item"> |
| |
| |
| <p class="copyright"> |
| |
| © Copyright 2025 The Apache Software Foundation. |
| <br/> |
| |
| </p> |
| |
| </div> |
| |
| <div class="footer-item"> |
| |
| </div> |
| |
| <div class="footer-item"> |
| |
| </div> |
| |
| </div> |
| </footer> |
| |
| |
| </main> |
| </div> |
| </div> |
| |
| <!-- Scripts loaded after <body> so the DOM is not blocked --> |
| <script src="_static/scripts/bootstrap.js?digest=dfe6caa3a7d634c4db9b"></script> |
| <script src="_static/scripts/pydata-sphinx-theme.js?digest=dfe6caa3a7d634c4db9b"></script> |
| |
| <footer class="bd-footer"> |
| </footer> |
| </body> |
| </html> |