progress
This commit is contained in:
129
links/url.go
Normal file
129
links/url.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package links
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v4"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
)
|
||||
|
||||
var psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
type URL struct {
|
||||
ID string
|
||||
URL string
|
||||
NURL string // normalized URL
|
||||
Short string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (u *URL) StoreURL(ctx context.Context, db *pgxpool.Pool) error {
|
||||
stmt := psql.Insert("urls").
|
||||
Columns("id", "url", "nurl", "short", "created_at").
|
||||
Values(u.ID, u.URL, u.NURL, u.Short, u.Short, u.CreatedAt)
|
||||
query, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := db.Exec(ctx, query, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Normalize cleans the URL to only the parts we care about
|
||||
func Normalize(u *url.URL) *url.URL {
|
||||
norm := &url.URL{
|
||||
Scheme: u.Scheme,
|
||||
Host: u.Host,
|
||||
Path: u.Path,
|
||||
RawPath: u.RawPath,
|
||||
}
|
||||
return norm
|
||||
}
|
||||
|
||||
func NormalizeString(s string) (string, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
u = Normalize(u)
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
func New(u *url.URL) *URL {
|
||||
link := URL{
|
||||
ID: uuid.NewString(),
|
||||
URL: u.String(),
|
||||
NURL: Normalize(u).String(),
|
||||
Short: GenCode(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
return link
|
||||
}
|
||||
|
||||
func FromString(s string) (*URL, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return New(u), nil
|
||||
}
|
||||
|
||||
func Lookup(ctx context.Context, db *pgxpool.Pool, s string) (string, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
u = Normalize(u)
|
||||
|
||||
stmt := psql.Select("short").From("urls").
|
||||
Where(squirrel.Eq{"nurl": u.String()})
|
||||
query, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
row := db.QueryRow(ctx, query, args...)
|
||||
|
||||
var short string
|
||||
err := row.Scan(&short)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return short, nil
|
||||
}
|
||||
|
||||
func StoreURL(ctx context.Context, db *pgxpool.Pool, s string) (string, error) {
|
||||
short, err := Lookup(ctx, db, s)
|
||||
if err == nil {
|
||||
return short, nil
|
||||
}
|
||||
|
||||
if err != pgx.ErrNoRows {
|
||||
return "", err
|
||||
}
|
||||
|
||||
u, err := FromString(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = u.Store(ctx, db)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return u.Short, nil
|
||||
}
|
||||
|
||||
func RetrieveURL(ctx context.Context, db *pgxpool.Pool, short string) (string, error) {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user