Beispiel #1
0
// setupMiddleware is an internal method where we setup GIN middleware
func setupMiddleware(r *gin.Engine) {
	// TODO: CACHE_URL should come from an environment variable but this requires
	// validating and parsing of the connection url into it's base components.
	store, err := sessions.NewRedisStore(10, "tcp", "localhost:6379", "", []byte(config.Config.Session_Secret))
	if err != nil {
		log.Fatalln("Failed to connect to Redis.", err)
	}

	r.Use(
		secure.Secure(secure.Options{ // TODO: we should get these from config
			AllowedHosts:          []string{},
			SSLRedirect:           false,
			SSLHost:               "",
			SSLProxyHeaders:       map[string]string{"X-Forwarded-Proto": "https"},
			STSSeconds:            315360000,
			STSIncludeSubdomains:  true,
			FrameDeny:             true,
			ContentTypeNosniff:    true,
			BrowserXssFilter:      true,
			ContentSecurityPolicy: "default-src 'self'",
		}),
		sessions.Sessions("session", store),
		auth.UserMiddleware(),
	)
}
Beispiel #2
0
func mapRoutes(router *gin.Engine) {

	router.Use(cors.Middleware(cors.Config{
		Origins: "http://openbonfires.github.io, https://openbonfires.github.io",
	}))

	//mapped router for authenticated urls only
	api := router.Group("/api")
	api.GET("/randomquote", func(c *gin.Context) {
		res, err := http.Get("http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=en")
		if err == nil {
			defer res.Body.Close()
			body, err := ioutil.ReadAll(res.Body)
			if err == nil {
				c.String(http.StatusOK, string(body))
			} else {
				c.String(http.StatusInternalServerError, "Unable to read the response date from the random quotes API.")
			}
		} else {
			c.String(http.StatusInternalServerError, "Unable to communicate with random quotes API.")
		}
	})

	//All other requests
	router.Use(func(c *gin.Context) {
		c.String(http.StatusNotFound, "Requested url does not exist")
		c.Abort()
	})
}
Beispiel #3
0
// Init initializes application routers.
func Init(g *gin.Engine) {
	g.Use(middleware.UserFromToken())

	// Home page.
	g.GET("/", Home)

	// Health check group.
	h := g.Group("/h")
	{
		h.GET("/ping", health.Ping)
	}

	// User related group.
	u := g.Group("/user")
	{
		usin := u.Group("/signin")
		usin.Use(middleware.NotAuthenticated())
		{
			usin.POST("/:service", auth.SignIn)
			usin.GET("/:service/complete", auth.SignInComplete)
		}

		urepos := u.Group("/repos")
		urepos.Use(middleware.Authenticated())
		{
			urepos.GET("/:service", repos.ReposList)
			urepos.PATCH("/:service", repos.ReposUpdate)
		}
	}
}
Beispiel #4
0
//Setup gin Engine server
func initGin(ginEngine *gin.Engine) {
	ginEngine.Use(logrusLogger())
	ginEngine.POST("/assignment", putAssignment)
	ginEngine.POST("/submission", putSubmission)
	ginEngine.GET("/plugin/langs", getSupportedLangs)
	ginEngine.GET("/debug/vars", expvarGin.Handler())
	ginEngine.GET("/health", healthCheck)
}
Beispiel #5
0
func main() {
	flag.Parse()
	if *logToFile {
		logWriteTo, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
		if err != nil {
			log.Printf("error opening to log file: %v", err)
		}
		if logWriteTo != nil {
			log.SetOutput(logWriteTo)
		}
	}
	gin.SetMode(*ginMode)
	var route *gin.Engine
	if *useGinLogger {
		route = gin.Default()
	} else {
		route = gin.New()
		route.Use(logger)
	}

	route.GET("/", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{"message": "Its an entry point :)"})
	})

	route.GET("/token", func(ctx *gin.Context) {
		tokenString := auth.GetToken(secretpassword)
		ctx.JSON(200, gin.H{"token": tokenString})
	})
	route.GET("/dbaccessor", func(ctx *gin.Context) {
		ctx.JSON(200, getFakeDbData())
	})
	route.Use(auth.Auth(secretpassword))
	route.POST("/auth", func(ctx *gin.Context) {
		ak := ctx.Request.FormValue("authkey")
		if ak == "" {
			ctx.JSON(401, "No auth key")
		} else if !auth.VerifyAuthKey(ak) {
			ctx.JSON(401, "Wrong key")
		} else {
			ctx.Redirect(http.StatusFound, "/user")
		}
	})
	route.GET("/user", func(ctx *gin.Context) {
		key := ctx.MustGet("authKey")
		udetails := dbAccessor(key.(string))
		ctx.JSON(200, gin.H{"user": udetails})
	})
	route.GET("/user/:id", func(ctx *gin.Context) {
		id := ctx.Params.ByName("id")
		ctx.JSON(200, find(id))
	})

	if err := route.Run(fmt.Sprintf(":%d", *port)); err != nil {
		logFatal("Http not running: ", err)
	} else {
		logPrintln("shutting down")
	}
}
Beispiel #6
0
func (m *Armor) useConfiguredMiddleware(r *gin.Engine) {
	middlewareStack := m.Config.GetStringArray("middleware")

	for _, name := range middlewareStack {
		if mid := m.GetMiddleware(name); mid != nil {
			r.Use(mid)
		}
	}
}
Beispiel #7
0
// Builds NewRelicService
func (s *NewRelicService) Build(r *gin.Engine) error {
	if !s.Config.Enabled {
		log.Info("NewRelicService is disabled")
		return nil
	}

	r.Use(newrelic.NewRelic(s.Config.LicenseKey, s.Config.AppName, s.Config.Verbose))
	return nil
}
Beispiel #8
0
func main() {
	var engine *gin.Engine = gin.New()
	engine.Use(gin.Logger())
	engine.Use(gin.Recovery())
	engine.GET("/:name", func(c *gin.Context) {
		c.String(http.StatusOK, "Hello %s\n", c.Param("name"))
	})
	engine.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "Index\n")
	})
	engine.Run(":8080")
}
func Register(engine *gin.Engine) {
	engine.Use(Recovery)
	engine.Use(Errors)

	engine.GET("/events", eventsGet)
	engine.GET("/profile", profileGet)
	engine.POST("/profile", profilePost)
	engine.DELETE("/profile", profileDel)
	engine.GET("/ping", pingGet)
	engine.POST("/stop", stopPost)
	engine.GET("/status", statusGet)
}
Beispiel #10
0
func initMiddleware(r *gin.Engine) {
	r.Use(gin.Recovery(), gin.Logger())
	//init session
	session.Init(config.GLOBAL_CONFIG.Sessionkey)
	r.Use(func(c *gin.Context) {
		sess, err := session.GetSessionManager().SessionStart(c.Writer, c.Request)
		if err != nil {
			log.Println(err)
		}
		defer sess.SessionRelease(c.Writer)
		sessionutil.InitContextSession(c, sess)
		c.Next()
	})
}
Beispiel #11
0
func (s *Static) Install(engine *gin.Engine) error {
	var err error
	var root string

	fs, err := LoadAssetFileSystem("/dist", true)
	if err == nil {
		log.Println("Serving static content from binary")
		engine.Use(static.Serve("/", fs))

	} else {
		log.Println("warning: could not read assets from binary:", err)

		toTry := []string{
			settings.StaticAppRoot,
			"./dist",
		}
		if envRoot := os.Getenv("HTML_ROOT"); envRoot != "" {
			toTry = append([]string{envRoot}, toTry...)
		}

		for _, path := range toTry {
			if _, err = os.Stat(path); err != nil {
				log.Println("warning: could not serve from", path)
			} else {
				root = path
				break
			}
		}

		if err != nil {
			return err
		}

		log.Println("Serving static content from", root)

		prefix := "/"
		fs := static.LocalFile(root, true)
		staticHandler := static.Serve(prefix, fs)
		engine.Use(func(c *gin.Context) {
			if fs.Exists(prefix, c.Request.URL.Path) {
				if s.UserAuthenticator.BasicAuthForUser(c) {
					staticHandler(c)
				}
			}
		})
	}

	return nil
}
Beispiel #12
0
//setSessions initializes sessions & csrf middlewares
func setSessions(router *gin.Engine) {
	config := system.GetConfig()
	//https://github.com/gin-gonic/contrib/tree/master/sessions
	store := sessions.NewCookieStore([]byte(config.SessionSecret))
	store.Options(sessions.Options{HttpOnly: true, MaxAge: 7 * 86400}) //Also set Secure: true if using SSL, you should though
	router.Use(sessions.Sessions("gin-session", store))
	//https://github.com/utrack/gin-csrf
	router.Use(csrf.Middleware(csrf.Options{
		Secret: config.SessionSecret,
		ErrorFunc: func(c *gin.Context) {
			c.String(400, "CSRF token mismatch")
			c.Abort()
		},
	}))
}
Beispiel #13
0
func registerMiddleware(e *gin.Engine) {
	//------------------------
	// Third-party middleware
	//------------------------
	// See https://github.com/thoas/stats
	s := stats.New()
	e.Use(func(ctx *gin.Context) {
		beginning, recorder := s.Begin(ctx.Writer)
		ctx.Next()
		s.End(beginning, recorder)
	})
	// Route
	e.GET("/stats", func(c *gin.Context) {
		logger.Log.Info("In stats")
		c.JSON(http.StatusOK, s.Data())
	})
}
Beispiel #14
0
// Prepares the application to use the AirbrakeService. The function will:
//
// 1. Add a recovery handler to gin
// 2. Replace app.OnException with a version that writes the airbrak in addition
//    to logging
// 3. Sets the Notifier object that will be used to push notices to Airbrake
func (s *AirbrakeService) Build(r *gin.Engine) error {
	if !s.Config.Enabled {
		log.Info("AirbrakeService is disabled")
		return nil
	}

	s.Notifier = gobrake.NewNotifier(s.Config.ProjectID, s.Config.ProjectKey)
	s.Notifier.SetHost(s.Config.Host)
	s.Notifier.AddFilter(func(notice *gobrake.Notice) *gobrake.Notice {
		notice.Context["environment"] = gin.Mode()
		return notice
	})

	r.Use(s.RecoveryMiddleware())

	return nil
}
Beispiel #15
0
// Register all endpoint handlers
func Register(engine *gin.Engine) {
	engine.Use(Limiter)
	engine.Use(Recovery)

	dbGroup := engine.Group("")
	dbGroup.Use(Database)

	dbGroup.GET("/check", checkGet)
	dbGroup.POST("/request/google", requestGooglePost)
	dbGroup.POST("/request/saml", requestSamlPost)
	dbGroup.GET("/callback/google", callbackGoogleGet)
	dbGroup.POST("/callback/saml", callbackGoogleGet)
	dbGroup.GET("/update/google", updateGoogleGet)

	dbGroup.POST("/v1/request/google", requestGoogle2Post)
	dbGroup.POST("/v1/request/saml", requestSamlPost)
	dbGroup.GET("/v1/callback/google", callbackGoogleGet)
	dbGroup.POST("/v1/callback/saml", callbackSamlPost)
	dbGroup.GET("/v1/update/google", updateGoogleGet)
}
Beispiel #16
0
func newSession(engine *gin.Engine, conf AuthConf, store sessions.CookieStore) {
	engine.Use(sessions.Sessions(conf.Session.CookieKey, store))

	options := sessions.Options{
		Path:     "/",
		MaxAge:   conf.Session.MaxAge,
		HttpOnly: true,
	}
	store.Options(options)

	authConf = conf

	gob.Register(conf.LoginUser)

	engine.POST(conf.Login.url, conf.Login.handle)
	engine.POST(conf.Logout.url, conf.Logout.handle)
	engine.GET(conf.LoginSuccess.url, conf.LoginSuccess.handle)
	engine.GET(conf.LoginFailed.url, conf.LoginFailed.handle)
	engine.GET(conf.UnAuthenticated.url, conf.UnAuthenticated.handle)
	engine.GET(conf.IsAuthenticated.url, conf.IsAuthenticated.handle)

}
Beispiel #17
0
func initMiddleware(e *gin.Engine) {
	e.Use(defaultContentTypeMiddleware())
}
Beispiel #18
0
func (self *CORSController) Init(r *gin.Engine) {
	r.Use(self.corsMiddleware)
}
Beispiel #19
0
func defineMiddleware(router *gin.Engine) {
	router.Use(gin.Logger())
	router.Use(gin.Recovery())
}
// Use adds the middleware to a gin engine.
func (p *Prometheus) Use(e *gin.Engine) {
	e.Use(p.handlerFunc())
	e.GET(p.MetricsPath, prometheusHandler())
}
Beispiel #21
0
func (r *__react__) bind(ro *gin.Engine) {
	r.engine = ro
	r.init()
	ro.Use(r.handle)
}
Beispiel #22
0
func ExposeRoutes(router *gin.Engine) {
	router.LoadHTMLGlob("web/templates/*.html")
	router.HTMLRender = createCustomRender()
	if config.IsEnvironment("production") && config.GetConfig("SPACE_CDN") != "" {
		spaceCDN = config.GetConfig("SPACE_CDN")
	} else {
		spaceCDN = "/public"
		router.Static("/public", "web/public")
	}
	store := sessions.NewCookieStore([]byte(config.GetConfig("SPACE_SESSION_SECRET")))
	store.Options(sessions.Options{
		Secure:   config.IsEnvironment("production"),
		HttpOnly: true,
	})
	router.Use(sessions.Sessions("jupiter.session", store))
	views := router.Group("/")
	{
		views.GET("/", jupiterHandler)
		views.GET("/profile", jupiterHandler)

		views.GET("/signup", func(c *gin.Context) {
			c.HTML(http.StatusOK, "satellite", utils.H{
				"AssetsEndpoint": spaceCDN,
				"Title":          " - Sign up",
				"Satellite":      "io",
				"Data": utils.H{
					"feature.gates": utils.H{
						"user.create": feature.Active("user.create"),
					},
				},
			})
		})

		views.GET("/signin", func(c *gin.Context) {
			c.HTML(http.StatusOK, "satellite", utils.H{
				"AssetsEndpoint": spaceCDN,
				"Title":          " - Sign in",
				"Satellite":      "ganymede",
			})
		})

		views.GET("/signout", func(c *gin.Context) {
			session := sessions.Default(c)

			userPublicId := session.Get("userPublicId")
			if userPublicId != nil {
				session.Delete("userPublicId")
				session.Save()
			}

			c.Redirect(http.StatusFound, "/signin")
		})

		views.GET("/session", func(c *gin.Context) {
			session := sessions.Default(c)

			userPublicId := session.Get("userPublicId")
			if userPublicId != nil {
				c.Redirect(http.StatusFound, "/")
				return
			}

			var nextPath string = "/"
			var scope string = c.Query("scope")
			var grantType string = c.Query("grant_type")
			var code string = c.Query("code")
			var clientId string = c.Query("client_id")
			var _nextPath string = c.Query("_")
			//var state string = c.Query("state")

			if scope == "" || grantType == "" || code == "" || clientId == "" {
				// Original response:
				// c.String(http.StatusMethodNotAllowed, "Missing required parameters")
				c.Redirect(http.StatusFound, "/signin")
				return
			}
			if _nextPath != "" {
				if _nextPath, err := url.QueryUnescape(_nextPath); err == nil {
					nextPath = _nextPath
				}
			}

			client := services.FindOrCreateClient("Jupiter")
			if client.Key == clientId && grantType == oauth.AuthorizationCode && scope == models.PublicScope {
				grantToken := services.FindSessionByToken(code, models.GrantToken)
				if grantToken.ID != 0 {
					session.Set("userPublicId", grantToken.User.PublicId)
					session.Save()
					services.InvalidateSession(grantToken)
					c.Redirect(http.StatusFound, nextPath)
					return
				}
			}

			c.Redirect(http.StatusFound, "/signin")
		})

		views.GET("/authorize", authorizeHandler)
		views.POST("/authorize", authorizeHandler)

		views.GET("/error", func(c *gin.Context) {
			errorReason := c.Query("response_type")

			c.HTML(http.StatusOK, "error", utils.H{
				"AssetsEndpoint": spaceCDN,
				"errorReason":    errorReason,
			})
		})

		views.POST("/token", func(c *gin.Context) {
			var grantType string = c.PostForm("grant_type")

			authorizationBasic := strings.Replace(c.Request.Header.Get("Authorization"), "Basic ", "", 1)
			client := oauth.ClientAuthentication(authorizationBasic)
			if client.ID == 0 {
				c.Header("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", c.Request.RequestURI))
				c.JSON(http.StatusUnauthorized, utils.H{
					"error": oauth.AccessDenied,
				})
				return
			}

			switch grantType {
			// Authorization Code Grant
			case oauth.AuthorizationCode:
				result, err := oauth.AccessTokenRequest(utils.H{
					"grant_type":   grantType,
					"code":         c.PostForm("code"),
					"redirect_uri": c.PostForm("redirect_uri"),
					"client":       client,
				})
				if err != nil {
					c.JSON(http.StatusMethodNotAllowed, utils.H{
						"error": result["error"],
					})
					return
				} else {
					c.JSON(http.StatusOK, utils.H{
						"user_id":       result["user_id"],
						"access_token":  result["access_token"],
						"token_type":    result["token_type"],
						"expires_in":    result["expires_in"],
						"refresh_token": result["refresh_token"],
						"scope":         result["scope"],
					})
					return
				}
				return
			// Refreshing an Access Token
			case oauth.RefreshToken:
				result, err := oauth.RefreshTokenRequest(utils.H{
					"grant_type":    grantType,
					"refresh_token": c.PostForm("refresh_token"),
					"scope":         c.PostForm("scope"),
					"client":        client,
				})
				if err != nil {
					c.JSON(http.StatusMethodNotAllowed, utils.H{
						"error": result["error"],
					})
					return
				} else {
					c.JSON(http.StatusOK, utils.H{
						"user_id":       result["user_id"],
						"access_token":  result["access_token"],
						"token_type":    result["token_type"],
						"expires_in":    result["expires_in"],
						"refresh_token": result["refresh_token"],
						"scope":         result["scope"],
					})
					return
				}
				return
			// Resource Owner Password Credentials Grant
			// Client Credentials Grant
			case oauth.Password, oauth.ClientCredentials:
				c.JSON(http.StatusMethodNotAllowed, utils.H{
					"error": oauth.UnsupportedGrantType,
				})
				return
			default:
				c.JSON(http.StatusBadRequest, utils.H{
					"error": oauth.InvalidRequest,
				})
				return
			}
		})
	}
}
Beispiel #23
0
func Register(r *gin.Engine) {

	r.Use(func(c *gin.Context) {
		// Run this on all requests
		// Should be moved to a proper middleware
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type,Token")
		c.Next()
	})
	r.GET("/", func(c *gin.Context) {
		c.String(200, "Y'all ready for this? \n\nOh no! They were ready for that.")
		//c.JSON(200, gin.H{"Pong": "Ping"})
	})

	//Auth
	authHandler := new(handlers.CCAuthHandler)
	r.POST("/auth/login", authHandler.BasicAuth)

	//Middleware
	// r.Use(authHandler.TokenAuthMiddleware())
	// User routes
	userApi := new(api.CCUser)
	r.GET("/user", userApi.Get)
	r.POST("/user", userApi.Post)
	r.DELETE("/user", userApi.Delete)

	// Program routes
	programApi := new(api.CCProgram)
	r.GET("/program", programApi.Get)
	r.POST("/program", programApi.Post)
	r.DELETE("/program", programApi.Delete)

	// Event routes
	eventApi := new(api.CCEvent)
	r.GET("/event", eventApi.Get)
	r.POST("/event", eventApi.Post)
	r.PUT("/event/edit", eventApi.Edit)
	r.DELETE("/event", eventApi.Delete)

	// Volunteer routes
	volunteerApi := new(api.CCVolunteer)
	r.GET("/event/volunteer", volunteerApi.Get)
	r.POST("/event/volunteer", volunteerApi.Post)
	r.PUT("/event/volunteer/log", volunteerApi.LogTime)
	r.DELETE("/event/volunteer", volunteerApi.Delete)

	// Moments routes
	momentApi := new(api.CCMoment)
	r.GET("/event/moment", momentApi.Get)
	r.DELETE("/event/moment", momentApi.Delete)
	r.POST("/event/moment", momentApi.Post)

	//Rating
	r.POST("/event/moment/rate", momentApi.Rate)

	//Credits
	r.GET("/event/moment/credit", momentApi.Credit)

	//Image Upload
	//Auth
	uploadHandler := new(handlers.CCUploadHandler)
	r.POST("/upload", uploadHandler.Upload)
}
Beispiel #24
0
func Router(r *gin.Engine) {

	r.Use(ValidCityMiddleware())

	r.GET("/temperature/:city", func(c *gin.Context) {
		city := c.Param("city")

		url := fmt.Sprintf("%s/weather?q=%s&units=imperial&appid=%s",
			apiBaseUrl, city, appId)

		GetOpenWeatherMapData(url, func(data gin.H, err error) {
			if err != nil {
				c.JSON(404, gin.H{
					"message": "Data Not Available",
				})
			} else {
				dataMap := objects.Map(data)
				data = gin.H{
					"temperature": gin.H{
						"units":   "Fahrenheit",
						"low":     dataMap.Get("main.temp_min"),
						"high":    dataMap.Get("main.temp_max"),
						"current": dataMap.Get("main.temp"),
					},
				}
				c.JSON(200, data)
			}
		})
	})

	r.GET("/wind/:city", func(c *gin.Context) {
		city := c.Param("city")

		url := fmt.Sprintf("%s/weather?q=%s&units=imperial&appid=%s",
			apiBaseUrl, city, appId)

		GetOpenWeatherMapData(url, func(data gin.H, err error) {
			if err != nil {
				c.JSON(404, gin.H{
					"message": "Data Not Available",
				})
			} else {
				dataMap := objects.Map(data)
				data = gin.H{
					"wind": gin.H{
						"speed": gin.H{
							"value": dataMap.Get("wind.speed"),
							"units": "mph",
						},
						"direction": gin.H{
							"value": dataMap.Get("wind.deg"),
							"units": "degrees",
						},
					},
				}
				c.JSON(200, data)
			}
		})
	})

}
Beispiel #25
0
// Application entry point
func main() {

	fmt.Printf("\n%s (%s) %s\n\n", APP_TITLE, APP_NAME, APP_VERSION)

	// Setup the logging infrastructure
	initialiseLogging()

	// Setup some default values
	opt = new(Options)
	opt.ConfigFile = "./" + APP_NAME + ".config"
	opt.CsvField = -1
	opt.CsvDelimiter = ","
	opt.RemoveQuotes = false
	opt.Format = FORMAT_ALL // Default to all output

	goptions.ParseAndFail(opt)

	// Increment the CSV field to make it easier for the user, since our arrays are 0 based
	if opt.CsvField > -1 {
		opt.CsvField -= 1
	}

	// Validate the mode value
	switch opt.Mode {
	case MODE_SERVER:
		// Load the applications configuration such as ports and IP
		config = loadConfig(opt.ConfigFile, true)
	case MODE_FILE:
		if len(opt.InputFile) == 0 {
			logger.Fatal("Input file path must be supplied when in file mode")
		}

		if len(opt.OutputFile) == 0 {
			logger.Fatal("Output file path must be supplied when in file mode")
		}

		// Load the applications configuration such as ports and IP
		config = loadConfig(opt.ConfigFile, false)
	default:
		logger.Fatal("Invalid mode value (m): %v", opt.Mode)
	}

	// Validate the format value
	switch opt.Format {
	case FORMAT_UNIDENTIFIED:
	case FORMAT_IDENTIFIED:
	case FORMAT_ALL:
	default:
		logger.Fatal("Invalid format value (f): %v", opt.Format)
	}

	// Lets make sure that the users input file actually exists
	if _, err := os.Stat(opt.DataFile); os.IsNotExist(err) {
		logger.Fatal("Data file does not exist")
	}

	processDataFile(opt.DataFile)

	// Start the web API interface if the user wants it running
	if opt.Mode == "s" {
		logger.Info("HTTP API server running: " + config.ApiIp + ":" + fmt.Sprintf("%d", config.ApiPort))
		go func() {
			var r *gin.Engine
			if config.ShowRequests == true {
				r = gin.Default()
			} else {
				gin.SetMode(gin.ReleaseMode)
				r = gin.New()

				r.Use(gin.Recovery())
			}

			r.GET("/single/:hash/", lookupSingleHash)
			r.POST("/bulk", lookupMultipleHashes)
			r.Run(config.ApiIp + ":" + fmt.Sprintf("%d", config.ApiPort))
		}()

		var wg sync.WaitGroup
		wg.Add(1)
		wg.Wait()
	} else {
		processInputFile()
	}
}