Skip to content

Instantly share code, notes, and snippets.

@sineer
Last active August 29, 2015 14:07
Show Gist options
  • Save sineer/70093a607dff5a8e86fa to your computer and use it in GitHub Desktop.
Save sineer/70093a607dff5a8e86fa to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
const (
OK = 0
ERR = 1
)
type Status struct {
code int
msg string
}
type Scan struct {
url string
body string
err error
status *Status
}
func NewScanSuccess(url string, body string) *Scan {
return &Scan{url, body, nil, &Status{OK, "O.K."}}
}
func NewScanError(url string, err error) *Scan {
return &Scan{url, "", err, &Status{ERR, "ERROR!"}}
}
// Convert list of URL(s) into a Buffered Channel that emit Scan struct
func getStatus(urls []string) <-chan Scan {
out := make(chan Scan, len(urls))
go func() {
for _, url := range urls {
// DO HTTP GET
resp, err := http.Get(url)
if err != nil {
out <- *NewScanError(url, err)
} else {
// PROCESS RESPONSE
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
out <- *NewScanError(url, err)
} else {
// HTTP GET RESPONSE HAS A BODY!
// ENQUEUE BODY AS STRING IN OUT CHAN
out <- *NewScanSuccess(url, string(body))
}
}
}
close(out)
}()
return out
}
func processStatus(in <-chan Scan) <-chan Scan {
out := make(chan Scan)
go func() {
for scan := range in {
scan.status = evalStatus(scan.body)
out <- scan
}
close(out)
}()
return out
}
func evalStatus(body string) *Status {
status := &Status{OK, "Status O.K."}
lines := strings.Split(body, "\n")
for _, line := range lines {
minus := strings.Index(line, "-")
if minus >= 0 {
colon := strings.Index(line, ":")
if colon >= 0 {
attr := strings.Split(line[minus:colon], " ")[1]
value := strings.Split(line[colon:], " ")[1]
// fmt.Printf("ATTR NAME: %s VALUE VALUE: %s\n", attr, value)
// PROCESS "VALID" ATTR/VALUE PAIR
if value != "true" {
status = &Status{ERR, "Attr: " + attr + " is false!"}
break // ERR! SKIP REMAINING LINE(s).
} else {
// fmt.Printf("Status ATTR: %s is O.K.", attr)
}
}
}
// fmt.Printf("LINE: %s\n", line)
}
return status
}
func main() {
urls := []string{
"https://gist.githubusercontent.com/sineer/3effbc864988af67c181/raw/2d9ecb3c16fa63d52252e30c8b02c647d87d63df/test_valid.yml",
"https://gist.githubusercontent.com/sineer/ebb12db17abfbf6288c4/raw/d34e707bd045fb3495fdb9d4c6b8da59980d13e6/test.yml",
}
scan := make(map[string]Scan, len(urls))
// Setup Pipeline to launch Concurrent Scan(s):
for res := range processStatus(getStatus(urls)) {
if res.url == "" {
fmt.Println("ERROR: Invalid Response!")
} else {
scan[res.url] = res
if res.err != nil {
// HTTP GET ERROR!
fmt.Printf("SCAN[%s] ERROR: %s\n", res.url, scan[res.url].err)
} else if res.status == nil {
// NIL status error!
fmt.Printf("NIL STATUS ERR! url: %s\n", res.url)
} else if res.status.code != 0 {
// STATUS ERROR!
fmt.Printf("SCAN[%s] STATUS ERROR: %s\n", res.url, scan[res.url].status.msg)
} else {
// fmt.Prinltf("SCAN[%s] BODY: %s\n", url, scan[url].body)
fmt.Printf("SCAN[%s] SUCCESS! STATUS: %s\n", res.url, scan[res.url].status.msg)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment