Skip to content

Commit

Permalink
adding messages
Browse files Browse the repository at this point in the history
  • Loading branch information
untoldone committed Feb 18, 2015
1 parent 4f37793 commit e45aa92
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 11 deletions.
28 changes: 28 additions & 0 deletions api/messages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package api

import (
"net/http"
"github.com/gorilla/context"
)

func AddMessage(r *http.Request, message string) {
rawMessages, ok := context.GetOk(r, "messages")

if ok {
messages := rawMessages.([]string)
messages = append(messages, message)
context.Set(r, "messages", messages)
} else {
context.Set(r, "messages", []string{ message })
}
}

func GetMessages(r *http.Request) []string {
rawMessages, ok := context.GetOk(r, "messages")

if ok {
return rawMessages.([]string)
} else {
return []string{}
}
}
13 changes: 13 additions & 0 deletions api/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ var defaultRenderer = render.New(render.Options{})

func Render(w http.ResponseWriter, req *http.Request, status int, v interface{}) {
vars := req.URL.Query()

messages := GetMessages(req)
if body, ok := v.(map[string]interface{}); ok && len(messages) > 0 {
if m, ok := body["meta"]; ok {
if meta, ok := m.(map[string]interface{}); ok {
meta["messages"] = messages
}
} else {
body["meta"] = map[string]interface{} {
"messages": messages,
}
}
}

if callback, ok := vars["callback"]; ok {
defaultRenderer.JSONP(w, status, callback[0], v)
Expand Down
15 changes: 9 additions & 6 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,28 @@ func Server() {
port := viper.GetString("bloomapiPort")
n := negroni.Classic()

// Middleware setup
// Pre-Router 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")

// 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")

n.UseHandler(router)

// Post-Router Middleware setup
n.Use(middleware.NewClearContext())

log.Println("Running Server")
n.Run(":" + port)
}
18 changes: 18 additions & 0 deletions handler/item_handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package handler

import (
"regexp"
"net/http"
"encoding/json"
"strings"
Expand All @@ -11,13 +12,30 @@ import (
"github.com/untoldone/bloomapi/api"
)

var validElasticSearchRegexp = regexp.MustCompile(`\A[a-zA-Z0-9\-\_\:\.]+\z`)

func ItemHandler (w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
source := strings.ToLower(vars["source"])
id := vars["id"]

conn := api.Conn().SearchConnection()

if !validElasticSearchRegexp.MatchString(source) {
api.Render(w, req, http.StatusNotFound, "item not found")
return
}

if !validElasticSearchRegexp.MatchString(id) {
api.Render(w, req, http.StatusNotFound, "item not found")
return
}

if source != "usgov.hhs.npi" {
api.AddMessage(req, "Warning: Use the dataset, '" + source + "', without an API key is for development-use only. Use of this API without a key may be rate-limited in the future. For hosted, production access, please email '[email protected]' for an API key.")
api.AddMessage(req, "Warning: The dataset, '" + source + "', is currently in beta and is subject to change. If you'd like to be notified before changes to this dataset, email '[email protected]' and ask for an API key referencing this message.")
}

result, err := conn.Get("source", source, id, nil)
if err != nil && err.Error() == elastigo.RecordNotFound.Error() {
api.Render(w, req, http.StatusNotFound, "item not found")
Expand Down
19 changes: 16 additions & 3 deletions handler/search_helper.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package handler

import (
"fmt"
"encoding/json"
"regexp"
"net/http"
"github.com/mattbaird/elastigo/lib"

"github.com/untoldone/bloomapi/api"
)

var esTypeExceptionRegex = regexp.MustCompile(`FormatException`)

func phraseMatches (paramSets []*SearchParamSet) []interface{} {
var experimentalOperationMessage = "Warning: The operation, '%s', is currently in beta and is subject to change. If you'd like to be notified before changes to this functionality, email '[email protected]' and ask for an API key referencing this message."

func phraseMatches (paramSets []*SearchParamSet, r *http.Request) []interface{} {
elasticPhrases := make([]interface{}, len(paramSets))
for index, set := range paramSets {
shouldValues := make([]map[string]interface{}, len(set.Values))
Expand All @@ -23,12 +27,14 @@ func phraseMatches (paramSets []*SearchParamSet) []interface{} {
},
}
case "fuzzy":
api.AddMessage(r, fmt.Sprintf(experimentalOperationMessage, "fuzzy"))
shouldValues[vIndex] = map[string]interface{} {
"fuzzy": map[string]interface{} {
set.Key: value,
},
}
case "prefix":
api.AddMessage(r, fmt.Sprintf(experimentalOperationMessage, "prefix"))
shouldValues[vIndex] = map[string]interface{} {
"prefix": map[string]interface{} {
set.Key: value,
Expand Down Expand Up @@ -79,15 +85,22 @@ func phraseMatches (paramSets []*SearchParamSet) []interface{} {
return elasticPhrases
}

func Search(sourceType string, params *SearchParams) (map[string]interface{}, error) {
func Search(sourceType string, params *SearchParams, r *http.Request) (map[string]interface{}, error) {
conn := api.Conn().SearchConnection()

if sourceType != "usgov.hhs.npi" {
api.AddMessage(r, "Warning: Use the dataset, '" + sourceType + "', without an API key is for development-use only. Use of this API without a key may be rate-limited in the future. For hosted, production access, please email '[email protected]' for an API key.")
api.AddMessage(r, "Warning: The dataset, '" + sourceType + "', is currently in beta and is subject to change. If you'd like to be notified before changes to this dataset, email '[email protected]' and ask for an API key referencing this message.")
}

matches := phraseMatches(params.paramSets, r)

query := map[string]interface{} {
"from": params.Offset,
"size": params.Limit,
"query": map[string]interface{} {
"bool": map[string]interface{} {
"must": phraseMatches(params.paramSets),
"must": matches,
},
},
}
Expand Down
12 changes: 11 additions & 1 deletion handler/search_source_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,23 @@ func SearchSourceHandler (w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
source := strings.ToLower(vars["source"])

if !validElasticSearchRegexp.MatchString(source) {
api.Render(w, req, http.StatusOK, map[string]interface{}{
"meta": map[string]interface{}{
"rowCount": 0,
},
"result": []string{},
})
return
}

params, err := ParseSearchParams(req.URL.Query())
if err != nil {
api.Render(w, req, http.StatusBadRequest, err)
return
}

results, err := Search(source, params)
results, err := Search(source, params, req)
if err != nil {
log.Println(err)
api.Render(w, req, http.StatusInternalServerError, "Internal Server Error")
Expand Down
2 changes: 1 addition & 1 deletion handler_compat/npi_search_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func NpiSearchHandler (w http.ResponseWriter, req *http.Request) {
return
}

results, err := handler.Search("usgov.hhs.npi", params)
results, err := handler.Search("usgov.hhs.npi", params, req)
if err != nil {
switch err.(type) {
case api.ParamsError:
Expand Down
17 changes: 17 additions & 0 deletions middleware/clear_context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package middleware

import (
"net/http"
"github.com/gorilla/context"
)

type ClearContext struct {}

func NewClearContext() *ClearContext {
return &ClearContext{}
}

func (s *ClearContext) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
context.Clear(r)
next(rw, r)
}

0 comments on commit e45aa92

Please sign in to comment.