Skip to content

Instantly share code, notes, and snippets.

@holyjak
Last active December 17, 2019 15:52
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save holyjak/5ca5f72ec1cb9ecda9674527a35fbf95 to your computer and use it in GitHub Desktop.
Klipse - #355
<!DOCTYPE html>
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-97603551-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-97603551-2');
</script>
<meta charset="utf-8">
<title>Holy on Dev: nREPL over HTTP(s) with Drawbridge in 2020</title>
<meta name="keywords" content="clojure,tool">
<meta name="description" content="Sometimes the only way to get REPL into your production application is to tunnel it over HTTP. nREPL has a transport and Ring handler for that provided by Drawbridge. Heroku has a nice but too dated guide on using nREPL with Drawbridge. I would like to fill the missing bits here.">
<meta property="og:description" content="Sometimes the only way to get REPL into your production application is to tunnel it over HTTP. nREPL has a transport and Ring handler for that provided by Drawbridge. Heroku has a nice but too dated guide on using nREPL with Drawbridge. I would like to fill the missing bits here.">
<meta property="og:url" content="https://blog.jakubholy.net/2019-12-12-nrepl-over-http-with-drwabridge-in-2020/" />
<meta property="og:title" content="nREPL over HTTP(s) with Drawbridge in 2020" />
<meta property="og:type" content="article" />
<meta content="width=device-width, initial-scale=1" name="viewport">
<link href="/css/normalize.css" rel="stylesheet" type="text/css" />
<link href="/css/blog.css" rel="stylesheet" type="text/css" />
<link href="/css/lotus-highlightjs.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<aside id="sidebar">
<div id="logo">
<a id="logo-content" title="Holy on Dev" href="/">
<div id="sidebar-logo-row">
<img class="icon" src="/img/avatar.jpg" alt="author image">
<div id="sidebar-author-block">
<div id="sidebar-author" class="text">Jakub Holý</div>
<div id="sidebar-subtitle" class="text">Building the right thing, building it right, fast</div>
</div>
</div>
<div id="sidebar-title" class="text">Holy on Dev</div>
</a>
</div>
<nav id="sidebar-links">
<nav id="menucont">
<input type="checkbox" id="menu-checkbox" class="menu-checkbox">
<label for="menu-checkbox" class="menutitle">
<svg class="icon icon-menu-up" aria-hidden="true"><use xlink:href="/img/icons.svg#icon-menu-up"></use></svg>
<svg class="icon icon-menu-down" aria-hidden="true"><use xlink:href="/img/icons.svg#icon-menu-down"></use></svg>
<span class="menu-text">Menu</span>
</label>
<ul class="menu">
<li><a title="Home" href="/"><div class="menu-item-text">
<svg class="icon" aria-hidden="true"><use xlink:href="/img/icons.svg#icon-home"></use></svg>
<span class="large-screen">Home</span>
</div></a></li>
<li><a title="Search" href="/search/" aria-label="search"><div class="menu-item-text">
<svg class="icon" aria-hidden="true"><use xlink:href="/img/icons.svg#search"></use></svg>
<span class="large-screen">Search</span>
</div></a></li>
<li ><a title="Tags" href="/tags/"><div class="menu-item-text">
<svg class="icon" aria-hidden="true"><use xlink:href="/img/icons.svg#tag"></use></svg>
Tags
</div></a></li>
<li ><a title="Archives" href="/archives/"><div class="menu-item-text">Archives</div></a></li>
<li><a title="RSS" href="/feed.xml"><div class="menu-item-text">
<svg class="icon" aria-hidden="true"><use xlink:href="/img/icons.svg#icon-rss"></use></svg>
RSS</div></a></li>
<li><a href="https://holyjak.tumblr.com/" title="Recommended links feed" aria-label="Recommended links feed"><div class="menu-item-text">
<svg class="icon" aria-hidden="true"><use xlink:href="/img/icons.svg#icon-tumblr"></use></svg>
<span class="large-screen">Tumblr</span>
</div></a></li>
<li><a aria-label="contact" href="/contact/"><div class="menu-item-text">
<svg class="icon" aria-hidden="true"><use xlink:href="/img/icons.svg#icon-mail"></use></svg>
<span class="large-screen">Contact</span>
</div></a></li>
</ul>
</nav>
<!--nav id="socialmedia">
<ul>
<li><a title="LinkedIn" href="https://www.linkedin.com/in/jakubholydotnet" rel="external"><svg class="icon icon-linkedin"><use xlink:href="/img/icons.svg#icon-linkedin"></use></svg></a></li>
<li><a title="GitHub" href="https://github.com/holyjak" rel="external"><svg class="icon icon-github-circled"><use xlink:href="/img/icons.svg#icon-github-circled"></use></svg></a></li>
<li><a title="RSS Feed" href="/feed.xml"><svg class="icon icon-rss-squared"><use xlink:href="/img/icons.svg#icon-rss-squared"></use></svg></a></li>
</ul>
</nav-->
</nav>
</aside>
<article id="main">
<div id="post">
<div class="post-header">
<div id="post-meta">
<h1>nREPL over HTTP(s) with Drawbridge in 2020</h1>
<div class="byline">
<span class="date">December 12, 2019</span>
</div>
</div>
</div>
<div>
<ol class="toc"><li><a href="#_server">Server</a></li><li><a href="#_client">Client</a></li><ol><li><a href="#_lein">Lein</a></li><li><a href="#_clj">clj</a></li></ol></ol>
<html><body><div class="paragraph">
<p>Sometimes the only way to get REPL into your production application is to tunnel it over HTTP. nREPL has a transport and Ring handler for that provided by <a href="https://github.com/nrepl/drawbridge">Drawbridge</a>. Heroku has a nice but too dated <a href="https://devcenter.heroku.com/articles/debugging-clojure">guide on using nREPL with Drawbridge</a>. I would like to fill the missing bits here.</p>
</div>
<!--more-->
<div class="sect1">
<h2 id="_server">Server</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-clojure" data-lang="clojure">[ring/ring-core "1.8.0"]
[ring/ring-jetty-adapter "1.8.0"]
[nrepl/nrepl "0.6.0"]
[nrepl/drawbridge "0.2.1"]</code></pre>
</div>
</div>
<div class="paragraph">
<p>and test JS:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-klipse-js nohighlight" data-lang="klipse-js">console.log("hi");
1 + 2;</code></pre>
</div>
</div>
<div class="paragraph">
<p>we start Jetty and hook nREPL into it via Drawbridge:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-clojure" data-lang="clojure">(ns minbedrift-uav.webrepl
"Start a nREPL server over HTTP"
(:require
[drawbridge.core]
[ring.adapter.jetty :refer [run-jetty]]
[ring.middleware.keyword-params]
[ring.middleware.nested-params]
[ring.middleware.params]
[ring.middleware.session]))
(def drawbridge-handler
(-&gt; (drawbridge.core/ring-handler)
(ring.middleware.keyword-params/wrap-keyword-params)
(ring.middleware.nested-params/wrap-nested-params)
(ring.middleware.params/wrap-params)
(ring.middleware.session/wrap-session)))
(defn -main []
(run-jetty
#(if (= "/repl" (:uri %))
(drawbridge-handler %)
{:status "OK" :body "Do something else..."})
{:port 5555, :join? true}))</code></pre>
</div>
</div>
<div class="paragraph">
<p>In practice you would run it in addition to your main API/.. and thus wanted <code>:join? false</code> so that the process doesn’t block on starting the REPL server.</p>
</div>
<div class="paragraph">
<p>Refer to the original <a href="https://devcenter.heroku.com/articles/debugging-clojure">Heroku Drawbridge guide</a> for details and regarding adding authentication</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_client">Client</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_lein">Lein</h3>
<div class="paragraph">
<p>The simples way I have found to connect is using Leiningen:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-clojure" data-lang="clojure">;; project.clj
(defproject whatever "0.1.0-SNAPSHOT"
:plugins [[nrepl/drawbridge "0.2.1"]])</code></pre>
</div>
</div>
<div class="paragraph">
<p>and <code>lein :connect http://localhost:5555/repl</code> (the <code>http://</code> is key).</p>
</div>
</div>
<div class="sect2">
<h3 id="_clj">clj</h3>
<div class="paragraph">
<p>It <em>should</em> be possible to do this with <code>clj</code>:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>clj -Sdeps '{:deps {nrepl/drawbridge {:mvn/version "0.2.1"}}}' \
-m nrepl.cmdline --transport drawbridge.client/ring-client-transport \
--connect --host localhost --port 5555</pre>
</div>
</div>
<div class="paragraph">
<p>but it doesn’t as of v.0.2.1, see <a href="https://github.com/nrepl/drawbridge/issues/40">nrepl/drawbridge#40</a>.</p>
</div>
<div class="paragraph">
<p>(If you get instead an exception in <code>bencode.clj</code> then you forgot to specify the drawbridge transport and use the default bencode one.)</p>
</div>
</div>
</div>
</div></body></html>
</div>
<div id="post-tags">
<br/>
<b>Tags: </b>
<a href="/tags/clojure/">clojure</a>
<a href="/tags/tool/">tool</a>
</div>
<br/>
<div id="prev-next">
<div class="prev"></div>
<div class="next"></div>
</div>
</div>
<hr/>
<div id="footercont">
Copyright &copy; 2019 Jakub Holý
<br>Powered by <a href="http://cryogenweb.org">Cryogen</a>
<br>Theme by <a href="http://github.com/KingMob">KingMob</a>
</div>
</article>
<!--
<script src="/js/highlight.pack.js" type="text/javascript" async onload="hljs.initHighlightingOnLoad();"></script>
-->
<link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">
<script>
window.klipse_settings = {
"selector" : ".language-klipse",
"selector_js" : ".language-klipse-js"
};
</script>
<script src="https://storage.googleapis.com/app.klipse.tech/plugin_prod/js/klipse_plugin.min.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment