diff --git a/api/conn.go b/api/conn.go new file mode 100644 index 0000000..767310f --- /dev/null +++ b/api/conn.go @@ -0,0 +1,15 @@ +package api + +import ( + "github.com/gocodo/bloomdb" +) + +var bloomConn *bloomdb.BloomDatabase + +func Conn() *bloomdb.BloomDatabase { + if bloomConn == nil { + bloomConn = bloomdb.CreateDB() + } + + return bloomConn +} \ No newline at end of file diff --git a/lib/params_error.go b/api/params_error.go similarity index 53% rename from lib/params_error.go rename to api/params_error.go index cb28bbe..74ff2ed 100644 --- a/lib/params_error.go +++ b/api/params_error.go @@ -1,17 +1,17 @@ -package bloomapi +package api -type paramsError struct { +type ParamsError struct { Name string `json:"name"` Message string `json:"message"` Params map[string]string `json:"parameters"` } -func (e paramsError) Error() string { +func (e ParamsError) Error() string { return e.Message } -func NewParamsError(message string, params map[string]string) paramsError { - return paramsError{ +func NewParamsError(message string, params map[string]string) ParamsError { + return ParamsError{ "ParameterError", message, params, diff --git a/lib/render.go b/api/render.go similarity index 72% rename from lib/render.go rename to api/render.go index 104c301..f7863e1 100644 --- a/lib/render.go +++ b/api/render.go @@ -1,4 +1,4 @@ -package bloomapi +package api import ( "net/http" @@ -7,7 +7,7 @@ import ( var defaultRenderer = render.New(render.Options{}) -func renderJSON(w http.ResponseWriter, req *http.Request, status int, v interface{}) { +func Render(w http.ResponseWriter, req *http.Request, status int, v interface{}) { vars := req.URL.Query() if callback, ok := vars["callback"]; ok { diff --git a/bloomapi.go b/bloomapi.go index 1ecfd20..b9d2df5 100644 --- a/bloomapi.go +++ b/bloomapi.go @@ -4,7 +4,7 @@ import ( "os" "fmt" "github.com/spf13/viper" - "github.com/untoldone/bloomapi/lib" + "github.com/untoldone/bloomapi/cmd" ) func showUsage() { @@ -35,11 +35,11 @@ func main() { switch arg { case "server": - bloomapi.Server() + cmd.Server() case "bootstrap": - bloomapi.Bootstrap() + cmd.Bootstrap() case "drop": - bloomapi.Drop() + cmd.Drop() default: fmt.Println("Invalid command:", arg) showUsage() diff --git a/bootstrap.sql b/cmd/bootstrap.go similarity index 67% rename from bootstrap.sql rename to cmd/bootstrap.go index 985c319..b04ed83 100644 --- a/bootstrap.sql +++ b/cmd/bootstrap.go @@ -1,4 +1,27 @@ -CREATE TABLE sources +package cmd + +import ( + "log" + "github.com/gocodo/bloomdb" +) + +func Bootstrap() { + bdb := bloomdb.CreateDB() + + conn, err := bdb.SqlConnection() + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + _, err = conn.Exec(bootstrapSql) + if err != nil { + log.Fatal(err) + } +} + +var bootstrapSql = +`CREATE TABLE sources ( id uuid, name character varying(255), @@ -31,4 +54,4 @@ CREATE TABLE search_types last_updated timestamp, last_checked timestamp, CONSTRAINT search_types_id_key UNIQUE (id) -); \ No newline at end of file +);` \ No newline at end of file diff --git a/lib/drop.go b/cmd/drop.go similarity index 60% rename from lib/drop.go rename to cmd/drop.go index 65a6821..e895b18 100644 --- a/lib/drop.go +++ b/cmd/drop.go @@ -1,28 +1,27 @@ -package bloomapi +package cmd import ( "log" - "io/ioutil" "github.com/gocodo/bloomdb" ) func Drop() { bloomdb := bloomdb.CreateDB() - file, err := ioutil.ReadFile("drop.sql") - if err != nil { - log.Fatal("Failed to read file.", err) - } - - metaSql := string(file[:]) conn, err := bloomdb.SqlConnection() if err != nil { log.Fatal("Failed to get database connection.", err) } defer conn.Close() - _, err = conn.Exec(metaSql) + _, err = conn.Exec(dropSql) if err != nil { log.Fatal("Failed to create metadata tables.", err) } -} \ No newline at end of file +} + +var dropSql = +`DROP TABLE IF EXISTS sources; +DROP TABLE IF EXISTS source_tables; +DROP TABLE IF EXISTS source_versions; +DROP TABLE IF EXISTS search_types;` \ No newline at end of file diff --git a/cmd/server.go b/cmd/server.go new file mode 100644 index 0000000..9f2a2df --- /dev/null +++ b/cmd/server.go @@ -0,0 +1,39 @@ +package cmd + +import ( + "log" + "github.com/codegangsta/negroni" + "github.com/spf13/viper" + "github.com/gorilla/mux" + + "github.com/untoldone/bloomapi/middleware" + "github.com/untoldone/bloomapi/handler" + "github.com/untoldone/bloomapi/handler_compat" +) + +func Server() { + port := viper.GetString("bloomapiPort") + n := negroni.Classic() + + // Middleware setup + n.Use(middleware.NewAuthentication()) + + // Router setup + router := mux.NewRouter() + + // Current API + router.HandleFunc("/api/sources", handler.SourcesHandler).Methods("GET") + router.HandleFunc("/api/search/{source}", handler.SearchSourceHandler).Methods("GET") + router.HandleFunc("/api/sources/{source}/{id}", handler.ItemHandler).Methods("GET") + + // For Backwards Compatibility Feb 13, 2015 + router.HandleFunc("/api/search", handler_compat.NpiSearchHandler).Methods("GET") + router.HandleFunc("/api/search/npi", handler_compat.NpiSearchHandler).Methods("GET") + router.HandleFunc("/api/npis/{npi:[0-9]+}", handler_compat.NpiItemHandler).Methods("GET") + router.HandleFunc("/api/sources/npi/{npi:[0-9]+}", handler_compat.NpiItemHandler).Methods("GET") + + n.UseHandler(router) + + log.Println("Running Server") + n.Run(":" + port) +} \ No newline at end of file diff --git a/drop.sql b/drop.sql deleted file mode 100644 index 4f0f6f2..0000000 --- a/drop.sql +++ /dev/null @@ -1,4 +0,0 @@ -DROP TABLE IF EXISTS sources; -DROP TABLE IF EXISTS source_tables; -DROP TABLE IF EXISTS source_versions; -DROP TABLE IF EXISTS search_types; \ No newline at end of file diff --git a/lib/item_handler.go b/handler/item_handler.go similarity index 66% rename from lib/item_handler.go rename to handler/item_handler.go index 8966be0..7a61d2c 100644 --- a/lib/item_handler.go +++ b/handler/item_handler.go @@ -1,4 +1,4 @@ -package bloomapi +package handler import ( "net/http" @@ -7,6 +7,8 @@ import ( "github.com/gorilla/mux" "github.com/mattbaird/elastigo/lib" "log" + + "github.com/untoldone/bloomapi/api" ) func ItemHandler (w http.ResponseWriter, req *http.Request) { @@ -14,16 +16,15 @@ func ItemHandler (w http.ResponseWriter, req *http.Request) { source := strings.ToLower(vars["source"]) id := vars["id"] - conn := bdb.SearchConnection() + conn := api.Conn().SearchConnection() result, err := conn.Get("source", source, id, nil) - log.Println(err, elastigo.RecordNotFound) if err != nil && err.Error() == elastigo.RecordNotFound.Error() { - renderJSON(w, req, http.StatusNotFound, "item not found") + api.Render(w, req, http.StatusNotFound, "item not found") return } else if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } @@ -31,13 +32,12 @@ func ItemHandler (w http.ResponseWriter, req *http.Request) { err = json.Unmarshal(*result.Source, &found) if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } body := map[string]interface{} { "result": found } - keysToStrings(body) - renderJSON(w, req, http.StatusOK, body) + api.Render(w, req, http.StatusOK, body) return } \ No newline at end of file diff --git a/lib/params.go b/handler/parse_search_params.go similarity index 66% rename from lib/params.go rename to handler/parse_search_params.go index 0fa4cff..0526771 100644 --- a/lib/params.go +++ b/handler/parse_search_params.go @@ -1,32 +1,34 @@ -package bloomapi +package handler import ( "regexp" "strings" "strconv" + + "github.com/untoldone/bloomapi/api" ) -type searchParams struct { +type SearchParams struct { Offset uint64 Limit uint64 - paramSets []*paramSet + paramSets []*SearchParamSet } -type paramSet struct { +type SearchParamSet struct { Key string Op string Values []string } -func (p *paramSet) SetKey(key string) { +func (p *SearchParamSet) SetKey(key string) { p.Key = key } -func (p *paramSet) SetOp(op string) { +func (p *SearchParamSet) SetOp(op string) { p.Op = op } -func (p *paramSet) SetValues(values []string) { +func (p *SearchParamSet) SetValues(values []string) { p.Values = values } @@ -34,7 +36,7 @@ var keyRegexp = regexp.MustCompile("\\Akey(\\d+)\\z") var valueRegexp = regexp.MustCompile("\\Avalue(\\d+)\\z") var opRegexp = regexp.MustCompile("\\Aop(\\d+)\\z") -func parseParams (params map[string][]string) (*searchParams, error) { +func ParseSearchParams(params map[string][]string) (*SearchParams, error) { // Ensure no unknown parameters unknown := make([]string, 0) for key, _ := range params { @@ -56,18 +58,18 @@ func parseParams (params map[string][]string) (*searchParams, error) { paramsMap[key] = "is an unknown parameter" } - return nil, NewParamsError(message, paramsMap) + return nil, api.NewParamsError(message, paramsMap) } // Ensure params in sets of key/op/value - paramSets := map[string]*paramSet{} + paramSets := map[string]*SearchParamSet{} for key, values := range params { if keyRegexp.MatchString(key) { sub := keyRegexp.FindStringSubmatch(key) index := sub[1] _, ok := paramSets[index] if !ok { - paramSets[index] = ¶mSet{} + paramSets[index] = &SearchParamSet{} } paramSets[index].SetKey(values[0]) @@ -78,7 +80,7 @@ func parseParams (params map[string][]string) (*searchParams, error) { index := sub[1] _, ok := paramSets[index] if !ok { - paramSets[index] = ¶mSet{} + paramSets[index] = &SearchParamSet{} } paramSets[index].SetValues(values) @@ -89,7 +91,7 @@ func parseParams (params map[string][]string) (*searchParams, error) { index := sub[1] _, ok := paramSets[index] if !ok { - paramSets[index] = ¶mSet{} + paramSets[index] = &SearchParamSet{} } paramSets[index].SetOp(values[0]) @@ -98,11 +100,11 @@ func parseParams (params map[string][]string) (*searchParams, error) { for _, set := range paramSets { if set.Key == "" { - return nil, NewParamsError("one or more key/op/value sets are missing a key", map[string]string{}) + return nil, api.NewParamsError("one or more key/op/value sets are missing a key", map[string]string{}) } if set.Values == nil || len(set.Values) == 0 { - return nil, NewParamsError("one or more key/op/value sets are missing a value", map[string]string{}) + return nil, api.NewParamsError("one or more key/op/value sets are missing a value", map[string]string{}) } hasValue := false @@ -114,11 +116,11 @@ func parseParams (params map[string][]string) (*searchParams, error) { } if !hasValue { - return nil, NewParamsError("one or more key/op/value sets are missing a value", map[string]string{}) + return nil, api.NewParamsError("one or more key/op/value sets are missing a value", map[string]string{}) } if set.Op == "" { - return nil, NewParamsError("one or more key/op/value sets are missing a op", map[string]string{}) + return nil, api.NewParamsError("one or more key/op/value sets are missing a op", map[string]string{}) } if set.Op != "eq" && @@ -128,7 +130,7 @@ func parseParams (params map[string][]string) (*searchParams, error) { set.Op != "gt" && set.Op != "lte" && set.Op != "lt" { - return nil, NewParamsError("invalid operation " + set.Op, map[string]string{}) + return nil, api.NewParamsError("invalid operation " + set.Op, map[string]string{}) } } @@ -138,7 +140,7 @@ func parseParams (params map[string][]string) (*searchParams, error) { if offset, ok := params["offset"]; ok { offsetValue, err = strconv.ParseUint(offset[0], 0, 64) if err != nil { - return nil, NewParamsError("offset must be a positive number", + return nil, api.NewParamsError("offset must be a positive number", map[string]string{"offset": "must be a positive number"}) } } @@ -147,13 +149,13 @@ func parseParams (params map[string][]string) (*searchParams, error) { if limit, ok := params["limit"]; ok { limitValue, err = strconv.ParseUint(limit[0], 0, 64) if err != nil { - return nil, NewParamsError("limit must be a positive number", + return nil, api.NewParamsError("limit must be a positive number", map[string]string{"limit": "must be a positive number"}) } // Ensure limit is less than 100 if limitValue > 100 { - return nil, NewParamsError("limit must be less than 100", + return nil, api.NewParamsError("limit must be less than 100", map[string]string{"limit": "must less than 100"}) } } @@ -162,14 +164,14 @@ func parseParams (params map[string][]string) (*searchParams, error) { limitValue = 100 } - listSets := make([]*paramSet, len(paramSets)) + listSets := make([]*SearchParamSet, len(paramSets)) i := 0 for _, v := range paramSets { listSets[i] = v i += 1 } - return &searchParams{ + return &SearchParams{ offsetValue, limitValue, listSets, diff --git a/lib/search_helper.go b/handler/search_helper.go similarity index 88% rename from lib/search_helper.go rename to handler/search_helper.go index 63310bc..3dd6f8b 100644 --- a/lib/search_helper.go +++ b/handler/search_helper.go @@ -1,14 +1,16 @@ -package bloomapi +package handler import ( "encoding/json" "regexp" "github.com/mattbaird/elastigo/lib" + + "github.com/untoldone/bloomapi/api" ) var esTypeExceptionRegex = regexp.MustCompile(`FormatException`) -func phraseMatches (paramSets []*paramSet) []interface{} { +func phraseMatches (paramSets []*SearchParamSet) []interface{} { elasticPhrases := make([]interface{}, len(paramSets)) for index, set := range paramSets { shouldValues := make([]map[string]interface{}, len(set.Values)) @@ -77,8 +79,8 @@ func phraseMatches (paramSets []*paramSet) []interface{} { return elasticPhrases } -func search(sourceType string, params *searchParams) (map[string]interface{}, error) { - conn := bdb.SearchConnection() +func Search(sourceType string, params *SearchParams) (map[string]interface{}, error) { + conn := api.Conn().SearchConnection() query := map[string]interface{} { "from": params.Offset, @@ -95,7 +97,7 @@ func search(sourceType string, params *searchParams) (map[string]interface{}, er switch terr := err.(type) { case elastigo.ESError: if esTypeExceptionRegex.MatchString(terr.What) { - return nil, NewParamsError("one or more values were of an unexpected type", map[string]string{}) + return nil, api.NewParamsError("one or more values were of an unexpected type", map[string]string{}) } else { return nil, err } @@ -118,7 +120,5 @@ func search(sourceType string, params *searchParams) (map[string]interface{}, er "result": hits, } - keysToStrings(cleanedResult) - return cleanedResult, nil; } \ No newline at end of file diff --git a/lib/search_source_handler.go b/handler/search_source_handler.go similarity index 50% rename from lib/search_source_handler.go rename to handler/search_source_handler.go index bcc8afa..1063295 100644 --- a/lib/search_source_handler.go +++ b/handler/search_source_handler.go @@ -1,29 +1,31 @@ -package bloomapi +package handler import ( "net/http" "github.com/gorilla/mux" "strings" "log" + + "github.com/untoldone/bloomapi/api" ) func SearchSourceHandler (w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) source := strings.ToLower(vars["source"]) - params, err := parseParams(req.URL.Query()) + params, err := ParseSearchParams(req.URL.Query()) if err != nil { - renderJSON(w, req, http.StatusBadRequest, err) + api.Render(w, req, http.StatusBadRequest, err) return } - results, err := search(source, params) + results, err := Search(source, params) if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } - renderJSON(w, req, http.StatusOK, results) + api.Render(w, req, http.StatusOK, results) return } \ No newline at end of file diff --git a/lib/sources_handler.go b/handler/sources_handler.go similarity index 75% rename from lib/sources_handler.go rename to handler/sources_handler.go index dd59baa..f248c34 100644 --- a/lib/sources_handler.go +++ b/handler/sources_handler.go @@ -1,9 +1,11 @@ -package bloomapi +package handler import ( "net/http" "time" "log" + + "github.com/untoldone/bloomapi/api" ) type dataSource struct { @@ -15,17 +17,17 @@ type dataSource struct { func SourcesHandler (w http.ResponseWriter, req *http.Request) { - conn, err := bdb.SqlConnection() + conn, err := api.Conn().SqlConnection() if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } rows, err := conn.Query("SELECT name, last_updated, last_checked FROM search_types") if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } defer rows.Close() @@ -42,7 +44,7 @@ func SourcesHandler (w http.ResponseWriter, req *http.Request) { err := rows.Scan(&source, &update, &checked) if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } @@ -58,5 +60,5 @@ func SourcesHandler (w http.ResponseWriter, req *http.Request) { // Backcompat Feb 13, 2015 sources = append(sources, dataSource{"NPI", npiUpdated, npiChecked, "READY"}) - renderJSON(w, req, http.StatusOK, map[string][]dataSource{"result": sources}) + api.Render(w, req, http.StatusOK, map[string][]dataSource{"result": sources}) } \ No newline at end of file diff --git a/handler_compat/keys_to_string.go b/handler_compat/keys_to_string.go new file mode 100644 index 0000000..309ed0f --- /dev/null +++ b/handler_compat/keys_to_string.go @@ -0,0 +1,23 @@ +package handler_compat + +import "strconv" + +// Helper to turn all non-string values into strings. +// This is to ensure API backwards compatibility for clients +// that expect all values to be strings +func valuesToStrings(toConvert map[string]interface{}) { + for k, v := range toConvert { + switch v.(type) { + case int: + toConvert[k] = strconv.Itoa(v.(int)) + case float64: + toConvert[k] = strconv.FormatFloat(v.(float64), 'f', -1, 64) + case map[string]interface{}: + valuesToStrings(v.(map[string]interface{})) + case []interface{}: + for _, elm := range v.([]interface{}) { + valuesToStrings(elm.(map[string]interface{})) + } + } + } +} \ No newline at end of file diff --git a/lib/npi_handler.go b/handler_compat/npi_item_handler.go similarity index 69% rename from lib/npi_handler.go rename to handler_compat/npi_item_handler.go index 31fb706..cb2024c 100644 --- a/lib/npi_handler.go +++ b/handler_compat/npi_item_handler.go @@ -1,17 +1,19 @@ -package bloomapi +package handler_compat import ( "net/http" "encoding/json" "github.com/gorilla/mux" "log" + + "github.com/untoldone/bloomapi/api" ) -func NpiHandler (w http.ResponseWriter, req *http.Request) { +func NpiItemHandler (w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) npi := vars["npi"] - conn := bdb.SearchConnection() + conn := api.Conn().SearchConnection() result, err := conn.Search("source", "usgov.hhs.npi", nil, map[string]interface{} { "query": map[string]interface{} { @@ -26,12 +28,12 @@ func NpiHandler (w http.ResponseWriter, req *http.Request) { }) if err != nil { log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") return } if result.Hits.Total == 0 { - renderJSON(w, req, http.StatusNotFound, "npi not found") + api.Render(w, req, http.StatusNotFound, "npi not found") return } else { hits := make([]interface{}, len(result.Hits.Hits)) @@ -42,9 +44,9 @@ func NpiHandler (w http.ResponseWriter, req *http.Request) { } body := map[string]interface{} {"result": hits[0]} - keysToStrings(body) + valuesToStrings(body) - renderJSON(w, req, http.StatusOK, body) + api.Render(w, req, http.StatusOK, body) return } } \ No newline at end of file diff --git a/handler_compat/npi_search_handler.go b/handler_compat/npi_search_handler.go new file mode 100644 index 0000000..164f6a8 --- /dev/null +++ b/handler_compat/npi_search_handler.go @@ -0,0 +1,35 @@ +package handler_compat + +import ( + "net/http" + "log" + + "github.com/untoldone/bloomapi/api" + "github.com/untoldone/bloomapi/handler" +) + +func NpiSearchHandler (w http.ResponseWriter, req *http.Request) { + params, err := handler.ParseSearchParams(req.URL.Query()) + if err != nil { + api.Render(w, req, http.StatusBadRequest, err) + return + } + + results, err := handler.Search("usgov.hhs.npi", params) + if err != nil { + switch err.(type) { + case api.ParamsError: + api.Render(w, req, http.StatusBadRequest, err) + return + default: + log.Println(err) + api.Render(w, req, http.StatusInternalServerError, "Internal Server Error") + return + } + } + + valuesToStrings(results) + + api.Render(w, req, http.StatusOK, results) + return +} \ No newline at end of file diff --git a/lib/bloomapi.go b/lib/bloomapi.go deleted file mode 100644 index 4384681..0000000 --- a/lib/bloomapi.go +++ /dev/null @@ -1,58 +0,0 @@ -package bloomapi - -import ( - "fmt" - "net/http" - "github.com/gorilla/mux" - "github.com/codegangsta/negroni" - "github.com/gorilla/context" - "github.com/spf13/viper" - "github.com/gocodo/bloomdb" -) - -var bdb *bloomdb.BloomDatabase - -func Server() { - fmt.Println("Running Server") - - bdb = bloomdb.CreateDB() - router := mux.NewRouter() - - // For Backwards Compatibility Feb 13, 2015 - router.HandleFunc("/api/search", SearchHandler).Methods("GET") - router.HandleFunc("/api/search/npi", SearchHandler).Methods("GET") - router.HandleFunc("/api/npis/{npi:[0-9]+}", NpiHandler).Methods("GET") - router.HandleFunc("/api/sources/npi/{npi:[0-9]+}", NpiHandler).Methods("GET") - - router.HandleFunc("/api/sources", SourcesHandler).Methods("GET") - router.HandleFunc("/api/search/{source}", SearchSourceHandler).Methods("GET") - router.HandleFunc("/api/sources/{source}/{id}", ItemHandler).Methods("GET") - - /*runtime.SetBlockProfileRate(1) - dr := router.PathPrefix("/debug/pprof").Subrouter() - dr.HandleFunc("/", pprof.Index) - dr.HandleFunc("/cmdline", pprof.Cmdline) - dr.HandleFunc("/profile", pprof.Profile) - dr.HandleFunc("/symbol", pprof.Symbol) - dr.HandleFunc("/block", pprof.Handler("block").ServeHTTP) - dr.HandleFunc("/heap", pprof.Handler("heap").ServeHTTP) - dr.HandleFunc("/goroutine", pprof.Handler("goroutine").ServeHTTP) - dr.HandleFunc("/threadcreate", pprof.Handler("threadcreate").ServeHTTP)*/ - - n := negroni.Classic() - n.Use(negroni.HandlerFunc(func (rw http.ResponseWriter, req *http.Request, next http.HandlerFunc) { - vars := req.URL.Query() - secret := vars["secret"] - - if len(secret) > 0 && secret[0] != "" { - renderJSON(rw, req, 401, map[string]string{ - "name": "Unauthorized", - "message": "Please contact support@bloomapi.com if this is in error", - }) - } else { - next(rw, req) - } - })) - n.UseHandler(context.ClearHandler(router)) - n.Run(":" + viper.GetString("bloomapiPort")) -} diff --git a/lib/bootstrap.go b/lib/bootstrap.go deleted file mode 100644 index 3ef2b73..0000000 --- a/lib/bootstrap.go +++ /dev/null @@ -1,29 +0,0 @@ -package bloomapi - -import ( - "io/ioutil" - "log" - "github.com/gocodo/bloomdb" -) - -func Bootstrap() { - bdb := bloomdb.CreateDB() - - conn, err := bdb.SqlConnection() - if err != nil { - log.Fatal(err) - } - defer conn.Close() - - file, err := ioutil.ReadFile("bootstrap.sql") - if err != nil { - log.Fatal(err) - } - - query := string(file[:]) - - _, err = conn.Exec(query) - if err != nil { - log.Fatal(err) - } -} \ No newline at end of file diff --git a/lib/keys_to_string.go b/lib/keys_to_string.go deleted file mode 100644 index ded539b..0000000 --- a/lib/keys_to_string.go +++ /dev/null @@ -1,20 +0,0 @@ -package bloomapi - -import "strconv" - -func keysToStrings(toConvert map[string]interface{}) { - for k, v := range toConvert { - switch v.(type) { - case int: - toConvert[k] = strconv.Itoa(v.(int)) - case float64: - toConvert[k] = strconv.FormatFloat(v.(float64), 'f', -1, 64) - case map[string]interface{}: - keysToStrings(v.(map[string]interface{})) - case []interface{}: - for _, elm := range v.([]interface{}) { - keysToStrings(elm.(map[string]interface{})) - } - } - } -} \ No newline at end of file diff --git a/lib/search_handler.go b/lib/search_handler.go deleted file mode 100644 index 5e163b5..0000000 --- a/lib/search_handler.go +++ /dev/null @@ -1,30 +0,0 @@ -package bloomapi - -import ( - "net/http" - "log" -) - -func SearchHandler (w http.ResponseWriter, req *http.Request) { - params, err := parseParams(req.URL.Query()) - if err != nil { - renderJSON(w, req, http.StatusBadRequest, err) - return - } - - results, err := search("usgov.hhs.npi", params) - if err != nil { - switch err.(type) { - case paramsError: - renderJSON(w, req, http.StatusBadRequest, err) - return - default: - log.Println(err) - renderJSON(w, req, http.StatusInternalServerError, "Internal Server Error") - return - } - } - - renderJSON(w, req, http.StatusOK, results) - return -} \ No newline at end of file diff --git a/middleware/authentication.go b/middleware/authentication.go new file mode 100644 index 0000000..996b953 --- /dev/null +++ b/middleware/authentication.go @@ -0,0 +1,27 @@ +package middleware + +import ( + "net/http" + + "github.com/untoldone/bloomapi/api" +) + +type Authentication struct {} + +func NewAuthentication() *Authentication { + return &Authentication{} +} + +func (s *Authentication) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + vars := r.URL.Query() + secret := vars["secret"] + + if len(secret) > 0 && secret[0] != "" { + api.Render(rw, r, 401, map[string]string{ + "name": "Unauthorized", + "message": "Please contact support@bloomapi.com if this is in error", + }) + } else { + next(rw, r) + } +} \ No newline at end of file