Skip to content

Commit

Permalink
http server development
Browse files Browse the repository at this point in the history
  • Loading branch information
nexus166 committed Jul 23, 2021
1 parent 6a8a692 commit 547c88f
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 132 deletions.
171 changes: 39 additions & 132 deletions cmd/xprint/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,10 @@ package main

import (
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"sort"
"strconv"
Expand All @@ -37,15 +31,15 @@ var (
s string
isFile bool
}
unsafe *bool = flag.Bool("u", unsafeMode(), fmt.Sprintf("allow evaluation of dangerous template functions (%v)", unsafeFuncs())) //
showFns *bool = flag.Bool("F", false, "print available template functions and exit") //
debug *bool = flag.Bool("D", false, "debug init and template rendering activities") //
startDebuggingOnce sync.Once //
output *os.File //
argsfirst *bool = flag.Bool("a", false, "output arguments (if any) before stdin (if any), instead of the opposite") //
showVersion *bool = flag.Bool("v", false, "print build version/date and exit") //
server *string = flag.String("s", "", "start a render server on given address") //
semver, commit, built = "v0.0.0-dev", "local", "a while ago" //
unsafe *bool = flag.Bool("u", unsafeMode(), fmt.Sprintf("allow evaluation of dangerous template functions (%v)", unsafeFuncs())) //
showFns *bool = flag.Bool("F", false, "print available template functions and exit") //
debug *bool = flag.Bool("D", false, "debug init and template rendering activities") //
startDebuggingOnce sync.Once //
output *os.File //
argsfirst *bool = flag.Bool("a", false, "output arguments (if any) before stdin (if any), instead of the opposite") //
showVersion *bool = flag.Bool("v", false, "print build version/date and exit") //
//server *string = flag.String("s", "", "start a render server on given address") //
semver, commit, built = "v0.0.0-dev", "local", "a while ago" //
)

func unsafeFuncs() []string {
Expand Down Expand Up @@ -202,34 +196,37 @@ func init() {
}

func main() {
if *server != "" {
if output == nil {
output = os.Stderr
}
var err error
l, err = log.New(log.Formats[log.StdFormat].String(), log.Formats[log.DefTimeFmt].String(), loglvl, *logcolor, *name, output)
if err != nil {
panic(err)
}
u, err := url.Parse(*server)
if err != nil {
panic(err)
}
proto := strings.Split(u.Scheme, ":")[0]
var addr string
if proto != "unix" {
addr = net.JoinHostPort(u.Hostname(), u.Port())
} else {
addr = u.Hostname()
}
lis, err := net.Listen(proto, addr)
if err != nil {
panic(err)
/*
if *server != "" {
if output == nil {
output = os.Stderr
}
var err error
l, err = log.New(log.Formats[log.StdFormat].String(), log.Formats[log.DefTimeFmt].String(), loglvl, *logcolor, *name, output)
if err != nil {
panic(err)
}
u, err := url.Parse(*server)
if err != nil {
panic(err)
}
proto := strings.Split(u.Scheme, ":")[0]
var addr string
if proto != "unix" {
addr = net.JoinHostPort(u.Hostname(), u.Port())
} else {
addr = u.Hostname()
}
lis, err := net.Listen(proto, addr)
if err != nil {
panic(err)
}
l.Noticef("set up %s listener on %s", proto, lis.Addr().String())
http.HandleFunc("/render", renderServer)
http.HandleFunc("/", uiPage)
panic(http.Serve(lis, nil).Error())
}
l.Noticef("set up %s listener on %s", proto, lis.Addr().String())
http.HandleFunc("/render", renderServer)
panic(http.Serve(lis, nil).Error())
}
*/
buf := new(bytes.Buffer)
if len(_templates) > 0 {
if *debug {
Expand Down Expand Up @@ -284,93 +281,3 @@ func main() {
l.Debugf("%s", buf.String())
}
}

type jresp struct {
Status int `json:"status"`
Results interface{} `json:"results,omitempty"`
Error error `json:"error,omitempty"`
}

func renderServer(w http.ResponseWriter, r *http.Request) {
l.Noticef("new request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr)
if *debug {
b, _ := httputil.DumpRequest(r, true)
l.Debugf("request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, string(b))
}
if r.Method != http.MethodPost {
l.Errorf("rejected request ( %s %s ) from %s: bad method", r.Method, r.URL, r.RemoteAddr)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
var postTemplates map[string]string
if err := json.NewDecoder(r.Body).Decode(&postTemplates); err != nil {
l.Errorf("error processing request ( %s %s ) from %s: invalid body: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: fmt.Errorf(
`must submit a map[key]value JSON object where key is a string identifier for the template and value is the base64-encoded template itself. a special map["data"] field (also base64 encoded) may be provided, it will not be considered a template but as a data object to apply to the templates in template.Execute`,
),
})
return
}
var postedData interface{}
if v, ok := postTemplates["data"]; ok {
b, err := base64.StdEncoding.DecodeString(v)
if err != nil {
l.Warningf("error decoding map[data] from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: err,
})
return
}
postedData = string(b)
delete(postTemplates, "data")
}
if len(postTemplates) < 1 {
l.Infof("request ( %s %s ) from %s: no content", r.Method, r.URL, r.RemoteAddr)
w.WriteHeader(http.StatusNoContent)
return
}
tpl := template.New("").Funcs(buildFuncMap(*unsafe))
for n, t := range postTemplates {
b, err := base64.RawStdEncoding.DecodeString(t)
if err != nil {
l.Warningf("error decoding templates from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: err,
})
return
}
tpl, err = tpl.New(n).Parse(string(b))
if err != nil {
l.Warningf("error processing request ( %s %s ) from %s: tpl.New: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: err,
})
return
}
}
buf := new(bytes.Buffer)
if err := tpl.Execute(buf, postedData); err != nil {
l.Warningf("error processing request ( %s %s ) from %s: tpl.Execute: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusInternalServerError,
Error: err,
})
return
}
w.WriteHeader(http.StatusOK)
_, err := io.Copy(w, buf)
if err != nil {
l.Warningf("error sending response to request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, err)
}
l.Infof("processed request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr)
}
152 changes: 152 additions & 0 deletions cmd/xprint/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package main

/*
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httputil"
"text/template"
)
type jresp struct {
Status int `json:"status"`
Results interface{} `json:"results,omitempty"`
Error error `json:"error,omitempty"`
}
func renderServer(w http.ResponseWriter, r *http.Request) {
l.Noticef("new request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr)
if *debug {
b, _ := httputil.DumpRequest(r, true)
l.Debugf("request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, string(b))
}
if r.Method != http.MethodPost {
l.Errorf("rejected request ( %s %s ) from %s: bad method", r.Method, r.URL, r.RemoteAddr)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
if err := r.ParseMultipartForm(32 << 20); err != nil {
l.Errorf("error processing request ( %s %s ) from %s: invalid form data: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
j, _ := json.MarshalIndent(r.Form, "", " ")
fmt.Println(string(j))
var postTemplates map[string]string
if err := json.NewDecoder(r.Body).Decode(&postTemplates); err != nil {
l.Errorf("error processing request ( %s %s ) from %s: invalid body: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: fmt.Errorf(
`must submit a map[key]value JSON object where key is a string identifier for the template and value is the base64-encoded template itself. a special map["data"] field (also base64 encoded) may be provided, it will not be considered a template but as a data object to apply to the templates in template.Execute`,
),
})
return
}
var postedData interface{}
if v, ok := postTemplates["data"]; ok {
b, err := base64.StdEncoding.DecodeString(v)
if err != nil {
l.Warningf("error decoding map[data] from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: err,
})
return
}
postedData = string(b)
delete(postTemplates, "data")
}
if len(postTemplates) < 1 {
l.Infof("request ( %s %s ) from %s: no content", r.Method, r.URL, r.RemoteAddr)
w.WriteHeader(http.StatusNoContent)
return
}
tpl := template.New("").Funcs(buildFuncMap(*unsafe))
for n, t := range postTemplates {
b, err := base64.RawStdEncoding.DecodeString(t)
if err != nil {
l.Warningf("error decoding templates from request ( %s %s ) from %s: b64dec: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: err,
})
return
}
tpl, err = tpl.New(n).Parse(string(b))
if err != nil {
l.Warningf("error processing request ( %s %s ) from %s: tpl.New: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusBadRequest,
Error: err,
})
return
}
}
buf := new(bytes.Buffer)
if err := tpl.Execute(buf, postedData); err != nil {
l.Warningf("error processing request ( %s %s ) from %s: tpl.Execute: %s", r.Method, r.URL, r.RemoteAddr, err)
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(jresp{
Status: http.StatusInternalServerError,
Error: err,
})
return
}
w.WriteHeader(http.StatusOK)
_, err := io.Copy(w, buf)
if err != nil {
l.Warningf("error sending response to request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, err)
}
l.Infof("processed request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr)
}
//http.Error()
func uiPage(w http.ResponseWriter, r *http.Request) {
l.Noticef("new request ( %s %s ) from %s", r.Method, r.URL, r.RemoteAddr)
if *debug {
b, _ := httputil.DumpRequest(r, true)
l.Debugf("request ( %s %s ) from %s: %s", r.Method, r.URL, r.RemoteAddr, string(b))
}
if r.Method != http.MethodGet {
l.Errorf("rejected request ( %s %s ) from %s: bad method", r.Method, r.URL, r.RemoteAddr)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`<!DOCTYPE html>
<style>
Body {
display:flex;
font-family: Calibri, Helvetica, sans-serif;
background-color: #303030;
}
h1 {text-align: center;}
p {text-align: center;}
div {text-align: center;}
</style>
<html>
<head>
<title>xprint render page</title>
</head>
<body>
<form enctype="multipart/form-data" action="/render" method="POST">
<textarea id="template">main template</textarea>
<textarea id="data">data</textarea>
<input type="file" id="templates" name="templates" multiple>
<input type="submit">render</button>
</form>
</body>
</html>
`))
}
*/

0 comments on commit 547c88f

Please sign in to comment.