initial commit
This commit is contained in:
parent
9baa0fab25
commit
fc46164556
14 changed files with 243 additions and 0 deletions
20
cmd/maot-shortner/main.go
Normal file
20
cmd/maot-shortner/main.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"maot-shortner/internal/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Starting app...")
|
||||||
|
|
||||||
|
db, err := database.InitDatabase()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server := NewServer(db)
|
||||||
|
|
||||||
|
fmt.Println("App listening on port 3032")
|
||||||
|
server.ListenAndServe()
|
||||||
|
}
|
||||||
32
cmd/maot-shortner/server.go
Normal file
32
cmd/maot-shortner/server.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"maot-shortner/internal/database"
|
||||||
|
"maot-shortner/internal/handlers"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
http.Server
|
||||||
|
db *database.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(db *database.Database) *Server {
|
||||||
|
return &Server{
|
||||||
|
Server: http.Server{
|
||||||
|
Addr: ":3032",
|
||||||
|
Handler: createMux(db),
|
||||||
|
},
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMux(db *database.Database) http.Handler {
|
||||||
|
r := http.NewServeMux()
|
||||||
|
|
||||||
|
linkHandler := handlers.NewLinkHandler(db)
|
||||||
|
r.HandleFunc("GET /api/links", linkHandler.ListLinks)
|
||||||
|
r.HandleFunc("GET /{id}", linkHandler.GetUrl)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
12
go.mod
Normal file
12
go.mod
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
module maot-shortner
|
||||||
|
|
||||||
|
go 1.24.5
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.30 // indirect
|
||||||
|
golang.org/x/text v0.27.0 // indirect
|
||||||
|
gorm.io/driver/sqlite v1.6.0 // indirect
|
||||||
|
gorm.io/gorm v1.30.1 // indirect
|
||||||
|
)
|
||||||
12
go.sum
Normal file
12
go.sum
Normal file
|
|
@ -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.30 h1:bVreufq3EAIG1Quvws73du3/QgdeZ3myglJlrzSYYCY=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.30/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||||
|
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||||
|
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||||
|
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||||
|
gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
|
||||||
|
gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
19
internal/app/routes.go
Normal file
19
internal/app/routes.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"maot-shortner/internal/handlers"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HandlerList struct {
|
||||||
|
*handlers.LinkHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateMux(handlers HandlerList) *http.ServeMux {
|
||||||
|
r := http.NewServeMux()
|
||||||
|
|
||||||
|
r.HandleFunc("/links", handlers.LinkHandler.ListLinks)
|
||||||
|
r.HandleFunc("/", handlers.LinkHandler.Handle)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
1
internal/config/config.go
Normal file
1
internal/config/config.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package config
|
||||||
23
internal/database/database.go
Normal file
23
internal/database/database.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"maot-shortner/internal/domain"
|
||||||
|
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
*gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitDatabase() (database *Database, err error) {
|
||||||
|
log.Println("Starting database...")
|
||||||
|
|
||||||
|
db, err := gorm.Open(sqlite.Open("shortener.db"), &gorm.Config{})
|
||||||
|
db.AutoMigrate(domain.ImportModels()...)
|
||||||
|
|
||||||
|
database = &Database{db}
|
||||||
|
return database, err
|
||||||
|
}
|
||||||
16
internal/database/link.go
Normal file
16
internal/database/link.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"maot-shortner/internal/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *Database) GetLinks(ctx context.Context) ([]*domain.Link, error) {
|
||||||
|
links := make([]*domain.Link, 0)
|
||||||
|
|
||||||
|
if err := db.WithContext(ctx).Find(&links).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return links, nil
|
||||||
|
}
|
||||||
12
internal/domain/link.go
Normal file
12
internal/domain/link.go
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Link struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
ShortURL string `json:"short_url"`
|
||||||
|
LongURL string `json:"long_url"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
}
|
||||||
7
internal/domain/models.go
Normal file
7
internal/domain/models.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
func ImportModels() []any {
|
||||||
|
return []any{
|
||||||
|
&Link{},
|
||||||
|
}
|
||||||
|
}
|
||||||
7
internal/handlers/handler.go
Normal file
7
internal/handlers/handler.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type Handler interface {
|
||||||
|
Handle(w http.ResponseWriter, r *http.Request)
|
||||||
|
}
|
||||||
51
internal/handlers/link.go
Normal file
51
internal/handlers/link.go
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"maot-shortner/internal/database"
|
||||||
|
"maot-shortner/internal/services"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinkHandler struct {
|
||||||
|
db *database.Database
|
||||||
|
linkService *services.LinkService
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *LinkHandler) Handle(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(&Response{Message: "Ola"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinkHandler(db *database.Database) *LinkHandler {
|
||||||
|
return &LinkHandler{
|
||||||
|
db: db,
|
||||||
|
linkService: services.NewLinkService(db),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *LinkHandler) ListLinks(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
linkList, err := h.linkService.GetLinks(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("Failed to list links: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(linkList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *LinkHandler) GetUrl(w http.ResponseWriter, r *http.Request) {
|
||||||
|
currentCode := r.PathValue("id")
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(&Response{Message: currentCode})
|
||||||
|
}
|
||||||
10
internal/repositories/link.go
Normal file
10
internal/repositories/link.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"maot-shortner/internal/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LinkRepository interface {
|
||||||
|
GetLinks(ctx context.Context) ([]*domain.Link, error)
|
||||||
|
}
|
||||||
21
internal/services/link.go
Normal file
21
internal/services/link.go
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"maot-shortner/internal/domain"
|
||||||
|
"maot-shortner/internal/repositories"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LinkService struct {
|
||||||
|
repo repositories.LinkRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinkService(repo repositories.LinkRepository) *LinkService {
|
||||||
|
return &LinkService{
|
||||||
|
repo: repo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LinkService) GetLinks(ctx context.Context) ([]*domain.Link, error) {
|
||||||
|
return s.repo.GetLinks(ctx)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue