shortr/cmd/main.go
2024-09-11 17:58:42 +03:00

120 lines
2.4 KiB
Go

package main
import (
"fmt"
"math/rand"
"net/http"
"net/url"
"time"
"github.com/4rkal/shortr/models"
"github.com/4rkal/shortr/views"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
type FormData struct {
Url string `form:"url"`
}
type StatsFormData struct {
Id string `form:"id"`
}
var linkMap = map[string]*models.Link{
"example": {Id: "example", Url: "https://example.com"},
}
func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.Secure())
e.GET("/stats", StatsHandler)
e.POST("/stats", StatsSubmissionHandler)
e.GET("/:id", RedirectHandler)
e.GET("/", IndexHandler)
e.POST("/submit", SubmitHandler)
e.Logger.Fatal(e.Start(":8080"))
}
func RedirectHandler(c echo.Context) error {
id := c.Param("id")
link, found := linkMap[id]
if !found {
return c.String(http.StatusNotFound, "Link not found")
}
link.Clicks = link.Clicks + 1
return c.Redirect(http.StatusMovedPermanently, link.Url)
}
func IndexHandler(c echo.Context) error {
return views.Index().Render(c.Request().Context(), c.Response())
}
func SubmitHandler(c echo.Context) error {
var data FormData
if err := c.Bind(&data); err != nil {
return err
}
fmt.Println(data)
if !isURL(data.Url) {
return c.JSON(http.StatusBadRequest, "not a valid url")
}
var id string
for {
id = generateRandomString(6)
if _, exists := linkMap[id]; !exists {
break
}
}
linkMap[id] = &models.Link{Id: id, Url: data.Url}
return views.Submission(id).Render(c.Request().Context(), c.Response())
}
func StatsHandler(c echo.Context) error {
return views.StatsForm().Render(c.Request().Context(), c.Response())
}
func StatsSubmissionHandler(c echo.Context) error {
var data StatsFormData
if err := c.Bind(&data); err != nil {
return err
}
link, found := linkMap[data.Id]
if !found {
return c.String(http.StatusNotFound, "Id not found")
}
return views.Stats(link).Render(c.Request().Context(), c.Response())
}
func isURL(s string) bool {
_, err := url.ParseRequestURI(s)
return err == nil
}
func generateRandomString(length int) string {
seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
var result []byte
for i := 0; i < length; i++ {
index := seededRand.Intn(len(charset))
result = append(result, charset[index])
}
return string(result)
}