<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Express on dev.endevour</title><link>https://devendevour.iankulin.com/tags/express/</link><description>Recent content in Express on dev.endevour</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 28 Apr 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://devendevour.iankulin.com/tags/express/index.xml" rel="self" type="application/rss+xml"/><item><title>Express router for better code organisation</title><link>https://devendevour.iankulin.com/express-router-for-better-code-organisation/</link><pubDate>Mon, 28 Apr 2025 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/express-router-for-better-code-organisation/</guid><description>&lt;p&gt;A Node/Express app I&amp;rsquo;m working on has been sprouting routes so much that the &lt;code&gt;server.js&lt;/code&gt; file has swollen to 800 lines - way past my 200-250 comfort zone, so it&amp;rsquo;s time to organise the routes into their own files. That seems like a good topic for a beginner blog post, so let&amp;rsquo;s dive in.&lt;/p&gt;
&lt;p&gt;Imagine we&amp;rsquo;ve written this little Node/Express app.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;import express from &amp;#34;express&amp;#34;;
import {
 dbCustomersGet,
 dbCustomersGetById,
 dbCustomersDelete,
 dbOrdersGet,
 dbOrdersGetById,
 dbOrdersGetByCustomerId,
 dbOrdersDelete,
} from &amp;#34;./db.js&amp;#34;;

const app = express();
app.set(&amp;#34;view engine&amp;#34;, &amp;#34;ejs&amp;#34;);
const port = 3002;

app.use(express.urlencoded({ extended: true }));

app.get(&amp;#34;/&amp;#34;, (req, res) =&amp;gt; {
 res.redirect(&amp;#34;/customers&amp;#34;);
});

app.get(&amp;#34;/customers&amp;#34;, (req, res) =&amp;gt; {
 const customers = dbCustomersGet();
 res.render(&amp;#34;customers&amp;#34;, { customers });
});

app.get(&amp;#34;/customers/:id&amp;#34;, (req, res) =&amp;gt; {
 const customer = dbCustomersGetById(req.params.id);
 const orders = dbOrdersGetByCustomerId(req.params.id);
 res.render(&amp;#34;customer&amp;#34;, { customer, orders });
});

app.get(&amp;#34;/customers/:id/delete&amp;#34;, (req, res) =&amp;gt; {
 dbCustomersDelete(req.params.id);
 res.redirect(&amp;#34;/customers&amp;#34;);
});

app.get(&amp;#34;/orders&amp;#34;, (req, res) =&amp;gt; {
 const orders = dbOrdersGet();
 res.render(&amp;#34;orders&amp;#34;, { orders });
});

app.get(&amp;#34;/orders/:id&amp;#34;, (req, res) =&amp;gt; {
 const order = dbOrdersGetById(req.params.id);
 const customer = dbCustomersGetById(order.customerId);
 res.render(&amp;#34;order&amp;#34;, { order, customer });
});

app.get(&amp;#34;/orders/:id/delete&amp;#34;, (req, res) =&amp;gt; {
 dbOrdersDelete(req.params.id);
 res.redirect(&amp;#34;/orders&amp;#34;);
});

app.listen(port, () =&amp;gt; {
 console.log(`Listening on http://127.0.0.1:${port}`);
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Although concocted, this would seem familiar to anyone who&amp;rsquo;s built a CRUD business app.&lt;/p&gt;</description></item><item><title>Uploading files to a web app with Node</title><link>https://devendevour.iankulin.com/uploading-files-to-a-web-app-with-node/</link><pubDate>Mon, 02 Sep 2024 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/uploading-files-to-a-web-app-with-node/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/screen-shot-2024-08-18-at-3.09.38-pm.jpg" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;My default approach to web apps at the moment is Node/Express SSR. I needed to have users be able to upload files this week, and as usual there&amp;rsquo;s an express middleware that makes it trivial. This post just steps through using &lt;a href="https://github.com/expressjs/multer" target="_blank" rel="noopener"&gt;multer&lt;/a&gt; to make it simple to enable file uploads on your website.&lt;/p&gt;
&lt;h3 id="express--middleware"&gt;Express &amp;amp; middleware&lt;/h3&gt; &lt;p&gt;Before we look at file uploading, it&amp;rsquo;s worth just explaining how it fits with the other tools we&amp;rsquo;re using:&lt;/p&gt;</description></item><item><title>Authentication basics for Node apps</title><link>https://devendevour.iankulin.com/authentication-basics-for-node-apps/</link><pubDate>Mon, 19 Aug 2024 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/authentication-basics-for-node-apps/</guid><description>&lt;p&gt;&lt;a href="https://unsplash.com/photos/calahorra-tower-torre-de-la-calahorra-in-cordoba-spain-a-fortified-gate-built-during-the-late-12th-century-by-the-almohads-to-protect-the-nearby-roman-bridge-in-the-historic-center-of-cordoba-andalusia-spain-ECsukeqrDoo" target="_blank" rel="noopener"&gt;&lt;img src="https://devendevour.iankulin.com/images/screen-shot-2024-08-10-at-8.59.01-pm.jpg" alt="" class="img-responsive"&gt; &lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Pretty much every serious web app needs to include a way for users to log in securely and to be served their content. Since there&amp;rsquo;s a lot of complexity in this, it&amp;rsquo;s highly advisable to use good libraries to support this. In a future post we&amp;rsquo;re going to use those libraries, but first I want to explain what&amp;rsquo;s happening at the lower level and tease out some of the concepts as we build a secure system from the ground up.&lt;/p&gt;</description></item><item><title>Quick &amp;amp; Dirty auth with nginx &amp;amp; Node</title><link>https://devendevour.iankulin.com/quick-dirty-auth-with-nginx-node/</link><pubDate>Fri, 23 Feb 2024 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/quick-dirty-auth-with-nginx-node/</guid><description>&lt;p&gt;One of the basic requirements for any serious web app is a proper users/roles/authentication system - but if you&amp;rsquo;re just throwing up a utility of some kind on a public IP for testing, and you don&amp;rsquo;t want it to be abused, then this could be an option. There&amp;rsquo;s a few components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your app. In this demo it&amp;rsquo;s going to be Node, but it could be Go or whatever your server-side poison is. The app is listening for connections on a non-web port (ie not on 80 or 443), I&amp;rsquo;m going to use the traditional 3000.&lt;/li&gt;
&lt;li&gt;A firewall. That port (in my example 3000) must not be accessible from the internet. It has to be blocked by a firewall.&lt;/li&gt;
&lt;li&gt;A web server (I&amp;rsquo;m using nginx) that enforces basic auth.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I briefly discussed web server basic auth earlier - it&amp;rsquo;s a system built into the web server that requires a log in for a route, and authenticates it against the credentials in a password file (usually named &lt;code&gt;.htpasswrd&lt;/code&gt;) and only serves the content if authenticated.&lt;/p&gt;</description></item><item><title>Simple SQLite in Express</title><link>https://devendevour.iankulin.com/simple-sqlite-in-express/</link><pubDate>Thu, 28 Dec 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/simple-sqlite-in-express/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/shmbo_an_artificial_intelligence_entitys_head_embodying_the_ess_f348db7a-e7b6-4620-beda-44fdb8e565d3.jpg" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have experience with &lt;a href="https://www.sqlite.org/index.html" target="_blank" rel="noopener"&gt;SQLite&lt;/a&gt; and want to shift one of my apps over from Mongoose since apparently SQLite is &lt;a href="https://www.sqlite.org/whentouse.html" target="_blank" rel="noopener"&gt;much more capable&lt;/a&gt; than I imagined. My usual tactic when trying something new is to try and get a minimal project working on it, so what follows is the simplest possible node/express REST API to demo SQLite.&lt;/p&gt;
&lt;p&gt;The simplest possible Express app is going to look something like this. Of course we would have gone to the terminal with &lt;code&gt;npm i express&lt;/code&gt; first so this could run.&lt;/p&gt;</description></item><item><title>Displaying markdown as HTML</title><link>https://devendevour.iankulin.com/displaying-markdown-as-html/</link><pubDate>Wed, 08 Nov 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/displaying-markdown-as-html/</guid><description>&lt;p&gt;In the spirit of over-complicating things, when I wanted to collect all the links to the services on my homelab into one place, I decided I needed to write them in markdown, and have them converted on the fly into HTML by a server. Then when I couldn&amp;rsquo;t find exactly what I was after (&lt;a href="http://harpjs.com/" target="_blank" rel="noopener"&gt;Harp&lt;/a&gt; was closest) of course, I decided to write it.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/distracted.jpg" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;h3 id="markdown"&gt;Markdown&lt;/h3&gt; &lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Markdown" target="_blank" rel="noopener"&gt;Markdown&lt;/a&gt; has definitely been having it&amp;rsquo;s moment over the last couple of years. It&amp;rsquo;s a simple open format mark-up language that is quite readable in it&amp;rsquo;s source form. Although it&amp;rsquo;s now very fashionable as an input for static site generators, most people will have run in to it when adding simple formatting to forum comments or on instant messaging platforms.&lt;/p&gt;</description></item><item><title>Using Node.js to return a static file</title><link>https://devendevour.iankulin.com/using-node-js-to-return-a-static-file/</link><pubDate>Sun, 02 Jul 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/using-node-js-to-return-a-static-file/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/rajeshtva_node.js_609056a9-3b73-46f5-bc4f-c1f110e3a367.png" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;As mentioned in the &lt;a href="https://devendevour.iankulin.com/complicating-the-temperature-api/"&gt;previous post&lt;/a&gt; , stage one is just to return the same static text file, but from the Node server, rather than NGINX. That&amp;rsquo;s non-trivial to a rank beginner since I need to figure out 1) how to serve a static file from Node, and 2) how to configure NGINX to hand off calls to the API to Node. This post will look at both of those, but it&amp;rsquo;s first probably worth just setting out what each of the puzzle pieces are.&lt;/p&gt;</description></item><item><title>Complicating the Temperature API</title><link>https://devendevour.iankulin.com/complicating-the-temperature-api/</link><pubDate>Wed, 28 Jun 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/complicating-the-temperature-api/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/gandalfthebeard_personal_dashboard_with_share_prices_photograph_bda71695-3d15-4521-9df1-8170f5906d8b.jpg" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been slammed with other work, so my web dev learning has fallen well behind. Luckily, the YouTube procrastination algorithm noticed this and suggested I watch a video from &lt;a href="https://www.youtube.com/@codewithcon" target="_blank" rel="noopener"&gt;CodeWithCon&lt;/a&gt; titled &lt;a href="https://www.youtube.com/watch?v=KNa-wMpry00&amp;amp;list=PLkJHe6eU_tzeoe7vKUEa4MrS74CpVEwdI&amp;amp;index=3&amp;amp;t=305s" target="_blank" rel="noopener"&gt;Learn Backend in 10 MINUTES&lt;/a&gt; .&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/KNa-wMpry00?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;

&lt;p&gt;Since I was watching a video of a guy learning to land a C152 at St Baths (a skill I do &lt;em&gt;not&lt;/em&gt; need) at the time, it was hard to argue with myself that I didn&amp;rsquo;t have ten minutes to learn all of backend programming.&lt;/p&gt;</description></item></channel></rss>