├── examples
├── ego
│ ├── public
│ │ ├── css
│ │ │ └── base.css
│ │ ├── js
│ │ │ └── base.js
│ │ ├── src
│ │ │ ├── icons
│ │ │ │ ├── font.ttf
│ │ │ │ └── icon.vgo
│ │ │ └── toast
│ │ │ │ ├── toast.css
│ │ │ │ └── toast.js
│ │ ├── head.vgo
│ │ ├── head
│ │ │ └── head.vgo
│ │ ├── layout.html
│ │ └── banner.vgo
│ ├── views
│ │ ├── css
│ │ │ └── base.css
│ │ ├── src
│ │ │ ├── icons
│ │ │ │ └── font.ttf
│ │ │ └── toast
│ │ │ │ ├── toast.css
│ │ │ │ └── toast.js
│ │ ├── html
│ │ │ ├── head_head.html
│ │ │ └── banner.html
│ │ └── js
│ │ │ └── ajax.js
│ └── main.go
├── app-engine
│ ├── app.yaml
│ ├── hello.go
│ └── README.md
├── grpc
│ ├── README.md
│ ├── grpc
│ │ └── server.go
│ ├── ego
│ │ └── main.go
│ └── pb
│ │ ├── helloworld.proto
│ │ └── helloworld.pb.go
├── auto-tls
│ ├── example1.go
│ └── example2
│ │ └── example2.go
├── basic
│ ├── main_test.go
│ └── main.go
├── upload-file
│ ├── single
│ │ ├── public
│ │ │ └── index.html
│ │ └── main.go
│ └── multiple
│ │ ├── public
│ │ └── index.html
│ │ └── main.go
├── realtime-advanced
│ ├── rooms.go
│ ├── main.go
│ ├── stats.go
│ ├── routes.go
│ └── resources
│ │ └── static
│ │ ├── prismjs.min.css
│ │ └── realtime.js
├── template
│ └── main.go
├── realtime-chat
│ ├── rooms.go
│ ├── main.go
│ └── template.go
├── graceful-shutdown
│ ├── close
│ │ └── server.go
│ └── graceful-shutdown
│ │ └── server.go
├── multiple-service
│ └── main.go
└── custom-validation
│ └── server.go
├── codecov.yml
├── mid
├── rego
│ ├── router.go
│ ├── base.go
│ ├── data.go
│ ├── doc.go
│ ├── fmt.go
│ ├── html.go
│ ├── lexer.go
│ ├── uncss.go
│ ├── mincss.go
│ ├── min.go
│ ├── compile.go
│ ├── js.go
│ ├── css.go
│ ├── trim.go
│ ├── find.go
│ ├── file.go
│ └── fn.go
├── binding
│ ├── example
│ │ ├── test.proto
│ │ └── test.pb.go
│ ├── query.go
│ ├── xml.go
│ ├── msgpack.go
│ ├── protobuf.go
│ ├── json.go
│ ├── form.go
│ ├── binding_body_test.go
│ ├── default_validator.go
│ └── binding.go
├── new_test.go
├── json
│ ├── json.go
│ └── jsoniter.go
├── render
│ ├── data.go
│ ├── xml.go
│ ├── redirect.go
│ ├── yaml.go
│ ├── msgpack.go
│ ├── text.go
│ ├── reader.go
│ ├── render.go
│ ├── ffjson.go
│ ├── jsoniter.go
│ ├── html.go
│ └── json.go
├── new.go
├── util
│ ├── fs.go
│ ├── path_test.go
│ ├── path.go
│ ├── errors_test.go
│ └── errors.go
├── recovery_test.go
├── recovery.go
└── logger.go
├── test
├── basic
│ ├── hello.tmpl
│ └── raw.tmpl
├── testdata
│ ├── cert.pem
│ └── key.pem
└── benchmarks_test.go
├── .github
├── CONTRIBUTING.md
├── issue_template.md
└── pull_request_template.md
├── img
├── head.png
└── test.png
├── context_appengine.go
├── docs
├── doc.go
├── doc.md
├── CHANGELOG.md
└── AUTHORS.md
├── egoS
├── README.md
└── egos.go
├── circle.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── mode.go
├── recovery_test.go
├── Gopkg.toml
├── debug.go
├── auth.go
├── response_writer.go
├── recovery.go
├── debug_test.go
├── utils_test.go
├── response_writer_test.go
├── utils.go
├── logger.go
├── CONTRIBUTING.md
└── routergroup_test.go
/examples/ego/public/css/base.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/ego/public/js/base.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/ego/views/css/base.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | # codecov:
2 | # token:
--------------------------------------------------------------------------------
/mid/rego/router.go:
--------------------------------------------------------------------------------
1 | package rego
2 |
--------------------------------------------------------------------------------
/test/basic/hello.tmpl:
--------------------------------------------------------------------------------
1 |
Hello {[{.name}]}
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Ego
2 |
3 |
--------------------------------------------------------------------------------
/test/basic/raw.tmpl:
--------------------------------------------------------------------------------
1 | Date: {[{.now | formatAsDate}]}
2 |
--------------------------------------------------------------------------------
/img/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-ego/ego/HEAD/img/head.png
--------------------------------------------------------------------------------
/img/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-ego/ego/HEAD/img/test.png
--------------------------------------------------------------------------------
/context_appengine.go:
--------------------------------------------------------------------------------
1 | // +build appengine
2 |
3 | package ego
4 |
5 | func init() {
6 | defaultAppEngine = true
7 | }
8 |
--------------------------------------------------------------------------------
/examples/ego/public/src/icons/font.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-ego/ego/HEAD/examples/ego/public/src/icons/font.ttf
--------------------------------------------------------------------------------
/examples/ego/views/src/icons/font.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-ego/ego/HEAD/examples/ego/views/src/icons/font.ttf
--------------------------------------------------------------------------------
/docs/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package ego Go open-source, high-performance, modular, full-stack web framework.
3 |
4 | Please make sure
5 | */
6 |
7 | package ego
8 |
--------------------------------------------------------------------------------
/examples/app-engine/app.yaml:
--------------------------------------------------------------------------------
1 | application: hello
2 | version: 1
3 | runtime: go
4 | api_version: go1
5 |
6 | handlers:
7 | - url: /.*
8 | script: _go_app
--------------------------------------------------------------------------------
/examples/ego/public/head.vgo:
--------------------------------------------------------------------------------
1 |
2 | import (
3 | "icons"
4 | icon "icons/icon.vgo"
5 | )
6 |
7 |
8 |
{title}
9 |
{ahead}
10 |
11 |
12 | ...
13 |
14 |
15 |
16 |
17 |
18 | //
19 |
20 |
21 | ...
22 |
--------------------------------------------------------------------------------
/mid/binding/example/test.proto:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | enum FOO {X=17;};
4 |
5 | message Test {
6 | required string label = 1;
7 | optional int32 type = 2[default=77];
8 | repeated int64 reps = 3;
9 | optional group OptionalGroup = 4{
10 | required string RequiredField = 5;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/egoS/README.md:
--------------------------------------------------------------------------------
1 | # Ego Default Server
2 |
3 | This is API experiment for Ego.
4 |
5 | ```go
6 | package main
7 |
8 | import (
9 | "github.com/go-ego/ego"
10 | "github.com/go-ego/ego/egoS"
11 | )
12 |
13 | func main() {
14 | egoS.GET("/", func(c *ego.Context) { c.String(200, "Hello World") })
15 | egoS.Run()
16 | }
17 | ```
18 |
--------------------------------------------------------------------------------
/examples/grpc/README.md:
--------------------------------------------------------------------------------
1 | ## How to run this example
2 |
3 | 1. run grpc server
4 |
5 | ```sh
6 | $ go run grpc/server.go
7 | ```
8 |
9 | 2. run ego server
10 |
11 | ```sh
12 | $ go run ego/main.go
13 | ```
14 |
15 | 3. use curl command to test it
16 |
17 | ```sh
18 | $ curl -v 'http://localhost:8052/rest/n/thinkerou'
19 | ```
20 |
--------------------------------------------------------------------------------
/examples/ego/public/src/icons/icon.vgo:
--------------------------------------------------------------------------------
1 | // pkg icon
2 |
3 |
7 |
8 |
23 |
--------------------------------------------------------------------------------
/examples/auto-tls/example1.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 |
6 | "github.com/go-ego/autotls"
7 | "github.com/go-ego/ego"
8 | )
9 |
10 | func main() {
11 | r := ego.Default()
12 |
13 | // Ping handler
14 | r.GET("/ping", func(c *ego.Context) {
15 | c.String(200, "pong")
16 | })
17 |
18 | log.Fatal(autotls.Run(r, "example1.com", "example2.com"))
19 | }
20 |
--------------------------------------------------------------------------------
/docs/doc.md:
--------------------------------------------------------------------------------
1 | ## import
2 |
3 | ```html
4 |
5 | import (
6 | "icons"
7 | icon "icons/icon.vgo"
8 | )
9 |
10 |
11 |
ego:{{.head}}
12 |
13 |
14 | vclass={icon-share-to}
15 | node={ id="slot1"}
16 | prpo={node---1}
17 |
18 |
19 |
20 | {{range .parArr}}
21 |
arr::: {{.}}
22 | {{end}}
23 |
24 |
25 |
26 | ```
--------------------------------------------------------------------------------
/examples/ego/public/head/head.vgo:
--------------------------------------------------------------------------------
1 | // pkg head
2 |
3 | import (
4 | "icons"
5 | icon "icons/icon.vgo"
6 | )
7 |
8 |
9 |
ego:{{.head}}
10 |
11 |
12 | vclass={icon-share-to}
13 | node={ id="slot1"}
14 | prpo={node---1}
15 |
16 |
17 |
18 | {{range .parArr}}
19 |
arr::: {{.}}
20 | {{end}}
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/ego/public/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | my-ego
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/mid/new_test.go:
--------------------------------------------------------------------------------
1 | package mid
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-ego/ego"
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestCreateDefaultRouter(t *testing.T) {
11 | router := ego.Default()
12 | assert.Len(t, router.Handlers, 2)
13 | }
14 |
15 | func TestCreateClassicRouter(t *testing.T) {
16 | router := ego.Classic()
17 | assert.Len(t, router.Handlers, 2)
18 | }
19 |
--------------------------------------------------------------------------------
/mid/json/json.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Bo-Yi Wu. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build !jsoniter
6 |
7 | package json
8 |
9 | import (
10 | "encoding/json"
11 | )
12 |
13 | var (
14 | Marshal = json.Marshal
15 | MarshalIndent = json.MarshalIndent
16 | NewDecoder = json.NewDecoder
17 | )
18 |
--------------------------------------------------------------------------------
/examples/basic/main_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net/http"
5 | "net/http/httptest"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestPingRoute(t *testing.T) {
12 | router := setupRouter()
13 |
14 | w := httptest.NewRecorder()
15 | req, _ := http.NewRequest("GET", "/ping", nil)
16 | router.ServeHTTP(w, req)
17 |
18 | assert.Equal(t, 200, w.Code)
19 | assert.Equal(t, "pong", w.Body.String())
20 | }
21 |
--------------------------------------------------------------------------------
/mid/json/jsoniter.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Bo-Yi Wu. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build jsoniter
6 |
7 | package json
8 |
9 | import (
10 | "github.com/json-iterator/go"
11 | )
12 |
13 | var (
14 | json = jsoniter.ConfigCompatibleWithStandardLibrary
15 | Marshal = json.Marshal
16 | MarshalIndent = json.MarshalIndent
17 | NewDecoder = json.NewDecoder
18 | )
19 |
--------------------------------------------------------------------------------
/examples/upload-file/single/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Single file upload
6 |
7 |
8 | Upload single file with fields
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/mid/rego/base.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/data.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/doc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/fmt.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/html.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/lexer.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/uncss.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/mid/rego/mincss.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
--------------------------------------------------------------------------------
/examples/upload-file/multiple/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Multiple file upload
6 |
7 |
8 | Upload multiple files with fields
9 |
10 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/mid/binding/query.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import "net/http"
8 |
9 | type queryBinding struct{}
10 |
11 | func (queryBinding) Name() string {
12 | return "query"
13 | }
14 |
15 | func (queryBinding) Bind(req *http.Request, obj interface{}) error {
16 | values := req.URL.Query()
17 | if err := mapForm(obj, values); err != nil {
18 | return err
19 | }
20 | return validate(obj)
21 | }
22 |
--------------------------------------------------------------------------------
/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ## Ego 0.10.0, Nile River
4 |
5 | ### Add
6 |
7 | - [NEW] Add TestFile
8 | - [NEW] Add \*context.ShouldBindWith()
9 | - [NEW] Add custom template delimiters
10 | - [NEW] Add more test: Add middleware_test and other
11 | - [NEW] Add circleci
12 |
13 | ### Update
14 |
15 | - Update vendor.json
16 | - Update name and refactoring
17 | - Update examples json.html
18 | - Update Build-tools name
19 | - Update and Cleanup README.md
20 | - Move changelog.md and authors.md
21 |
22 | ### Fix
23 |
24 | - Fix handlers registered
25 | - Fix time binding
26 |
27 |
--------------------------------------------------------------------------------
/examples/app-engine/hello.go:
--------------------------------------------------------------------------------
1 | package hello
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/go-ego/ego"
7 | )
8 |
9 | // This function's name is a must. App engine uses it to drive the requests properly.
10 | func init() {
11 | // Starts a new ego instance with no middle-ware
12 | r := ego.New()
13 |
14 | // Define your handlers
15 | r.GET("/", func(c *ego.Context) {
16 | c.String(http.StatusOK, "Hello World!")
17 | })
18 | r.GET("/ping", func(c *ego.Context) {
19 | c.String(http.StatusOK, "pong")
20 | })
21 |
22 | // Handle all requests using net/http
23 | http.Handle("/", r)
24 | }
25 |
--------------------------------------------------------------------------------
/docs/AUTHORS.md:
--------------------------------------------------------------------------------
1 | List of all the awesome people working to make Ego the best Web Framework in Go.
2 |
3 | @[vz](https://github.com/vcaesar)
4 |
5 | See [contributors page](https://github.com/go-ego/ego/graphs/contributors)for full list of contributors
6 |
7 |
8 | List of all the awesome people working to make Gin the best Web Framework in Go.
9 |
10 | ## gin 0.x series authors
11 |
12 | **Maintainer:** Manu Martinez-Almeida (@manucorporat), Javier Provecho (@javierprovecho)
13 |
14 | See [contributors page](https://github.com/gin-gonic/gin/graphs/contributors)for full list of contributors.
15 |
16 |
--------------------------------------------------------------------------------
/examples/auto-tls/example2/example2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 |
6 | "github.com/go-ego/autotls"
7 | "github.com/go-ego/ego"
8 | "golang.org/x/crypto/acme/autocert"
9 | )
10 |
11 | func main() {
12 | r := ego.Default()
13 |
14 | // Ping handler
15 | r.GET("/ping", func(c *ego.Context) {
16 | c.String(200, "pong")
17 | })
18 |
19 | m := autocert.Manager{
20 | Prompt: autocert.AcceptTOS,
21 | HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"),
22 | Cache: autocert.DirCache("/var/www/.cache"),
23 | }
24 |
25 | log.Fatal(autotls.RunWithManager(r, &m))
26 | }
27 |
--------------------------------------------------------------------------------
/mid/render/data.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import "net/http"
8 |
9 | type Data struct {
10 | ContentType string
11 | Data []byte
12 | }
13 |
14 | // Render (Data) writes data with custom ContentType.
15 | func (r Data) Render(w http.ResponseWriter) (err error) {
16 | r.WriteContentType(w)
17 | _, err = w.Write(r.Data)
18 | return
19 | }
20 |
21 | func (r Data) WriteContentType(w http.ResponseWriter) {
22 | writeContentType(w, []string{r.ContentType})
23 | }
24 |
--------------------------------------------------------------------------------
/examples/app-engine/README.md:
--------------------------------------------------------------------------------
1 | # Guide to run ego under App Engine LOCAL Development Server
2 |
3 | 1. Download, install and setup Go in your computer. (That includes setting your `$GOPATH`.)
4 | 2. Download SDK for your platform from [here](https://cloud.google.com/appengine/docs/standard/go/download): `https://cloud.google.com/appengine/docs/standard/go/download`
5 | 3. Download ego source code using: `$ go get github.com/go-ego/ego`
6 | 4. Navigate to examples folder: `$ cd $GOPATH/src/github.com/go-ego/ego/examples//app-engine`
7 |
8 | 5. Run it: `$ dev_appserver.py .` (notice that you have to run this script by Python2)
--------------------------------------------------------------------------------
/mid/render/xml.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import (
8 | "encoding/xml"
9 | "net/http"
10 | )
11 |
12 | type XML struct {
13 | Data interface{}
14 | }
15 |
16 | var xmlContentType = []string{"application/xml; charset=utf-8"}
17 |
18 | func (r XML) Render(w http.ResponseWriter) error {
19 | r.WriteContentType(w)
20 | return xml.NewEncoder(w).Encode(r.Data)
21 | }
22 |
23 | func (r XML) WriteContentType(w http.ResponseWriter) {
24 | writeContentType(w, xmlContentType)
25 | }
26 |
--------------------------------------------------------------------------------
/examples/realtime-advanced/rooms.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "github.com/dustin/go-broadcast"
4 |
5 | var roomChannels = make(map[string]broadcast.Broadcaster)
6 |
7 | func openListener(roomid string) chan interface{} {
8 | listener := make(chan interface{})
9 | room(roomid).Register(listener)
10 | return listener
11 | }
12 |
13 | func closeListener(roomid string, listener chan interface{}) {
14 | room(roomid).Unregister(listener)
15 | close(listener)
16 | }
17 |
18 | func room(roomid string) broadcast.Broadcaster {
19 | b, ok := roomChannels[roomid]
20 | if !ok {
21 | b = broadcast.NewBroadcaster(10)
22 | roomChannels[roomid] = b
23 | }
24 | return b
25 | }
26 |
--------------------------------------------------------------------------------
/mid/new.go:
--------------------------------------------------------------------------------
1 | package mid
2 |
3 | import (
4 | "github.com/go-ego/ego"
5 | // "github.com/go-ego/ego/mid/logger"
6 | )
7 |
8 | // Classic returns an Engine instance with the Logger and Recovery middleware already attached.
9 | func Classic() *ego.Engine {
10 | engine := ego.New()
11 | engine.Use(Logger(), Recovery())
12 | // engine.Use(logger.Logger(), logger.Recovery())
13 | return engine
14 | }
15 |
16 | // Default returns an Engine instance with the Logger and Recovery middleware already attached.
17 | func Default() *ego.Engine {
18 | engine := ego.New()
19 | engine.Use(Logger(), Recovery())
20 | // engine.Use(logger.Logger(), logger.Recovery())
21 | return engine
22 | }
23 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | # circle.yml #
2 | # machine:
3 | # go:
4 | # version: 1.9.1
5 |
6 | version: 2
7 |
8 | jobs:
9 | build:
10 | docker:
11 | - image: govgo/go:1.10.3
12 | working_directory: /gopath/src/github.com/go-ego/ego
13 | steps:
14 | - checkout
15 | # specify any bash command here prefixed with `run: `
16 | - run: go get -v -t -d ./...
17 | - run: go test -v ./...
18 | # codecov.io
19 | - run: go test -v -covermode=count -coverprofile=coverage.out
20 | - run: bash <(curl -s https://codecov.io/bash)
21 |
22 | # test:
23 | # post:
24 | # - go test -v -covermode=count -coverprofile=coverage.out
25 | # - bash <(curl -s https://codecov.io/bash)
26 |
--------------------------------------------------------------------------------
/mid/render/redirect.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import (
8 | "fmt"
9 | "net/http"
10 | )
11 |
12 | type Redirect struct {
13 | Code int
14 | Request *http.Request
15 | Location string
16 | }
17 |
18 | func (r Redirect) Render(w http.ResponseWriter) error {
19 | if (r.Code < 300 || r.Code > 308) && r.Code != 201 {
20 | panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code))
21 | }
22 | http.Redirect(w, r.Request, r.Location, r.Code)
23 | return nil
24 | }
25 |
26 | func (r Redirect) WriteContentType(http.ResponseWriter) {}
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | .DS_Store
3 | .vscode
4 | .idea
5 | testf
6 |
7 | vendor
8 |
9 | # Debug files
10 | *.dSYM/
11 | *.su
12 | debug
13 |
14 | # Architecture specific extensions/prefixes
15 | *.[568vq]
16 | [568vq].out
17 |
18 | *.cgo1.go
19 | *.cgo2.c
20 | _cgo_defun.c
21 | _cgo_gotypes.go
22 | _cgo_export.*
23 |
24 | _testmain.go
25 |
26 | *.o
27 | *.ko
28 | *.obj
29 | *.elf
30 |
31 | # Precompiled Headers
32 | *.gch
33 | *.pch
34 |
35 | # Libraries
36 | *.lib
37 | *.a
38 | *.la
39 | *.lo
40 |
41 | # Shared objects (inc. Windows DLLs)
42 | *.dll
43 | *.so
44 | *.so.*
45 | *.dylib
46 |
47 | # Executables
48 | *.exe
49 | *.out
50 | *.app
51 | *.i*86
52 | *.x86_64
53 | *.hex
54 |
--------------------------------------------------------------------------------
/examples/ego/public/src/toast/toast.css:
--------------------------------------------------------------------------------
1 | .toast-container {
2 | position: fixed;
3 | z-index: 9999;
4 | /* bottom: 60px; */
5 | top: 10rem;
6 | width: 100%;
7 | -webkit-transition: opacity .8s;
8 | transition: opacity .8s;
9 | opacity: 0;
10 | }
11 |
12 | .toast-container.active {
13 | opacity: 0.8;
14 | }
15 |
16 | .toast-msg {
17 | width: 5.5rem;
18 | height: 5.5rem;
19 | margin: 2px auto;
20 | padding: 10px;
21 | text-align: center;
22 | border-radius: 7px;
23 | background-color: #343434;
24 | color: #ffffff;
25 | font-size: 2.6rem;
26 | /* background-color: #d8d8d8;
27 | color: #555; */
28 | }
29 |
30 | .toast-text {
31 | font-size: 1.8rem;
32 | margin-top: 8px;
33 | }
34 |
--------------------------------------------------------------------------------
/examples/ego/views/src/toast/toast.css:
--------------------------------------------------------------------------------
1 | .toast-container {
2 | position: fixed;
3 | z-index: 9999;
4 | /* bottom: 60px; */
5 | top: 10rem;
6 | width: 100%;
7 | -webkit-transition: opacity .8s;
8 | transition: opacity .8s;
9 | opacity: 0;
10 | }
11 |
12 | .toast-container.active {
13 | opacity: 0.8;
14 | }
15 |
16 | .toast-msg {
17 | width: 5.5rem;
18 | height: 5.5rem;
19 | margin: 2px auto;
20 | padding: 10px;
21 | text-align: center;
22 | border-radius: 7px;
23 | background-color: #343434;
24 | color: #ffffff;
25 | font-size: 2.6rem;
26 | /* background-color: #d8d8d8;
27 | color: #555; */
28 | }
29 |
30 | .toast-text {
31 | font-size: 1.8rem;
32 | margin-top: 8px;
33 | }
34 |
--------------------------------------------------------------------------------
/examples/template/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "html/template"
6 | "net/http"
7 | "time"
8 |
9 | "github.com/go-ego/ego"
10 | )
11 |
12 | func formatAsDate(t time.Time) string {
13 | year, month, day := t.Date()
14 | return fmt.Sprintf("%d%02d/%02d", year, month, day)
15 | }
16 |
17 | func main() {
18 | router := ego.Default()
19 | router.Delims("{[{", "}]}")
20 | router.SetFuncMap(template.FuncMap{
21 | "formatAsDate": formatAsDate,
22 | })
23 | router.LoadHTMLFiles("../../test/basic/raw.tmpl")
24 |
25 | router.GET("/raw", func(c *ego.Context) {
26 | c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{
27 | "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
28 | })
29 | })
30 |
31 | router.Run(":8080")
32 | }
33 |
--------------------------------------------------------------------------------
/mid/render/yaml.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import (
8 | "net/http"
9 |
10 | "gopkg.in/yaml.v2"
11 | )
12 |
13 | type YAML struct {
14 | Data interface{}
15 | }
16 |
17 | var yamlContentType = []string{"application/x-yaml; charset=utf-8"}
18 |
19 | func (r YAML) Render(w http.ResponseWriter) error {
20 | r.WriteContentType(w)
21 |
22 | bytes, err := yaml.Marshal(r.Data)
23 | if err != nil {
24 | return err
25 | }
26 |
27 | w.Write(bytes)
28 | return nil
29 | }
30 |
31 | func (r YAML) WriteContentType(w http.ResponseWriter) {
32 | writeContentType(w, yamlContentType)
33 | }
34 |
--------------------------------------------------------------------------------
/examples/realtime-chat/rooms.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "github.com/dustin/go-broadcast"
4 |
5 | var roomChannels = make(map[string]broadcast.Broadcaster)
6 |
7 | func openListener(roomid string) chan interface{} {
8 | listener := make(chan interface{})
9 | room(roomid).Register(listener)
10 | return listener
11 | }
12 |
13 | func closeListener(roomid string, listener chan interface{}) {
14 | room(roomid).Unregister(listener)
15 | close(listener)
16 | }
17 |
18 | func deleteBroadcast(roomid string) {
19 | b, ok := roomChannels[roomid]
20 | if ok {
21 | b.Close()
22 | delete(roomChannels, roomid)
23 | }
24 | }
25 |
26 | func room(roomid string) broadcast.Broadcaster {
27 | b, ok := roomChannels[roomid]
28 | if !ok {
29 | b = broadcast.NewBroadcaster(10)
30 | roomChannels[roomid] = b
31 | }
32 | return b
33 | }
34 |
--------------------------------------------------------------------------------
/mid/binding/xml.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import (
8 | "bytes"
9 | "encoding/xml"
10 | "io"
11 | "net/http"
12 | )
13 |
14 | type xmlBinding struct{}
15 |
16 | func (xmlBinding) Name() string {
17 | return "xml"
18 | }
19 |
20 | func (xmlBinding) Bind(req *http.Request, obj interface{}) error {
21 | return decodeXML(req.Body, obj)
22 | }
23 |
24 | func (xmlBinding) BindBody(body []byte, obj interface{}) error {
25 | return decodeXML(bytes.NewReader(body), obj)
26 | }
27 | func decodeXML(r io.Reader, obj interface{}) error {
28 | decoder := xml.NewDecoder(r)
29 | if err := decoder.Decode(obj); err != nil {
30 | return err
31 | }
32 | return validate(obj)
33 | }
34 |
--------------------------------------------------------------------------------
/examples/realtime-advanced/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "runtime"
6 |
7 | "github.com/go-ego/ego"
8 | )
9 |
10 | func main() {
11 | ConfigRuntime()
12 | StartWorkers()
13 | StartEgo()
14 | }
15 |
16 | func ConfigRuntime() {
17 | nuCPU := runtime.NumCPU()
18 | runtime.GOMAXPROCS(nuCPU)
19 | fmt.Printf("Running with %d CPUs\n", nuCPU)
20 | }
21 |
22 | func StartWorkers() {
23 | go statsWorker()
24 | }
25 |
26 | func StartEgo() {
27 | ego.SetMode(ego.ReleaseMode)
28 |
29 | router := ego.New()
30 | router.Use(rateLimit, ego.Recovery())
31 | router.LoadHTMLGlob("resources/*.templ.html")
32 | router.Static("/static", "resources/static")
33 | router.GET("/", index)
34 | router.GET("/room/:roomid", roomGET)
35 | router.POST("/room-post/:roomid", roomPOST)
36 | router.GET("/stream/:roomid", streamRoom)
37 |
38 | router.Run(":80")
39 | }
40 |
--------------------------------------------------------------------------------
/mid/render/msgpack.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import (
8 | "net/http"
9 |
10 | "github.com/ugorji/go/codec"
11 | )
12 |
13 | type MsgPack struct {
14 | Data interface{}
15 | }
16 |
17 | var msgpackContentType = []string{"application/msgpack; charset=utf-8"}
18 |
19 | func (r MsgPack) WriteContentType(w http.ResponseWriter) {
20 | writeContentType(w, msgpackContentType)
21 | }
22 |
23 | func (r MsgPack) Render(w http.ResponseWriter) error {
24 | return WriteMsgPack(w, r.Data)
25 | }
26 |
27 | func WriteMsgPack(w http.ResponseWriter, obj interface{}) error {
28 | writeContentType(w, msgpackContentType)
29 | var h codec.Handle = new(codec.MsgpackHandle)
30 | return codec.NewEncoder(w, h).Encode(obj)
31 | }
32 |
--------------------------------------------------------------------------------
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 | 1. Please speak English, this is the language everybody of us can speak and write.
2 | 2. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-ego/ego
3 | 3. Please take a moment to search that an issue doesn't already exist.
4 | 4. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report.
5 |
6 | **You MUST delete the content above including this line before posting, otherwise your issue will be invalid.**
7 |
8 | - Ego version (or commit ref):
9 | - Go version:
10 | - Gcc version:
11 | - Operating system and bit:
12 | - Can you reproduce the bug at [Examples](https://github.com/go-ego/ego/tree/master/examples):
13 | - [ ] Yes (provide example code)
14 | - [ ] No
15 | - [ ] Not relevant
16 | - Provide example code:
17 | ```Go
18 |
19 | ```
20 | - Log gist:
21 |
22 | ## Description
23 |
24 | ...
25 |
--------------------------------------------------------------------------------
/mid/render/text.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import (
8 | "fmt"
9 | "io"
10 | "net/http"
11 | )
12 |
13 | type String struct {
14 | Format string
15 | Data []interface{}
16 | }
17 |
18 | var plainContentType = []string{"text/plain; charset=utf-8"}
19 |
20 | func (r String) Render(w http.ResponseWriter) error {
21 | WriteString(w, r.Format, r.Data)
22 | return nil
23 | }
24 |
25 | func (r String) WriteContentType(w http.ResponseWriter) {
26 | writeContentType(w, plainContentType)
27 | }
28 |
29 | func WriteString(w http.ResponseWriter, format string, data []interface{}) {
30 | writeContentType(w, plainContentType)
31 | if len(data) > 0 {
32 | fmt.Fprintf(w, format, data...)
33 | } else {
34 | io.WriteString(w, format)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/examples/ego/public/banner.vgo:
--------------------------------------------------------------------------------
1 | import (
2 | "toast"
3 | head "head.vgo"
4 |
5 | "icons"
6 | icon "icons/icon.vgo"
7 | )
8 |
9 |
10 |
11 | title={go,go,go}
12 | ahead="{{.head}}"
13 | node={id="head-11"}
14 |
15 |
16 |
17 |
18 |
19 | vclass={icon-share-to}
20 | node={ slot1}
21 | prpo={node---1}
22 |
23 |
24 |
25 |
29 |
30 |
31 | banner
32 |
33 |
34 |
37 |
38 |
52 |
53 |
--------------------------------------------------------------------------------
/mid/binding/msgpack.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import (
8 | "bytes"
9 | "io"
10 | "net/http"
11 |
12 | "github.com/ugorji/go/codec"
13 | )
14 |
15 | type msgpackBinding struct{}
16 |
17 | func (msgpackBinding) Name() string {
18 | return "msgpack"
19 | }
20 |
21 | func (msgpackBinding) Bind(req *http.Request, obj interface{}) error {
22 | return decodeMsgPack(req.Body, obj)
23 | }
24 |
25 | func (msgpackBinding) BindBody(body []byte, obj interface{}) error {
26 | return decodeMsgPack(bytes.NewReader(body), obj)
27 | }
28 |
29 | func decodeMsgPack(r io.Reader, obj interface{}) error {
30 | cdc := new(codec.MsgpackHandle)
31 | if err := codec.NewDecoder(r, cdc).Decode(&obj); err != nil {
32 | return err
33 | }
34 | return validate(obj)
35 | }
36 |
--------------------------------------------------------------------------------
/mid/render/reader.go:
--------------------------------------------------------------------------------
1 | package render
2 |
3 | import (
4 | "io"
5 | "net/http"
6 | "strconv"
7 | )
8 |
9 | type Reader struct {
10 | ContentType string
11 | ContentLength int64
12 | Reader io.Reader
13 | Headers map[string]string
14 | }
15 |
16 | // Render (Reader) writes data with custom ContentType and headers.
17 | func (r Reader) Render(w http.ResponseWriter) (err error) {
18 | r.WriteContentType(w)
19 | r.Headers["Content-Length"] = strconv.FormatInt(r.ContentLength, 10)
20 | r.writeHeaders(w, r.Headers)
21 | _, err = io.Copy(w, r.Reader)
22 | return
23 | }
24 |
25 | func (r Reader) WriteContentType(w http.ResponseWriter) {
26 | writeContentType(w, []string{r.ContentType})
27 | }
28 |
29 | func (r Reader) writeHeaders(w http.ResponseWriter, headers map[string]string) {
30 | header := w.Header()
31 | for k, v := range headers {
32 | if val := header[k]; len(val) == 0 {
33 | header[k] = []string{v}
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/examples/grpc/grpc/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net"
6 |
7 | pb "github.com/go-ego/ego/examples/grpc/pb"
8 | "golang.org/x/net/context"
9 | "google.golang.org/grpc"
10 | "google.golang.org/grpc/reflection"
11 | )
12 |
13 | // server is used to implement helloworld.GreeterServer.
14 | type server struct{}
15 |
16 | // SayHello implements helloworld.GreeterServer
17 | func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
18 | return &pb.HelloReply{Message: "Hello " + in.Name}, nil
19 | }
20 |
21 | func main() {
22 | lis, err := net.Listen("tcp", ":50051")
23 | if err != nil {
24 | log.Fatalf("failed to listen: %v", err)
25 | }
26 | s := grpc.NewServer()
27 | pb.RegisterGreeterServer(s, &server{})
28 |
29 | // Register reflection service on gRPC server.
30 | reflection.Register(s)
31 | if err := s.Serve(lis); err != nil {
32 | log.Fatalf("failed to serve: %v", err)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 | sudo: false
3 | go:
4 | # - 1.7.x
5 | - 1.8.x
6 | - 1.9.x
7 | - 1.10.x
8 | - tip
9 |
10 | # env:
11 | # global:
12 | # - GO15VENDOREXPERIMENT=1
13 | # matrix:
14 | # - TARGET=amd64
15 | # - TARGET=arm64
16 | # - TARGET=arm
17 | # - TARGET=386
18 | # - TARGET=ppc64le
19 | go_import_path: github.com/go-ego/ego
20 |
21 | before_install:
22 | - export PATH=$PATH:$HOME/gopath/bin
23 | - go get -t -v ./...
24 |
25 | # script:
26 | # # - ./go.test.sh
27 | # - go test -v -covermode=count -coverprofile=coverage.out
28 |
29 |
30 | # after_success:
31 | # - bash <(curl -s https://codecov.io/bash)
32 |
33 | ###
34 | # notifications:
35 | # webhooks:
36 | # urls:
37 | # - https://webhooks.gitter.im/e/777
38 | # on_success: change # options: [always|never|change] default: always
39 | # on_failure: always # options: [always|never|change] default: always
40 | # on_start: false # default: false
--------------------------------------------------------------------------------
/examples/graceful-shutdown/close/server.go:
--------------------------------------------------------------------------------
1 | // +build go1.8
2 |
3 | package main
4 |
5 | import (
6 | "log"
7 | "net/http"
8 | "os"
9 | "os/signal"
10 |
11 | "github.com/go-ego/ego"
12 | )
13 |
14 | func main() {
15 | router := ego.Default()
16 | router.GET("/", func(c *ego.Context) {
17 | c.String(http.StatusOK, "Welcome ego Server")
18 | })
19 |
20 | server := &http.Server{
21 | Addr: ":8080",
22 | Handler: router,
23 | }
24 |
25 | quit := make(chan os.Signal)
26 | signal.Notify(quit, os.Interrupt)
27 |
28 | go func() {
29 | <-quit
30 | log.Println("receive interrupt signal")
31 | if err := server.Close(); err != nil {
32 | log.Fatal("Server Close:", err)
33 | }
34 | }()
35 |
36 | if err := server.ListenAndServe(); err != nil {
37 | if err == http.ErrServerClosed {
38 | log.Println("Server closed under request")
39 | } else {
40 | log.Fatal("Server closed unexpect")
41 | }
42 | }
43 |
44 | log.Println("Server exiting")
45 | }
46 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | The pull request will be closed without any reasons if it does not satisfy any of following requirements:
2 |
3 | 1. Make sure you are targeting the `master` branch, pull requests on release branches are only allowed for bug fixes.
4 | 2. Please read contributing guidelines: [CONTRIBUTING](https://github.com/go-ego/ego/blob/master/CONTRIBUTING.md)
5 | 3. Describe what your pull request does and which issue you're targeting (if any and Please use English)
6 | 4. ... if it is not related to any particular issues, explain why we should not reject your pull request.
7 | 5. The Commits must use English, must be test and No useless submissions.
8 |
9 | **You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.**
10 |
11 | **Please provide Issues links to:**
12 |
13 | - Issues: #1
14 |
15 | **Provide test code:**
16 |
17 | ```Go
18 |
19 | ```
20 |
21 | ## Description
22 |
23 | ...
24 |
--------------------------------------------------------------------------------
/examples/upload-file/single/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/go-ego/ego"
8 | )
9 |
10 | func main() {
11 | router := ego.Default()
12 | // Set a lower memory limit for multipart forms (default is 32 MiB)
13 | router.MaxMultipartMemory = 8 << 20 // 8 MiB
14 | router.Static("/", "./public")
15 | router.POST("/upload", func(c *ego.Context) {
16 | name := c.PostForm("name")
17 | email := c.PostForm("email")
18 |
19 | // Source
20 | file, err := c.FormFile("file")
21 | if err != nil {
22 | c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
23 | return
24 | }
25 |
26 | if err := c.SaveUploadedFile(file, file.Filename); err != nil {
27 | c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
28 | return
29 | }
30 |
31 | c.String(http.StatusOK, fmt.Sprintf("File %s uploaded successfully with fields name=%s and email=%s.", file.Filename, name, email))
32 | })
33 | router.Run(":8080")
34 | }
35 |
--------------------------------------------------------------------------------
/mid/binding/protobuf.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import (
8 | "io/ioutil"
9 | "net/http"
10 |
11 | "github.com/golang/protobuf/proto"
12 | )
13 |
14 | type protobufBinding struct{}
15 |
16 | func (protobufBinding) Name() string {
17 | return "protobuf"
18 | }
19 |
20 | func (b protobufBinding) Bind(req *http.Request, obj interface{}) error {
21 | buf, err := ioutil.ReadAll(req.Body)
22 | if err != nil {
23 | return err
24 | }
25 | return b.BindBody(buf, obj)
26 | }
27 |
28 | func (protobufBinding) BindBody(body []byte, obj interface{}) error {
29 | if err := proto.Unmarshal(body, obj.(proto.Message)); err != nil {
30 | return err
31 | }
32 | // Here it's same to return validate(obj), but util now we cann't add
33 | // `binding:""` to the struct which automatically generate by gen-proto
34 | return nil
35 | // return validate(obj)
36 | }
37 |
--------------------------------------------------------------------------------
/examples/upload-file/multiple/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/go-ego/ego"
8 | )
9 |
10 | func main() {
11 | router := ego.Default()
12 | // Set a lower memory limit for multipart forms (default is 32 MiB)
13 | router.MaxMultipartMemory = 8 << 20 // 8 MiB
14 | router.Static("/", "./public")
15 | router.POST("/upload", func(c *ego.Context) {
16 | name := c.PostForm("name")
17 | email := c.PostForm("email")
18 |
19 | // Multipart form
20 | form, err := c.MultipartForm()
21 | if err != nil {
22 | c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
23 | return
24 | }
25 | files := form.File["files"]
26 |
27 | for _, file := range files {
28 | if err := c.SaveUploadedFile(file, file.Filename); err != nil {
29 | c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
30 | return
31 | }
32 | }
33 |
34 | c.String(http.StatusOK, fmt.Sprintf("Uploaded successfully %d files with fields name=%s and email=%s.", len(files), name, email))
35 | })
36 | router.Run(":8080")
37 | }
38 |
--------------------------------------------------------------------------------
/mid/render/render.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import "net/http"
8 |
9 | type Render interface {
10 | Render(http.ResponseWriter) error
11 | WriteContentType(w http.ResponseWriter)
12 | }
13 |
14 | var (
15 | _ Render = JSON{}
16 | _ Render = IJSON{}
17 | _ Render = FFJSON{}
18 | _ Render = IndentedJSON{}
19 | _ Render = SecureJSON{}
20 | _ Render = JsonpJSON{}
21 | _ Render = XML{}
22 | _ Render = String{}
23 | _ Render = Redirect{}
24 | _ Render = Data{}
25 | _ Render = HTML{}
26 | _ HTMLRender = HTMLDebug{}
27 | _ HTMLRender = HTMLProduction{}
28 | _ Render = YAML{}
29 | _ Render = MsgPack{}
30 | _ Render = Reader{}
31 | _ Render = AsciiJSON{}
32 | )
33 |
34 | func writeContentType(w http.ResponseWriter, value []string) {
35 | header := w.Header()
36 | if val := header["Content-Type"]; len(val) == 0 {
37 | header["Content-Type"] = value
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 go-ego Project Developers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/grpc/ego/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 |
8 | "github.com/go-ego/ego"
9 | pb "github.com/go-ego/ego/examples/grpc/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | func main() {
14 | // Set up a connection to the server.
15 | conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
16 | if err != nil {
17 | log.Fatalf("did not connect: %v", err)
18 | }
19 | defer conn.Close()
20 | client := pb.NewGreeterClient(conn)
21 |
22 | // Set up a http setver.
23 | r := ego.Default()
24 | r.GET("/rest/n/:name", func(c *ego.Context) {
25 | name := c.Param("name")
26 |
27 | // Contact the server and print out its response.
28 | req := &pb.HelloRequest{Name: name}
29 | res, err := client.SayHello(c, req)
30 | if err != nil {
31 | c.JSON(http.StatusInternalServerError, ego.Map{
32 | "error": err.Error(),
33 | })
34 | return
35 | }
36 |
37 | c.JSON(http.StatusOK, ego.Map{
38 | "result": fmt.Sprint(res.Message),
39 | })
40 | })
41 |
42 | // Run http server
43 | if err := r.Run(":8052"); err != nil {
44 | log.Fatalf("could not run server: %v", err)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/testdata/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC9DCCAdygAwIBAgIQUNSK+OxWHYYFxHVJV0IlpDANBgkqhkiG9w0BAQsFADAS
3 | MRAwDgYDVQQKEwdBY21lIENvMB4XDTE3MTExNjEyMDA0N1oXDTE4MTExNjEyMDA0
4 | N1owEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
5 | AQoCggEBAKmyj/YZpD59Bpy4w3qf6VzMw9uUBsWp+IP4kl7z5cmGHYUHn/YopTLH
6 | vR23GAB12p6Km5QWzCBuJF4j61PJXHfg3/rjShZ77JcQ3kzxuy1iKDI+DNKN7Klz
7 | rdjJ49QD0lczZHeBvvCL7JsJFKFjGy62rnStuW8LaIEdtjXT+GUZTxJh6G7yPYfD
8 | MS1IsdMQGOdbGwNa+qogMuQPh0TzHw+C73myKrjY6pREijknMC/rnIMz9dLPt6Kl
9 | xXy4br443dpY6dYGIhDuKhROT+vZ05HKasuuQUFhY7v/KoUpEZMB9rfUSzjQ5fak
10 | eDUAMniXRcd+DmwvboG2TI6ixmuPK+ECAwEAAaNGMEQwDgYDVR0PAQH/BAQDAgWg
11 | MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDwYDVR0RBAgwBocE
12 | fwAAATANBgkqhkiG9w0BAQsFAAOCAQEAMXOLvj7BFsxdbcfRPBd0OFrH/8lI7vPV
13 | LRcJ6r5iv0cnNvZXXbIOQLbg4clJAWjoE08nRm1KvNXhKdns0ELEV86YN2S6jThq
14 | rIGrBqKtaJLB3M9BtDSiQ6SGPLYrWvmhj3Avi8PbSGy51bpGbqopd16j6LYU7Cp2
15 | TefMRlOAFtHojpCVon1CMpqcNxS0WNlQ3lUBSrw3HB0o12x++roja2ibF54tSHXB
16 | KUuadoEzN+mMBwenEBychmAGzdiG4GQHRmhigh85+mtW6UMGiqyCZHs0EgE9FCLL
17 | sRrsTI/VOzLz6lluygXkOsXrP+PP0SvmE3eylWjj9e2nj/u/Cy2YKg==
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------
/examples/ego/views/html/head_head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | my-ego
8 |
9 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
ego:{{.head}}
30 |
34 |
35 | {{range .parArr}}
36 |
arr:::: {{.}}
37 | {{end}}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/mid/util/fs.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "net/http"
5 | "os"
6 | )
7 |
8 | type (
9 | OnlyfilesFS struct {
10 | fs http.FileSystem
11 | }
12 | neuteredReaddirFile struct {
13 | http.File
14 | }
15 | )
16 |
17 | // Dir returns a http.Filesystem that can be used by http.FileServer(). It is used internally
18 | // in router.Static().
19 | // in router.Static().
20 | // if listDirectory == true, then it works the same as http.Dir() otherwise it returns
21 | // a filesystem that prevents http.FileServer() to list the directory files.
22 | func Dir(root string, listDirectory bool) http.FileSystem {
23 | fs := http.Dir(root)
24 | if listDirectory {
25 | return fs
26 | }
27 | return &OnlyfilesFS{fs}
28 | }
29 |
30 | // Open conforms to http.Filesystem.
31 | func (fs OnlyfilesFS) Open(name string) (http.File, error) {
32 | f, err := fs.fs.Open(name)
33 | if err != nil {
34 | return nil, err
35 | }
36 | return neuteredReaddirFile{f}, nil
37 | }
38 |
39 | // Readdir overrides the http.File default implementation.
40 | func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
41 | // this disables directory listing
42 | return nil, nil
43 | }
44 |
--------------------------------------------------------------------------------
/examples/graceful-shutdown/graceful-shutdown/server.go:
--------------------------------------------------------------------------------
1 | // +build go1.8
2 |
3 | package main
4 |
5 | import (
6 | "context"
7 | "log"
8 | "net/http"
9 | "os"
10 | "os/signal"
11 | "time"
12 |
13 | "github.com/go-ego/ego"
14 | )
15 |
16 | func main() {
17 | router := ego.Default()
18 | router.GET("/", func(c *ego.Context) {
19 | time.Sleep(5 * time.Second)
20 | c.String(http.StatusOK, "Welcome ego Server")
21 | })
22 |
23 | srv := &http.Server{
24 | Addr: ":8080",
25 | Handler: router,
26 | }
27 |
28 | go func() {
29 | // service connections
30 | if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
31 | log.Fatalf("listen: %s\n", err)
32 | }
33 | }()
34 |
35 | // Wait for interrupt signal to gracefully shutdown the server with
36 | // a timeout of 5 seconds.
37 | quit := make(chan os.Signal)
38 | signal.Notify(quit, os.Interrupt)
39 | <-quit
40 | log.Println("Shutdown Server ...")
41 |
42 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
43 | defer cancel()
44 | if err := srv.Shutdown(ctx); err != nil {
45 | log.Fatal("Server Shutdown:", err)
46 | }
47 | log.Println("Server exiting")
48 | }
49 |
--------------------------------------------------------------------------------
/mid/render/ffjson.go:
--------------------------------------------------------------------------------
1 | package render
2 |
3 | import (
4 | "encoding/json"
5 | "net/http"
6 |
7 | "github.com/pquerna/ffjson/ffjson"
8 | )
9 |
10 | type (
11 | FFJSON struct {
12 | Data interface{}
13 | }
14 |
15 | FFIndentedJSON struct {
16 | Data interface{}
17 | }
18 | )
19 |
20 | func (r FFJSON) Render(w http.ResponseWriter) (err error) {
21 | if err = FFWriteJSON(w, r.Data); err != nil {
22 | panic(err)
23 | }
24 | return
25 | }
26 |
27 | func (r FFJSON) WriteContentType(w http.ResponseWriter) {
28 | writeContentType(w, jsonContentType)
29 | }
30 |
31 | func FFWriteJSON(w http.ResponseWriter, obj interface{}) error {
32 | writeContentType(w, jsonContentType)
33 | ffjsonBytes, err := ffjson.Marshal(obj)
34 | if err != nil {
35 | return err
36 | }
37 | w.Write(ffjsonBytes)
38 | return nil
39 | }
40 |
41 | func (r FFIndentedJSON) Render(w http.ResponseWriter) error {
42 | r.WriteContentType(w)
43 | jsonBytes, err := json.MarshalIndent(r.Data, "", " ")
44 | if err != nil {
45 | return err
46 | }
47 | w.Write(jsonBytes)
48 | return nil
49 | }
50 |
51 | func (r FFIndentedJSON) WriteContentType(w http.ResponseWriter) {
52 | writeContentType(w, jsonContentType)
53 | }
54 |
--------------------------------------------------------------------------------
/mid/binding/json.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import (
8 | "bytes"
9 | "io"
10 | "net/http"
11 |
12 | "github.com/go-ego/ego/mid/json"
13 | )
14 |
15 | // EnableDecoderUseNumber is used to call the UseNumber method on the JSON
16 | // Decoder instance. UseNumber causes the Decoder to unmarshal a number into an
17 | // interface{} as a Number instead of as a float64.
18 | var EnableDecoderUseNumber = false
19 |
20 | type jsonBinding struct{}
21 |
22 | func (jsonBinding) Name() string {
23 | return "json"
24 | }
25 |
26 | func (jsonBinding) Bind(req *http.Request, obj interface{}) error {
27 | return decodeJSON(req.Body, obj)
28 | }
29 |
30 | func (jsonBinding) BindBody(body []byte, obj interface{}) error {
31 | return decodeJSON(bytes.NewReader(body), obj)
32 | }
33 |
34 | func decodeJSON(r io.Reader, obj interface{}) error {
35 | decoder := json.NewDecoder(r)
36 | if EnableDecoderUseNumber {
37 | decoder.UseNumber()
38 | }
39 | if err := decoder.Decode(obj); err != nil {
40 | return err
41 | }
42 | return validate(obj)
43 | }
44 |
--------------------------------------------------------------------------------
/examples/grpc/pb/helloworld.proto:
--------------------------------------------------------------------------------
1 | // Copyright 2015 gRPC authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | syntax = "proto3";
16 |
17 | option java_multiple_files = true;
18 | option java_package = "io.grpc.examples.helloworld";
19 | option java_outer_classname = "HelloWorldProto";
20 |
21 | package helloworld;
22 |
23 | // The greeting service definition.
24 | service Greeter {
25 | // Sends a greeting
26 | rpc SayHello (HelloRequest) returns (HelloReply) {}
27 | }
28 |
29 | // The request message containing the user's name.
30 | message HelloRequest {
31 | string name = 1;
32 | }
33 |
34 | // The response message containing the greetings
35 | message HelloReply {
36 | string message = 1;
37 | }
38 |
--------------------------------------------------------------------------------
/examples/realtime-chat/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "math/rand"
7 |
8 | "github.com/go-ego/ego"
9 | )
10 |
11 | func main() {
12 | router := ego.Default()
13 | router.SetHTMLTemplate(html)
14 |
15 | router.GET("/room/:roomid", roomGET)
16 | router.POST("/room/:roomid", roomPOST)
17 | router.DELETE("/room/:roomid", roomDELETE)
18 | router.GET("/stream/:roomid", stream)
19 |
20 | router.Run(":3000")
21 | }
22 |
23 | func stream(c *ego.Context) {
24 | roomid := c.Param("roomid")
25 | listener := openListener(roomid)
26 | defer closeListener(roomid, listener)
27 |
28 | c.Stream(func(w io.Writer) bool {
29 | c.SSEvent("message", <-listener)
30 | return true
31 | })
32 | }
33 |
34 | func roomGET(c *ego.Context) {
35 | roomid := c.Param("roomid")
36 | userid := fmt.Sprint(rand.Int31())
37 | c.HTML(200, "chat_room", ego.Map{
38 | "roomid": roomid,
39 | "userid": userid,
40 | })
41 | }
42 |
43 | func roomPOST(c *ego.Context) {
44 | roomid := c.Param("roomid")
45 | userid := c.PostForm("user")
46 | message := c.PostForm("message")
47 | room(roomid).Submit(userid + ": " + message)
48 |
49 | c.JSON(200, ego.Map{
50 | "status": "success",
51 | "message": message,
52 | })
53 | }
54 |
55 | func roomDELETE(c *ego.Context) {
56 | roomid := c.Param("roomid")
57 | deleteBroadcast(roomid)
58 | }
59 |
--------------------------------------------------------------------------------
/examples/ego/public/src/toast/toast.js:
--------------------------------------------------------------------------------
1 | var classActive = 'active';
2 |
3 | var toast = function(msg, type, time) {
4 | if (type == undefined) {
5 | type = "error";
6 | };
7 | if (time == undefined) {
8 | time = 2000;
9 | };
10 | var toast = document.createElement('div');
11 | toast.classList.add('toast-container');
12 | var html = '' +
13 | '
' +
14 | '
' + msg + '
' +
15 | '
';
16 | var docmsg = document.getElementById('toast-msg');
17 | if (docmsg == undefined) {
18 | toast.innerHTML = html;
19 | }
20 | toast.addEventListener('webkitTransitionEnd', function() {
21 | if (!toast.classList.contains(classActive)) {
22 | toast.parentNode.removeChild(toast);
23 | }
24 | });
25 | document.body.appendChild(toast);
26 |
27 | var mlength = msg.length;
28 | if (mlength > 5) {
29 | var mlen = (mlength - 5) / 1.5;
30 | var mrem = 5.5 + mlen;
31 | var docmsg = document.getElementById('toast-msg');
32 | docmsg.style.width = mrem + "rem";
33 | }
34 | toast.offsetHeight;
35 | toast.classList.add(classActive);
36 | setTimeout(function() {
37 | toast.classList.remove(classActive);
38 | }, time);
39 | };
40 |
--------------------------------------------------------------------------------
/examples/ego/views/src/toast/toast.js:
--------------------------------------------------------------------------------
1 | var classActive = 'active';
2 |
3 | var toast = function(msg, type, time) {
4 | if (type == undefined) {
5 | type = "error";
6 | };
7 | if (time == undefined) {
8 | time = 2000;
9 | };
10 | var toast = document.createElement('div');
11 | toast.classList.add('toast-container');
12 | var html = '' +
13 | '
' +
14 | '
' + msg + '
' +
15 | '
';
16 | var docmsg = document.getElementById('toast-msg');
17 | if (docmsg == undefined) {
18 | toast.innerHTML = html;
19 | }
20 | toast.addEventListener('webkitTransitionEnd', function() {
21 | if (!toast.classList.contains(classActive)) {
22 | toast.parentNode.removeChild(toast);
23 | }
24 | });
25 | document.body.appendChild(toast);
26 |
27 | var mlength = msg.length;
28 | if (mlength > 5) {
29 | var mlen = (mlength - 5) / 1.5;
30 | var mrem = 5.5 + mlen;
31 | var docmsg = document.getElementById('toast-msg');
32 | docmsg.style.width = mrem + "rem";
33 | }
34 | toast.offsetHeight;
35 | toast.classList.add(classActive);
36 | setTimeout(function() {
37 | toast.classList.remove(classActive);
38 | }, time);
39 | };
40 |
--------------------------------------------------------------------------------
/examples/realtime-advanced/stats.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "runtime"
5 | "sync"
6 | "time"
7 |
8 | "github.com/manucorporat/stats"
9 | )
10 |
11 | var (
12 | ips = stats.New()
13 | messages = stats.New()
14 | users = stats.New()
15 | mutexStats sync.RWMutex
16 | savedStats map[string]uint64
17 | )
18 |
19 | func statsWorker() {
20 | c := time.Tick(1 * time.Second)
21 | var lastMallocs uint64
22 | var lastFrees uint64
23 | for range c {
24 | var stats runtime.MemStats
25 | runtime.ReadMemStats(&stats)
26 |
27 | mutexStats.Lock()
28 | savedStats = map[string]uint64{
29 | "timestamp": uint64(time.Now().Unix()),
30 | "HeapInuse": stats.HeapInuse,
31 | "StackInuse": stats.StackInuse,
32 | "Mallocs": stats.Mallocs - lastMallocs,
33 | "Frees": stats.Frees - lastFrees,
34 | "Inbound": uint64(messages.Get("inbound")),
35 | "Outbound": uint64(messages.Get("outbound")),
36 | "Connected": connectedUsers(),
37 | }
38 | lastMallocs = stats.Mallocs
39 | lastFrees = stats.Frees
40 | messages.Reset()
41 | mutexStats.Unlock()
42 | }
43 | }
44 |
45 | func connectedUsers() uint64 {
46 | connected := users.Get("connected") - users.Get("disconnected")
47 | if connected < 0 {
48 | return 0
49 | }
50 | return uint64(connected)
51 | }
52 |
53 | func Stats() map[string]uint64 {
54 | mutexStats.RLock()
55 | defer mutexStats.RUnlock()
56 |
57 | return savedStats
58 | }
59 |
--------------------------------------------------------------------------------
/mid/recovery_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package mid
6 |
7 | import (
8 | "bytes"
9 | "testing"
10 |
11 | "github.com/go-ego/ego"
12 | "github.com/stretchr/testify/assert"
13 | )
14 |
15 | // TestPanicInHandler assert that panic has been recovered.
16 | func TestPanicInHandler(t *testing.T) {
17 | buffer := new(bytes.Buffer)
18 | router := ego.New()
19 | router.Use(RecoveryWithWriter(buffer))
20 | router.GET("/recovery", func(_ *ego.Context) {
21 | panic("Oupps, Houston, we have a problem")
22 | })
23 | // RUN
24 | w := performRequest(router, "GET", "/recovery")
25 | // TEST
26 | assert.Equal(t, 500, w.Code)
27 | assert.Contains(t, buffer.String(), "GET /recovery")
28 | assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
29 | assert.Contains(t, buffer.String(), "TestPanicInHandler")
30 | }
31 |
32 | // TestPanicWithAbort assert that panic has been recovered even if context.Abort was used.
33 | func TestPanicWithAbort(t *testing.T) {
34 | router := ego.New()
35 | router.Use(RecoveryWithWriter(nil))
36 | router.GET("/recovery", func(c *ego.Context) {
37 | c.AbortWithStatus(400)
38 | panic("Oupps, Houston, we have a problem")
39 | })
40 | // RUN
41 | w := performRequest(router, "GET", "/recovery")
42 | // TEST
43 | assert.Equal(t, 400, w.Code)
44 | }
45 |
--------------------------------------------------------------------------------
/examples/multiple-service/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "time"
7 |
8 | "github.com/go-ego/ego"
9 | "golang.org/x/sync/errgroup"
10 | )
11 |
12 | var (
13 | g errgroup.Group
14 | )
15 |
16 | func router01() http.Handler {
17 | e := ego.New()
18 | e.Use(ego.Recovery())
19 | e.GET("/", func(c *ego.Context) {
20 | c.JSON(
21 | http.StatusOK,
22 | ego.Map{
23 | "code": http.StatusOK,
24 | "error": "Welcome server 01",
25 | },
26 | )
27 | })
28 |
29 | return e
30 | }
31 |
32 | func router02() http.Handler {
33 | e := ego.New()
34 | e.Use(ego.Recovery())
35 | e.GET("/", func(c *ego.Context) {
36 | c.JSON(
37 | http.StatusOK,
38 | ego.Map{
39 | "code": http.StatusOK,
40 | "error": "Welcome server 02",
41 | },
42 | )
43 | })
44 |
45 | return e
46 | }
47 |
48 | func main() {
49 | server01 := &http.Server{
50 | Addr: ":8080",
51 | Handler: router01(),
52 | ReadTimeout: 5 * time.Second,
53 | WriteTimeout: 10 * time.Second,
54 | }
55 |
56 | server02 := &http.Server{
57 | Addr: ":8081",
58 | Handler: router02(),
59 | ReadTimeout: 5 * time.Second,
60 | WriteTimeout: 10 * time.Second,
61 | }
62 |
63 | g.Go(func() error {
64 | return server01.ListenAndServe()
65 | })
66 |
67 | g.Go(func() error {
68 | return server02.ListenAndServe()
69 | })
70 |
71 | if err := g.Wait(); err != nil {
72 | log.Fatal(err)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/mid/rego/min.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
13 | import (
14 | "regexp"
15 |
16 | "github.com/tdewolff/minify"
17 | "github.com/tdewolff/minify/css"
18 | "github.com/tdewolff/minify/html"
19 | "github.com/tdewolff/minify/js"
20 | "github.com/tdewolff/minify/json"
21 | "github.com/tdewolff/minify/svg"
22 | "github.com/tdewolff/minify/xml"
23 | )
24 |
25 | func minStr(data, mediatype string) (string, error) {
26 | m := minify.New()
27 | m.AddFunc("text/css", css.Minify)
28 | m.AddFunc("text/javascript", js.Minify)
29 | m.AddFunc("text/html", html.Minify)
30 | m.AddFunc("image/svg+xml", svg.Minify)
31 | m.AddFuncRegexp(regexp.MustCompile("[/+]json$"), json.Minify)
32 | m.AddFuncRegexp(regexp.MustCompile("[/+]xml$"), xml.Minify)
33 |
34 | var err error
35 | // b, err = m.Bytes(mediatype, b)
36 | data, err = m.String(mediatype, data)
37 | if err != nil {
38 | return "", err
39 | }
40 | // fmt.Println(data)
41 |
42 | return data, nil
43 | }
44 |
--------------------------------------------------------------------------------
/examples/custom-validation/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net/http"
5 | "reflect"
6 | "time"
7 |
8 | "github.com/go-ego/ego"
9 | "github.com/go-ego/ego/mid/binding"
10 | validator "gopkg.in/go-playground/validator.v8"
11 | )
12 |
13 | type Booking struct {
14 | CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
15 | CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
16 | }
17 |
18 | func bookableDate(
19 | v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
20 | field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
21 | ) bool {
22 | if date, ok := field.Interface().(time.Time); ok {
23 | today := time.Now()
24 | if today.Year() > date.Year() || today.YearDay() > date.YearDay() {
25 | return false
26 | }
27 | }
28 | return true
29 | }
30 |
31 | func main() {
32 | route := ego.Default()
33 | // binding.Validator.RegisterValidation("bookabledate", bookableDate)
34 | if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
35 | v.RegisterValidation("bookabledate", bookableDate)
36 | }
37 | route.GET("/bookable", getBookable)
38 | route.Run(":8085")
39 | }
40 |
41 | func getBookable(c *ego.Context) {
42 | var b Booking
43 | if err := c.ShouldBindWith(&b, binding.Query); err == nil {
44 | c.JSON(http.StatusOK, ego.Map{"message": "Booking dates are valid!"})
45 | } else {
46 | c.JSON(http.StatusBadRequest, ego.Map{"error": err.Error()})
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/mid/binding/form.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import "net/http"
8 |
9 | // 32 MB
10 | const defaultMemory = 32 * 1024 * 1024
11 |
12 | type (
13 | formBinding struct{}
14 | formPostBinding struct{}
15 | formMultipartBinding struct{}
16 | )
17 |
18 | func (formBinding) Name() string {
19 | return "form"
20 | }
21 |
22 | func (formBinding) Bind(req *http.Request, obj interface{}) error {
23 | if err := req.ParseForm(); err != nil {
24 | return err
25 | }
26 | req.ParseMultipartForm(defaultMemory)
27 | if err := mapForm(obj, req.Form); err != nil {
28 | return err
29 | }
30 | return validate(obj)
31 | }
32 |
33 | func (formPostBinding) Name() string {
34 | return "form-urlencoded"
35 | }
36 |
37 | func (formPostBinding) Bind(req *http.Request, obj interface{}) error {
38 | if err := req.ParseForm(); err != nil {
39 | return err
40 | }
41 | if err := mapForm(obj, req.PostForm); err != nil {
42 | return err
43 | }
44 | return validate(obj)
45 | }
46 |
47 | func (formMultipartBinding) Name() string {
48 | return "multipart/form-data"
49 | }
50 |
51 | func (formMultipartBinding) Bind(req *http.Request, obj interface{}) error {
52 | if err := req.ParseMultipartForm(defaultMemory); err != nil {
53 | return err
54 | }
55 | if err := mapForm(obj, req.MultipartForm.Value); err != nil {
56 | return err
57 | }
58 | return validate(obj)
59 | }
60 |
--------------------------------------------------------------------------------
/examples/basic/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/go-ego/ego"
5 | )
6 |
7 | var DB = make(map[string]string)
8 |
9 | func setupRouter() *ego.Engine {
10 | // Disable Console Color
11 | // ego.DisableConsoleColor()
12 | r := ego.Default()
13 |
14 | // Ping test
15 | r.GET("/ping", func(c *ego.Context) {
16 | c.String(200, "pong")
17 | })
18 |
19 | // Get user value
20 | r.GET("/user/:name", func(c *ego.Context) {
21 | user := c.Params.ByName("name")
22 | value, ok := DB[user]
23 | if ok {
24 | c.JSON(200, ego.Map{"user": user, "value": value})
25 | } else {
26 | c.JSON(200, ego.Map{"user": user, "status": "no value"})
27 | }
28 | })
29 |
30 | // Authorized group (uses ego.BasicAuth() middleware)
31 | // Same than:
32 | // authorized := r.Group("/")
33 | // authorized.Use(ego.BasicAuth(ego.Credentials{
34 | // "foo": "bar",
35 | // "manu": "123",
36 | //}))
37 | authorized := r.Group("/", ego.BasicAuth(ego.Accounts{
38 | "foo": "bar", // user:foo password:bar
39 | "manu": "123", // user:manu password:123
40 | }))
41 |
42 | authorized.POST("admin", func(c *ego.Context) {
43 | user := c.MustGet(ego.AuthUserKey).(string)
44 |
45 | // Parse JSON
46 | var json struct {
47 | Value string `json:"value" binding:"required"`
48 | }
49 |
50 | if c.Bind(&json) == nil {
51 | DB[user] = json.Value
52 | c.JSON(200, ego.Map{"status": "ok"})
53 | }
54 | })
55 |
56 | return r
57 | }
58 |
59 | func main() {
60 | r := setupRouter()
61 | // Listen and Server in 0.0.0.0:8080
62 | r.Run(":8080")
63 | }
64 |
--------------------------------------------------------------------------------
/examples/ego/main.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package main
12 |
13 | import (
14 | // "fmt"
15 | "github.com/go-ego/ego"
16 | )
17 |
18 | // const httpUrl string = "http://127.0.0.1:3000"
19 |
20 | func main() {
21 |
22 | router := ego.Classic()
23 | ego.UseRenders()
24 | // router := ego.Default()
25 |
26 | router.Static("/js", "./views/js")
27 | router.Static("/src", "./views/src")
28 | router.GlobHTML("views/html/*")
29 |
30 | // strUrl := httpUrl + "/test/hlist"
31 | // paramMap := ego.Map{
32 | // "lon": "10.1010101",
33 | // "lat": "20.202020",
34 | // "type": "1",
35 | // }
36 | // router.TestHtml(strUrl, paramMap)
37 |
38 | router.Ego("/banner/", "banner.html", ego.Map{
39 | "head": "Test to load the HTML template",
40 | })
41 |
42 | parArr := [5]int{1, 2, 3, 4, 5}
43 | router.Ego("/head/", "head/head.html", ego.Map{
44 | "head": "Test to load the HTML template",
45 | "parArr": parArr,
46 | })
47 |
48 | // rMap := ego.Map{
49 | // "/b1/": "banner.html",
50 | // "/b2/": "banner.html",
51 | // "/he/": "head/head.html",
52 | // }
53 | // router.EgoGroup(rMap)
54 |
55 | router.Run(":3100")
56 | }
57 |
--------------------------------------------------------------------------------
/examples/realtime-chat/template.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "html/template"
4 |
5 | var html = template.Must(template.New("chat_room").Parse(`
6 |
7 |
8 | {{.roomid}}
9 |
10 |
11 |
12 |
33 |
34 |
35 | Welcome to {{.roomid}} room
36 |
37 |
42 |
43 |
44 | `))
45 |
--------------------------------------------------------------------------------
/mid/binding/binding_body_test.go:
--------------------------------------------------------------------------------
1 | package binding
2 |
3 | import (
4 | "bytes"
5 | "io/ioutil"
6 | "testing"
7 |
8 | "github.com/go-ego/ego/mid/binding/example"
9 | "github.com/golang/protobuf/proto"
10 | "github.com/stretchr/testify/assert"
11 | "github.com/ugorji/go/codec"
12 | )
13 |
14 | func TestBindingBody(t *testing.T) {
15 | for _, tt := range []struct {
16 | name string
17 | binding BindingBody
18 | body string
19 | want string
20 | }{
21 | {
22 | name: "JSON bidning",
23 | binding: JSON,
24 | body: `{"foo":"FOO"}`,
25 | },
26 | {
27 | name: "XML bidning",
28 | binding: XML,
29 | body: `
30 |
31 | FOO
32 | `,
33 | },
34 | {
35 | name: "MsgPack binding",
36 | binding: MsgPack,
37 | body: msgPackBody(t),
38 | },
39 | } {
40 | t.Logf("testing: %s", tt.name)
41 | req := requestWithBody("POST", "/", tt.body)
42 | form := FooStruct{}
43 | body, _ := ioutil.ReadAll(req.Body)
44 | assert.NoError(t, tt.binding.BindBody(body, &form))
45 | assert.Equal(t, FooStruct{"FOO"}, form)
46 | }
47 | }
48 |
49 | func msgPackBody(t *testing.T) string {
50 | test := FooStruct{"FOO"}
51 | h := new(codec.MsgpackHandle)
52 | buf := bytes.NewBuffer(nil)
53 | assert.NoError(t, codec.NewEncoder(buf, h).Encode(test))
54 | return buf.String()
55 | }
56 |
57 | func TestBindingBodyProto(t *testing.T) {
58 | test := example.Test{
59 | Label: proto.String("FOO"),
60 | }
61 | data, _ := proto.Marshal(&test)
62 | req := requestWithBody("POST", "/", string(data))
63 | form := example.Test{}
64 | body, _ := ioutil.ReadAll(req.Body)
65 | assert.NoError(t, ProtoBuf.BindBody(body, &form))
66 | assert.Equal(t, test, form)
67 | }
68 |
--------------------------------------------------------------------------------
/test/testdata/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEogIBAAKCAQEAqbKP9hmkPn0GnLjDep/pXMzD25QGxan4g/iSXvPlyYYdhQef
3 | 9iilMse9HbcYAHXanoqblBbMIG4kXiPrU8lcd+Df+uNKFnvslxDeTPG7LWIoMj4M
4 | 0o3sqXOt2Mnj1APSVzNkd4G+8IvsmwkUoWMbLraudK25bwtogR22NdP4ZRlPEmHo
5 | bvI9h8MxLUix0xAY51sbA1r6qiAy5A+HRPMfD4LvebIquNjqlESKOScwL+ucgzP1
6 | 0s+3oqXFfLhuvjjd2ljp1gYiEO4qFE5P69nTkcpqy65BQWFju/8qhSkRkwH2t9RL
7 | ONDl9qR4NQAyeJdFx34ObC9ugbZMjqLGa48r4QIDAQABAoIBAD5mhd+GMEo2KU9J
8 | 9b/Ku8I/HapJtW/L/7Fvn0tBPncrVQGM+zpGWfDhV95sbGwG6lwwNeNvuqIWPlNL
9 | vAY0XkdKrrIQEDdSXH50WnpKzXxzwrou7QIj5Cmvevbjzl4xBZDBOilj0XWczmV4
10 | IljyG5XC4UXQeAaoWEZaSZ1jk8yAt2Zq1Hgg7HqhHsK/arWXBgax+4K5nV/s9gZx
11 | yjKU9mXTIs7k/aNnZqwQKqcZF+l3mvbZttOaFwsP14H0I8OFWhnM9hie54Dejqxi
12 | f4/llNxDqUs6lqJfP3qNxtORLcFe75M+Yl8v7g2hkjtLdZBakPzSTEx3TAK/UHgi
13 | aM8DdxECgYEA3fmg/PI4EgUEj0C3SCmQXR/CnQLMUQgb54s0asp4akvp+M7YCcr1
14 | pQd3HFUpBwhBcJg5LeSe87vLupY7pHCKk56cl9WY6hse0b9sP/7DWJuGiO62m0E0
15 | vNjQ2jpG99oR2ROIHHeWsGCpGLmrRT/kY+vR3M+AOLZniXlOCw8k0aUCgYEAw7WL
16 | XFWLxgZYQYilywqrQmfv1MBfaUCvykO6oWB+f6mmnihSFjecI+nDw/b3yXVYGEgy
17 | 0ebkuw0jP8suC8wBqX9WuXj+9nZNomJRssJyOMiEhDEqUiTztFPSp9pdruoakLTh
18 | Wk1p9NralOqGPUmxpXlFKVmYRTUbluikVxDypI0CgYBn6sqEQH0hann0+o4TWWn9
19 | PrYkPUAbm1k8771tVTZERR/W3Dbldr/DL5iCihe39BR2urziEEqdvkglJNntJMar
20 | TzDuIBADYQjvltb9qq4XGFBGYMLaMg+XbUVxNKEuvUdnwa4R7aZ9EfN34MwekkfA
21 | w5Cu9/GGG1ajVEfGA6PwBQKBgA3o71jGs8KFXOx7e90sivOTU5Z5fc6LTHNB0Rf7
22 | NcJ5GmCPWRY/KZfb25AoE4B8GKDRMNt+X69zxZeZJ1KrU0rqxA02rlhyHB54gnoE
23 | G/4xMkn6/JkOC0w70PMhMBtohC7YzFOQwQEoNPT0nkno3Pl33xSLS6lPlwBo1JVj
24 | nPtZAoGACXNLXYkR5vexE+w6FGl59r4RQhu1XU8Mr5DIHeB7kXPN3RKbS201M+Tb
25 | SB5jbu0iDV477XkzSNmhaksFf2wM9MT6CaE+8n3UU5tMa+MmBGgwYTp/i9HkqVh5
26 | jjpJifn1VWBINd4cpNzwCg9LXoo0tbtUPWwGzqVeyo/YE5GIHGo=
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/mid/binding/default_validator.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package binding
6 |
7 | import (
8 | "reflect"
9 | "sync"
10 |
11 | "gopkg.in/go-playground/validator.v8"
12 | )
13 |
14 | type defaultValidator struct {
15 | once sync.Once
16 | validate *validator.Validate
17 | }
18 |
19 | var _ StructValidator = &defaultValidator{}
20 |
21 | // ValidateStruct receives any kind of type, but only performed
22 | // struct or pointer to struct type.
23 | func (v *defaultValidator) ValidateStruct(obj interface{}) error {
24 | value := reflect.ValueOf(obj)
25 | valueType := value.Kind()
26 | if valueType == reflect.Ptr {
27 | valueType = value.Elem().Kind()
28 | }
29 |
30 | if valueType == reflect.Struct {
31 | v.lazyinit()
32 | if err := v.validate.Struct(obj); err != nil {
33 | return err
34 | }
35 | }
36 | return nil
37 | }
38 |
39 | // Engine returns the underlying validator engine which powers the default
40 | // Validator instance. This is useful if you want to register custom validations
41 | // or struct level validations. See validator GoDoc for more info -
42 | // https://godoc.org/gopkg.in/go-playground/validator.v8
43 | func (v *defaultValidator) Engine() interface{} {
44 | v.lazyinit()
45 | return v.validate
46 | }
47 |
48 | func (v *defaultValidator) lazyinit() {
49 | v.once.Do(func() {
50 | config := &validator.Config{TagName: "binding"}
51 | v.validate = validator.New(config)
52 | })
53 | }
54 |
55 | func kindOfData(data interface{}) reflect.Kind {
56 | value := reflect.ValueOf(data)
57 | valueType := value.Kind()
58 | if valueType == reflect.Ptr {
59 | valueType = value.Elem().Kind()
60 | }
61 | return valueType
62 | }
63 |
--------------------------------------------------------------------------------
/mode.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ego
6 |
7 | import (
8 | "io"
9 | "os"
10 |
11 | "github.com/go-ego/ego/mid/binding"
12 | )
13 |
14 | const (
15 | // EnvEgoMode set the mode env
16 | EnvEgoMode = "EGO_MODE"
17 |
18 | DebugMode = "debug"
19 | ReleaseMode = "release"
20 | TestMode = "test"
21 | )
22 |
23 | const (
24 | debugCode = iota
25 | releaseCode
26 | testCode
27 | )
28 |
29 | var (
30 | // DefaultWriter is the default io.Writer used the Ego for debug output and
31 | // middleware output like Logger() or Recovery().
32 | // Note that both Logger and Recovery provides custom ways to configure their
33 | // output io.Writer.
34 | // To support coloring in Windows use:
35 | // import "github.com/mattn/go-colorable"
36 | // ego.DefaultWriter = colorable.NewColorableStdout()
37 | DefaultWriter io.Writer = os.Stdout
38 | DefaultErrorWriter io.Writer = os.Stderr
39 |
40 | egoMode = debugCode
41 | modeName = DebugMode
42 | )
43 |
44 | func init() {
45 | mode := os.Getenv(EnvEgoMode)
46 | SetMode(mode)
47 | }
48 |
49 | // SetMode set ego mode
50 | func SetMode(value string) {
51 | switch value {
52 | case DebugMode, "":
53 | egoMode = debugCode
54 | case ReleaseMode:
55 | egoMode = releaseCode
56 | case TestMode:
57 | egoMode = testCode
58 | default:
59 | panic("ego mode unknown: " + value)
60 | }
61 | if value == "" {
62 | value = DebugMode
63 | }
64 | modeName = value
65 | }
66 |
67 | func DisableBindValidation() {
68 | binding.Validator = nil
69 | }
70 |
71 | func EnableJsonDecoderUseNumber() {
72 | binding.EnableDecoderUseNumber = true
73 | }
74 |
75 | func Mode() string {
76 | return modeName
77 | }
78 |
--------------------------------------------------------------------------------
/recovery_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ego
6 |
7 | import (
8 | "bytes"
9 | "testing"
10 |
11 | "github.com/stretchr/testify/assert"
12 | )
13 |
14 | // TestPanicInHandler assert that panic has been recovered.
15 | func TestPanicInHandler(t *testing.T) {
16 | buffer := new(bytes.Buffer)
17 | router := New()
18 | router.Use(RecoveryWithWriter(buffer))
19 | router.GET("/recovery", func(_ *Context) {
20 | panic("Oupps, Houston, we have a problem")
21 | })
22 | // RUN
23 | w := performRequest(router, "GET", "/recovery")
24 | // TEST
25 | assert.Equal(t, 500, w.Code)
26 | assert.Contains(t, buffer.String(), "GET /recovery")
27 | assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
28 | assert.Contains(t, buffer.String(), "TestPanicInHandler")
29 | }
30 |
31 | // TestPanicWithAbort assert that panic has been recovered even if context.Abort was used.
32 | func TestPanicWithAbort(t *testing.T) {
33 | router := New()
34 | router.Use(RecoveryWithWriter(nil))
35 | router.GET("/recovery", func(c *Context) {
36 | c.AbortWithStatus(400)
37 | panic("Oupps, Houston, we have a problem")
38 | })
39 | // RUN
40 | w := performRequest(router, "GET", "/recovery")
41 | // TEST
42 | assert.Equal(t, 400, w.Code)
43 | }
44 |
45 | func TestSource(t *testing.T) {
46 | bs := source(nil, 0)
47 | assert.Equal(t, []byte("???"), bs)
48 |
49 | in := [][]byte{
50 | []byte("Hello world."),
51 | []byte("Hi, ego.."),
52 | }
53 | bs = source(in, 10)
54 | assert.Equal(t, []byte("???"), bs)
55 |
56 | bs = source(in, 1)
57 | assert.Equal(t, []byte("Hello world."), bs)
58 | }
59 |
60 | func TestFunction(t *testing.T) {
61 | bs := function(1)
62 | assert.Equal(t, []byte("???"), bs)
63 | }
64 |
--------------------------------------------------------------------------------
/mid/render/jsoniter.go:
--------------------------------------------------------------------------------
1 | package render
2 |
3 | import (
4 | "bytes"
5 | "net/http"
6 |
7 | "github.com/json-iterator/go"
8 | )
9 |
10 | var ijson = jsoniter.ConfigCompatibleWithStandardLibrary
11 |
12 | type IJSON struct {
13 | Data interface{}
14 | }
15 |
16 | type IIndentedJSON struct {
17 | Data interface{}
18 | }
19 |
20 | type ISecureJSON struct {
21 | Prefix string
22 | Data interface{}
23 | }
24 |
25 | type ISecureJSONPrefix string
26 |
27 | // var jsonContentType = []string{"application/json; charset=utf-8"}
28 |
29 | func (r IJSON) Render(w http.ResponseWriter) (err error) {
30 | if err = IWriteJSON(w, r.Data); err != nil {
31 | panic(err)
32 | }
33 | return
34 | }
35 |
36 | func (r IJSON) WriteContentType(w http.ResponseWriter) {
37 | writeContentType(w, jsonContentType)
38 | }
39 |
40 | func IWriteJSON(w http.ResponseWriter, obj interface{}) error {
41 | writeContentType(w, jsonContentType)
42 | jsonBytes, err := ijson.Marshal(obj)
43 | if err != nil {
44 | return err
45 | }
46 | w.Write(jsonBytes)
47 | return nil
48 | }
49 |
50 | func (r IIndentedJSON) Render(w http.ResponseWriter) error {
51 | r.WriteContentType(w)
52 | jsonBytes, err := ijson.MarshalIndent(r.Data, "", " ")
53 | if err != nil {
54 | return err
55 | }
56 | w.Write(jsonBytes)
57 | return nil
58 | }
59 |
60 | func (r IIndentedJSON) WriteContentType(w http.ResponseWriter) {
61 | writeContentType(w, jsonContentType)
62 | }
63 |
64 | func (r ISecureJSON) Render(w http.ResponseWriter) error {
65 | r.WriteContentType(w)
66 | jsonBytes, err := ijson.Marshal(r.Data)
67 | if err != nil {
68 | return err
69 | }
70 | // if the jsonBytes is array values
71 | if bytes.HasPrefix(jsonBytes, []byte("[")) && bytes.HasSuffix(jsonBytes, []byte("]")) {
72 | w.Write([]byte(r.Prefix))
73 | }
74 | w.Write(jsonBytes)
75 | return nil
76 | }
77 |
78 | func (r ISecureJSON) WriteContentType(w http.ResponseWriter) {
79 | writeContentType(w, jsonContentType)
80 | }
81 |
--------------------------------------------------------------------------------
/mid/rego/compile.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | // Package rego renders vgo
12 | package rego
13 |
14 | import (
15 | "strings"
16 | )
17 |
18 | func RendersVgo(name string) {
19 | var (
20 | rname string
21 | racss string
22 | rajs string
23 | )
24 |
25 | layout, err := Readfile("public/layout.html")
26 | if err != nil {
27 | panic(err)
28 | }
29 |
30 | if len(name) > 0 {
31 | rname = "public/" + name + ".vgo"
32 | } else {
33 | rname = "public/banner.vgo"
34 | }
35 |
36 | abanner, err := Readfile(rname)
37 | if err != nil {
38 | panic(err)
39 | }
40 |
41 | notes := TrimNotes(abanner)
42 | _, retext, _, class, recss, rejs := ImpStr(notes)
43 |
44 | aRecss, aRejs := styScr(notes)
45 |
46 | for i := 0; i < len(aRecss); i++ {
47 | racss += aRecss[i]
48 | }
49 |
50 | for i := 0; i < len(aRejs); i++ {
51 | rajs += aRejs[i]
52 | }
53 |
54 | for h := 0; h < len(recss); h++ {
55 | for i := 0; i < len(recss[h]); i++ {
56 | if strings.Contains(racss, recss[h][i]) {
57 | recss[h][i] = ""
58 | }
59 | racss += recss[h][i]
60 | }
61 | }
62 |
63 | for h := 0; h < len(rejs); h++ {
64 | for i := 0; i < len(rejs[h]); i++ {
65 | if strings.Contains(rajs, rejs[h][i]) {
66 | rejs[h][i] = ""
67 | }
68 | rajs += rejs[h][i]
69 | }
70 | }
71 |
72 | trimtext := TrimIs(retext)
73 |
74 | var wname string
75 | if strings.Contains(name, "/") {
76 | sname := strings.Split(name, "/")
77 | wname = sname[0] + "_" + sname[1]
78 | } else {
79 | wname = name
80 | }
81 |
82 | WHtml(class, layout, racss, trimtext, rajs, wname)
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/mid/render/html.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package render
6 |
7 | import (
8 | "html/template"
9 | "net/http"
10 | )
11 |
12 | type Delims struct {
13 | Left string
14 | Right string
15 | }
16 |
17 | type HTMLRender interface {
18 | Instance(string, interface{}) Render
19 | }
20 |
21 | type HTMLProduction struct {
22 | Template *template.Template
23 | Delims Delims
24 | }
25 |
26 | type HTMLDebug struct {
27 | Files []string
28 | Glob string
29 | Delims Delims
30 | FuncMap template.FuncMap
31 | }
32 |
33 | type HTML struct {
34 | Template *template.Template
35 | Name string
36 | Data interface{}
37 | }
38 |
39 | var htmlContentType = []string{"text/html; charset=utf-8"}
40 |
41 | func (r HTMLProduction) Instance(name string, data interface{}) Render {
42 | return HTML{
43 | Template: r.Template,
44 | Name: name,
45 | Data: data,
46 | }
47 | }
48 |
49 | func (r HTMLDebug) Instance(name string, data interface{}) Render {
50 | return HTML{
51 | Template: r.loadTemplate(),
52 | Name: name,
53 | Data: data,
54 | }
55 | }
56 | func (r HTMLDebug) loadTemplate() *template.Template {
57 | if r.FuncMap == nil {
58 | r.FuncMap = template.FuncMap{}
59 | }
60 | if len(r.Files) > 0 {
61 | return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...))
62 | }
63 | if r.Glob != "" {
64 | return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob))
65 | }
66 | panic("the HTML debug render was created without files or glob pattern")
67 | }
68 |
69 | func (r HTML) Render(w http.ResponseWriter) error {
70 | r.WriteContentType(w)
71 |
72 | if r.Name == "" {
73 | return r.Template.Execute(w, r.Data)
74 | }
75 | return r.Template.ExecuteTemplate(w, r.Name, r.Data)
76 | }
77 |
78 | func (r HTML) WriteContentType(w http.ResponseWriter) {
79 | writeContentType(w, htmlContentType)
80 | }
81 |
--------------------------------------------------------------------------------
/examples/ego/views/html/banner.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | my-ego
8 |
9 |
10 |
24 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
go,go,go
46 |
{{.head}}
47 |
51 |
55 |
56 |
60 |
banner
61 |
62 |
64 |
65 |
66 |
67 |
68 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/Gopkg.toml:
--------------------------------------------------------------------------------
1 | # Gopkg.toml example
2 | #
3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
4 | # for detailed Gopkg.toml documentation.
5 | #
6 | # required = ["github.com/user/thing/cmd/thing"]
7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8 | #
9 | # [[constraint]]
10 | # name = "github.com/user/project"
11 | # version = "1.0.0"
12 | #
13 | # [[constraint]]
14 | # name = "github.com/user/project2"
15 | # branch = "dev"
16 | # source = "github.com/myfork/project2"
17 | #
18 | # [[override]]
19 | # name = "github.com/x/y"
20 | # version = "2.4.0"
21 | #
22 | # [prune]
23 | # non-go = false
24 | # go-tests = true
25 | # unused-packages = true
26 |
27 |
28 | [[constraint]]
29 | branch = "master"
30 | name = "github.com/dustin/go-broadcast"
31 |
32 | [[constraint]]
33 | branch = "master"
34 | name = "github.com/gin-contrib/sse"
35 |
36 | [[constraint]]
37 | branch = "master"
38 | name = "github.com/go-ego/autotls"
39 |
40 | [[constraint]]
41 | name = "github.com/golang/protobuf"
42 | version = "1.0.0"
43 |
44 | [[constraint]]
45 | name = "github.com/json-iterator/go"
46 | version = "1.1.3"
47 |
48 | [[constraint]]
49 | branch = "master"
50 | name = "github.com/manucorporat/stats"
51 |
52 | [[constraint]]
53 | name = "github.com/mattn/go-isatty"
54 | version = "0.0.3"
55 |
56 | [[constraint]]
57 | branch = "master"
58 | name = "github.com/pquerna/ffjson"
59 |
60 | [[constraint]]
61 | name = "github.com/stretchr/testify"
62 | version = "1.2.1"
63 |
64 | [[constraint]]
65 | name = "github.com/tdewolff/minify"
66 | version = "2.3.4"
67 |
68 | [[constraint]]
69 | name = "github.com/ugorji/go"
70 | version = "1.1.1"
71 |
72 | [[constraint]]
73 | branch = "master"
74 | name = "golang.org/x/crypto"
75 |
76 | [[constraint]]
77 | branch = "master"
78 | name = "golang.org/x/net"
79 |
80 | [[constraint]]
81 | branch = "master"
82 | name = "golang.org/x/sync"
83 |
84 | [[constraint]]
85 | name = "gopkg.in/go-playground/validator.v8"
86 | version = "8.18.2"
87 |
88 | [[constraint]]
89 | name = "gopkg.in/yaml.v2"
90 | version = "2.2.1"
91 |
92 | [prune]
93 | go-tests = true
94 | unused-packages = true
95 |
--------------------------------------------------------------------------------
/examples/realtime-advanced/routes.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "html"
6 | "io"
7 | "strings"
8 | "time"
9 |
10 | "github.com/go-ego/ego"
11 | )
12 |
13 | func rateLimit(c *ego.Context) {
14 | ip := c.ClientIP()
15 | value := int(ips.Add(ip, 1))
16 | if value%50 == 0 {
17 | fmt.Printf("ip: %s, count: %d\n", ip, value)
18 | }
19 | if value >= 200 {
20 | if value%200 == 0 {
21 | fmt.Println("ip blocked")
22 | }
23 | c.Abort()
24 | c.String(503, "you were automatically banned :)")
25 | }
26 | }
27 |
28 | func index(c *ego.Context) {
29 | c.Redirect(301, "/room/hn")
30 | }
31 |
32 | func roomGET(c *ego.Context) {
33 | roomid := c.Param("roomid")
34 | nick := c.Query("nick")
35 | if len(nick) < 2 {
36 | nick = ""
37 | }
38 | if len(nick) > 13 {
39 | nick = nick[0:12] + "..."
40 | }
41 | c.HTML(200, "room_loego.templ.html", ego.Map{
42 | "roomid": roomid,
43 | "nick": nick,
44 | "timestamp": time.Now().Unix(),
45 | })
46 |
47 | }
48 |
49 | func roomPOST(c *ego.Context) {
50 | roomid := c.Param("roomid")
51 | nick := c.Query("nick")
52 | message := c.PostForm("message")
53 | message = strings.TrimSpace(message)
54 |
55 | validMessage := len(message) > 1 && len(message) < 200
56 | validNick := len(nick) > 1 && len(nick) < 14
57 | if !validMessage || !validNick {
58 | c.JSON(400, ego.Map{
59 | "status": "failed",
60 | "error": "the message or nickname is too long",
61 | })
62 | return
63 | }
64 |
65 | post := ego.Map{
66 | "nick": html.EscapeString(nick),
67 | "message": html.EscapeString(message),
68 | }
69 | messages.Add("inbound", 1)
70 | room(roomid).Submit(post)
71 | c.JSON(200, post)
72 | }
73 |
74 | func streamRoom(c *ego.Context) {
75 | roomid := c.Param("roomid")
76 | listener := openListener(roomid)
77 | ticker := time.NewTicker(1 * time.Second)
78 | users.Add("connected", 1)
79 | defer func() {
80 | closeListener(roomid, listener)
81 | ticker.Stop()
82 | users.Add("disconnected", 1)
83 | }()
84 |
85 | c.Stream(func(w io.Writer) bool {
86 | select {
87 | case msg := <-listener:
88 | messages.Add("outbound", 1)
89 | c.SSEvent("message", msg)
90 | case <-ticker.C:
91 | c.SSEvent("stats", Stats())
92 | }
93 | return true
94 | })
95 | }
96 |
--------------------------------------------------------------------------------
/debug.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ego
6 |
7 | import (
8 | "bytes"
9 | "html/template"
10 | "log"
11 | )
12 |
13 | func init() {
14 | log.SetFlags(0)
15 | }
16 |
17 | // IsDebugging returns true if the framework is running in debug mode.
18 | // Use SetMode(ego.ReleaseMode) to disable debug mode.
19 | func IsDebugging() bool {
20 | return egoMode == debugCode
21 | }
22 |
23 | func debugPrintRoute(httpMethod, absolutePath string, handlers HandlersChain) {
24 | if IsDebugging() {
25 | nuHandlers := len(handlers)
26 | handlerName := nameOfFunction(handlers.Last())
27 | debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers)
28 | }
29 | }
30 |
31 | func debugPrintLoadTemplate(tmpl *template.Template) {
32 | if IsDebugging() {
33 | var buf bytes.Buffer
34 | for _, tmpl := range tmpl.Templates() {
35 | buf.WriteString("\t- ")
36 | buf.WriteString(tmpl.Name())
37 | buf.WriteString("\n")
38 | }
39 | debugPrint("Loaded HTML Templates (%d): \n%s\n", len(tmpl.Templates()), buf.String())
40 | }
41 | }
42 |
43 | func debugPrint(format string, values ...interface{}) {
44 | if IsDebugging() {
45 | log.Printf("[EGO-debug] "+format, values...)
46 | }
47 | }
48 |
49 | func debugPrintWARNINGDefault() {
50 | debugPrint(`[WARNING] Now Ego requires Go 1.8 or later and Go 1.x will be required soon.`)
51 |
52 | debugPrint(`[WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
53 | `)
54 | }
55 |
56 | func debugPrintWARNINGNew() {
57 | debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production.
58 | - using env: export EGO_MODE=release
59 | - using code: ego.SetMode(ego.ReleaseMode)
60 |
61 | `)
62 | }
63 |
64 | func debugPrintWARNINGSetHTMLTemplate() {
65 | debugPrint(`[WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called
66 | at initialization. ie. before any route is registered or the router is listening in a socket:
67 |
68 | router := ego.Default()
69 | router.SetHTMLTemplate(template) // << good place
70 |
71 | `)
72 | }
73 |
74 | func debugPrintError(err error) {
75 | if err != nil {
76 | debugPrint("[ERROR] %v\n", err)
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/mid/util/path_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 Julien Schmidt. All rights reserved.
2 | // Based on the path package, Copyright 2009 The Go Authors.
3 | // Use of this source code is governed by a BSD-style license that can be found
4 | // at https://github.com/julienschmidt/httprouter/blob/master/LICENSE
5 |
6 | package util
7 |
8 | import (
9 | "runtime"
10 | "testing"
11 |
12 | "github.com/stretchr/testify/assert"
13 | )
14 |
15 | var cleanTests = []struct {
16 | path, result string
17 | }{
18 | // Already clean
19 | {"/", "/"},
20 | {"/abc", "/abc"},
21 | {"/a/b/c", "/a/b/c"},
22 | {"/abc/", "/abc/"},
23 | {"/a/b/c/", "/a/b/c/"},
24 |
25 | // missing root
26 | {"", "/"},
27 | {"a/", "/a/"},
28 | {"abc", "/abc"},
29 | {"abc/def", "/abc/def"},
30 | {"a/b/c", "/a/b/c"},
31 |
32 | // Remove doubled slash
33 | {"//", "/"},
34 | {"/abc//", "/abc/"},
35 | {"/abc/def//", "/abc/def/"},
36 | {"/a/b/c//", "/a/b/c/"},
37 | {"/abc//def//ghi", "/abc/def/ghi"},
38 | {"//abc", "/abc"},
39 | {"///abc", "/abc"},
40 | {"//abc//", "/abc/"},
41 |
42 | // Remove . elements
43 | {".", "/"},
44 | {"./", "/"},
45 | {"/abc/./def", "/abc/def"},
46 | {"/./abc/def", "/abc/def"},
47 | {"/abc/.", "/abc/"},
48 |
49 | // Remove .. elements
50 | {"..", "/"},
51 | {"../", "/"},
52 | {"../../", "/"},
53 | {"../..", "/"},
54 | {"../../abc", "/abc"},
55 | {"/abc/def/ghi/../jkl", "/abc/def/jkl"},
56 | {"/abc/def/../ghi/../jkl", "/abc/jkl"},
57 | {"/abc/def/..", "/abc"},
58 | {"/abc/def/../..", "/"},
59 | {"/abc/def/../../..", "/"},
60 | {"/abc/def/../../..", "/"},
61 | {"/abc/def/../../../ghi/jkl/../../../mno", "/mno"},
62 |
63 | // Combinations
64 | {"abc/./../def", "/def"},
65 | {"abc//./../def", "/def"},
66 | {"abc/../../././../def", "/def"},
67 | }
68 |
69 | func TestPathClean(t *testing.T) {
70 | for _, test := range cleanTests {
71 | assert.Equal(t, test.result, CleanPath(test.path))
72 | assert.Equal(t, test.result, CleanPath(test.result))
73 | }
74 | }
75 |
76 | func TestPathCleanMallocs(t *testing.T) {
77 | if testing.Short() {
78 | t.Skip("skipping malloc count in short mode")
79 | }
80 | if runtime.GOMAXPROCS(0) > 1 {
81 | t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
82 | return
83 | }
84 |
85 | for _, test := range cleanTests {
86 | allocs := testing.AllocsPerRun(100, func() { CleanPath(test.result) })
87 | assert.EqualValues(t, allocs, 0)
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/examples/ego/views/js/ajax.js:
--------------------------------------------------------------------------------
1 | function ajax(options) {
2 | options = options || {};
3 | options.type = (options.type || "GET").toUpperCase();
4 | options.dataType = options.dataType || "json";
5 | var params = formatParams(options.data);
6 |
7 | if (window.XMLHttpRequest) {
8 | var xhr = new XMLHttpRequest();
9 | } else {
10 | var xhr = new ActiveXObject('Microsoft.XMLHTTP');
11 | }
12 |
13 | xhr.onreadystatechange = function() {
14 | if (xhr.readyState == 4) {
15 | var status = xhr.status;
16 | if (status >= 200 && status < 300) {
17 | options.success && options.success(xhr.responseText, xhr.responseXML);
18 | } else {
19 | options.fail && options.fail(status);
20 | }
21 | }
22 | }
23 |
24 | if (options.type == "GET") {
25 | xhr.open("GET", options.url + "?" + params, true);
26 | xhr.send(null);
27 | } else if (options.type == "POST") {
28 | xhr.open("POST", options.url, true);
29 |
30 | xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
31 | xhr.send(params);
32 | }
33 | }
34 |
35 | function formatParams(data) {
36 | var arr = [];
37 | for (var name in data) {
38 | arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]));
39 | }
40 | arr.push(("v=" + Math.random()).replace(".", ""));
41 | return arr.join("&");
42 | }
43 |
44 | function jsonp(options) {
45 | options = options || {};
46 | if (!options.url || !options.callback) {
47 | throw new Error("Parameter is not legal !");
48 | }
49 |
50 | var callbackName = ('jsonp_' + Math.random()).replace(".", "");
51 | var oHead = document.getElementsByTagName('head')[0];
52 | options.data[options.callback] = callbackName;
53 | var params = formatParams(options.data);
54 | var oscr = document.createElement('script');
55 | oHead.appendChild(oscr);
56 |
57 | window[callbackName] = function(json) {
58 | oHead.removeChild(oscr);
59 | clearTimeout(oscr.timer);
60 | window[callbackName] = null;
61 | options.success && options.success(json);
62 | };
63 |
64 | oscr.src = options.url + '?' + params;
65 |
66 | if (options.time) {
67 | oscr.timer = setTimeout(function() {
68 | window[callbackName] = null;
69 | oHead.removeChild(oscr);
70 | options.fail && options.fail({ message: "Time out !" });
71 | }, time);
72 | }
73 | };
--------------------------------------------------------------------------------
/mid/rego/js.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
13 | import (
14 | // "fmt"
15 | "strings"
16 | )
17 |
18 | func reJs(str string) string {
19 | amap := Map{
20 | //fn
21 | "func ": "function ",
22 | "fn ": "function ",
23 | "log(": "console.log(",
24 | "doc.": "document.",
25 | "win.": "window.",
26 | "nav.": "navigator.",
27 | //doc
28 | "doc(#": "document.getElementById(",
29 | "docid(": "document.getElementById(",
30 | "doctag(": "document.getElementsByTagName(",
31 | "doclass(": "document.getElementsByClassName(",
32 | "docname(": "document.getElementsByName(",
33 | "docquery(": "document.querySelector(",
34 | "docall(": "document.querySelectorAll(",
35 | //???
36 | "docId(": "document.getElementById(",
37 | "docTag(": "document.getElementsByTagName(",
38 | "docClass(": "document.getElementsByClassName(",
39 | "docName(": "document.getElementsByName(",
40 | "docQuery(": "document.querySelector(",
41 | "docAll(": "document.querySelectorAll(",
42 | "tag(": "getElementsByTagName(",
43 | "class(": "getElementsByClassName(",
44 | "name(": "getElementsByName(",
45 | "query(": "querySelector(",
46 | "all(": "querySelectorAll(",
47 | //val
48 | ".html": ".innerHTML",
49 | ".val": ".value",
50 | ".text": ".innerText",
51 | //style
52 | ".color": ".style.color",
53 | "fonts": ".style.fontSize",
54 | "fontf": "style.fontFamily",
55 | //
56 | ".addEvent(": ".addEventListener(",
57 | }
58 |
59 | rejs := re(str, amap)
60 | return rejs
61 | }
62 |
63 | func reIf(str string) string {
64 | iftext := strings.Replace(str, "if ", "if (", -1)
65 | // fmt.Println("str--------", iftext)
66 | strtext := strings.Replace(iftext, " {", "){", -1)
67 | return strtext
68 | }
69 |
70 | func reWhile(str string) string {
71 | fortext := strings.Replace(str, "while ", "while (", -1)
72 | strtext := strings.Replace(fortext, " {", "){", -1)
73 | return strtext
74 | }
75 |
76 | func reFor(str string) string {
77 | fortext := strings.Replace(str, "for ", "for (", -1)
78 | strtext := strings.Replace(fortext, " {", "){", -1)
79 | return strtext
80 | }
81 |
82 | func reVar(str string) string {
83 | vartext := strings.Replace(str, ":=", "var ", -1)
84 | strtext := strings.Replace(vartext, " {", "){", -1)
85 | return strtext
86 | }
87 |
88 | func reLen(str string) string {
89 | lentext := strings.Replace(str, "len(", " ", -1)
90 | strtext := strings.Replace(lentext, ")", ".length", -1)
91 | return strtext
92 | }
93 |
--------------------------------------------------------------------------------
/examples/realtime-advanced/resources/static/prismjs.min.css:
--------------------------------------------------------------------------------
1 | /* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+go */
2 | /**
3 | * prism.js default theme for JavaScript, CSS and HTML
4 | * Based on dabblet (http://dabblet.com)
5 | * @author Lea Verou
6 | */
7 |
8 | code[class*="language-"],
9 | pre[class*="language-"] {
10 | color: black;
11 | text-shadow: 0 1px white;
12 | font-family: Consolas, Monaco, 'Andale Mono', monospace;
13 | direction: ltr;
14 | text-align: left;
15 | white-space: pre;
16 | word-spacing: normal;
17 | word-break: normal;
18 | line-height: 1.5;
19 |
20 | -moz-tab-size: 4;
21 | -o-tab-size: 4;
22 | tab-size: 4;
23 |
24 | -webkit-hyphens: none;
25 | -moz-hyphens: none;
26 | -ms-hyphens: none;
27 | hyphens: none;
28 | }
29 |
30 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
31 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
32 | text-shadow: none;
33 | background: #b3d4fc;
34 | }
35 |
36 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
37 | code[class*="language-"]::selection, code[class*="language-"] ::selection {
38 | text-shadow: none;
39 | background: #b3d4fc;
40 | }
41 |
42 | @media print {
43 | code[class*="language-"],
44 | pre[class*="language-"] {
45 | text-shadow: none;
46 | }
47 | }
48 |
49 | /* Code blocks */
50 | pre[class*="language-"] {
51 | padding: 1em;
52 | margin: .5em 0;
53 | overflow: auto;
54 | }
55 |
56 | :not(pre) > code[class*="language-"],
57 | pre[class*="language-"] {
58 | background: #f5f2f0;
59 | }
60 |
61 | /* Inline code */
62 | :not(pre) > code[class*="language-"] {
63 | padding: .1em;
64 | border-radius: .3em;
65 | }
66 |
67 | .token.comment,
68 | .token.prolog,
69 | .token.doctype,
70 | .token.cdata {
71 | color: slategray;
72 | }
73 |
74 | .token.punctuation {
75 | color: #999;
76 | }
77 |
78 | .namespace {
79 | opacity: .7;
80 | }
81 |
82 | .token.property,
83 | .token.tag,
84 | .token.boolean,
85 | .token.number,
86 | .token.constant,
87 | .token.symbol,
88 | .token.deleted {
89 | color: #905;
90 | }
91 |
92 | .token.selector,
93 | .token.attr-name,
94 | .token.string,
95 | .token.char,
96 | .token.builtin,
97 | .token.inserted {
98 | color: #690;
99 | }
100 |
101 | .token.operator,
102 | .token.entity,
103 | .token.url,
104 | .language-css .token.string,
105 | .style .token.string {
106 | color: #a67f59;
107 | background: hsla(0, 0%, 100%, .5);
108 | }
109 |
110 | .token.atrule,
111 | .token.attr-value,
112 | .token.keyword {
113 | color: #07a;
114 | }
115 |
116 | .token.function {
117 | color: #DD4A68;
118 | }
119 |
120 | .token.regex,
121 | .token.important,
122 | .token.variable {
123 | color: #e90;
124 | }
125 |
126 | .token.important,
127 | .token.bold {
128 | font-weight: bold;
129 | }
130 | .token.italic {
131 | font-style: italic;
132 | }
133 |
134 | .token.entity {
135 | cursor: help;
136 | }
137 |
138 |
--------------------------------------------------------------------------------
/mid/rego/css.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
13 | // "fmt"
14 |
15 | func reCss(str string) string {
16 | amap := Map{
17 | //text
18 | "lh:": "line-height:",
19 | "ta:": "text-align:",
20 | "va:": "vertical-align:",
21 | "td:": "text-decoration:",
22 | "tt:": "text-transform:",
23 | "ti:": "text-indent:",
24 | "ts:": "text-shadow:",
25 | "ws:": "white-space:",
26 | "wb:": "word-break:",
27 | "to:": "text-overflow:",
28 | //font
29 | // "f:": "font",
30 | "fs:": "font-size:",
31 | "ff:": "font-family:",
32 | "fst:": "font-style:",
33 | "fw:": "font-weight:",
34 | "fv:": "font-variant:",
35 | //bg
36 | "bg:": "background:",
37 | // "bgc:": "background-color:",
38 | "bc:": "background-color:",
39 | "bi:": "background-image:",
40 | "bp:": "background-position:",
41 | "bgr:": "background-repeat:",
42 | "ba:": "background-attachment:",
43 | "bgs": "background-size:",
44 | "bo:": "background-origin:",
45 | "bgc:": "background-clip:",
46 | //margin
47 | "mg:": "margin:",
48 | "ml:": "margin-left:",
49 | "mr:": "margin-right:",
50 | "mt:": "margin-top:",
51 | "mb:": "margin-bottom:",
52 | //
53 | "mh:": "max-height:",
54 | "mw": "max-width:",
55 | "mih": "min-height:",
56 | "miw": "min-width:",
57 | "vb:": "visibility:",
58 | "dp:": "display:",
59 | "pt:": "position:",
60 | //padding
61 | "pd:": "padding:",
62 | "pdt:": "padding-top:",
63 | "pb:": "padding-bottom:",
64 | "pr:": "padding-right:",
65 | "pl:": "padding-left:",
66 | //list
67 | "ls:": "list-style:",
68 | "lst:": "list-style-type:",
69 | "lsi:": "list-style-image:",
70 | "lsp:": "list-style-position:",
71 | //border
72 | "bd:": "border:",
73 | "bw:": "border-width:",
74 | "bt:": "border-top:",
75 | "bb:": "border-bottom:",
76 | "bl:": "border-left:",
77 | "bri:": "border-right:",
78 | "bdi:": "border-image:",
79 | // border-style
80 | "bs:": "border-style:",
81 | "bts:": "border-top-style:",
82 | "brs:": "border-right-style:",
83 | "bbs:": "border-bottom-style:",
84 | "bls:": "border-left-style:",
85 | "bdc:": "border-color:",
86 | "br:": "border-radius:",
87 | "bca:": "border-collapse:",
88 | // "bdca:": "border-collapse:",
89 | "boxs:": "box-shadow",
90 | //outline
91 | "oc:": "outline-color:",
92 | "os:": "outline-style:",
93 | "ow:": "outline-width:",
94 | //
95 | "tf:": "transform",
96 | }
97 |
98 | recss := re(str, amap)
99 | return recss
100 | }
101 |
--------------------------------------------------------------------------------
/mid/binding/example/test.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: test.proto
3 | // DO NOT EDIT!
4 |
5 | /*
6 | Package example is a generated protocol buffer package.
7 |
8 | It is generated from these files:
9 | test.proto
10 |
11 | It has these top-level messages:
12 | Test
13 | */
14 | package example
15 |
16 | import proto "github.com/golang/protobuf/proto"
17 | import math "math"
18 |
19 | // Reference imports to suppress errors if they are not otherwise used.
20 | var _ = proto.Marshal
21 | var _ = math.Inf
22 |
23 | type FOO int32
24 |
25 | const (
26 | FOO_X FOO = 17
27 | )
28 |
29 | var FOO_name = map[int32]string{
30 | 17: "X",
31 | }
32 | var FOO_value = map[string]int32{
33 | "X": 17,
34 | }
35 |
36 | func (x FOO) Enum() *FOO {
37 | p := new(FOO)
38 | *p = x
39 | return p
40 | }
41 | func (x FOO) String() string {
42 | return proto.EnumName(FOO_name, int32(x))
43 | }
44 | func (x *FOO) UnmarshalJSON(data []byte) error {
45 | value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO")
46 | if err != nil {
47 | return err
48 | }
49 | *x = FOO(value)
50 | return nil
51 | }
52 |
53 | type Test struct {
54 | Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
55 | Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
56 | Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
57 | Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
58 | XXX_unrecognized []byte `json:"-"`
59 | }
60 |
61 | func (m *Test) Reset() { *m = Test{} }
62 | func (m *Test) String() string { return proto.CompactTextString(m) }
63 | func (*Test) ProtoMessage() {}
64 |
65 | const Default_Test_Type int32 = 77
66 |
67 | func (m *Test) GetLabel() string {
68 | if m != nil && m.Label != nil {
69 | return *m.Label
70 | }
71 | return ""
72 | }
73 |
74 | func (m *Test) GetType() int32 {
75 | if m != nil && m.Type != nil {
76 | return *m.Type
77 | }
78 | return Default_Test_Type
79 | }
80 |
81 | func (m *Test) GetReps() []int64 {
82 | if m != nil {
83 | return m.Reps
84 | }
85 | return nil
86 | }
87 |
88 | func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
89 | if m != nil {
90 | return m.Optionalgroup
91 | }
92 | return nil
93 | }
94 |
95 | type Test_OptionalGroup struct {
96 | RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
97 | XXX_unrecognized []byte `json:"-"`
98 | }
99 |
100 | func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
101 | func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
102 | func (*Test_OptionalGroup) ProtoMessage() {}
103 |
104 | func (m *Test_OptionalGroup) GetRequiredField() string {
105 | if m != nil && m.RequiredField != nil {
106 | return *m.RequiredField
107 | }
108 | return ""
109 | }
110 |
111 | func init() {
112 | proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
113 | }
114 |
--------------------------------------------------------------------------------
/mid/util/path.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 Julien Schmidt. All rights reserved.
2 | // Based on the path package, Copyright 2009 The Go Authors.
3 | // Use of this source code is governed by a BSD-style license that can be found
4 | // in the LICENSE file.
5 |
6 | package util
7 |
8 | // CleanPath is the URL version of path.Clean, it returns a canonical URL path
9 | // for p, eliminating . and .. elements.
10 | //
11 | // The following rules are applied iteratively until no further processing can
12 | // be done:
13 | // 1. Replace multiple slashes with a single slash.
14 | // 2. Eliminate each . path name element (the current directory).
15 | // 3. Eliminate each inner .. path name element (the parent directory)
16 | // along with the non-.. element that precedes it.
17 | // 4. Eliminate .. elements that begin a rooted path:
18 | // that is, replace "/.." by "/" at the beginning of a path.
19 | //
20 | // If the result of this process is an empty string, "/" is returned.
21 | func CleanPath(p string) string {
22 | // Turn empty string into "/"
23 | if p == "" {
24 | return "/"
25 | }
26 |
27 | n := len(p)
28 | var buf []byte
29 |
30 | // Invariants:
31 | // reading from path; r is index of next byte to process.
32 | // writing to buf; w is index of next byte to write.
33 |
34 | // path must start with '/'
35 | r := 1
36 | w := 1
37 |
38 | if p[0] != '/' {
39 | r = 0
40 | buf = make([]byte, n+1)
41 | buf[0] = '/'
42 | }
43 |
44 | trailing := n > 1 && p[n-1] == '/'
45 |
46 | // A bit more clunky without a 'lazybuf' like the path package, but the loop
47 | // gets completely inlined (bufApp). So in contrast to the path package this
48 | // loop has no expensive function calls (except 1x make)
49 |
50 | for r < n {
51 | switch {
52 | case p[r] == '/':
53 | // empty path element, trailing slash is added after the end
54 | r++
55 |
56 | case p[r] == '.' && r+1 == n:
57 | trailing = true
58 | r++
59 |
60 | case p[r] == '.' && p[r+1] == '/':
61 | // . element
62 | r += 2
63 |
64 | case p[r] == '.' && p[r+1] == '.' && (r+2 == n || p[r+2] == '/'):
65 | // .. element: remove to last /
66 | r += 3
67 |
68 | if w > 1 {
69 | // can backtrack
70 | w--
71 |
72 | if buf == nil {
73 | for w > 1 && p[w] != '/' {
74 | w--
75 | }
76 | } else {
77 | for w > 1 && buf[w] != '/' {
78 | w--
79 | }
80 | }
81 | }
82 |
83 | default:
84 | // real path element.
85 | // add slash if needed
86 | if w > 1 {
87 | bufApp(&buf, p, w, '/')
88 | w++
89 | }
90 |
91 | // copy element
92 | for r < n && p[r] != '/' {
93 | bufApp(&buf, p, w, p[r])
94 | w++
95 | r++
96 | }
97 | }
98 | }
99 |
100 | // re-append trailing slash
101 | if trailing && w > 1 {
102 | bufApp(&buf, p, w, '/')
103 | w++
104 | }
105 |
106 | if buf == nil {
107 | return p[:w]
108 | }
109 | return string(buf[:w])
110 | }
111 |
112 | // bufApp internal helper to lazily create a buffer if necessary.
113 | func bufApp(buf *[]byte, s string, w int, c byte) {
114 | if *buf == nil {
115 | if s[w] == c {
116 | return
117 | }
118 |
119 | *buf = make([]byte, len(s))
120 | copy(*buf, s[:w])
121 | }
122 | (*buf)[w] = c
123 | }
124 |
--------------------------------------------------------------------------------
/auth.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ego
6 |
7 | import (
8 | "crypto/subtle"
9 | "encoding/base64"
10 | "net/http"
11 | "strconv"
12 | )
13 |
14 | // AuthUserKey is the cookie name for user credential in basic auth.
15 | const AuthUserKey = "user"
16 |
17 | type (
18 | // Accounts defines a key/value for user/pass list of authorized logins.
19 | Accounts map[string]string
20 | authPairs []authPair
21 | )
22 |
23 | type authPair struct {
24 | value string
25 | user string
26 | }
27 |
28 | func (a authPairs) searchCredential(authValue string) (string, bool) {
29 | if authValue == "" {
30 | return "", false
31 | }
32 | for _, pair := range a {
33 | if pair.value == authValue {
34 | return pair.user, true
35 | }
36 | }
37 | return "", false
38 | }
39 |
40 | // BasicAuthForRealm returns a Basic HTTP Authorization middleware. It takes as arguments a map[string]string where
41 | // the key is the user name and the value is the password, as well as the name of the Realm.
42 | // If the realm is empty, "Authorization Required" will be used by default.
43 | // (see http://tools.ietf.org/html/rfc2617#section-1.2)
44 | func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc {
45 | if realm == "" {
46 | realm = "Authorization Required"
47 | }
48 | realm = "Basic realm=" + strconv.Quote(realm)
49 | pairs := processAccounts(accounts)
50 | return func(c *Context) {
51 | // Search user in the slice of allowed credentials.
52 | user, found := pairs.searchCredential(c.requestHeader("Authorization"))
53 | if !found {
54 | // Credentials doesn't match, we return 401 and abort handlers chain.
55 | c.Header("WWW-Authenticate", realm)
56 | c.AbortWithStatus(http.StatusUnauthorized)
57 | return
58 | }
59 |
60 | // The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using
61 | // c.MustGet(ego.AuthUserKey).
62 | c.Set(AuthUserKey, user)
63 | }
64 | }
65 |
66 | // BasicAuth returns a Basic HTTP Authorization middleware. It takes as argument a map[string]string where
67 | // the key is the user name and the value is the password.
68 | func BasicAuth(accounts Accounts) HandlerFunc {
69 | return BasicAuthForRealm(accounts, "")
70 | }
71 |
72 | func processAccounts(accounts Accounts) authPairs {
73 | assert1(len(accounts) > 0, "Empty list of authorized credentials")
74 | pairs := make(authPairs, 0, len(accounts))
75 | for user, password := range accounts {
76 | assert1(user != "", "User can not be empty")
77 | value := authorizationHeader(user, password)
78 | pairs = append(pairs, authPair{
79 | value: value,
80 | user: user,
81 | })
82 | }
83 | return pairs
84 | }
85 |
86 | func authorizationHeader(user, password string) string {
87 | base := user + ":" + password
88 | return "Basic " + base64.StdEncoding.EncodeToString([]byte(base))
89 | }
90 |
91 | func secureCompare(given, actual string) bool {
92 | if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 {
93 | return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1
94 | }
95 | // Securely compare actual to itself to keep constant time, but always return false.
96 | return subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 && false
97 | }
98 |
--------------------------------------------------------------------------------
/response_writer.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2 | // Use of this source code is governed by a MIT style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ego
6 |
7 | import (
8 | "bufio"
9 | "io"
10 | "net"
11 | "net/http"
12 | )
13 |
14 | const (
15 | noWritten = -1
16 | defaultStatus = http.StatusOK
17 | )
18 |
19 | // ResponseWriter ...
20 | type ResponseWriter interface {
21 | responseWriterBase
22 | // get the http.Pusher for server push
23 | Pusher() http.Pusher
24 | }
25 |
26 | type (
27 | responseWriterBase interface {
28 | http.ResponseWriter
29 | http.Hijacker
30 | http.Flusher
31 | http.CloseNotifier
32 |
33 | // Returns the HTTP response status code of the current request.
34 | Status() int
35 |
36 | // Returns the number of bytes already written into the response http body.
37 | // See Written()
38 | Size() int
39 |
40 | // Writes the string into the response body.
41 | WriteString(string) (int, error)
42 |
43 | // Returns true if the response body was already written.
44 | Written() bool
45 |
46 | // Forces to write the http header (status code + headers).
47 | WriteHeaderNow()
48 | }
49 |
50 | responseWriter struct {
51 | http.ResponseWriter
52 | size int
53 | status int
54 | }
55 | )
56 |
57 | var _ ResponseWriter = &responseWriter{}
58 |
59 | func (w *responseWriter) reset(writer http.ResponseWriter) {
60 | w.ResponseWriter = writer
61 | w.size = noWritten
62 | w.status = defaultStatus
63 | }
64 |
65 | func (w *responseWriter) Pusher() (pusher http.Pusher) {
66 | if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
67 | return pusher
68 | }
69 | return nil
70 | }
71 |
72 | func (w *responseWriter) WriteHeader(code int) {
73 | if code > 0 && w.status != code {
74 | if w.Written() {
75 | debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code)
76 | }
77 | w.status = code
78 | }
79 | }
80 |
81 | func (w *responseWriter) WriteHeaderNow() {
82 | if !w.Written() {
83 | w.size = 0
84 | w.ResponseWriter.WriteHeader(w.status)
85 | }
86 | }
87 |
88 | func (w *responseWriter) Write(data []byte) (n int, err error) {
89 | w.WriteHeaderNow()
90 | n, err = w.ResponseWriter.Write(data)
91 | w.size += n
92 | return
93 | }
94 |
95 | func (w *responseWriter) WriteString(s string) (n int, err error) {
96 | w.WriteHeaderNow()
97 | n, err = io.WriteString(w.ResponseWriter, s)
98 | w.size += n
99 | return
100 | }
101 |
102 | func (w *responseWriter) Status() int {
103 | return w.status
104 | }
105 |
106 | func (w *responseWriter) Size() int {
107 | return w.size
108 | }
109 |
110 | func (w *responseWriter) Written() bool {
111 | return w.size != noWritten
112 | }
113 |
114 | // Hijack implements the http.Hijacker interface.
115 | func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
116 | if w.size < 0 {
117 | w.size = 0
118 | }
119 | return w.ResponseWriter.(http.Hijacker).Hijack()
120 | }
121 |
122 | // CloseNotify implements the http.CloseNotify interface.
123 | func (w *responseWriter) CloseNotify() <-chan bool {
124 | return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
125 | }
126 |
127 | // Flush implements the http.Flush interface.
128 | func (w *responseWriter) Flush() {
129 | w.WriteHeaderNow()
130 | w.ResponseWriter.(http.Flusher).Flush()
131 | }
132 |
--------------------------------------------------------------------------------
/mid/rego/trim.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
2 | // file at the top-level directory of this distribution and at
3 | // https://github.com/go-ego/ego/blob/master/LICENSE
4 | //
5 | // Licensed under the Apache License, Version 2.0 or the MIT license
7 | // , at your
8 | // option. This file may not be copied, modified, or distributed
9 | // except according to those terms.
10 |
11 | package rego
12 |
13 | import (
14 | // "fmt"
15 | "regexp"
16 | "strings"
17 | )
18 |
19 | func TrimNotes(rfile string) string {
20 | regc := regexp.MustCompile("(?U)\\/\\*[\\s\\S]*\\*\\/|\\/\\/.*(\n|\r)")
21 |
22 | rname := rfile + "\n"
23 | restr := regc.ReplaceAllString(rname, "")
24 | return restr
25 | }
26 |
27 | func TrimSlot(text string) string {
28 | slot := strings.Replace(text, " ", "", -1)
29 | // fmt.Println(slot)
30 | return slot
31 | }
32 |
33 | func TrimQ(tkey string, restr []string) []string {
34 | var reval []string
35 | for i := 0; i < len(restr); i++ {
36 | tval := strings.Trim(restr[i], tkey+"\\=\\")
37 | bval := strings.Trim(tval, `\"`)
38 |
39 | reval = append(reval, bval)
40 | }
41 | return reval
42 | }
43 |
44 | func TrimTVal(tkey string, restr []string) []string {
45 | var reval []string
46 | for i := 0; i < len(restr); i++ {
47 | tval := strings.Trim(restr[i], tkey+"\\=\\")
48 | var bval string
49 |
50 | if strings.HasSuffix(tval, "}") {
51 | bval = strings.Trim(tval, `\{|\}`)
52 | } else {
53 | bval = strings.Trim(tval, `\"`)
54 | }
55 |
56 | reval = append(reval, bval)
57 | }
58 | return reval
59 | }
60 |
61 | func TrimVal(fval []string, keyarr, header, tvgostr string) string {
62 | tkey := TrimB(keyarr)
63 | tfval := TrimTVal(tkey, fval)
64 |
65 | if len(header) == 0 {
66 | header = strings.Replace(tvgostr, keyarr, tfval[0], -1)
67 | } else {
68 | header = strings.Replace(header, keyarr, tfval[0], -1)
69 | }
70 |
71 | return header
72 | }
73 |
74 | func Quotation(rfile string) []string {
75 | regc := regexp.MustCompile(`(?U)\".*\"`)
76 | restr := regc.FindAllString(rfile, -1)
77 | return restr
78 | }
79 |
80 | func TrimQt(str string) string {
81 | restr := strings.Trim(str, `\"`)
82 | return restr
83 | }
84 |
85 | func TrimB(str string) string {
86 | restr := strings.Trim(str, `\{|\}`)
87 | return restr
88 | }
89 |
90 | //TrimBlank
91 | func TrimBlank(str string) string {
92 | regt := regexp.MustCompile(`\t|\r|\n|\"|\s*`)
93 | restr := regt.ReplaceAllString(str, "")
94 | return restr
95 | }
96 |
97 | func TrimIs(str string) string {
98 | regt := regexp.MustCompile("(?U)\\