github.com/jackc/pgx/v5@v5.5.5/examples/url_shortener/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "io" 6 "log" 7 "net/http" 8 "os" 9 10 "github.com/jackc/pgx/v5" 11 "github.com/jackc/pgx/v5/pgxpool" 12 ) 13 14 var db *pgxpool.Pool 15 16 func getUrlHandler(w http.ResponseWriter, req *http.Request) { 17 var url string 18 err := db.QueryRow(context.Background(), "select url from shortened_urls where id=$1", req.URL.Path).Scan(&url) 19 switch err { 20 case nil: 21 http.Redirect(w, req, url, http.StatusSeeOther) 22 case pgx.ErrNoRows: 23 http.NotFound(w, req) 24 default: 25 http.Error(w, "Internal server error", http.StatusInternalServerError) 26 } 27 } 28 29 func putUrlHandler(w http.ResponseWriter, req *http.Request) { 30 id := req.URL.Path 31 var url string 32 if body, err := io.ReadAll(req.Body); err == nil { 33 url = string(body) 34 } else { 35 http.Error(w, "Internal server error", http.StatusInternalServerError) 36 return 37 } 38 39 if _, err := db.Exec(context.Background(), `insert into shortened_urls(id, url) values ($1, $2) 40 on conflict (id) do update set url=excluded.url`, id, url); err == nil { 41 w.WriteHeader(http.StatusOK) 42 } else { 43 http.Error(w, "Internal server error", http.StatusInternalServerError) 44 } 45 } 46 47 func deleteUrlHandler(w http.ResponseWriter, req *http.Request) { 48 if _, err := db.Exec(context.Background(), "delete from shortened_urls where id=$1", req.URL.Path); err == nil { 49 w.WriteHeader(http.StatusOK) 50 } else { 51 http.Error(w, "Internal server error", http.StatusInternalServerError) 52 } 53 } 54 55 func urlHandler(w http.ResponseWriter, req *http.Request) { 56 switch req.Method { 57 case "GET": 58 getUrlHandler(w, req) 59 60 case "PUT": 61 putUrlHandler(w, req) 62 63 case "DELETE": 64 deleteUrlHandler(w, req) 65 66 default: 67 w.Header().Add("Allow", "GET, PUT, DELETE") 68 w.WriteHeader(http.StatusMethodNotAllowed) 69 } 70 } 71 72 func main() { 73 poolConfig, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL")) 74 if err != nil { 75 log.Fatalln("Unable to parse DATABASE_URL:", err) 76 } 77 78 db, err = pgxpool.NewWithConfig(context.Background(), poolConfig) 79 if err != nil { 80 log.Fatalln("Unable to create connection pool:", err) 81 } 82 83 http.HandleFunc("/", urlHandler) 84 85 log.Println("Starting URL shortener on localhost:8080") 86 err = http.ListenAndServe("localhost:8080", nil) 87 if err != nil { 88 log.Fatalln("Unable to start web server:", err) 89 } 90 }