Last active
December 17, 2019 15:52
Star
You must be signed in to star a gist
Klipse - #355
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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 | |
(-> (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 © 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