From d2480cb3aa78e6faa4891913b6543c1e8b70340a Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Tue, 15 Oct 2019 15:03:45 -0700 Subject: [PATCH 1/4] add basic API endpoint for rendering markdown --- postrender.go | 42 ++++++++++++++++++++++++++++++++++++++++++ routes.go | 3 +++ 2 files changed, 45 insertions(+) diff --git a/postrender.go b/postrender.go index 83fb5ad..2f55896 100644 --- a/postrender.go +++ b/postrender.go @@ -11,9 +11,12 @@ package writefreely import ( + "encoding/json" "fmt" "html" "html/template" + "io/ioutil" + "net/http" "regexp" "strings" "unicode" @@ -234,3 +237,42 @@ func shortPostDescription(content string) string { } return strings.TrimSpace(fmt.Sprintf(fmtStr, strings.Replace(stringmanip.Substring(content, 0, maxLen-truncation), "\n", " ", -1))) } + +func handleRenderMarkdown(app *App, w http.ResponseWriter, r *http.Request) error { + // TODO: accept header + if !IsJSON(r.Header.Get("Content-Type")) { + fmt.Println("missing header") + } + + in := struct { + BaseURL string `json:"base_url"` + RawBody string `json:"raw_body"` + }{ + BaseURL: "", + } + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + return ErrInternalGeneral + } + + err = json.Unmarshal(body, &in) + if err != nil { + return ErrInternalGeneral + } + + out := struct { + Body string `json:"body"` + }{ + Body: applyMarkdown([]byte(in.RawBody), in.BaseURL, nil), + } + + js, err := json.Marshal(out) + if err != nil { + return ErrInternalGeneral + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(js) + return nil +} diff --git a/routes.go b/routes.go index 0113e93..25a8bf3 100644 --- a/routes.go +++ b/routes.go @@ -110,6 +110,9 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router { // Sign up validation write.HandleFunc("/api/alias", handler.All(handleUsernameCheck)).Methods("POST") + apiGenerate := write.PathPrefix("/api/generate/").Subrouter() + apiGenerate.HandleFunc("/markdownify", handler.All(handleRenderMarkdown)).Methods("POST") + // Handle collections write.HandleFunc("/api/collections", handler.All(newCollection)).Methods("POST") apiColls := write.PathPrefix("/api/collections/").Subrouter() From a266d8e0322d3dc40e3b1599d76bf514b06438d2 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Fri, 29 Nov 2019 08:12:54 -0500 Subject: [PATCH 2/4] Update IsJSON call in handleRenderMarkdown() --- postrender.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/postrender.go b/postrender.go index 2f55896..8ab90aa 100644 --- a/postrender.go +++ b/postrender.go @@ -239,8 +239,7 @@ func shortPostDescription(content string) string { } func handleRenderMarkdown(app *App, w http.ResponseWriter, r *http.Request) error { - // TODO: accept header - if !IsJSON(r.Header.Get("Content-Type")) { + if !IsJSON(r) { fmt.Println("missing header") } From 26d906ae92ba4d4079a45f3bcb96bde1f91ad887 Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Tue, 17 Dec 2019 12:27:34 -0800 Subject: [PATCH 3/4] clean up responses and logging, change endpoint - return an error with invalid request types - simplify json decoding - return error and success consistent with app conventions - endpoint change from /api/generate/markdownify to /api/markdown - fix nil pointer dereference when passing a base_url --- postrender.go | 31 ++++++++----------------------- routes.go | 3 +-- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/postrender.go b/postrender.go index 8ab90aa..f5b5649 100644 --- a/postrender.go +++ b/postrender.go @@ -15,7 +15,6 @@ import ( "fmt" "html" "html/template" - "io/ioutil" "net/http" "regexp" "strings" @@ -24,7 +23,9 @@ import ( "github.com/microcosm-cc/bluemonday" stripmd "github.com/writeas/go-strip-markdown" + "github.com/writeas/impart" blackfriday "github.com/writeas/saturday" + "github.com/writeas/web-core/log" "github.com/writeas/web-core/stringmanip" "github.com/writeas/writefreely/config" "github.com/writeas/writefreely/parse" @@ -240,7 +241,7 @@ func shortPostDescription(content string) string { func handleRenderMarkdown(app *App, w http.ResponseWriter, r *http.Request) error { if !IsJSON(r) { - fmt.Println("missing header") + return impart.HTTPError{Status: http.StatusUnsupportedMediaType, Message: "Markdown API only supports JSON requests"} } in := struct { @@ -250,28 +251,12 @@ func handleRenderMarkdown(app *App, w http.ResponseWriter, r *http.Request) erro BaseURL: "", } - body, err := ioutil.ReadAll(r.Body) + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&in) if err != nil { - return ErrInternalGeneral + log.Error("Couldn't parse markdown JSON request: %v", err) + return ErrBadJSON } - err = json.Unmarshal(body, &in) - if err != nil { - return ErrInternalGeneral - } - - out := struct { - Body string `json:"body"` - }{ - Body: applyMarkdown([]byte(in.RawBody), in.BaseURL, nil), - } - - js, err := json.Marshal(out) - if err != nil { - return ErrInternalGeneral - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(js) - return nil + return impart.WriteSuccess(w, applyMarkdown([]byte(in.RawBody), in.BaseURL, app.cfg), http.StatusOK) } diff --git a/routes.go b/routes.go index a37e0de..4334f9f 100644 --- a/routes.go +++ b/routes.go @@ -110,8 +110,7 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router { // Sign up validation write.HandleFunc("/api/alias", handler.All(handleUsernameCheck)).Methods("POST") - apiGenerate := write.PathPrefix("/api/generate/").Subrouter() - apiGenerate.HandleFunc("/markdownify", handler.All(handleRenderMarkdown)).Methods("POST") + write.HandleFunc("/api/markdown", handler.All(handleRenderMarkdown)).Methods("POST") // Handle collections write.HandleFunc("/api/collections", handler.All(newCollection)).Methods("POST") From dae65b7d1fadc9d6dd3a25b6a98714adf437a80a Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Thu, 19 Dec 2019 08:28:06 -0800 Subject: [PATCH 4/4] retain output structure in response --- postrender.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/postrender.go b/postrender.go index f5b5649..02b156b 100644 --- a/postrender.go +++ b/postrender.go @@ -258,5 +258,11 @@ func handleRenderMarkdown(app *App, w http.ResponseWriter, r *http.Request) erro return ErrBadJSON } - return impart.WriteSuccess(w, applyMarkdown([]byte(in.RawBody), in.BaseURL, app.cfg), http.StatusOK) + out := struct { + Body string `json:"body"` + }{ + Body: applyMarkdown([]byte(in.RawBody), in.BaseURL, app.cfg), + } + + return impart.WriteSuccess(w, out, http.StatusOK) }