Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
192 lines (170 sloc) 5.61 KB
package importserver
import (
"bytes"
"fmt"
"net/http"
"path/filepath"
"strings"
"text/template"
)
var (
indexPaths = []string{
"",
"index.html",
"index.htm",
"default.htm",
}
)
// Data represents the data needed to create a http.Handler.
type Data struct {
Title string
PathToGoRedirect map[string]*GoRedirect
ExtraLinkToName map[string]string
}
// GoRedirect represents a go redirect.
type GoRedirect struct {
URL string
VCS string
Repository string
Images []*Image
Private bool
}
// StandardGithubGoRedirect returns a GoRedirect for a Github repo with the Images from StandardGithubImageSet.
func StandardGithubGoRedirect(goPackage string, githubUser string, githubRepo string) *GoRedirect {
return &GoRedirect{
VCS: "git",
URL: goPackage,
Repository: fmt.Sprintf("https://github.com/%s/%s", githubUser, githubRepo),
Images: StandardGithubImageSet(goPackage, githubUser, githubRepo),
}
}
// StandardPrivateGithubGoRedirect returns a private GoRedirect for a Github repo with no Images.
func StandardPrivateGithubGoRedirect(goPackage string, githubUser string, githubRepo string) *GoRedirect {
return &GoRedirect{
VCS: "git",
URL: goPackage,
Repository: fmt.Sprintf("https://github.com/%s/%s", githubUser, githubRepo),
Private: true,
}
}
// Image represents an image to display on the index page.
type Image struct {
URL string
Source string
}
// StandardGithubImageSet returns Images for a GitHub repo for CircleCI, Go Report Card, GoDoc, and a MIT License badge.
func StandardGithubImageSet(goPackage string, githubUser string, githubRepo string) []*Image {
return []*Image{
{
URL: fmt.Sprintf("https://circleci.com/gh/%s/%s/tree/master", githubUser, githubRepo),
Source: fmt.Sprintf("https://circleci.com/gh/%s/%s/tree/master.png", githubUser, githubRepo),
},
{
URL: fmt.Sprintf("http://goreportcard.com/report/%s", goPackage),
Source: fmt.Sprintf("http://goreportcard.com/badge/%s", goPackage),
},
{
URL: fmt.Sprintf("https://godoc.org/%s", goPackage),
Source: "http://img.shields.io/badge/GoDoc-Reference-blue.svg",
},
{
URL: fmt.Sprintf("https://github.com/%s/%s/blob/master/LICENSE", githubUser, githubRepo),
Source: "http://img.shields.io/badge/License-MIT-blue.svg",
},
}
}
// StandardGithubGoRedirectBuilder uses a common base go package and GitHub user to build GoRedirects.
type StandardGithubGoRedirectBuilder interface {
GoRedirect(relGoPackage string, githubRepo string) *GoRedirect
PrivateGoRedirect(relGoPackage string, githubRepo string) *GoRedirect
}
// NewStandardGithubGoRedirectBuilder returns a StandardGithubGoRedirectBuilder for the given base go package and GitHub user.
func NewStandardGithubGoRedirectBuilder(baseGoPackage string, githubUser string) StandardGithubGoRedirectBuilder {
return newStandardGithubGoRedirectBuilder(baseGoPackage, githubUser)
}
type standardGithubGoRedirectBuilder struct {
baseGoPackage string
githubUser string
}
func newStandardGithubGoRedirectBuilder(baseGoPackage string, githubUser string) *standardGithubGoRedirectBuilder {
return &standardGithubGoRedirectBuilder{baseGoPackage, githubUser}
}
func (s *standardGithubGoRedirectBuilder) GoRedirect(relGoPackage string, githubRepo string) *GoRedirect {
return StandardGithubGoRedirect(fmt.Sprintf("%s/%s", s.baseGoPackage, relGoPackage), s.githubUser, githubRepo)
}
func (s *standardGithubGoRedirectBuilder) PrivateGoRedirect(relGoPackage string, githubRepo string) *GoRedirect {
return StandardPrivateGithubGoRedirect(fmt.Sprintf("%s/%s", s.baseGoPackage, relGoPackage), s.githubUser, githubRepo)
}
// NewHandler returns a new http.Handler.
func NewHandler(templateDirPath string, data *Data) (http.Handler, error) {
return newHandler(templateDirPath, data)
}
type handler struct {
pathToPage map[string][]byte
}
func newHandler(templateDirPath string, data *Data) (*handler, error) {
pathToPage, err := generatePathToPage(templateDirPath, data)
if err != nil {
return nil, err
}
return &handler{pathToPage}, nil
}
func (h *handler) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) {
path := strings.TrimPrefix(strings.TrimSuffix(request.URL.Path, "/"), "/")
if page := getPage(h.pathToPage, path); page != nil {
_, _ = responseWriter.Write(page)
return
}
http.NotFound(responseWriter, request)
}
func getPage(pathToPage map[string][]byte, path string) []byte {
page, ok := pathToPage[path]
if ok {
return page
}
split := strings.Split(path, "/")
lenSplit := len(split)
if lenSplit > 1 {
for i := lenSplit - 1; i > 0; i-- {
path = strings.Join(split[0:i], "/")
page, ok = pathToPage[path]
if ok {
return page
}
}
}
return nil
}
func generatePathToPage(templateDirPath string, data *Data) (map[string][]byte, error) {
tmpl, err := template.ParseFiles(filepath.Join(templateDirPath, "go.html"))
if err != nil {
return nil, err
}
indexTmpl, err := template.ParseFiles(filepath.Join(templateDirPath, "index.html"))
if err != nil {
return nil, err
}
pathToPage := make(map[string][]byte)
for path, goRedirect := range data.PathToGoRedirect {
page, err := generatePage(tmpl, goRedirect)
if err != nil {
return nil, err
}
pathToPage[path] = page
}
indexPage, err := generatePage(indexTmpl, data)
if err != nil {
return nil, err
}
for _, indexPath := range indexPaths {
pathToPage[indexPath] = indexPage
}
return pathToPage, nil
}
func generatePage(t *template.Template, data interface{}) ([]byte, error) {
buffer := bytes.NewBuffer(nil)
if err := t.Execute(buffer, data); err != nil {
return nil, err
}
return buffer.Bytes(), nil
}