Skip to content

Commit

Permalink
ghttpserver
Browse files Browse the repository at this point in the history
  • Loading branch information
snail007 committed Jan 12, 2024
1 parent 688f058 commit 59a6cd9
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 67 deletions.
5 changes: 5 additions & 0 deletions core/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package gcore
import (
"bufio"
"context"
"embed"
"io"
"net"
"net/http"
Expand Down Expand Up @@ -173,6 +174,8 @@ type APIServer interface {
Ctx() Ctx
ListenerFactory() func(addr string) (net.Listener, error)
SetListenerFactory(listenerFactory func(addr string) (net.Listener, error))
ServeEmbedFS(fs embed.FS, urlPath string)
ServeFiles(rootPath, urlPath string)
}

type HTTPServer interface {
Expand Down Expand Up @@ -206,6 +209,8 @@ type HTTPServer interface {
Listen() (err error)
ListenTLS() (err error)
SetCtx(ctx Ctx)
ServeEmbedFS(fs embed.FS, urlPath string)
ServeFiles(rootPath, urlPath string)
}

type Controller interface {
Expand Down
10 changes: 10 additions & 0 deletions http/server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"embed"
"fmt"
gcore "github.com/snail007/gmc/core"
ghttputil "github.com/snail007/gmc/internal/util/http"
"github.com/snail007/gmc/module/log"
gfile "github.com/snail007/gmc/util/file"
"io"
"io/ioutil"
"log"
Expand Down Expand Up @@ -409,3 +411,11 @@ func (this *APIServer) Listeners() []net.Listener {
func (this *APIServer) Listener() net.Listener {
return this.listener
}

func (s *APIServer) ServeEmbedFS(fs embed.FS, urlPath string) {
serveEmbedFS(s.router, fs, urlPath)
}

func (s *APIServer) ServeFiles(rootPath, urlPath string) {
serveFiles(s.router, gfile.Abs(rootPath), urlPath)
}
18 changes: 18 additions & 0 deletions http/server/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package ghttpserver

import (
gcore "github.com/snail007/gmc/core"
"github.com/snail007/gmc/http/template/testdata"
"net"
"testing"

Expand Down Expand Up @@ -180,3 +181,20 @@ func TestAPIServer_createListener(t *testing.T) {
assert.Nil(e)
assert.IsType((*MyListener)(nil), api.listener)
}

func TestAPIServer_ServeFiles(t *testing.T) {
assert := assert.New(t)
api := NewAPIServer(gcore.ProviderCtx()(), ":")
api.ServeEmbedFS(testdata.TplFS, "/tpls/")
api.ServeFiles("tests", "/files/")

w, r := mockRequest("/tpls/f/f.txt")
api.ServeHTTP(w, r)
str, _ := result(w)
assert.Equal("f", str)

w, r = mockRequest("/files/d.txt")
api.ServeHTTP(w, r)
str, _ = result(w)
assert.Equal("d", str)
}
43 changes: 43 additions & 0 deletions http/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@
package ghttpserver

import (
"bytes"
"compress/gzip"
"context"
"crypto/tls"
"crypto/x509"
"embed"
"encoding/base64"
"fmt"
gcore "github.com/snail007/gmc/core"
ghttputil "github.com/snail007/gmc/internal/util/http"
"github.com/snail007/gmc/module/log"
gfile "github.com/snail007/gmc/util/file"
"io"
"io/ioutil"
"log"
"mime"
"net"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
Expand Down Expand Up @@ -576,6 +580,7 @@ func (s *HTTPServer) SetLog(l gcore.Logger) {
s.logger = l
return
}

func (s *HTTPServer) callMiddleware(ctx gcore.Ctx, middleware []gcore.Middleware) (isStop bool) {
for _, fn := range middleware {
func() {
Expand All @@ -591,3 +596,41 @@ func (s *HTTPServer) callMiddleware(ctx gcore.Ctx, middleware []gcore.Middleware
}
return
}

func (s *HTTPServer) ServeEmbedFS(fs embed.FS, urlPath string) {
serveEmbedFS(s.router, fs, urlPath)
}

func (s *HTTPServer) ServeFiles(rootPath, urlPath string) {
serveFiles(s.router, gfile.Abs(rootPath), urlPath)
}

func serveEmbedFS(router gcore.HTTPRouter, fs embed.FS, urlPath string) {
urlPath = strings.TrimSuffix(urlPath, "/")
bindPath := urlPath + "/*filepath"
router.HandlerFuncAny(bindPath, func(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, urlPath+"/")
b, err := fs.ReadFile(path)
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not Found"))
return
}
http.ServeContent(w, r, filepath.Base(path), time.Time{}, bytes.NewReader(b))
})
}

func serveFiles(router gcore.HTTPRouter, root, urlPath string) {
urlPath = strings.TrimSuffix(urlPath, "/")
bindPath := urlPath + "/*filepath"
router.HandlerFuncAny(bindPath, func(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, urlPath+"/")
b, err := os.ReadFile(filepath.Join(root, path))
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not Found"))
return
}
http.ServeContent(w, r, filepath.Base(path), time.Time{}, bytes.NewReader(b))
})
}
26 changes: 26 additions & 0 deletions http/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/snail007/gmc/core"
gcontroller "github.com/snail007/gmc/http/controller"
gsession "github.com/snail007/gmc/http/session"
"github.com/snail007/gmc/http/template/testdata"
gctx "github.com/snail007/gmc/module/ctx"
ghttppprof "github.com/snail007/gmc/util/pprof"
"io/ioutil"
Expand Down Expand Up @@ -660,3 +661,28 @@ func TestSetBinBytes(t *testing.T) {
})
assert.Equal(t, defaultBinData["test/a"], []byte("aa"))
}

func TestHTTPServer_ServeEmbedFS(t *testing.T) {
assert := assert.New(t)
s := mockHTTPServer()
s.ServeEmbedFS(testdata.TplFS, "/tpls/")
s.ServeFiles("tests", "/files/")

w, r := mockRequest("/tpls/f/f.txt")
s.ServeHTTP(w, r)
str, _ := result(w)
assert.Equal("f", str)

w, r = mockRequest("/files/d.txt")
s.ServeHTTP(w, r)
str, _ = result(w)
assert.Equal("d", str)

w, r = mockRequest("/tpls/none.txt")
s.ServeHTTP(w, r)
assert.Equal(404, w.Result().StatusCode)

w, r = mockRequest("/files/none.txt")
s.ServeHTTP(w, r)
assert.Equal(404, w.Result().StatusCode)
}
57 changes: 57 additions & 0 deletions http/template/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
package gtemplate

import (
"embed"
"encoding/base64"
"errors"
gcore "github.com/snail007/gmc/core"
gctx "github.com/snail007/gmc/module/ctx"
glog "github.com/snail007/gmc/module/log"
gcond "github.com/snail007/gmc/util/cond"
"io/fs"
"path/filepath"
"strings"
)

func Init(ctx gcore.Ctx) (tpl gcore.Template, err error) {
Expand Down Expand Up @@ -58,3 +65,53 @@ func RenderStringWithFunc(tpl string, data map[string]interface{}, funcMap map[s
r, e := RenderBytesWithFunc([]byte(tpl), data, funcMap)
return string(r), e
}

type EmbedTemplateFS struct {
root string
ext string
fs embed.FS
tpl *Template
}

// NewEmbedTemplateFS parse template files from fs embed.FS to tpl *Template,
// it should be called before tpl.Parse(), if the tpl parsed already , nil returned.
func NewEmbedTemplateFS(tpl *Template, fs embed.FS, rootDir string) *EmbedTemplateFS {
return &EmbedTemplateFS{
fs: fs,
tpl: tpl,
root: rootDir,
ext: ".html",
}
}

func (s *EmbedTemplateFS) SetExt(ext string) *EmbedTemplateFS {
s.ext = ext
return s
}

func (s *EmbedTemplateFS) Parse() (err error) {
if s.tpl.parsed {
return errors.New("tpl parsed already")
}
bindData := map[string]string{}
err = fs.WalkDir(s.fs, s.root, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && filepath.Ext(d.Name()) == s.ext {
b, _ := s.fs.ReadFile(path)
key := strings.TrimSuffix(path, s.ext)
trimPrefix := gcond.Cond(s.root == "", "", strings.TrimRight(s.root, "/")+"/").String()
if len(trimPrefix) > 0 {
key = strings.TrimPrefix(key, trimPrefix)
}
bindData[key] = base64.StdEncoding.EncodeToString(b)
}
return nil
})
if err != nil {
return err
}
s.tpl.SetBinBase64(bindData)
return nil
}
13 changes: 13 additions & 0 deletions http/template/helper_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package gtemplate

import (
"github.com/snail007/gmc/http/template/testdata"
gctx "github.com/snail007/gmc/module/ctx"
gmap "github.com/snail007/gmc/util/map"
"github.com/stretchr/testify/assert"
"testing"
Expand All @@ -23,3 +25,14 @@ func TestRender(t *testing.T) {
//fmt.Println(err.Error())
assert.Equal(t, "abbc", d)
}

func TestNewEmbedTemplateFS(t *testing.T) {
tpl, _ := NewTemplate(gctx.NewCtx(), "")
efs := NewEmbedTemplateFS(tpl, testdata.TplFS, "tpl").SetExt(".html")
efs.Parse()
assert.Len(t, efs.tpl.binData, 4)

//err
tpl.Parse()
assert.Error(t, NewEmbedTemplateFS(tpl, testdata.TplFS, ".").Parse())
}
1 change: 1 addition & 0 deletions http/template/testdata/e.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e
1 change: 1 addition & 0 deletions http/template/testdata/f/f.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
f
6 changes: 6 additions & 0 deletions http/template/testdata/fs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package testdata

import "embed"

//go:embed *
var TplFS embed.FS
1 change: 1 addition & 0 deletions http/template/testdata/g.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
g
1 change: 1 addition & 0 deletions http/template/testdata/tpl/a.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a
1 change: 1 addition & 0 deletions http/template/testdata/tpl/a/aa.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aa
1 change: 1 addition & 0 deletions http/template/testdata/tpl/a/c/c.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c
1 change: 1 addition & 0 deletions http/template/testdata/tpl/b/b.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
b
1 change: 1 addition & 0 deletions http/template/testdata/tpl/d.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d
Loading

0 comments on commit 59a6cd9

Please sign in to comment.