Add search endpoint
parent
28ca48667f
commit
7b5aeeb87e
37
app.go
37
app.go
|
@ -41,6 +41,7 @@ func NewDatetime() (*Datetime, error) {
|
||||||
mux.Handle("/js/", http.FileServer(http.Dir("assets")))
|
mux.Handle("/js/", http.FileServer(http.Dir("assets")))
|
||||||
mux.Handle("/css/", http.FileServer(http.Dir("assets")))
|
mux.Handle("/css/", http.FileServer(http.Dir("assets")))
|
||||||
mux.Handle("/favicon.ico", http.FileServer(http.Dir("assets")))
|
mux.Handle("/favicon.ico", http.FileServer(http.Dir("assets")))
|
||||||
|
mux.HandleFunc("/search", app.search)
|
||||||
mux.HandleFunc("/", app.index)
|
mux.HandleFunc("/", app.index)
|
||||||
|
|
||||||
return app, nil
|
return app, nil
|
||||||
|
@ -51,6 +52,11 @@ type appRequest struct {
|
||||||
Req Request
|
Req Request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type appSearch struct {
|
||||||
|
App Datetime
|
||||||
|
Req map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
// index handles all incoming page requests
|
// index handles all incoming page requests
|
||||||
func (app Datetime) index(w http.ResponseWriter, req *http.Request) {
|
func (app Datetime) index(w http.ResponseWriter, req *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
|
@ -86,3 +92,34 @@ func (app Datetime) index(w http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search handles zone search queries
|
||||||
|
func (app Datetime) search(w http.ResponseWriter, req *http.Request) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if req.Method != http.MethodGet && req.Method != http.MethodHead {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl := app.loadTemplate("search", w, req)
|
||||||
|
if tmpl == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if req.Method == http.MethodHead {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do search
|
||||||
|
search := map[string]string{
|
||||||
|
"hi": "hello",
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Debug("rendering template", zap.Reflect("search", search))
|
||||||
|
err = tmpl.Execute(w, appSearch{app, search})
|
||||||
|
if err != nil {
|
||||||
|
l.Error("templating failed", zap.Error(err))
|
||||||
|
app.templateError(HTTPError{http.StatusInternalServerError, err}, w, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
5
mime.go
5
mime.go
|
@ -57,6 +57,7 @@ type responseType int
|
||||||
const (
|
const (
|
||||||
responsePlain responseType = iota
|
responsePlain responseType = iota
|
||||||
responseHTML responseType = iota
|
responseHTML responseType = iota
|
||||||
|
responseJSON responseType = iota
|
||||||
responseAny responseType = iota
|
responseAny responseType = iota
|
||||||
responseUnknown responseType = iota
|
responseUnknown responseType = iota
|
||||||
)
|
)
|
||||||
|
@ -64,6 +65,7 @@ const (
|
||||||
const (
|
const (
|
||||||
responsePlainMime = "text/plain"
|
responsePlainMime = "text/plain"
|
||||||
responseHTMLMime = "text/html"
|
responseHTMLMime = "text/html"
|
||||||
|
responseJSONMime = "application/json"
|
||||||
responseAnyMime = "*/*"
|
responseAnyMime = "*/*"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,6 +79,9 @@ func chooseResponseType(accept string) responseType {
|
||||||
if m.media == responseHTMLMime {
|
if m.media == responseHTMLMime {
|
||||||
return responseHTML
|
return responseHTML
|
||||||
}
|
}
|
||||||
|
if m.media == responseJSONMime {
|
||||||
|
return responseJSON
|
||||||
|
}
|
||||||
if m.media == responseAnyMime {
|
if m.media == responseAnyMime {
|
||||||
return responseAny
|
return responseAny
|
||||||
}
|
}
|
||||||
|
|
15
template.go
15
template.go
|
@ -1,12 +1,18 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrTemplateNotFound is thrown when a template with the requested MIME type
|
||||||
|
// is not found.
|
||||||
|
var ErrTemplateNotFound = errors.New("unable to find template")
|
||||||
|
|
||||||
// loadTemplate returns a matching template for the request. It also causes an
|
// loadTemplate returns a matching template for the request. It also causes an
|
||||||
// error if the template is not found or the Accept parameters are incorrect.
|
// error if the template is not found or the Accept parameters are incorrect.
|
||||||
func (app Datetime) loadTemplate(name string, w http.ResponseWriter, req *http.Request) *template.Template {
|
func (app Datetime) loadTemplate(name string, w http.ResponseWriter, req *http.Request) *template.Template {
|
||||||
|
@ -17,8 +23,10 @@ func (app Datetime) loadTemplate(name string, w http.ResponseWriter, req *http.R
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if tmpl == nil {
|
if tmpl == nil {
|
||||||
l.Error("unable to find template", zap.String("name", name), zap.String("accept", accept))
|
err := fmt.Errorf("%w \"%s\" for \"%s\"", ErrTemplateNotFound, name, accept)
|
||||||
app.simpleError(HTTPError{http.StatusInternalServerError, ErrNoTemplate}, w, req)
|
l.Warn("unable to find template", zap.Error(err), zap.String("name", name), zap.String("accept", accept))
|
||||||
|
app.simpleError(HTTPError{http.StatusNotAcceptable, err}, w, req)
|
||||||
|
//app.simpleError(HTTPError{http.StatusInternalServerError, ErrNoTemplate}, w, req)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
|
@ -36,6 +44,9 @@ func (app Datetime) chooseTemplate(accept string, name string) (t *template.Temp
|
||||||
case responseHTML:
|
case responseHTML:
|
||||||
t = app.tmpl.Lookup(name + ".html")
|
t = app.tmpl.Lookup(name + ".html")
|
||||||
contentType = "text/html"
|
contentType = "text/html"
|
||||||
|
case responseJSON:
|
||||||
|
t = app.tmpl.Lookup(name + ".json")
|
||||||
|
contentType = "application/json"
|
||||||
case responseAny:
|
case responseAny:
|
||||||
t = app.tmpl.Lookup(name + ".txt")
|
t = app.tmpl.Lookup(name + ".txt")
|
||||||
contentType = "text/plain"
|
contentType = "text/plain"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -10,6 +11,8 @@ import (
|
||||||
var templateFuncs = map[string]interface{}{
|
var templateFuncs = map[string]interface{}{
|
||||||
"statusText": templateFuncStatusText,
|
"statusText": templateFuncStatusText,
|
||||||
"thisIsSafe": templateFuncThisIsSafe,
|
"thisIsSafe": templateFuncThisIsSafe,
|
||||||
|
// Encoding
|
||||||
|
"jsonMarshal": templateFuncJSONMarshal,
|
||||||
// Formatting
|
// Formatting
|
||||||
"formatOffset": templateFuncFormatOffset,
|
"formatOffset": templateFuncFormatOffset,
|
||||||
// Logic
|
// Logic
|
||||||
|
@ -23,6 +26,14 @@ func templateFuncThisIsSafe(s string) template.HTML {
|
||||||
return template.HTML(s)
|
return template.HTML(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func templateFuncJSONMarshal(v interface{}) string {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
func templateFuncFormatOffset(offset int) string {
|
func templateFuncFormatOffset(offset int) string {
|
||||||
return FormatZoneOffset(offset)
|
return FormatZoneOffset(offset)
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,9 @@
|
||||||
|
|
||||||
{{template "interactive-icons.html"}}
|
{{template "interactive-icons.html"}}
|
||||||
|
|
||||||
|
<!--
|
||||||
<script src="/js/third-party/luxon.min.js"></script>
|
<script src="/js/third-party/luxon.min.js"></script>
|
||||||
<script src="/js/interactive.js" async></script>
|
<script src="/js/interactive.js" async></script>
|
||||||
|
-->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{{.Req | jsonMarshal | thisIsSafe }}
|
Loading…
Reference in New Issue