Created
          August 23, 2014 01:52 
        
      - 
      
- 
        Save nickvanw/79b2f0f08e834738e9ef to your computer and use it in GitHub Desktop. 
    Parallel URL Fetcher
  
        
  
    
      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 ( | |
| "encoding/csv" | |
| "encoding/json" | |
| "fmt" | |
| "io/ioutil" | |
| "net/http" | |
| "strings" | |
| "sync" | |
| "github.com/codegangsta/negroni" | |
| ) | |
| const BASE_URL = "http://example.com/" | |
| func main() { | |
| mux := http.NewServeMux() | |
| mux.HandleFunc("/example", asyncUrlHandler) | |
| n := negroni.Classic() | |
| n.UseHandler(mux) | |
| n.Run(":3000") | |
| } | |
| func asyncUrlHandler(w http.ResponseWriter, req *http.Request) { | |
| queryData := req.URL.Query() | |
| format, ok := queryData["urls"] | |
| if !ok { | |
| w.WriteHeader(http.StatusBadRequest) | |
| w.Write([]byte("bad arguments")) | |
| return | |
| } | |
| data := strings.NewReader(format[0]) | |
| r := csv.NewReader(data) | |
| lines, err := r.Read() | |
| if err != nil { | |
| w.WriteHeader(http.StatusBadRequest) | |
| w.Write([]byte("bad arguments")) | |
| return | |
| } | |
| retChan := make(chan SiteOut) | |
| doneChan := make(chan struct{}) | |
| var wg sync.WaitGroup | |
| for _, v := range lines { | |
| wg.Add(1) | |
| go fetchUrl(v, retChan, &wg) | |
| } | |
| go func() { | |
| wg.Wait() | |
| doneChan <- struct{}{} | |
| }() | |
| var output []SiteOut | |
| for { | |
| select { | |
| case v := <-retChan: | |
| output = append(output, v) | |
| case <-doneChan: | |
| json.NewEncoder(w).Encode(output) | |
| req.Body.Close() | |
| return | |
| } | |
| } | |
| } | |
| func fetchUrl(url string, out chan SiteOut, wg *sync.WaitGroup) { | |
| defer wg.Done() | |
| newSite := SiteOut{Base: url} | |
| fetchUrl := fmt.Sprintf("%s/%s", BASE_URL, url) | |
| resp, err := http.Get(fetchUrl) | |
| if err != nil { | |
| newSite.Data = "" | |
| out <- newSite | |
| return | |
| } | |
| defer resp.Body.Close() | |
| body, err := ioutil.ReadAll(resp.Body) | |
| if err != nil { | |
| newSite.Data = "" | |
| out <- newSite | |
| return | |
| } | |
| newSite.Data = string(body) | |
| out <- newSite | |
| } | |
| type SiteOut struct { | |
| Data string `json:"data"` | |
| Base string `json:"base"` | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment