...

Source file src/github.com/jackc/pgx/v5/examples/url_shortener/main.go

Documentation: github.com/jackc/pgx/v5/examples/url_shortener

     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  }
    91  

View as plain text