// HTTPServer is the constructor of the HTTP server func HTTPServer(redis *database.Redis, cache *mirrors.Cache) *HTTP { h := new(HTTP) h.redis = redis h.geoip = network.NewGeoIP() h.templates.mirrorlist = template.Must(h.LoadTemplates("mirrorlist")) h.templates.mirrorstats = template.Must(h.LoadTemplates("mirrorstats")) h.templates.downloadstats = template.Must(h.LoadTemplates("downloadstats")) h.templates.useragentstats = template.Must(h.LoadTemplates("useragentstats")) h.cache = cache h.stats = NewStats(redis) h.engine = DefaultEngine{} h.blockedUAs = GetConfig().UserAgentStatsConf.BlockedUserAgents h.uACountOnlyS = GetConfig().UserAgentStatsConf.CountOnlySpecialPath h.uACountSpecial = GetConfig().UserAgentStatsConf.CountSpecialPath h.parseUA = h.uACountOnlyS == false || len(h.blockedUAs) > 0 http.Handle("/", NewGzipHandler(h.requestDispatcher)) // Load the GeoIP databases if err := h.geoip.LoadGeoIP(); err != nil { if gerr, ok := err.(network.GeoIPError); ok { for _, e := range gerr.Errors { log.Critical(e.Error()) } if gerr.IsFatal() { if len(GetConfig().Fallbacks) == 0 { log.Fatal("Can't load the GeoIP databases, please set a valid path in the mirrorbits configuration") } else { log.Critical("Can't load the GeoIP databases, all requests will be served by the fallback mirrors") } } else { log.Critical("One or more GeoIP database could not be loaded, service will run in degraded mode") } } } // Initialize the random number generator rand.Seed(time.Now().UnixNano()) return h }
func (c *cli) CmdAdd(args ...string) error { cmd := SubCmd("add", "[OPTIONS] IDENTIFIER", "Add a new mirror") http := cmd.String("http", "", "HTTP base URL") rsync := cmd.String("rsync", "", "RSYNC base URL (for scanning only)") ftp := cmd.String("ftp", "", "FTP base URL (for scanning only)") sponsorName := cmd.String("sponsor-name", "", "Name of the sponsor") sponsorURL := cmd.String("sponsor-url", "", "URL of the sponsor") sponsorLogo := cmd.String("sponsor-logo", "", "URL of a logo to display for this mirror") adminName := cmd.String("admin-name", "", "Admin's name") adminEmail := cmd.String("admin-email", "", "Admin's email") customData := cmd.String("custom-data", "", "Associated data to return when the mirror is selected (i.e. json document)") continentOnly := cmd.Bool("continent-only", false, "The mirror should only handle its continent") countryOnly := cmd.Bool("country-only", false, "The mirror should only handle its country") asOnly := cmd.Bool("as-only", false, "The mirror should only handle clients in the same AS number") score := cmd.Int("score", 0, "Weight to give to the mirror during selection") comment := cmd.String("comment", "", "Comment") if err := cmd.Parse(args); err != nil { return nil } if cmd.NArg() < 1 { cmd.Usage() return nil } if strings.Contains(cmd.Arg(0), " ") { fmt.Fprintf(os.Stderr, "The identifier cannot contain a space\n") os.Exit(-1) } if *http == "" { fmt.Fprintf(os.Stderr, "You *must* pass at least an HTTP URL\n") os.Exit(-1) } if !strings.HasPrefix(*http, "http://") && !strings.HasPrefix(*http, "https://") { *http = "http://" + *http } u, err := url.Parse(*http) if err != nil { fmt.Fprintf(os.Stderr, "Can't parse HTTP url\n") os.Exit(-1) } ip, err := network.LookupMirrorIP(u.Host) if err == network.ErrMultipleAddresses { fmt.Fprintf(os.Stderr, "Warning: the hostname returned more than one address! This is highly unreliable.\n") } else if err != nil { log.Fatal("IP lookup failed: ", err.Error()) } geo := network.NewGeoIP() if err := geo.LoadGeoIP(); err != nil { log.Fatal(err.Error()) } geoRec := geo.GetRecord(ip) r := database.NewRedis() conn, err := r.Connect() if err != nil { log.Fatal("Redis: ", err) } defer conn.Close() key := fmt.Sprintf("MIRROR_%s", cmd.Arg(0)) exists, err := redis.Bool(conn.Do("EXISTS", key)) if err != nil { return err } if exists { fmt.Fprintf(os.Stderr, "Mirror %s already exists!\n", cmd.Arg(0)) os.Exit(-1) } // Normalize the URLs if http != nil { *http = utils.NormalizeURL(*http) } if rsync != nil { *rsync = utils.NormalizeURL(*rsync) } if ftp != nil { *ftp = utils.NormalizeURL(*ftp) } var latitude, longitude float32 var continentCode, countryCode string if geoRec.GeoIPRecord != nil { latitude = geoRec.GeoIPRecord.Latitude longitude = geoRec.GeoIPRecord.Longitude continentCode = geoRec.GeoIPRecord.ContinentCode countryCode = geoRec.GeoIPRecord.CountryCode } else { fmt.Fprintf(os.Stderr, "Warning: unable to guess the geographic location of %s\n", cmd.Arg(0)) } _, err = conn.Do("HMSET", key, "ID", cmd.Arg(0), "http", *http, "rsync", *rsync, "ftp", *ftp, "sponsorName", *sponsorName, "sponsorURL", *sponsorURL, "sponsorLogo", *sponsorLogo, "adminName", *adminName, "adminEmail", *adminEmail, "customData", *customData, "continentOnly", *continentOnly, "countryOnly", *countryOnly, "asOnly", *asOnly, "score", *score, "latitude", fmt.Sprintf("%f", latitude), "longitude", fmt.Sprintf("%f", longitude), "continentCode", continentCode, "countryCodes", countryCode, "asnum", geoRec.ASNum, "comment", strings.TrimSpace(*comment), "enabled", false, "up", false) if err != nil { goto oops } _, err = conn.Do("LPUSH", "MIRRORS", cmd.Arg(0)) if err != nil { goto oops } // Publish update database.Publish(conn, database.MIRROR_UPDATE, cmd.Arg(0)) fmt.Println("Mirror added successfully") return nil oops: fmt.Fprintf(os.Stderr, "Oops: %s", err) os.Exit(-1) return nil }