aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dict2rest/dict.go93
-rw-r--r--src/dict2rest/handlers.go103
-rw-r--r--src/dict2rest/logger.go4
-rw-r--r--src/dict2rest/main.go50
4 files changed, 154 insertions, 96 deletions
diff --git a/src/dict2rest/dict.go b/src/dict2rest/dict.go
index d3ae1e5..fa9690e 100644
--- a/src/dict2rest/dict.go
+++ b/src/dict2rest/dict.go
@@ -1,13 +1,8 @@
package main
import (
- "encoding/json"
- "github.com/julienschmidt/httprouter"
"golang.org/x/net/dict"
"log"
- "net/http"
- "strconv"
- "strings"
)
type definition struct {
@@ -20,85 +15,33 @@ type dictionary struct {
Desc string `json:"description"`
}
-type jsonError struct {
- Code int `json:"code"`
- Message string `json:"message"`
-}
-
-func Render(w http.ResponseWriter, status int, body interface{}) {
- w.WriteHeader(status)
- w.Header().Set("Content-Type", "application/json; charset=UTF-8")
- json.NewEncoder(w).Encode(body)
-}
-
-func FormatError(e error) jsonError {
- parts := strings.SplitN(e.Error(), "[", 2)
- log.Printf("Error %s", parts[0])
- parts = strings.SplitN(parts[0], " ", 2)
- code, err := strconv.Atoi(parts[0])
+func getDictClient() (*dict.Client, error) {
+ client, err := dict.Dial("tcp", dictServer)
if err != nil {
- return jsonError{
- Code: 500,
- Message: "Error parsing error o_0",
- }
- }
- return jsonError{
- Code: code,
- Message: strings.TrimSpace(parts[1]),
+ log.Printf("Unable to connect to dict server at %s", dictServer)
+ return nil, err
}
+ log.Println("Connected to", dictServer)
+ return client, nil
}
-func FormatDefinitions(defs []*dict.Defn) ([]definition, error) {
- definitions := make([]definition, len(defs))
- for i, def := range defs {
- definitions[i] = definition{
- Dictionary: def.Dict.Desc,
- Word: def.Word,
- Definition: string(def.Text[:]),
- }
- }
- return definitions, nil
-}
-
-func Databases(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
- var dicts []dictionary
- for _, d := range dictMap {
- dicts = append(dicts, dictionary{d.Name, d.Desc})
- }
- if len(dicts) == 0 {
- Render(w, 200, jsonError{554, "No databases present"})
- return
+func getDictionaries(*dict.Client) ([]dictionary, error) {
+ client, err := getDictClient()
+ if err != nil {
+ log.Printf("Unable to connect to dict server at %s", dictServer)
+ return nil, err
}
- Render(w, 200, dicts)
-}
-
-func Define(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
- word := ps.ByName("word")
- queryValues := r.URL.Query()
- d := queryValues.Get("dict")
- var dict string
+ defer client.Close()
- _, ok := dictMap[d]
- if d != "" && !ok {
- Render(w, 400, jsonError{500, "Invalid database"})
- return
- } else if d != "" && ok {
- dict = d
- } else {
- dict = "*"
- }
- defs, err := client.Define(dict, word)
+ dictArr, err := client.Dicts()
if err != nil {
- Render(w, 400, FormatError(err))
- return
+ return nil, err
}
- //log.Printf("DEFINE '%s' from '%s' found %d definitions", word, dict, len(defs))
- definitions, err := FormatDefinitions(defs)
- if err != nil {
- Render(w, 500, err)
- return
+ var dicts []dictionary
+ for _, d := range dictArr {
+ dicts = append(dicts, dictionary{d.Name, d.Desc})
}
- Render(w, 200, definitions)
+ return dicts, nil
}
diff --git a/src/dict2rest/handlers.go b/src/dict2rest/handlers.go
new file mode 100644
index 0000000..024a8d6
--- /dev/null
+++ b/src/dict2rest/handlers.go
@@ -0,0 +1,103 @@
+package main
+
+import (
+ "encoding/json"
+ "github.com/julienschmidt/httprouter"
+ "golang.org/x/net/dict"
+ "log"
+ "net/http"
+ "strconv"
+ "strings"
+)
+
+type jsonError struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+}
+
+func render(w http.ResponseWriter, status int, body interface{}) {
+ w.WriteHeader(status)
+ w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+ json.NewEncoder(w).Encode(body)
+}
+
+func formatError(e error) jsonError {
+ parts := strings.SplitN(e.Error(), "[", 2)
+ log.Printf("Error %s", parts[0])
+ parts = strings.SplitN(parts[0], " ", 2)
+ code, err := strconv.Atoi(parts[0])
+ if err != nil {
+ return jsonError{
+ Code: 500,
+ Message: "Error parsing error o_0",
+ }
+ }
+ return jsonError{
+ Code: code,
+ Message: strings.TrimSpace(parts[1]),
+ }
+}
+
+func formatDefinitions(defs []*dict.Defn) ([]definition, error) {
+ definitions := make([]definition, len(defs))
+ for i, def := range defs {
+ definitions[i] = definition{
+ Dictionary: def.Dict.Desc,
+ Word: def.Word,
+ Definition: string(def.Text[:]),
+ }
+ }
+ return definitions, nil
+}
+
+func dictDatabases(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
+ client, err := getDictClient()
+ if err != nil {
+ log.Printf("Unable to connect to dict server at %s", dictServer)
+ render(w, 500, jsonError{420, "Server temporarily unavailable"})
+ return
+ }
+
+ defer client.Close()
+
+ dicts, err := getDictionaries(client)
+ if err != nil {
+ render(w, 400, formatError(err))
+ return
+ }
+ render(w, 200, dicts)
+}
+
+func dictDefine(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
+ client, err := getDictClient()
+ if err != nil {
+ render(w, 500, jsonError{420, "Server temporarily unavailable"})
+ return
+ }
+ defer client.Close()
+
+ word := ps.ByName("word")
+ queryValues := r.URL.Query()
+ d := queryValues.Get("dict")
+
+ var dict string
+
+ if d != "" {
+ dict = d
+ } else {
+ dict = "*"
+ }
+
+ defs, err := client.Define(dict, word)
+ if err != nil {
+ render(w, 400, formatError(err))
+ return
+ }
+
+ definitions, err := formatDefinitions(defs)
+ if err != nil {
+ render(w, 500, err)
+ return
+ }
+ render(w, 200, definitions)
+}
diff --git a/src/dict2rest/logger.go b/src/dict2rest/logger.go
index b4b1187..709666b 100644
--- a/src/dict2rest/logger.go
+++ b/src/dict2rest/logger.go
@@ -20,8 +20,8 @@ func Logger(next http.Handler) http.Handler {
size, _ := bw.Apply(w)
// Usually milliseconds
- latency := time.Since(startTime).Seconds()
+ latency := time.Since(startTime).Seconds() * 1000
- log.Printf("%s %s %d %d (%v)\n", r.Method, r.URL.Path, bw.Status, size, latency)
+ log.Printf("%s %s %d %d (%.1fms)\n", r.Method, r.URL.Path, bw.Status, size, latency)
})
}
diff --git a/src/dict2rest/main.go b/src/dict2rest/main.go
index bbdd5d6..608ab8c 100644
--- a/src/dict2rest/main.go
+++ b/src/dict2rest/main.go
@@ -4,16 +4,16 @@ import (
"flag"
"github.com/julienschmidt/httprouter"
"github.com/justinas/alice"
+ "github.com/rs/cors"
"github.com/stretchr/graceful"
- "golang.org/x/net/dict"
"log"
"net/http"
"os"
"time"
)
-var client *dict.Client
-var dictMap map[string]dict.Dict
+// Globals
+var dictServer string
func main() {
var err error
@@ -25,35 +25,47 @@ func main() {
flag.Parse()
- server := *dictHost + ":" + *dictPort
- client, err = dict.Dial("tcp", server)
+ dictServer = *dictHost + ":" + *dictPort
+
+ client, err := getDictClient()
if err != nil {
- log.Printf("Unable to connect to dict server %s", server)
os.Exit(1)
}
- log.Println("Connected to", server)
- var dictArr []dict.Dict
- dictArr, err = client.Dicts()
+ // Get the global list of databases
+ dicts, err := getDictionaries(client)
if err != nil {
- log.Fatal("Unable to get dictionaries")
+ log.Println("Unable to get database list")
+ os.Exit(1)
}
- dictMap = make(map[string]dict.Dict)
- for _, d := range dictArr {
- log.Println("Using dictionary", d.Name, d.Desc)
- dictMap[d.Name] = d
+ for _, d := range dicts {
+ log.Printf("Available dictionary %s: %s", d.Name, d.Desc)
}
+ // No need for it until a request comes in
+ client.Close()
+ // Define our routes
router := httprouter.New()
+ router.GET("/define/:word", dictDefine)
+ router.GET("/databases", dictDatabases)
+ router.GET("/db", dictDatabases)
+
+ // Define our middlewares
- router.GET("/define/:word", Define)
- router.GET("/databases", Databases)
- router.GET("/db", Databases)
+ // Going to need some CORS headers
+ cors := cors.New(cors.Options{
+ AllowedHeaders: []string{
+ "Accept", "Content-Type", "Origin",
+ },
+ AllowedMethods: []string{
+ "GET", "OPTIONS",
+ },
+ })
- chain := alice.New(Logger).Then(router)
+ chain := alice.New(cors.Handler, Logger).Then(router)
if *gzip {
- chain = alice.New(Logger, Gzip).Then(router)
+ chain = alice.New(cors.Handler, Logger, Gzip).Then(router)
log.Println("Using Gzip compression")
}