commit 1b3ae43d6144f4bc2b0c721e213fd66812225c46 Author: fede Date: Thu Mar 12 00:13:46 2026 -0300 primer intento de servicio para acortar urls diff --git a/.env b/.env new file mode 100644 index 0000000..e69de29 diff --git a/dto/reqbody.go b/dto/reqbody.go new file mode 100644 index 0000000..25b9503 --- /dev/null +++ b/dto/reqbody.go @@ -0,0 +1,5 @@ +package dto + +type ReqBody struct { + LongUrl string `json:"longUrl"` +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a505d45 --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module url-short + +go 1.25.7 + +require ( + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/mattn/go-sqlite3 v1.14.34 // indirect + golang.org/x/text v0.35.0 // indirect + gorm.io/driver/sqlite v1.6.0 // indirect + gorm.io/gorm v1.31.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..012faec --- /dev/null +++ b/go.sum @@ -0,0 +1,12 @@ +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk= +github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= +gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= +gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= +gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/main.go b/main.go new file mode 100644 index 0000000..eab23bd --- /dev/null +++ b/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "url-short/models" + "url-short/routes" + + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +func main() { + fmt.Println("Iniciando url-short") + + db, err := gorm.Open(sqlite.Open("shorturls.db"), &gorm.Config{}) + if err != nil { + panic("failed to connect database") + } + + fmt.Println("Se conecto a la base de datos") + + db.AutoMigrate(&models.Url{}) + + http.HandleFunc("/url", func(w http.ResponseWriter, r *http.Request){ + routes.Url(w, r, db) + }) + + port := ":8080" + if envPort := os.Getenv("PORT"); envPort != "" { + port = ":" + envPort + } + fmt.Println("Servidor escuchando en puerto: http://localhost"+ port) + err = http.ListenAndServe(port, nil) + if err != nil { + panic("Error starting server: " + err.Error()) + } +} diff --git a/models/url.go b/models/url.go new file mode 100644 index 0000000..388cb30 --- /dev/null +++ b/models/url.go @@ -0,0 +1,10 @@ +package models + +import "time" + +type Url struct { + Shorturl string `gorm:"primaryKey"` +// Id uint64 `gorm: "primaryKey;autoIncrement"` + Longurl string `gorm:"uniqueIndex:idx_lurl"` + Time time.Time `gorm:"autoCreateTime"` +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..ed5c704 --- /dev/null +++ b/readme.md @@ -0,0 +1,3 @@ +# Config +si se necesita especificar un puerto use la variable de entorno `PORT` +Ej, `PORT=8081 ./url-short` diff --git a/repository/CrearUrl.go b/repository/CrearUrl.go new file mode 100644 index 0000000..a30dd2b --- /dev/null +++ b/repository/CrearUrl.go @@ -0,0 +1,47 @@ +package repository + +import ( + "crypto/sha3" + "fmt" + "url-short/models" + + "gorm.io/gorm" +) + +func CrearUrl(longURL string, db *gorm.DB) (string, error) { + // checkeamos por longurl repetida + counturl := int64(0) + result := db.Model(&models.Url{}).Where("longurl = ?", longURL).Count(&counturl) + if result.Error != nil { + return "", result.Error + } + if counturl != 0 { + println(1) + var short models.Url + result = db.Model(&short).Where("longurl = ?", longURL).Select("shorturl").First(&short) + if result.Error != nil { + return "", result.Error + } + return short.Shorturl, nil + } + + // shortURL := base64.StdEncoding.EncodeToString([]byte(longURL))[:10] + sha := sha3.New224() + sha.Write([]byte(longURL)) + shortURL := fmt.Sprintf("%x", sha.Sum(nil))[:10] + + result = db.Model(&models.Url{}).Where("shorturl = ?", shortURL).Count(&counturl) + if result.Error != nil { + return "", result.Error + } + if counturl != 0 { + return shortURL, nil + } + + result = db.Create(&models.Url{Longurl: longURL, Shorturl: shortURL}) + + if result.Error != nil { + return "", result.Error + } + return shortURL, nil +} diff --git a/routes/url.go b/routes/url.go new file mode 100644 index 0000000..fe8814c --- /dev/null +++ b/routes/url.go @@ -0,0 +1,33 @@ +package routes + +import ( + "encoding/json" + "net/http" + "url-short/dto" + "url-short/repository" + + "gorm.io/gorm" +) +func Url(w http.ResponseWriter, r *http.Request, db *gorm.DB) { + if r.Method == http.MethodPost { + var reqBody dto.ReqBody + + err := json.NewDecoder(r.Body).Decode(&reqBody) + if err != nil { + http.Error(w, "Error: ", http.StatusBadRequest) + return + } + + shortUrl, err := repository.CrearUrl(reqBody.LongUrl, db) + if err != nil { + http.Error(w, "Error: "+err.Error(), http.StatusBadRequest) + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{ + "shortUrl": shortUrl, + }) + }else{ + http.Error(w, "404", http.StatusBadGateway); + } + + }