Skip to content

Commit

Permalink
Merge pull request #16 from Stratoscale/proxy
Browse files Browse the repository at this point in the history
add proxy support
  • Loading branch information
Eyal Posener committed Jan 31, 2018
2 parents 98fefbb + df33e07 commit 8b54071
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 101 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The json should be a dict with the following keys:
- `parsers` (list of [parser dicts](./README.md#parser-dict)): Which parsers to apply to the log files.
- `global` (dict of [attributes](./README.md#global-dict)): General configuration
- `cache` (dict of [attributes](./README.md#cache-dict)): Cache configuration
- `route` (dict of [attributes](./README.md#route-dict)): Route configuration

#### Source Dict

Expand Down Expand Up @@ -101,3 +102,7 @@ The UI expects the following keys in each parsed log:
- `size`
- `expiration`

#### Route Dict

- `base_path`
- `root_path`
2 changes: 1 addition & 1 deletion client/webpack/common/html-webpack-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ module.exports = function htmlWebpackPlugin(config, APP_PATH) {
favicon: path.resolve(APP_PATH, 'images', 'favico.png'),
template: path.resolve(APP_PATH, 'index.html'),
basePath: '{{ .BasePath }}', // will be replaced by the server with the actual path
rootPath: '/_static', // will be replaced by the server with the actual path
rootPath: '{{ .RootPath }}/_static', // will be replaced by the server with the actual path
}
}
15 changes: 8 additions & 7 deletions debug/pprof.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package debug

import (
"net/http"
"net/http/pprof"

"github.com/gorilla/mux"
)

func PProfHandle(m *http.ServeMux) {
m.HandleFunc("/debug/pprof/", pprof.Index)
m.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
m.HandleFunc("/debug/pprof/profile", pprof.Profile)
m.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
m.HandleFunc("/debug/pprof/trace", pprof.Trace)
func PProfHandle(r *mux.Router) {
r.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
r.PathPrefix("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
r.PathPrefix("/debug/pprof/profile").HandlerFunc(pprof.Profile)
r.PathPrefix("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
r.PathPrefix("/debug/pprof/trace").HandlerFunc(pprof.Trace)
}
56 changes: 33 additions & 23 deletions dynamic/dynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ import (

"github.com/Stratoscale/logserver/engine"
"github.com/Stratoscale/logserver/parse"
"github.com/Stratoscale/logserver/router"
"github.com/Stratoscale/logserver/route"
"github.com/Stratoscale/logserver/source"
"github.com/bluele/gcache"
"github.com/gorilla/mux"
)

const (
defaultMarkFile = "logstack.enable"
staticPath = "/_static"
)
const defaultMarkFile = "logstack.enable"

// Config is dynamic configuration
type Config struct {
Expand All @@ -26,18 +24,18 @@ type Config struct {
source.Flags
}

func New(c Config, engineConfig engine.Config, p parse.Parse, cache gcache.Cache) (http.Handler, error) {
func New(c Config, engineCfg engine.Config, routeCfg route.Config, p parse.Parse, cache gcache.Cache) (http.Handler, error) {
var err error
c.Root, err = filepath.Abs(c.Root)
if err != nil {
return nil, err
}
h := &handler{
Config: c,
engineConfig: engineConfig,
parse: p,
cache: cache,
static: http.StripPrefix(staticPath+"/", http.FileServer(http.Dir("./client/dist"))),
Config: c,
parse: p,
cache: cache,
engineCfg: engineCfg,
routeCfg: routeCfg,
}
if h.MarkFile == "" {
h.MarkFile = defaultMarkFile
Expand All @@ -47,17 +45,14 @@ func New(c Config, engineConfig engine.Config, p parse.Parse, cache gcache.Cache

type handler struct {
Config
engineConfig engine.Config
parse parse.Parse
cache gcache.Cache
static http.Handler
parse parse.Parse
cache gcache.Cache
route route.Config
engineCfg engine.Config
routeCfg route.Config
}

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, staticPath) {
h.static.ServeHTTP(w, r)
return
}
root, err := h.searchRoot(r.URL.Path)
if err != nil {
http.NotFound(w, r)
Expand Down Expand Up @@ -92,11 +87,26 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer src.CloseSources()

serverPath := root[len(h.Root):]
rtr := mux.NewRouter()

// add index.html serving at the serverPath which is the dynamic root
err = route.Index(rtr, route.Config{
// BasePath is used to determined the websocket path
BasePath: filepath.Join(h.routeCfg.RootPath, serverPath),
// RootPath is for taking the static files, which are served by the root handler
RootPath: ""})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

// add websocket handler on the server root
route.Engine(
rtr,
route.Config{RootPath: ""},
engine.New(h.engineCfg, src, h.parse, h.cache),
)

rtr, err := router.New(router.Config{
Engine: engine.New(h.engineConfig, src, h.parse, h.cache),
BasePath: serverPath,
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
Expand Down
3 changes: 3 additions & 0 deletions example/logserver.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
]
}
],
"route": {
"root_path": "/logserver"
},
"dynamic": {
"root": "./",
"open_journal": "/journal"
Expand Down
29 changes: 17 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import (
"github.com/Stratoscale/logserver/dynamic"
"github.com/Stratoscale/logserver/engine"
"github.com/Stratoscale/logserver/parse"
"github.com/Stratoscale/logserver/router"
"github.com/Stratoscale/logserver/route"
"github.com/Stratoscale/logserver/source"
"github.com/bakins/logrus-middleware"
"github.com/gorilla/mux"
)

var log = logrus.WithField("pkg", "main")
Expand Down Expand Up @@ -46,6 +47,7 @@ type config struct {
Parsers []parse.Config `json:"parsers"`
Dynamic dynamic.Config `json:"dynamic"`
Cache cache.Config `json:"cache"`
Route route.Config `json:"route"`
}

func (c config) journal() string {
Expand Down Expand Up @@ -91,33 +93,36 @@ func main() {

cache := cache.New(cfg.Cache)

var h http.Handler
r := mux.NewRouter()
route.Static(r, cfg.Route)

if !options.dynamic {
s, err := source.New(cfg.Sources, cache)
failOnErr(err, "Creating config")
defer s.CloseSources()

h, err = router.New(router.Config{
Engine: engine.New(cfg.Global, s, parser, cache),
})
failOnErr(err, "Creating router")
failOnErr(route.Index(r, cfg.Route), "Creating index")
route.Engine(r, cfg.Route, engine.New(cfg.Global, s, parser, cache))

} else {
var err error
h, err = dynamic.New(cfg.Dynamic, cfg.Global, parser, cache)
h, err := dynamic.New(cfg.Dynamic, cfg.Global, cfg.Route, parser, cache)
failOnErr(err, "Creating dynamic handler")
logMW := logrusmiddleware.Middleware{Logger: log.Logger}
h = logMW.Handler(h, "")
r.PathPrefix(cfg.Route.RootPath).Handler(http.StripPrefix(cfg.Route.RootPath, h))
}

log.Infof("Serving on http://%s", options.addr)
m := http.NewServeMux()
m.Handle("/", h)
// add debug handlers
if options.debug {
debug.PProfHandle(m)
debug.PProfHandle(r)
}

err = http.ListenAndServe(options.addr, m)
// add redirect of request that are not to the proxy path
route.Redirect(r, cfg.Route)

log.Infof("Serving on http://%s", options.addr)
err = http.ListenAndServe(options.addr, r)
failOnErr(err, "Serving")
}

Expand Down
10 changes: 2 additions & 8 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/Sirupsen/logrus"
"github.com/Stratoscale/logserver/engine"
"github.com/Stratoscale/logserver/parse"
"github.com/Stratoscale/logserver/router"
"github.com/Stratoscale/logserver/source"
"github.com/bluele/gcache"
"github.com/gorilla/websocket"
Expand Down Expand Up @@ -40,12 +39,7 @@ func TestHandler(t *testing.T) {
parser, err := parse.New(cfg.Parsers)
require.Nil(t, err)

h, err := router.New(router.Config{
Engine: engine.New(engine.Config{}, sources, parser, cache),
})
require.Nil(t, err)

s := httptest.NewServer(h)
s := httptest.NewServer(engine.New(engine.Config{}, sources, parser, cache))
defer s.Close()

tests := []struct {
Expand Down Expand Up @@ -317,7 +311,7 @@ func TestHandler(t *testing.T) {
},
}

addr := "ws://" + s.Listener.Addr().String() + "/_ws"
addr := "ws://" + s.Listener.Addr().String()

for _, tt := range tests {
tt := tt
Expand Down
88 changes: 88 additions & 0 deletions route/route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package route

import (
"bytes"
"fmt"
"net/http"
"path/filepath"
"text/template"

"strings"

"github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
)

const (
pathStatic = "/_static"
pathWS = "/_ws"
)

var (
indexTemplate = template.Must(template.ParseFiles("./client/dist/index.html"))
log = logrus.WithField("pkg", "router")
)

type Config struct {
BasePath string `json:"base_path"`
RootPath string `json:"root_path"`
}

func Static(r *mux.Router, c Config) {
var (
static = http.FileServer(http.Dir("./client/dist"))
path = filepath.Join(c.RootPath, pathStatic)
)
log.Infof("Adding static file serving on %s", path)
r.PathPrefix(path + "/").Handler(http.StripPrefix(path, static))
}

func Index(r *mux.Router, c Config) error {

if c.BasePath == "" && c.RootPath != "" {
c.BasePath = c.RootPath
}

var index = bytes.NewBuffer(nil)
if err := indexTemplate.Execute(index, c); err != nil {
return fmt.Errorf("executing index template: %s", err)
}

path := c.RootPath
if len(path) == 0 || path[len(path)-1] != '/' {
path += "/"
}

log.Infof("Adding index route on %s", path)
r.Path(path).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
if _, err := w.Write(index.Bytes()); err != nil {
log.WithError(err).Errorf("Writing index to response")
}
})
return nil
}

func Engine(r *mux.Router, c Config, engine http.Handler) {
path := filepath.Join(c.RootPath, pathWS)
log.Debugf("Adding engine route on %s", path)
r.Path(path).Handler(engine)
}

func Redirect(r *mux.Router, c Config) {
if c.RootPath == "" {
return
}
r.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, c.RootPath) {
http.NotFound(w, r)
return
}
dest := filepath.Join(c.RootPath, r.URL.Path)
if len(r.URL.Path) == 0 || r.URL.Path[len(r.URL.Path)-1] == '/' {
dest += "/"
}
log.Printf("Redirecting to %s", dest)
http.Redirect(w, r, dest, http.StatusTemporaryRedirect)
})
}
50 changes: 0 additions & 50 deletions router/router.go

This file was deleted.

0 comments on commit 8b54071

Please sign in to comment.