Skip to content
This repository has been archived by the owner on Jul 30, 2020. It is now read-only.

Commit

Permalink
server: refactor into a new package
Browse files Browse the repository at this point in the history
- Add 200 on / to make monitoring possible
- Put the API under /api/v1/
- Move the server logic to a separate package
  • Loading branch information
philips committed Aug 5, 2019
1 parent 4235743 commit 66707f6
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 84 deletions.
88 changes: 5 additions & 83 deletions rget/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package cmd
import (
"context"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
Expand All @@ -31,7 +30,7 @@ import (
"github.com/merklecounty/rget/autocert"
"github.com/merklecounty/rget/gitcache"
"github.com/merklecounty/rget/rgethash"
"github.com/merklecounty/rget/rgetwellknown"
"github.com/merklecounty/rget/rgetserver"
)

// serverCmd represents the server command
Expand All @@ -47,84 +46,6 @@ func init() {
rootCmd.AddCommand(serverCmd)
}

type rgetServer struct {
*gitcache.GitCache
projReqs *prometheus.CounterVec
}

func (r rgetServer) handler(resp http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
domain, err := rgetwellknown.TrimDigestDomain(req.Host)
if err != nil {
fmt.Printf("request for unknown host %v unable to parse: %v\n", req.Host, err)
}
if len(domain) > 0 {
r.projReqs.WithLabelValues(req.Method, domain).Inc()
}
http.Error(resp, "only POST is supported", http.StatusBadRequest)
return
}

err := req.ParseForm()
if err != nil {
http.Error(resp, "invalid request", http.StatusBadRequest)
return
}

sumsURL := req.Form.Get("url")
fmt.Printf("submission: %v\n", sumsURL)

// ensure the URL is coming from a host we know how to generate a
// domain for by parsing it using the wellknown libraries
domain, err := rgetwellknown.Domain(sumsURL)
if err != nil {
fmt.Printf("wellknown domain error: %v\n", err)
resp.WriteHeader(http.StatusOK)
return
}

r.projReqs.WithLabelValues(req.Method, domain).Inc()

// Step 1: Download the SHA256SUMS that is correct for the URL
response, err := http.Get(sumsURL)
var sha256file []byte
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
} else {
var err error
defer response.Body.Close()
sha256file, err = ioutil.ReadAll(response.Body)
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
}
}

sums := rgethash.FromSHA256SumFile(string(sha256file))

// Step 2: Save the file contents to the git repo by domain
_, err = r.GitCache.Get(context.Background(), sums.Domain())
if err == nil {
// TODO(philips): add rate limiting and DDoS protections here
fmt.Printf("cache hit: %v\n", sumsURL)
resp.WriteHeader(http.StatusOK)
return
}

// Step 3. Create the Certificate object for the domain and save that as well
ctdomain := sums.Domain() + "." + domain
err = r.GitCache.Put(context.Background(), ctdomain, sha256file)
if err != nil {
fmt.Printf("git put error: %v", err)
http.Error(resp, "internal service error", http.StatusInternalServerError)
return
}

resp.WriteHeader(http.StatusOK)
return
}

func server(cmd *cobra.Command, args []string) {
if len(args) < 2 {
fmt.Printf("missing required arguments (public git URL, private git URL)\n")
Expand Down Expand Up @@ -155,12 +76,13 @@ func server(cmd *cobra.Command, args []string) {
Help: "Total number of requests for a particular project",
}, []string{"method", "project"})

rs := rgetServer{
rs := rgetserver.Server{
GitCache: pubgc,
projReqs: rr,
ProjReqs: rr,
}

http.HandleFunc("/", rs.handler)
http.HandleFunc("/", rs.ReleaseHandler)
http.HandleFunc("/api/", rs.APIHandler)

privgc, err := gitcache.NewGitCache(privgit, &auth, "private")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion rget/cmd/submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func init() {
}

func submit(cmd *cobra.Command, args []string) {
resp, err := http.PostForm("https://"+rgetwellknown.PublicServiceHost, url.Values{
resp, err := http.PostForm("https://"+rgetwellknown.PublicServiceHost+"/api/v1/submit", url.Values{
"url": {args[0]},
})
defer resp.Body.Close()
Expand Down
108 changes: 108 additions & 0 deletions rgetserver/rgetserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package rgetserver

import (
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"

"github.com/prometheus/client_golang/prometheus"

"github.com/merklecounty/rget/gitcache"
"github.com/merklecounty/rget/rgethash"
"github.com/merklecounty/rget/rgetwellknown"
)

type Server struct {
*gitcache.GitCache
ProjReqs *prometheus.CounterVec
}

func (r Server) ReleaseHandler(resp http.ResponseWriter, req *http.Request) {
if req.Method != "GET" {
http.Error(resp, "only GET is supported", http.StatusBadRequest)
return
}

short, err := rgetwellknown.TrimDigestDomain(req.Host)
if err != nil {
fmt.Printf("request for unknown host %v unable to parse: %v\n", req.Host, err)
}
if len(short) > 0 {
r.ProjReqs.WithLabelValues(req.Method, short).Inc()
}

full := strings.TrimSuffix(req.Host, "."+rgetwellknown.PublicServiceHost)
fmt.Fprintf(resp, "<h2>%s</h2>", short)
fmt.Fprintf(resp, "<a href=\"https://github.com/merklecounty/records/blob/master/%s\">Merkle County Record</a>", full)

return
}

func (r Server) APIHandler(resp http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
http.Error(resp, "only POST is supported", http.StatusBadRequest)
return
}

err := req.ParseForm()
if err != nil {
http.Error(resp, "invalid request", http.StatusBadRequest)
return
}

sumsURL := req.Form.Get("url")
fmt.Printf("submission: %v\n", sumsURL)

// ensure the URL is coming from a host we know how to generate a
// domain for by parsing it using the wellknown libraries
domain, err := rgetwellknown.Domain(sumsURL)
if err != nil {
fmt.Printf("wellknown domain error: %v\n", err)
resp.WriteHeader(http.StatusOK)
return
}

r.ProjReqs.WithLabelValues(req.Method, domain).Inc()

// Step 1: Download the SHA256SUMS that is correct for the URL
response, err := http.Get(sumsURL)
var sha256file []byte
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
} else {
var err error
defer response.Body.Close()
sha256file, err = ioutil.ReadAll(response.Body)
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
}
}

sums := rgethash.FromSHA256SumFile(string(sha256file))

// Step 2: Save the file contents to the git repo by domain
_, err = r.GitCache.Get(context.Background(), sums.Domain())
if err == nil {
// TODO(philips): add rate limiting and DDoS protections here
fmt.Printf("cache hit: %v\n", sumsURL)
resp.WriteHeader(http.StatusOK)
return
}

// Step 3. Create the Certificate object for the domain and save that as well
ctdomain := sums.Domain() + "." + domain
err = r.GitCache.Put(context.Background(), ctdomain, sha256file)
if err != nil {
fmt.Printf("git put error: %v", err)
http.Error(resp, "internal service error", http.StatusInternalServerError)
return
}

resp.WriteHeader(http.StatusOK)
return
}

0 comments on commit 66707f6

Please sign in to comment.