DEV Community

Cover image for Handlers and Endpoints 🧶
Јане Џумеркоски
Јане Џумеркоски

Posted on

11

Handlers and Endpoints 🧶

Now it's time to put the components we built previously to good use, so during this part, we will be making sure those previously built components work together as expected.

We are going to build two endpoints to our API service :

  • One endpoint that will be used to generate a short URL and return it, when the initial long URL is provided. /encode
  • The other one will be used to return the original long URL when the short URL is provided. /decode/:short-url

Let's go ahead and create the handler package and define our handler's functions there. Create a folder called handler and create a file called handlers.go inside the folder. After that our project directory should look like the tree below :

├── go.mod
├── go.sum
├── main.go
└── shortener
   ├── shortener.go
   └── shortener_test.go
└── store
   ├── store.go
   └── store_test.go
└── handler
   └── handlers.go
Enter fullscreen mode Exit fullscreen mode

Now let’s define and implement our handlers.

We will be starting with implementing the CreateShortURL() handler function, this should be very straightforward :

  1. We will get the creation request body, parse it and extract the initial longURL and userId.
  2. Call our shortener.GenerateShortURL that we implemented in PART II and generate our shortened hash.
  3. Finally store the mapping of our output hash / shortURL with the initial longURL, here, we will be using the store.SaveURLInRedis() we implemented back in PART III
package handler

import (
    "github.com/labstack/echo/v4"
    "go-redis-url-shortener/shortener"
    "go-redis-url-shortener/store"
)

const host = "http://localhost:1323/"

// URLCreationRequest is request model definition
type URLCreationRequest struct {
    LongURL string `json:"long_url" binding:"required"`
    UserId  string `json:"user_id" binding:"required"`
}

func CreateShortURL(c echo.Context) error {
    cr := new(URLCreationRequest)
    if err := c.Bind(cr); err != nil {
        return err
    }

    shortUrl := shortener.GenerateShortURL(cr.LongURL, cr.UserId)
    store.SaveURLInRedis(shortUrl, cr.LongURL)

    return c.JSON(200, map[string]interface{}{
        "short_url": host + shortUrl,
    })
}
Enter fullscreen mode Exit fullscreen mode

The next step will be about returning the original URL, ReturnLongURL(), it will consist of :

  1. Getting the short URL from the path parameter /:shortUrl
  2. Call the store to retrieve the initial URL that corresponds to the short one provided in the path.
  3. And finally, return the long URL
func ReturnLongURL(c echo.Context) error {
    shortUrl := c.Param("short-url")
    initialUrl := store.RetrieveInitialURLFromRedis(shortUrl)
    return c.JSON(200, map[string]interface{}{
        "short_url": host + shortUrl,
        "long_url":  initialUrl,
    })
}
Enter fullscreen mode Exit fullscreen mode

After implementing our handlers, we should go straight to the main.go file to add the needed endpoints and initialize the store.

📝 Also don't forget to add the middleware library from Echo that we will use to solve our CORS issues. Middleware is a function chained in the HTTP request-response cycle with access to Echo#Context which it uses to perform a specific action, for example, logging every request or limiting the number of requests. Handler is processed in the end after all middleware are finished executing.

go get github.com/labstack/echo/v4/middleware
Enter fullscreen mode Exit fullscreen mode
package main

import (
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
    "go-redis-url-shortener/handlers"
    "go-redis-url-shortener/store"
    "net/http"
)

func main() {
    e := echo.New()

    e.Use(middleware.CORS())

    e.GET("/", func(c echo.Context) error {
        return c.JSON(http.StatusOK, map[string]interface{}{
            "message": "Welcome to Go URL Shortener with Redis !🚀",
        })
    })

    e.POST("/encode", func(c echo.Context) error {
        return handler.CreateShortURL(c)
    })

    e.GET("/decode/:short-url", func(c echo.Context) error {
        return handler.ReturnLongURL(c)
    })

    // Store initialization happens here
    store.InitializeStore()

    e.Logger.Fatal(e.Start(":1323"))
}
Enter fullscreen mode Exit fullscreen mode

📝 In more complex applications, the endpoints should live in a separate file, but for the sake of simplicity and since they are just two endpoints, we will be having them in the main.go file


Originally published at projectex.dev

API Trace View

How I Cut 22.3 Seconds Off an API Call with Sentry 🕒

Struggling with slow API calls? Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay