DEV Community

Austin
Austin

Posted on

NYMToDo - Completing the capstone!

Overview

So a few weeks ago I finally finished up my four part project that I've written about. This post is a bit late in terms of project completion, but I ended up starting another project and got pretty consumed in it (More details on that are coming!). Please forgive me if I leave out any details or this doesn't feel polished enough. I didn't expect to take this long to write the blogpost, but better late than never!

As a quick recap, this four part project contains the following:

All of these projects were written in Go.

The Why

This project was a bit ambitious, but it was something I wanted to do to help solidify my understanding of DSA concepts, HTTP, and Go. For context, I don't currently have a degree, nor do I work professionally as a Software Engineer. Getting a job as a Software Engineer is a huge goal of mine that I'm hoping I can accomplish by the end of the year.

In 2019, I did what a lot of others did, which was attending a coding bootcamp. This helped me learn the MERN stack primarily. Since then I have created some full stack applications, and I generally know how to get something done. I started this journey before AI was a thing, and I only utilize it as a tool to help me learn, and not as a crutch. I don't find enjoyment in something unless I'm doing the work myself.

I provide all this context to showcase where I am, and what I can do. I am a Software Engineer, and I can be useful to a team if given the chance. That said, there are certainly skills that I can improve on to make me an even better developer. Javascript and its many frameworks lead to fast development time (Go does as well to be fair) however, what I realized is that I was so focused on shipping resume projects and creating things to get a job that I didn't truly focus on the learning aspect. I decided to change that this year.

The biggest goal I had for myself with this project was to expose myself to how these things I use in full stack application development work from a lower level than I am used to. Sure, I can spin up a MongoDB instance or configure Nginx to serve a webapp, but why do I the things I do to make them work? Express is great, but what is actually going on when you create an HTTP server in Node and what is happening when you create your RESTful APIs? This project won't wow anybody or win any hackathons, but it was special to me because I started to finally understand the why.

Parsec Quick Overview

Parsec is a small reverse proxy (Go 1.22+) that maps host/path prefix → upstream with a static JSON file. It’s built on net/http, httputil.ReverseProxy, and a custom http.Transport.

My dev config boiled down to:

{
  "listen": ":5173",
  "routes": [
    {
      "match": { "prefix": "/api" },
      "upstream": "http://localhost:8080",
      "strip_prefix": "/api",
      "preserve_host": false
    },
    {
      "match": { "prefix": "/" },
      "upstream": "http://localhost:5174",
      "preserve_host": false
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

I run this inside my backend server:

h, _ := parsec.HandlerFromFile("./parsec.json")
go http.ListenAndServe(":8080", apiRouter) // Go API
http.ListenAndServe(":5173", h)            // Parsec proxy
Enter fullscreen mode Exit fullscreen mode

NYMToDo Quick Overview

This was a very very simple ToDo app. I can share screenshots if anyone really cares to see, but the general gist is there. I used React for the front end and had a little bit of fun with the UI. This isn't my finest overview work here, but this is my blogpost, not yours (kidding)!

Obstacles along the way

Incorrect Boolean

I had the config right and could hit the API directly:

curl http://localhost:8080/todos  → []
curl http://localhost:8080/api/todos → 404
Enter fullscreen mode Exit fullscreen mode

That’s expected because my backend lives at /todos, not /api/todos. Parsec’s strip_prefix is supposed to forward /api/todos -> /todos.

But through :5173 I kept getting 404—even when I deliberately pointed the upstream at a bogus port to force a 502.

At the end of the day and some time beating my head against an invisible wall, it all came down to developer error (shocker). I had the boolean logic incorrect.

In ServeHTTP I found:

hostOK := cr.host == "" || cr.host == reqHost
if !hostOK && strings.HasPrefix(path, cr.prefix) { // <- oops
    cr.rp.ServeHTTP(w, r)
    return
}
Enter fullscreen mode Exit fullscreen mode

That !hostOK inverted the logic: a wildcard host ("") would never match. After flipping it to:

if hostOK && strings.HasPrefix(path, cr.prefix) {
    cr.rp.ServeHTTP(w, r)
    return
}
Enter fullscreen mode Exit fullscreen mode

…requests started flowing. The tell was switching upstream to a dead port; a matched route should produce 502, not 404.

Second Speedbump

Vite was picky about the Host header. With upstream: http://127.0.0.1:5174 it wasn’t happy; switching to http://localhost:5174 made it fine. (I left preserve_host: false, which means the upstream sees Host: localhost:5174.)

Closing

There were a lot more issues along the way of this four part project, but all of them helped me learn lessons. This was a fun project that taught me a lot about how different aspects of tech work and how Go works as well.

Doing this at the minimal scale I did gave me a whole new appreciation for those who truly built amazing software that we all use everyday. Especially open source projects. I don't see myself doing more with this project currently. I wasn't trying to reinvent the wheel, I just wanted to create my own for the love of learning. I do think I will revisit some of these projects at a later time to refine them more and add more features. That said, I don't think I'd do the database in Go. There's nothing wrong with Go, but I don't think it's intended purposes is a fit. I'd like to explore Zig at some point, and that might be a time when I revisit the data store.

To anyone still reading this, thank you for taking the time to take a look at this! I'm very excited to share details about a project I've been working on for a few weeks that I am very proud of! Stay tuned.

Top comments (0)