GithubHelp home page GithubHelp logo

movinggauteng / shorty-rs Goto Github PK

View Code? Open in Web Editor NEW
14.0 3.0 0.0 25 KB

A simple URL shortener, written in Rust and gRPC

License: MIT License

Dockerfile 3.69% Rust 96.31%
grpc grpc-rust tower-grpc

shorty-rs's Introduction

shorty-rs

Shorty is a simple URL shortening (micro?)service, created initially for our internal use at Moving Gauteng. The first version was written in JavaScript https://github.com/MovingGauteng/shorty. The current version is written in Rust.

Rewrite

Why rewrite it? This needs some backstory. Moving Gauteng is a public transit info website. Think of Google Maps' transit data, except as a browsable catalogue in a website. We (royal 'we' because I'm the only software person in our house) initially wrote shorty because we own a domain called rwt.to (meant to be 'route to', from when I was trying out an A-B thing), and we had a need for sharing shorter URLs on social media.

Moving Gauteng is a pastime thing, it sucks a lot of time and money from us (we haven't made a cent from it), so when things go down, I lately have little time to see what's wrong. I've found good success with porting a lot of our backend stuff to Rust. Our biggest success is a service called vehicle-streams, that powers https://movinggauteng.co.za/explore. If you visit this URL you might have to pan/move the map to Johannesburg, South Africa, and it's best viewed during the GMT+2 04:00 to 21:00 (the page's incomplete though).

Anyways, a few months ago I realised that URLs shared from our site weren't being shortened anymore. So, shorty-js was down. I thought restarting the service would work, but after a few times, nothing gave. I didn't have time to look into it, so I thought I'd save it with the long list of "some-days".

I finally had a few hours to look at it, and instead of debugging it, I thought I'd just rewrite it in Rust, so I'd never have to look at it again.

This is the rewrite.

Why not use the thousands of existing services?

  1. I don't like external network calls to someone else, and don't like that dependency
  2. We had the domain and weren't actively using it

How can I run it?

Just use Docker. We've added a multistage Dockerbuild for convenience. It creates a container that's 6.33MB large.

Otherwise, your preferred Rust workflow is fine, if you're a Rust user. This will run on stable.

How does it work?

It is a gRPC server, that has 3 endpoints:

  1. shorten an URL (with some optional Google Analytics utm_ things)
  2. retrieve a shortened URL
  3. increment URL counter arbitrarily (should probably merge this with 2 above, happy to get PR ๐Ÿค”)

You configure your custom short enough URL through environment variables, then run the thing, and forget about it.

Architecture

Data Model and Storage

shorty-rs, like her predecessor, ([un]fortunately) uses MongoDB. A port to Postgres or something else would be quick to do. If you wish to volunteer that, please hide it behind a #[cfg] thing. I don't mind if that becomes a default feature. MongoDB works well for us, so we'd like to still use your improvements.

The data model is loosely like:

shortenedurl (
  id: string, // prefer BSON ObjectId with 24 characters, but UUID v4 should work)
  url: string, // the url that shorty creates
  original: string, // the original url that user supplies
  constructed: string, // the constructed url that is returned, with utm_ parameters
  ga_campaign: [GoogleAnalyticsCampaign], // see below, you might create a separate table for this, or add it to this one
  created: timestamp,
  accessed: timestamp, // last accessed date
  visits: integer, // incremented each time URL is accessed
)

// GoogleAnalyticsCampaign
(
  utm_source: string,
  utm_campaign: string,
  utm_medium: string,
  utm_content: string,
  utm_term: string
)

gRPC

We use tower-grpc. It performs very well.

Performance

It uses 2MB of RAM under load, I've done a bit of stress testing in the 3 hours that I wrote it, but I don't mind a few people hitting the service to try bring it down (please let us know if you do, so we can monitor what's happening). I normally use opentracing on our rust services, but I opted out this time, so I can't really say how fast it runs. It does a fairly simple job, so who cares?

How do I redirect URLs?

This is the part that we've left out for now, for now.

Write a service (or add an endpoint to your existing service) that takes the shortened URL, and redirects the user to their desired destination. Here is an example in NodeJS Express framework.

  app.get('/:shorty', function (req, res, next) {
    if (req.params.shorty.match(/([0-9a-zA-Z]{5,10})/)) {
      Shorty.GetUrl({
        url: `https://rwt.to/${req.params.shorty.trim()}` // replace with your domain
      }).then(data => {
        // thisi is why I'm saying better to make this endpoint redundant
        Shorty.AddCounter({id: data.id, value: 1}).catch(err => {});
        return res.redirect(data.url);
      }).catch(err => {
        return res.status(500).send('unable to find link');
      });
    } else {
      return res.status(500).json({error: 'incorrect parameters'});
    }
  })

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.