...

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

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

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

View as plain text