How I built Ngrok Alternative

azimjohn

Azimjon Pulatov

Posted on July 9, 2020

How I built Ngrok Alternative

Here's a quick intro of what I built

Ngrok is a fantastic tool that helps developers to expose their localhost to the Internet with minimal effort. One day I was going to share a local project with a client without deploying it somewhere. But this time I needed to expose 2 ports: one running frontend and the other backend of the project, I found out that the ngrok's free plan only allows one tunnel at a time. Later that day, I also found out that there's a 40-requests/minute limit.

Bam! An idea.
What if I build an alternative instead of paying $5/mo.?
That's what developers do, right? I also had the idea of making it open-source.

It's time to plan.
There are obviously 3 parts:

  • a developer with a command-line tool (cli)
  • a proxy server
  • a client with a browser.

I was sure there had to be at least those steps to make it work:

  1. a developer connects to the server via a cli with a port number: jprq 8000
  2. the server responds with an assigned domain. amazing-coder.jprq.live
  3. a client opens the domain in a browser: https://amazing-coder.jprq.live
  4. the server receives the request and sends it to the cli.
  5. the cli makes the request to localhost at the given port and sends the response to the server.
  6. the server responds back to the client with the response it received from the cli.

Here's a chart to help you picture those steps.
Alt Text

The cli and the server needs to make back and forth communication. A carefully managed TCP Sockets would do a great job but would take a long time to implement.
I decided to use and used the WebSocket Protocol. As you might know, WebSocket is a hop-by-hop protocol and sadly, my ngrok alternative now can't support Polling and HTTP streaming (because they never end or last too long).

The command-line tool is written in Python and published to PyPy. Currently implementing the command-line in javascript to publish in npm just for fun. And the server-side is in Golang. I think it was the best decision to choose golang because of its easy data sharing between goroutines and learned about leaking goroutines the hard way. I now have a good understanding of memory leaks because of this project.

Another small but impactful mistake I made during implementing the client-server communication was using JSON. I realized it only after adding a feature for handling files. With JSON one can only serialize strings. To turn file contents, bytes into a string, I needed to Base64 them. It turns out to be CPU intensive process. It's better to use BSON, I believe.

The project is open-source and waiting for your contribution. Take some time to visit the GitHub repo at github.com/azimjohn/jprq

Keep building,
Cheers.

💖 💪 🙅 🚩
azimjohn
Azimjon Pulatov

Posted on July 9, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

How I built Ngrok Alternative
python How I built Ngrok Alternative

July 9, 2020