Last active
August 29, 2015 14:07
-
-
Save sineer/70093a607dff5a8e86fa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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