mirror of
https://github.com/Luzifer/go-latestver.git
synced 2024-12-20 10:31:16 +00:00
Add feed generator
This commit is contained in:
parent
b364743a0b
commit
c18b3f2368
4 changed files with 98 additions and 14 deletions
97
api.go
97
api.go
|
@ -2,18 +2,29 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Luzifer/go-latestver/internal/config"
|
||||
"github.com/Luzifer/go-latestver/internal/database"
|
||||
"github.com/Luzifer/go-latestver/internal/fetcher"
|
||||
"github.com/gorilla/feeds"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func buildFullURL(u *url.URL) string {
|
||||
return strings.Join([]string{
|
||||
strings.TrimRight(cfg.BaseURL, "/"),
|
||||
strings.TrimLeft(u.String(), "/"),
|
||||
}, "/")
|
||||
}
|
||||
|
||||
func handleCatalogGet(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
|
@ -101,6 +112,78 @@ func handleCatalogList(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func handleLog(w http.ResponseWriter, r *http.Request) {
|
||||
logs, err := prepareLogForRequest(r)
|
||||
switch err {
|
||||
case nil:
|
||||
// This is fine
|
||||
|
||||
case config.ErrCatalogEntryNotFound:
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
|
||||
default:
|
||||
http.Error(w, "Unable to fetch logs", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err = json.NewEncoder(w).Encode(logs); err != nil {
|
||||
log.WithError(err).Error("Unable to encode logs")
|
||||
http.Error(w, "Unable to encode logs", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func handleLogFeed(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
logs, err := prepareLogForRequest(r)
|
||||
switch err {
|
||||
case nil:
|
||||
// This is fine
|
||||
|
||||
case config.ErrCatalogEntryNotFound:
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
|
||||
default:
|
||||
http.Error(w, "Unable to fetch logs", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
feedTitle = "Latestver Update Log"
|
||||
feedURL, _ = router.Get("catalog").URL()
|
||||
)
|
||||
if vars["name"] != "" {
|
||||
feedTitle = fmt.Sprintf("Latestver Update Log of %s:%s", vars["name"], vars["tag"])
|
||||
feedURL, _ = router.Get("catalog-entry").URL("name", vars["name"], "tag", vars["tag"])
|
||||
}
|
||||
|
||||
feed := &feeds.Feed{
|
||||
Description: "Generated by go-latestver: https://github.com/Luzifer/go-latestver",
|
||||
Link: &feeds.Link{Href: buildFullURL(feedURL)},
|
||||
Title: feedTitle,
|
||||
}
|
||||
|
||||
for _, le := range logs {
|
||||
catalogEntryURL, _ := router.Get("catalog-entry").URL("name", le.CatalogName, "tag", le.CatalogTag)
|
||||
feed.Add(&feeds.Item{
|
||||
Created: le.Timestamp.UTC(),
|
||||
Description: fmt.Sprintf("%s:%s updated to version %s from %s", le.CatalogName, le.CatalogTag, le.VersionTo, le.VersionFrom),
|
||||
Id: fmt.Sprintf("%s:%s-%s", le.CatalogName, le.CatalogTag, le.Timestamp.UTC().Format(time.RFC3339)),
|
||||
Link: &feeds.Link{Href: buildFullURL(catalogEntryURL)},
|
||||
Title: fmt.Sprintf("%s:%s %s", le.CatalogName, le.CatalogTag, le.VersionTo),
|
||||
})
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8")
|
||||
if err = feed.WriteRss(w); err != nil {
|
||||
log.WithError(err).Error("Unable to render RSS")
|
||||
http.Error(w, "Unable to render RSS", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func prepareLogForRequest(r *http.Request) ([]database.LogEntry, error) {
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
name, tag = vars["name"], vars["tag"]
|
||||
|
@ -124,19 +207,11 @@ func handleLog(w http.ResponseWriter, r *http.Request) {
|
|||
} else {
|
||||
ce, err := configFile.CatalogEntryByTag(name, tag)
|
||||
if errors.Is(err, config.ErrCatalogEntryNotFound) {
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
return nil, config.ErrCatalogEntryNotFound
|
||||
}
|
||||
|
||||
logs, err = storage.Logs.ListForCatalogEntry(&ce, num, page)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err = json.NewEncoder(w).Encode(logs); err != nil {
|
||||
log.WithError(err).Error("Unable to encode logs")
|
||||
http.Error(w, "Unable to encode logs", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
return logs, errors.Wrap(err, "listing log entries")
|
||||
}
|
||||
|
||||
func handleLogFeed(w http.ResponseWriter, r *http.Request) {} // FIXME
|
||||
|
|
1
go.mod
1
go.mod
|
@ -29,6 +29,7 @@ require (
|
|||
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||
github.com/gorilla/feeds v1.1.1 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -66,6 +66,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY=
|
||||
github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
|
|
12
main.go
12
main.go
|
@ -18,6 +18,7 @@ import (
|
|||
|
||||
var (
|
||||
cfg = struct {
|
||||
BaseURL string `flag:"base-url" default:"https://example.com/" description:"Base-URL the application is reachable at"`
|
||||
Config string `flag:"config,c" default:"config.yaml" description:"Configuration file with catalog entries"`
|
||||
Listen string `flag:"listen" default:":3000" description:"Port/IP to listen on"`
|
||||
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"`
|
||||
|
@ -28,6 +29,7 @@ var (
|
|||
}{}
|
||||
|
||||
configFile = config.New()
|
||||
router *mux.Router
|
||||
storage *database.Client
|
||||
|
||||
version = "dev"
|
||||
|
@ -73,14 +75,18 @@ func main() {
|
|||
scheduler.AddFunc("@every 1m", schedulerRun)
|
||||
scheduler.Start()
|
||||
|
||||
router := mux.NewRouter()
|
||||
router = mux.NewRouter()
|
||||
router.HandleFunc("/v1/catalog", handleCatalogList).Methods(http.MethodGet)
|
||||
router.HandleFunc("/v1/catalog/{name}/{tag}", handleCatalogGet).Methods(http.MethodGet)
|
||||
router.HandleFunc("/v1/catalog/{name}/{tag}/log", handleLog).Methods(http.MethodGet)
|
||||
router.HandleFunc("/v1/catalog/{name}/{tag}/log.rss", handleLogFeed).Methods(http.MethodGet)
|
||||
router.HandleFunc("/v1/catalog/{name}/{tag}/version", handleCatalogGetVersion).Methods(http.MethodGet)
|
||||
router.HandleFunc("/v1/log", handleLog).Methods(http.MethodGet)
|
||||
router.HandleFunc("/v1/log.rss", handleLogFeed).Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/", nil).Methods(http.MethodGet).Name("catalog")
|
||||
router.HandleFunc("/{name}/{tag}", nil).Methods(http.MethodGet).Name("catalog-entry")
|
||||
router.HandleFunc("/{name}/{tag}/log.rss", handleLogFeed).Methods(http.MethodGet).Name("catalog-entry-rss")
|
||||
router.HandleFunc("/log", nil).Methods(http.MethodGet)
|
||||
router.HandleFunc("/log.rss", handleLogFeed).Methods(http.MethodGet).Name("log-rss")
|
||||
|
||||
var handler http.Handler = router
|
||||
handler = httpHelper.GzipHandler(handler)
|
||||
|
|
Loading…
Reference in a new issue