├── .github └── workflows │ └── build.yaml ├── .gitignore ├── Dockerfile ├── Godeps ├── Godeps.json └── Readme ├── README.md ├── azure-pipelines.yml ├── combine-gif.gif ├── conf └── app.conf ├── controllers ├── chart.go ├── chartmuseum.go ├── deleteChart.go ├── login.go ├── main.go └── uploadChart.go ├── docker-compose.yaml ├── example_rabbitmq.png ├── home.png ├── image_builder.sh ├── logo.png ├── main.go ├── models ├── charts.go ├── error.go └── user.go ├── quickstart ├── routers └── router.go ├── services └── login.go ├── static ├── css │ └── styles.css ├── img │ ├── delete-button.png │ ├── icon_default.png │ ├── logo.png │ ├── logo_dark.png │ ├── logo_white.png │ ├── logo_white_old.png │ └── plus.png └── js │ └── reload.min.js ├── tests └── default_test.go ├── vendor ├── github.com │ ├── astaxie │ │ └── beego │ │ │ ├── .gitignore │ │ │ ├── .gosimpleignore │ │ │ ├── .travis.yml │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── admin.go │ │ │ ├── adminui.go │ │ │ ├── app.go │ │ │ ├── beego.go │ │ │ ├── config.go │ │ │ ├── config │ │ │ ├── config.go │ │ │ ├── fake.go │ │ │ ├── ini.go │ │ │ └── json.go │ │ │ ├── context │ │ │ ├── acceptencoder.go │ │ │ ├── context.go │ │ │ ├── input.go │ │ │ ├── output.go │ │ │ ├── param │ │ │ │ ├── conv.go │ │ │ │ ├── methodparams.go │ │ │ │ ├── options.go │ │ │ │ └── parsers.go │ │ │ ├── renderer.go │ │ │ └── response.go │ │ │ ├── controller.go │ │ │ ├── doc.go │ │ │ ├── error.go │ │ │ ├── filter.go │ │ │ ├── flash.go │ │ │ ├── grace │ │ │ ├── conn.go │ │ │ ├── grace.go │ │ │ ├── listener.go │ │ │ └── server.go │ │ │ ├── hooks.go │ │ │ ├── httplib │ │ │ ├── README.md │ │ │ └── httplib.go │ │ │ ├── log.go │ │ │ ├── logs │ │ │ ├── README.md │ │ │ ├── accesslog.go │ │ │ ├── color.go │ │ │ ├── color_windows.go │ │ │ ├── conn.go │ │ │ ├── console.go │ │ │ ├── file.go │ │ │ ├── jianliao.go │ │ │ ├── log.go │ │ │ ├── logger.go │ │ │ ├── multifile.go │ │ │ ├── slack.go │ │ │ └── smtp.go │ │ │ ├── mime.go │ │ │ ├── namespace.go │ │ │ ├── parser.go │ │ │ ├── plugins │ │ │ └── auth │ │ │ │ └── basic.go │ │ │ ├── policy.go │ │ │ ├── router.go │ │ │ ├── session │ │ │ ├── README.md │ │ │ ├── sess_cookie.go │ │ │ ├── sess_file.go │ │ │ ├── sess_mem.go │ │ │ ├── sess_utils.go │ │ │ └── session.go │ │ │ ├── staticfile.go │ │ │ ├── template.go │ │ │ ├── templatefunc.go │ │ │ ├── toolbox │ │ │ ├── healthcheck.go │ │ │ ├── profile.go │ │ │ ├── statistics.go │ │ │ └── task.go │ │ │ ├── tree.go │ │ │ └── utils │ │ │ ├── caller.go │ │ │ ├── debug.go │ │ │ ├── file.go │ │ │ ├── mail.go │ │ │ ├── rand.go │ │ │ ├── safemap.go │ │ │ ├── slice.go │ │ │ └── utils.go │ └── lib │ │ └── pq │ │ ├── .gitignore │ │ ├── .travis.sh │ │ ├── .travis.yml │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── array.go │ │ ├── buf.go │ │ ├── conn.go │ │ ├── conn_go18.go │ │ ├── copy.go │ │ ├── doc.go │ │ ├── encode.go │ │ ├── error.go │ │ ├── notify.go │ │ ├── oid │ │ ├── doc.go │ │ ├── gen.go │ │ └── types.go │ │ ├── rows.go │ │ ├── ssl.go │ │ ├── ssl_go1.7.go │ │ ├── ssl_permissions.go │ │ ├── ssl_renegotiation.go │ │ ├── ssl_windows.go │ │ ├── url.go │ │ ├── user_posix.go │ │ ├── user_windows.go │ │ └── uuid.go ├── golang.org │ └── x │ │ └── crypto │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── LICENSE │ │ ├── PATENTS │ │ └── acme │ │ ├── acme.go │ │ ├── autocert │ │ ├── autocert.go │ │ ├── cache.go │ │ ├── listener.go │ │ └── renewal.go │ │ ├── jws.go │ │ └── types.go └── gopkg.in │ └── yaml.v2 │ ├── .travis.yml │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── NOTICE │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── go.mod │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── views ├── chart.tpl ├── footer.tpl ├── head.tpl ├── header.tpl ├── index.tpl ├── login.tpl └── main.tpl /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | create: 4 | jobs: 5 | docker: 6 | if: ${{ startsWith(github.ref, 'refs/tags/v') }} 7 | runs-on: ubuntu-latest 8 | steps: 9 | - 10 | name: Checkout 11 | uses: actions/checkout@v2 12 | - 13 | name: Docker meta 14 | id: meta 15 | uses: docker/metadata-action@v3 16 | with: 17 | images: lowid/chartmuseum-ui 18 | tags: | 19 | type=semver,pattern={{version}} 20 | type=semver,pattern={{major}}.{{minor}} 21 | - 22 | name: Login to DockerHub 23 | if: github.event_name != 'pull_request' 24 | uses: docker/login-action@v1 25 | with: 26 | username: ${{ secrets.DOCKERHUB_USERNAME }} 27 | password: ${{ secrets.DOCKERHUB_TOKEN }} 28 | - 29 | name: Build and push 30 | uses: docker/build-push-action@v2 31 | with: 32 | context: . 33 | push: ${{ github.event_name != 'pull_request' }} 34 | tags: ${{ steps.meta.outputs.tags }} 35 | labels: ${{ steps.meta.outputs.labels }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | charts/ 3 | ui 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Stage 1 3 | # 4 | FROM library/golang:1 as builder 5 | 6 | # Godep for vendoring 7 | RUN go get github.com/tools/godep 8 | 9 | # Recompile the standard library without CGO 10 | RUN CGO_ENABLED=0 go install -a std 11 | 12 | ENV APP_DIR $GOPATH/src/github.com/chartmuseum/ui 13 | RUN mkdir -p $APP_DIR 14 | ADD . $APP_DIR 15 | 16 | # Compile the binary and statically link 17 | RUN cd $APP_DIR && \ 18 | GO111MODULE=auto CGO_ENABLED=0 godep go build -ldflags '-w -s' -o /chartmuseum-ui && \ 19 | cp -r views/ /views && \ 20 | cp -r static/ /static 21 | 22 | # 23 | # Stage 2 24 | # 25 | FROM alpine:3.8 26 | RUN apk add --no-cache curl cifs-utils ca-certificates \ 27 | && adduser -D -u 1000 chartmuseum 28 | COPY --from=builder /chartmuseum-ui /chartmuseum-ui 29 | COPY --from=builder /views /views 30 | COPY --from=builder /static /static 31 | USER 1000 32 | ENTRYPOINT ["/chartmuseum-ui"] 33 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "ui", 3 | "GoVersion": "go1.11", 4 | "GodepVersion": "v80", 5 | "Deps": [ 6 | { 7 | "ImportPath": "github.com/astaxie/beego", 8 | "Comment": "v1.10.1", 9 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 10 | }, 11 | { 12 | "ImportPath": "github.com/astaxie/beego/config", 13 | "Comment": "v1.10.1", 14 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 15 | }, 16 | { 17 | "ImportPath": "github.com/astaxie/beego/context", 18 | "Comment": "v1.10.1", 19 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 20 | }, 21 | { 22 | "ImportPath": "github.com/astaxie/beego/context/param", 23 | "Comment": "v1.10.1", 24 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 25 | }, 26 | { 27 | "ImportPath": "github.com/astaxie/beego/grace", 28 | "Comment": "v1.10.1", 29 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 30 | }, 31 | { 32 | "ImportPath": "github.com/astaxie/beego/httplib", 33 | "Comment": "v1.10.1", 34 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 35 | }, 36 | { 37 | "ImportPath": "github.com/astaxie/beego/logs", 38 | "Comment": "v1.10.1", 39 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 40 | }, 41 | { 42 | "ImportPath": "github.com/astaxie/beego/plugins/auth", 43 | "Comment": "v1.10.1", 44 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 45 | }, 46 | { 47 | "ImportPath": "github.com/astaxie/beego/session", 48 | "Comment": "v1.10.1", 49 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 50 | }, 51 | { 52 | "ImportPath": "github.com/astaxie/beego/toolbox", 53 | "Comment": "v1.10.1", 54 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 55 | }, 56 | { 57 | "ImportPath": "github.com/astaxie/beego/utils", 58 | "Comment": "v1.10.1", 59 | "Rev": "053a075344c118a5cc41981b29ef612bb53d20ca" 60 | }, 61 | { 62 | "ImportPath": "github.com/lib/pq", 63 | "Comment": "go1.0-cutoff-197-g27ea5d9", 64 | "Rev": "27ea5d92de30060e7121ddd543fe14e9a327e0cc" 65 | }, 66 | { 67 | "ImportPath": "github.com/lib/pq/oid", 68 | "Comment": "go1.0-cutoff-197-g27ea5d9", 69 | "Rev": "27ea5d92de30060e7121ddd543fe14e9a327e0cc" 70 | }, 71 | { 72 | "ImportPath": "golang.org/x/crypto/acme", 73 | "Rev": "ae8bce0030810cf999bb2b9868ae5c7c58e6343b" 74 | }, 75 | { 76 | "ImportPath": "golang.org/x/crypto/acme/autocert", 77 | "Rev": "ae8bce0030810cf999bb2b9868ae5c7c58e6343b" 78 | }, 79 | { 80 | "ImportPath": "gopkg.in/yaml.v2", 81 | "Comment": "v2.2.1", 82 | "Rev": "5420a8b6744d3b0345ab293f6fcba19c978f1183" 83 | } 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChartMuseumUI 2 | [![HitCount](http://hits.dwyl.io/idobry/chartmuseumui.svg)](http://hits.dwyl.io/idobry/chartmuseumui) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/dwyl/esta/issues) [![Go Report Card](https://goreportcard.com/badge/github.com/chartmuseum/ui)](https://goreportcard.com/report/github.com/chartmuseum/ui) 3 | 4 | 5 | 6 | # ChartMuseumUI 7 | 8 | ChartMuseumUI is a simple web app that (currently) provides GUI for your charts so you and your team can view and share the technologies your are using to any one at any time (in near future more capabilities will be added). 9 | ChartMuseumUI was written in Go (Golang) with the help of Beego Framework. 10 | 11 | 12 | 13 | ## Getting Started 14 | 15 | These instructions will get you started with your very own private chart repository and UI. 16 | 17 | ### Usage 18 | 19 | ChartMuseumUI uses [ChartMuseum](https://github.com/helm/chartmuseum) as a backend. 20 | To get started quickly, you can build and run the app using docker-compose. 21 | 22 | Clone this repo and run the following: 23 | 24 | ``` 25 | docker-compose up 26 | ``` 27 | 28 | This will start ChartMuseumUI at [http://localhost:3000](http://localhost:3000) 29 | and ChartMuseum at [http://localhost:8080](http://localhost:8080). 30 | Check out the source of [docker-compose.yaml](./docker-compose.yaml) and modify for your purposes. 31 | 32 | Here is an example docker-compose file defining ChartMuseum with Amazon S3 as a storage and exposing ChartMuseumUI on port 80: 33 | ``` 34 | version: '2.0' 35 | services: 36 | ui: 37 | image: idobry/chartmuseumui:latest 38 | environment: 39 | CHART_MUSEUM_URL: "http://chartmuseum:8080" 40 | ports: 41 | - 80:8080 42 | chartmuseum: 43 | image: chartmuseum/chartmuseum:latest 44 | volumes: 45 | - ~/.aws:/root/.aws:ro 46 | restart: always 47 | environment: 48 | PORT: 8080 49 | DEBUG: 1 50 | STORAGE: "amazon" 51 | STORAGE_AMAZON_BUCKET: "chartmuseum-bucket" 52 | STORAGE_AMAZON_PREFIX: "" 53 | STORAGE_AMAZON_REGION: "eu-west-1" 54 | ports: 55 | - 8080:8080 56 | ``` 57 | 58 | Copy this file and run 59 | 60 | ``` 61 | docker-compose up 62 | ``` 63 | Easy, right? now, we can add our private repository to our Helm client: 64 | ``` 65 | # choose any name you like 66 | $ helm repo add chartmuseum 67 | $ helm repo update 68 | # to view our repos list 69 | $ helm repo list 70 | NAME URL 71 | stable https://kubernetes-charts.storage.googleapis.com 72 | incubator http://storage.googleapis.com/kubernetes-charts-incubator 73 | chartmuseum http://localhost:8080 74 | ``` 75 | 76 | Let's upload a chart into our private repository: 77 | 78 | ``` 79 | $ cd /chart/path 80 | # create a chart package - this will create a .tgz file 81 | $ helm package . 82 | # copy packge name and run 83 | $ curl -L --data-binary "@" /api/charts 84 | ``` 85 | 86 | In the browser, navigate to localhost and view your charts 87 | 88 | ### Using with ChartMuseum with Multitenancy enabled 89 | 90 | To use ChartMuseumUI on a ChartMuseum with Multitenancy support enabled, add the following environment variable to ChartMuseumUI 91 | 92 | ``` 93 | CHART_MUSEUM_API_GET_CHARTS: "/api/org1/charts" 94 | ``` 95 | 96 | Currently only one organization is allowed per ChartMuseumUI. 97 | 98 | 99 | ### Adding authentication to ChartMuseumUI 100 | 101 | To add a simple basic auth to ChartMuseumUI, you can add the following configuration 102 | 103 | ``` 104 | BASIC_AUTH_USERS: '[{"username":"admin", "password":"password"}, {"username":"user", "password":"s3cr3t"}]' 105 | ``` 106 | 107 | ## Built With 108 | 109 | * [beego](https://beego.me/) - The web framework used 110 | * [go](https://golang.org/) - Programing language 111 | * [docker](https://www.docker.com/) - Packaged with docker 112 | 113 | 114 | ## Project Roadmap 115 | * Add login screen 116 | * Add more chartmuseum capabilitis: 117 | - Upload a chart 118 | - Support multiple 119 | - Delete a chart 120 | - Ask before deleting 121 | - Delete all versions button 122 | - Back to 'home' after delete all 123 | 124 | ## Contributing 125 | 126 | Code contributions are very welcome. If you are interested in helping make chartmuseumui great then feel free! 127 | 128 | 129 | ## Authors 130 | 131 | * **Ido Braunstain** - *Initial work* 132 | 133 | See also the list of [contributors](https://github.com/idobry/contributors) who participated in this project. 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Docker image 2 | # Build a Docker image to deploy, run, or push to a container registry. 3 | # Add steps that use Docker Compose, tag images, push to a registry, run an image, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/docker 5 | 6 | pool: 7 | vmImage: 'Ubuntu 16.04' 8 | 9 | variables: 10 | imageName: 'idobry/chartmuseumui:$(build.buildId)' 11 | 12 | steps: 13 | - script: docker build -f Dockerfile -t $(imageName) . 14 | displayName: 'docker build' 15 | -------------------------------------------------------------------------------- /combine-gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/combine-gif.gif -------------------------------------------------------------------------------- /conf/app.conf: -------------------------------------------------------------------------------- 1 | appname = ui 2 | httpport = 8080 3 | runmode = dev 4 | -------------------------------------------------------------------------------- /controllers/chart.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/astaxie/beego/logs" 6 | ) 7 | 8 | // ChartController handles getting and displaying charts 9 | type ChartController struct { 10 | beego.Controller 11 | } 12 | 13 | // Get render all versions of one specific chart 14 | func (c *ChartController) Get() { 15 | 16 | l := logs.GetLogger() 17 | l.Println("into chart page") 18 | 19 | var name string 20 | c.Ctx.Input.Bind(&name, "name") 21 | 22 | c.Data["chart"] = getCharts()[name] 23 | 24 | l.Println(getCharts()[name]) 25 | 26 | c.TplName = "chart.tpl" 27 | } 28 | -------------------------------------------------------------------------------- /controllers/chartmuseum.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "os" 5 | "os/exec" 6 | 7 | "github.com/chartmuseum/ui/models" 8 | 9 | "github.com/astaxie/beego/httplib" 10 | "github.com/astaxie/beego/logs" 11 | ) 12 | 13 | const apiGetCharts = "/api/charts" 14 | 15 | func getCharts() map[string][]models.Chart { 16 | 17 | l := logs.GetLogger() 18 | l.Printf("Getting charts on url: %s\n", getBaseURL()) 19 | res, err := httplib.Get(getBaseURL()).Debug(true).Bytes() 20 | if err != nil { 21 | l.Panic(err.Error) 22 | } 23 | 24 | charts, err := models.NewCharts(res) 25 | if err != nil { 26 | errorRes, innerErr := models.NewError(res) 27 | if innerErr != nil { 28 | l.Panic(innerErr) 29 | } 30 | l.Panicf("Error received from ChartMuseum application: %s\n", errorRes.Message, err) 31 | } 32 | return charts 33 | } 34 | 35 | func uploadChart(filePath string) { 36 | 37 | l := logs.GetLogger() 38 | 39 | cmd := exec.Command("curl", "-L", "--data-binary", "@"+filePath, getBaseURL()) 40 | out, err := cmd.CombinedOutput() 41 | if err != nil { 42 | l.Fatalf("cmd.Run() failed with %s\n", err) 43 | } 44 | l.Printf("combined out:\n%s\n", string(out)) 45 | } 46 | 47 | func deleteChart(name string, version string) { 48 | 49 | l := logs.GetLogger() 50 | l.Println("in deleteChart()") 51 | cmd := exec.Command("curl", "-X", "DELETE", getBaseURL()+"/"+name+"/"+version) 52 | out, err := cmd.CombinedOutput() 53 | if err != nil { 54 | l.Fatalf("cmd.Run() failed with %s\n", err) 55 | } 56 | l.Printf("combined out:\n%s\n", string(out)) 57 | } 58 | 59 | func getBaseURL() string { 60 | api := os.Getenv("CHART_MUSEUM_API_GET_CHARTS") 61 | if len(api) == 0 { 62 | api = apiGetCharts 63 | } 64 | url := os.Getenv("CHART_MUSEUM_URL") + api 65 | return url 66 | } 67 | -------------------------------------------------------------------------------- /controllers/deleteChart.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/astaxie/beego" 8 | "github.com/astaxie/beego/logs" 9 | ) 10 | 11 | // DeleteChartController handles requests for deleting charts from ChartMuseum 12 | type DeleteChartController struct { 13 | beego.Controller 14 | } 15 | 16 | // Chart reprecents a helm chart to be deleted 17 | type Chart struct { 18 | Name interface{} `form:"name"` 19 | Version interface{} `form:"version"` 20 | } 21 | 22 | // Post handles delete requests from the ui 23 | func (d *DeleteChartController) Post() { 24 | 25 | l := logs.GetLogger() 26 | l.Println("in DELETE") 27 | chart := Chart{} 28 | if err := d.ParseForm(&chart); err != nil { 29 | l.Println("Error in login form") 30 | os.Exit(1) 31 | } else { 32 | name := fmt.Sprintf("%s", chart.Name) 33 | version := fmt.Sprintf("%s", chart.Version) 34 | l.Println("into deleteChart()") 35 | deleteChart(name, version) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /controllers/login.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "database/sql" 5 | "os" 6 | 7 | "github.com/astaxie/beego" 8 | "github.com/astaxie/beego/logs" 9 | 10 | _ "github.com/lib/pq" 11 | ) 12 | 13 | var l = logs.GetLogger() 14 | 15 | type Login struct { 16 | Username interface{} `form:"username"` 17 | Password interface{} `form:"password"` 18 | } 19 | 20 | type LogInController struct { 21 | beego.Controller 22 | } 23 | 24 | type LogInPage struct { 25 | beego.Controller 26 | } 27 | 28 | func (this *LogInController) Post() { 29 | l.Println("in POST") 30 | login := Login{} 31 | if err := this.ParseForm(&login); err != nil { 32 | l.Println("Error in login form") 33 | os.Exit(1) 34 | } 35 | 36 | //connStr := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=verify-full", os.Getenv("DB_HOST"), login.Username, login.Password, os.Getenv("DB_NAME")) 37 | connStr := "dbname=db user=user password=user host=postgres sslmode=disable" 38 | 39 | sqlConnect(connStr) 40 | 41 | this.Redirect("/home", 303) 42 | 43 | } 44 | 45 | func (this *LogInPage) Get() { 46 | this.TplName = "login.tpl" 47 | } 48 | 49 | func sqlConnect(connStr string) { 50 | l.Println("sql connect") 51 | l.Println(connStr) 52 | 53 | beego.BConfig.WebConfig.Session.SessionProvider = "postgresql" 54 | beego.BConfig.WebConfig.Session.SessionProviderConfig = "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full" 55 | 56 | db, err := sql.Open("postgres", connStr) 57 | if err != nil { 58 | l.Println("Error in login form") 59 | os.Exit(1) 60 | } 61 | l.Println("error: " + err.Error()) 62 | err = db.Ping() 63 | if err != nil { 64 | panic(err) 65 | } 66 | l.Println("successful login to db") 67 | } 68 | -------------------------------------------------------------------------------- /controllers/main.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/astaxie/beego/logs" 6 | ) 7 | 8 | // MainController handles the front page 9 | type MainController struct { 10 | beego.Controller 11 | } 12 | 13 | // Get renders a list with all charts in ChartMuseum 14 | func (c *MainController) Get() { 15 | l := logs.GetLogger() 16 | l.Println("I'm alive") 17 | c.Data["charts"] = getCharts() 18 | c.TplName = "main.tpl" 19 | } 20 | -------------------------------------------------------------------------------- /controllers/uploadChart.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/astaxie/beego/logs" 6 | ) 7 | 8 | // UploadChartController handles requests for uploading new charts to ChartMuseum 9 | type UploadChartController struct { 10 | beego.Controller 11 | } 12 | 13 | // Post receives a chart and sends it to ChartMuseum 14 | func (u *UploadChartController) Post() { 15 | 16 | l := logs.GetLogger() 17 | l.Println("**UploadFile**") 18 | file, header, er := u.GetFile("chart") 19 | 20 | if er != nil { 21 | l.Println(er) 22 | } 23 | 24 | filePath := "/tmp/" + header.Filename 25 | 26 | if file != nil { 27 | l.Println("fileName:" + filePath) 28 | err := u.SaveToFile("chart", filePath) 29 | 30 | if err != nil { 31 | l.Println("*SaveToFile*", err.Error) 32 | } 33 | } 34 | l.Println("going into uploadChart()") 35 | uploadChart(filePath) 36 | 37 | } 38 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '2.0' 2 | services: 3 | ui: 4 | build: ./ 5 | #image: idobry/chartmuseumui:latest 6 | environment: 7 | CHART_MUSEUM_URL: http://chartmuseum:8080 8 | ports: 9 | - 3000:8080 10 | chartmuseum: 11 | image: chartmuseum/chartmuseum:v0.7.1 12 | ports: 13 | - 8080:8080 14 | volumes: 15 | - ./charts:/charts 16 | environment: 17 | PORT: 8080 18 | DEBUG: 1 19 | STORAGE: local 20 | STORAGE_LOCAL_ROOTDIR: /charts 21 | -------------------------------------------------------------------------------- /example_rabbitmq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/example_rabbitmq.png -------------------------------------------------------------------------------- /home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/home.png -------------------------------------------------------------------------------- /image_builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | go build . 6 | 7 | godep get 8 | 9 | godep save 10 | 11 | docker build . -t $1 12 | 13 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/logo.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "github.com/chartmuseum/ui/routers" 5 | 6 | "github.com/astaxie/beego" 7 | ) 8 | 9 | func main() { 10 | //beego.BConfig.WebConfig.Session.SessionOn = true 11 | beego.Run() 12 | } 13 | -------------------------------------------------------------------------------- /models/charts.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Chart reprecents a helm chart with all avaible info 8 | type Chart struct { 9 | Name string `json:"name"` 10 | Home string `json:"home"` 11 | Sources []string `json:"sources"` 12 | Version string `json:"version"` 13 | Description string `json:"description"` 14 | Maintainers []Maintainer `json:"maintainers"` 15 | Engine string `json:"engine"` 16 | Icon string `json:"icon"` 17 | Urls []string `json:"urls"` 18 | Created string `json:"created"` 19 | Digest string `json:"digest"` 20 | } 21 | 22 | // Maintainer reprecents a chart maintainer 23 | type Maintainer struct { 24 | Name string `json:"name"` 25 | Email string `json:"email"` 26 | } 27 | 28 | // NewCharts unmarshals a slice of charts from Json 29 | func NewCharts(data []byte) (map[string][]Chart, error) { 30 | var c map[string][]Chart 31 | err := json.Unmarshal(data, &c) 32 | return c, err 33 | } 34 | -------------------------------------------------------------------------------- /models/error.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Error reprecents an error received from ChartMuseum 8 | type Error struct { 9 | Message string `json:"error"` 10 | } 11 | 12 | // NewError unmarshals a slice of errors from Json 13 | func NewError(data []byte) (Error, error) { 14 | var e Error 15 | err := json.Unmarshal(data, &e) 16 | return e, err 17 | } 18 | -------------------------------------------------------------------------------- /models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // User reprecents a user that can login to ChartMuseumUI 8 | type User struct { 9 | Username string `json:"username"` 10 | Password string `json:"password"` 11 | } 12 | 13 | // NewUsers unmarshals a slice of users from Json 14 | func NewUsers(data []byte) ([]User, error) { 15 | var u []User 16 | err := json.Unmarshal(data, &u) 17 | return u, err 18 | } 19 | -------------------------------------------------------------------------------- /quickstart: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/quickstart -------------------------------------------------------------------------------- /routers/router.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/chartmuseum/ui/controllers" 7 | "github.com/chartmuseum/ui/services" 8 | 9 | "github.com/astaxie/beego" 10 | "github.com/astaxie/beego/logs" 11 | "github.com/astaxie/beego/plugins/auth" 12 | ) 13 | 14 | func init() { 15 | setupAuthentication() 16 | 17 | beego.Router("/", &controllers.MainController{}) 18 | //beego.Router("/login", &controllers.LogInController{}) 19 | beego.Router("/delete", &controllers.DeleteChartController{}) 20 | beego.Router("/receive", &controllers.UploadChartController{}) 21 | beego.Router("/home", &controllers.MainController{}) 22 | beego.Router("/home/chart/?:name", &controllers.ChartController{}) 23 | beego.Router("/chart/?:name", &controllers.ChartController{}) 24 | } 25 | 26 | func setupAuthentication() { 27 | l := logs.GetLogger() 28 | 29 | userJson := os.Getenv("BASIC_AUTH_USERS") 30 | if len(userJson) != 0 { 31 | l.Println("Using basic auth") 32 | authPlugin := auth.NewBasicAuthenticator(services.SecretAuth, "Authorization Required") 33 | beego.InsertFilter("*", beego.BeforeRouter, authPlugin, true) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /services/login.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | 7 | "github.com/chartmuseum/ui/models" 8 | 9 | "github.com/astaxie/beego/logs" 10 | ) 11 | 12 | // SecretAuth validates that a password matches a given username 13 | func SecretAuth(username, password string) bool { 14 | l := logs.GetLogger() 15 | 16 | users, err := getUsersFromEnv() 17 | if err != nil { 18 | l.Panic(err) 19 | } 20 | 21 | for _, user := range users { 22 | if username == user.Username && password == user.Password { 23 | return true 24 | } 25 | } 26 | return false 27 | } 28 | 29 | func getUsersFromEnv() ([]models.User, error) { 30 | 31 | l := logs.GetLogger() 32 | 33 | userJson := os.Getenv("BASIC_AUTH_USERS") 34 | if len(userJson) == 0 { 35 | return nil, errors.New("No users defined. Create environment var BASIC_AUTH_USERS") 36 | } 37 | 38 | users, err := models.NewUsers([]byte(userJson)) 39 | if err != nil { 40 | l.Panic(err) 41 | } 42 | 43 | return users, nil 44 | } 45 | -------------------------------------------------------------------------------- /static/img/delete-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/delete-button.png -------------------------------------------------------------------------------- /static/img/icon_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/icon_default.png -------------------------------------------------------------------------------- /static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/logo.png -------------------------------------------------------------------------------- /static/img/logo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/logo_dark.png -------------------------------------------------------------------------------- /static/img/logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/logo_white.png -------------------------------------------------------------------------------- /static/img/logo_white_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/logo_white_old.png -------------------------------------------------------------------------------- /static/img/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chartmuseum/ui/7bb86a850f6fc398f79fc55e9171e59777b27be2/static/img/plus.png -------------------------------------------------------------------------------- /static/js/reload.min.js: -------------------------------------------------------------------------------- 1 | function b(a){var c=new WebSocket(a);c.onclose=function(){setTimeout(function(){b(a)},2E3)};c.onmessage=function(){location.reload()}}try{if(window.WebSocket)try{b("ws://localhost:12450/reload")}catch(a){console.error(a)}else console.log("Your browser does not support WebSockets.")}catch(a){console.error("Exception during connecting to Reload:",a)}; 2 | -------------------------------------------------------------------------------- /tests/default_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "path/filepath" 7 | "runtime" 8 | "testing" 9 | 10 | _ "github.com/chartmuseum/ui/routers" 11 | 12 | "github.com/astaxie/beego" 13 | . "github.com/smartystreets/goconvey/convey" 14 | ) 15 | 16 | func init() { 17 | _, file, _, _ := runtime.Caller(1) 18 | apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator)))) 19 | beego.TestBeegoInit(apppath) 20 | } 21 | 22 | // TestBeego is a sample to run an endpoint test 23 | func TestBeego(t *testing.T) { 24 | r, _ := http.NewRequest("GET", "/", nil) 25 | w := httptest.NewRecorder() 26 | beego.BeeApp.Handlers.ServeHTTP(w, r) 27 | 28 | beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String()) 29 | 30 | Convey("Subject: Test Station Endpoint\n", t, func() { 31 | Convey("Status Code Should Be 200", func() { 32 | So(w.Code, ShouldEqual, 200) 33 | }) 34 | Convey("The Result Should Not Be Empty", func() { 35 | So(w.Body.Len(), ShouldBeGreaterThan, 0) 36 | }) 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | .DS_Store 4 | *.swp 5 | *.swo 6 | beego.iml 7 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/.gosimpleignore: -------------------------------------------------------------------------------- 1 | github.com/astaxie/beego/*/*:S1012 2 | github.com/astaxie/beego/*:S1012 3 | github.com/astaxie/beego/*/*:S1007 4 | github.com/astaxie/beego/*:S1007 -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "1.9.7" 5 | - "1.10.3" 6 | services: 7 | - redis-server 8 | - mysql 9 | - postgresql 10 | - memcached 11 | env: 12 | - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db 13 | - ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable" 14 | before_install: 15 | - git clone git://github.com/ideawu/ssdb.git 16 | - cd ssdb 17 | - make 18 | - cd .. 19 | install: 20 | - go get github.com/lib/pq 21 | - go get github.com/go-sql-driver/mysql 22 | - go get github.com/mattn/go-sqlite3 23 | - go get github.com/bradfitz/gomemcache/memcache 24 | - go get github.com/gomodule/redigo/redis 25 | - go get github.com/beego/x2j 26 | - go get github.com/couchbase/go-couchbase 27 | - go get github.com/beego/goyaml2 28 | - go get gopkg.in/yaml.v2 29 | - go get github.com/belogik/goes 30 | - go get github.com/siddontang/ledisdb/config 31 | - go get github.com/siddontang/ledisdb/ledis 32 | - go get github.com/ssdb/gossdb/ssdb 33 | - go get github.com/cloudflare/golz4 34 | - go get github.com/gogo/protobuf/proto 35 | - go get github.com/Knetic/govaluate 36 | - go get github.com/casbin/casbin 37 | - go get -u honnef.co/go/tools/cmd/gosimple 38 | - go get -u github.com/mdempsky/unconvert 39 | - go get -u github.com/gordonklaus/ineffassign 40 | - go get -u github.com/golang/lint/golint 41 | - go get -u github.com/go-redis/redis 42 | before_script: 43 | - psql --version 44 | - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" 45 | - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" 46 | - sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi" 47 | - sh -c "go get github.com/golang/lint/golint; golint ./...;" 48 | - sh -c "go list ./... | grep -v vendor | xargs go vet -v" 49 | - mkdir -p res/var 50 | - ./ssdb/ssdb-server ./ssdb/ssdb.conf -d 51 | after_script: 52 | -killall -w ssdb-server 53 | - rm -rf ./res/var/* 54 | script: 55 | - go test -v ./... 56 | - gosimple -ignore "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/) 57 | - unconvert $(go list ./... | grep -v /vendor/) 58 | - ineffassign . 59 | - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s 60 | - golint ./... 61 | addons: 62 | postgresql: "9.6" 63 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to beego 2 | 3 | beego is an open source project. 4 | 5 | It is the work of hundreds of contributors. We appreciate your help! 6 | 7 | Here are instructions to get you started. They are probably not perfect, 8 | please let us know if anything feels wrong or incomplete. 9 | 10 | ## Contribution guidelines 11 | 12 | ### Pull requests 13 | 14 | First of all. beego follow the gitflow. So please send you pull request 15 | to **develop** branch. We will close the pull request to master branch. 16 | 17 | We are always happy to receive pull requests, and do our best to 18 | review them as fast as possible. Not sure if that typo is worth a pull 19 | request? Do it! We will appreciate it. 20 | 21 | If your pull request is not accepted on the first try, don't be 22 | discouraged! Sometimes we can make a mistake, please do more explaining 23 | for us. We will appreciate it. 24 | 25 | We're trying very hard to keep beego simple and fast. We don't want it 26 | to do everything for everybody. This means that we might decide against 27 | incorporating a new feature. But we will give you some advice on how to 28 | do it in other way. 29 | 30 | ### Create issues 31 | 32 | Any significant improvement should be documented as [a GitHub 33 | issue](https://github.com/astaxie/beego/issues) before anybody 34 | starts working on it. 35 | 36 | Also when filing an issue, make sure to answer these five questions: 37 | 38 | - What version of beego are you using (bee version)? 39 | - What operating system and processor architecture are you using? 40 | - What did you do? 41 | - What did you expect to see? 42 | - What did you see instead? 43 | 44 | ### but check existing issues and docs first! 45 | 46 | Please take a moment to check that an issue doesn't already exist 47 | documenting your bug report or improvement proposal. If it does, it 48 | never hurts to add a quick "+1" or "I have this problem too". This will 49 | help prioritize the most common problems and requests. 50 | 51 | Also if you don't know how to use it. please make sure you have read though 52 | the docs in http://beego.me/docs -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 astaxie 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. -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/README.md: -------------------------------------------------------------------------------- 1 | # Beego [![Build Status](https://travis-ci.org/astaxie/beego.svg?branch=master)](https://travis-ci.org/astaxie/beego) [![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego) [![Foundation](https://img.shields.io/badge/Golang-Foundation-green.svg)](http://golangfoundation.org) [![Go Report Card](https://goreportcard.com/badge/github.com/astaxie/beego)](https://goreportcard.com/report/github.com/astaxie/beego) 2 | 3 | 4 | beego is used for rapid development of RESTful APIs, web apps and backend services in Go. 5 | It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding. 6 | 7 | ###### More info at [beego.me](http://beego.me). 8 | 9 | ## Quick Start 10 | 11 | #### Download and install 12 | 13 | go get github.com/astaxie/beego 14 | 15 | #### Create file `hello.go` 16 | ```go 17 | package main 18 | 19 | import "github.com/astaxie/beego" 20 | 21 | func main(){ 22 | beego.Run() 23 | } 24 | ``` 25 | #### Build and run 26 | 27 | go build hello.go 28 | ./hello 29 | 30 | #### Go to [http://localhost:8080](http://localhost:8080) 31 | 32 | Congratulations! You've just built your first **beego** app. 33 | 34 | ###### Please see [Documentation](http://beego.me/docs) for more. 35 | 36 | ## Features 37 | 38 | * RESTful support 39 | * MVC architecture 40 | * Modularity 41 | * Auto API documents 42 | * Annotation router 43 | * Namespace 44 | * Powerful development tools 45 | * Full stack for Web & API 46 | 47 | ## Documentation 48 | 49 | * [English](http://beego.me/docs/intro/) 50 | * [中文文档](http://beego.me/docs/intro/) 51 | * [Русский](http://beego.me/docs/intro/) 52 | 53 | ## Community 54 | 55 | * [http://beego.me/community](http://beego.me/community) 56 | * Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited from [here](https://github.com/beego/beedoc/issues/232) 57 | 58 | ## License 59 | 60 | beego source code is licensed under the Apache Licence, Version 2.0 61 | (http://www.apache.org/licenses/LICENSE-2.0.html). 62 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/beego.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package beego 16 | 17 | import ( 18 | "os" 19 | "path/filepath" 20 | "strconv" 21 | "strings" 22 | ) 23 | 24 | const ( 25 | // VERSION represent beego web framework version. 26 | VERSION = "1.10.1" 27 | 28 | // DEV is for develop 29 | DEV = "dev" 30 | // PROD is for production 31 | PROD = "prod" 32 | ) 33 | 34 | //hook function to run 35 | type hookfunc func() error 36 | 37 | var ( 38 | hooks = make([]hookfunc, 0) //hook function slice to store the hookfunc 39 | ) 40 | 41 | // AddAPPStartHook is used to register the hookfunc 42 | // The hookfuncs will run in beego.Run() 43 | // such as initiating session , starting middleware , building template, starting admin control and so on. 44 | func AddAPPStartHook(hf ...hookfunc) { 45 | hooks = append(hooks, hf...) 46 | } 47 | 48 | // Run beego application. 49 | // beego.Run() default run on HttpPort 50 | // beego.Run("localhost") 51 | // beego.Run(":8089") 52 | // beego.Run("127.0.0.1:8089") 53 | func Run(params ...string) { 54 | 55 | initBeforeHTTPRun() 56 | 57 | if len(params) > 0 && params[0] != "" { 58 | strs := strings.Split(params[0], ":") 59 | if len(strs) > 0 && strs[0] != "" { 60 | BConfig.Listen.HTTPAddr = strs[0] 61 | } 62 | if len(strs) > 1 && strs[1] != "" { 63 | BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1]) 64 | } 65 | 66 | BConfig.Listen.Domains = params 67 | } 68 | 69 | BeeApp.Run() 70 | } 71 | 72 | // RunWithMiddleWares Run beego application with middlewares. 73 | func RunWithMiddleWares(addr string, mws ...MiddleWare) { 74 | initBeforeHTTPRun() 75 | 76 | strs := strings.Split(addr, ":") 77 | if len(strs) > 0 && strs[0] != "" { 78 | BConfig.Listen.HTTPAddr = strs[0] 79 | BConfig.Listen.Domains = []string{strs[0]} 80 | } 81 | if len(strs) > 1 && strs[1] != "" { 82 | BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1]) 83 | } 84 | 85 | BeeApp.Run(mws...) 86 | } 87 | 88 | func initBeforeHTTPRun() { 89 | //init hooks 90 | AddAPPStartHook( 91 | registerMime, 92 | registerDefaultErrorHandler, 93 | registerSession, 94 | registerTemplate, 95 | registerAdmin, 96 | registerGzip, 97 | ) 98 | 99 | for _, hk := range hooks { 100 | if err := hk(); err != nil { 101 | panic(err) 102 | } 103 | } 104 | } 105 | 106 | // TestBeegoInit is for test package init 107 | func TestBeegoInit(ap string) { 108 | path := filepath.Join(ap, "conf", "app.conf") 109 | os.Chdir(ap) 110 | InitBeegoBeforeTest(path) 111 | } 112 | 113 | // InitBeegoBeforeTest is for test package init 114 | func InitBeegoBeforeTest(appConfigPath string) { 115 | if err := LoadAppConfig(appConfigProvider, appConfigPath); err != nil { 116 | panic(err) 117 | } 118 | BConfig.RunMode = "test" 119 | initBeforeHTTPRun() 120 | } 121 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/config/fake.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package config 16 | 17 | import ( 18 | "errors" 19 | "strconv" 20 | "strings" 21 | ) 22 | 23 | type fakeConfigContainer struct { 24 | data map[string]string 25 | } 26 | 27 | func (c *fakeConfigContainer) getData(key string) string { 28 | return c.data[strings.ToLower(key)] 29 | } 30 | 31 | func (c *fakeConfigContainer) Set(key, val string) error { 32 | c.data[strings.ToLower(key)] = val 33 | return nil 34 | } 35 | 36 | func (c *fakeConfigContainer) String(key string) string { 37 | return c.getData(key) 38 | } 39 | 40 | func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string { 41 | v := c.String(key) 42 | if v == "" { 43 | return defaultval 44 | } 45 | return v 46 | } 47 | 48 | func (c *fakeConfigContainer) Strings(key string) []string { 49 | v := c.String(key) 50 | if v == "" { 51 | return nil 52 | } 53 | return strings.Split(v, ";") 54 | } 55 | 56 | func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string { 57 | v := c.Strings(key) 58 | if v == nil { 59 | return defaultval 60 | } 61 | return v 62 | } 63 | 64 | func (c *fakeConfigContainer) Int(key string) (int, error) { 65 | return strconv.Atoi(c.getData(key)) 66 | } 67 | 68 | func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int { 69 | v, err := c.Int(key) 70 | if err != nil { 71 | return defaultval 72 | } 73 | return v 74 | } 75 | 76 | func (c *fakeConfigContainer) Int64(key string) (int64, error) { 77 | return strconv.ParseInt(c.getData(key), 10, 64) 78 | } 79 | 80 | func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 { 81 | v, err := c.Int64(key) 82 | if err != nil { 83 | return defaultval 84 | } 85 | return v 86 | } 87 | 88 | func (c *fakeConfigContainer) Bool(key string) (bool, error) { 89 | return ParseBool(c.getData(key)) 90 | } 91 | 92 | func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool { 93 | v, err := c.Bool(key) 94 | if err != nil { 95 | return defaultval 96 | } 97 | return v 98 | } 99 | 100 | func (c *fakeConfigContainer) Float(key string) (float64, error) { 101 | return strconv.ParseFloat(c.getData(key), 64) 102 | } 103 | 104 | func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 { 105 | v, err := c.Float(key) 106 | if err != nil { 107 | return defaultval 108 | } 109 | return v 110 | } 111 | 112 | func (c *fakeConfigContainer) DIY(key string) (interface{}, error) { 113 | if v, ok := c.data[strings.ToLower(key)]; ok { 114 | return v, nil 115 | } 116 | return nil, errors.New("key not find") 117 | } 118 | 119 | func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) { 120 | return nil, errors.New("not implement in the fakeConfigContainer") 121 | } 122 | 123 | func (c *fakeConfigContainer) SaveConfigFile(filename string) error { 124 | return errors.New("not implement in the fakeConfigContainer") 125 | } 126 | 127 | var _ Configer = new(fakeConfigContainer) 128 | 129 | // NewFakeConfig return a fake Configer 130 | func NewFakeConfig() Configer { 131 | return &fakeConfigContainer{ 132 | data: make(map[string]string), 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/context/param/conv.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | beecontext "github.com/astaxie/beego/context" 8 | "github.com/astaxie/beego/logs" 9 | ) 10 | 11 | // ConvertParams converts http method params to values that will be passed to the method controller as arguments 12 | func ConvertParams(methodParams []*MethodParam, methodType reflect.Type, ctx *beecontext.Context) (result []reflect.Value) { 13 | result = make([]reflect.Value, 0, len(methodParams)) 14 | for i := 0; i < len(methodParams); i++ { 15 | reflectValue := convertParam(methodParams[i], methodType.In(i), ctx) 16 | result = append(result, reflectValue) 17 | } 18 | return 19 | } 20 | 21 | func convertParam(param *MethodParam, paramType reflect.Type, ctx *beecontext.Context) (result reflect.Value) { 22 | paramValue := getParamValue(param, ctx) 23 | if paramValue == "" { 24 | if param.required { 25 | ctx.Abort(400, fmt.Sprintf("Missing parameter %s", param.name)) 26 | } else { 27 | paramValue = param.defaultValue 28 | } 29 | } 30 | 31 | reflectValue, err := parseValue(param, paramValue, paramType) 32 | if err != nil { 33 | logs.Debug(fmt.Sprintf("Error converting param %s to type %s. Value: %v, Error: %s", param.name, paramType, paramValue, err)) 34 | ctx.Abort(400, fmt.Sprintf("Invalid parameter %s. Can not convert %v to type %s", param.name, paramValue, paramType)) 35 | } 36 | 37 | return reflectValue 38 | } 39 | 40 | func getParamValue(param *MethodParam, ctx *beecontext.Context) string { 41 | switch param.in { 42 | case body: 43 | return string(ctx.Input.RequestBody) 44 | case header: 45 | return ctx.Input.Header(param.name) 46 | case path: 47 | return ctx.Input.Query(":" + param.name) 48 | default: 49 | return ctx.Input.Query(param.name) 50 | } 51 | } 52 | 53 | func parseValue(param *MethodParam, paramValue string, paramType reflect.Type) (result reflect.Value, err error) { 54 | if paramValue == "" { 55 | return reflect.Zero(paramType), nil 56 | } 57 | parser := getParser(param, paramType) 58 | value, err := parser.parse(paramValue, paramType) 59 | if err != nil { 60 | return result, err 61 | } 62 | 63 | return safeConvert(reflect.ValueOf(value), paramType) 64 | } 65 | 66 | func safeConvert(value reflect.Value, t reflect.Type) (result reflect.Value, err error) { 67 | defer func() { 68 | if r := recover(); r != nil { 69 | var ok bool 70 | err, ok = r.(error) 71 | if !ok { 72 | err = fmt.Errorf("%v", r) 73 | } 74 | } 75 | }() 76 | result = value.Convert(t) 77 | return 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/context/param/methodparams.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | //MethodParam keeps param information to be auto passed to controller methods 9 | type MethodParam struct { 10 | name string 11 | in paramType 12 | required bool 13 | defaultValue string 14 | } 15 | 16 | type paramType byte 17 | 18 | const ( 19 | param paramType = iota 20 | path 21 | body 22 | header 23 | ) 24 | 25 | //New creates a new MethodParam with name and specific options 26 | func New(name string, opts ...MethodParamOption) *MethodParam { 27 | return newParam(name, nil, opts) 28 | } 29 | 30 | func newParam(name string, parser paramParser, opts []MethodParamOption) (param *MethodParam) { 31 | param = &MethodParam{name: name} 32 | for _, option := range opts { 33 | option(param) 34 | } 35 | return 36 | } 37 | 38 | //Make creates an array of MethodParmas or an empty array 39 | func Make(list ...*MethodParam) []*MethodParam { 40 | if len(list) > 0 { 41 | return list 42 | } 43 | return nil 44 | } 45 | 46 | func (mp *MethodParam) String() string { 47 | options := []string{} 48 | result := "param.New(\"" + mp.name + "\"" 49 | if mp.required { 50 | options = append(options, "param.IsRequired") 51 | } 52 | switch mp.in { 53 | case path: 54 | options = append(options, "param.InPath") 55 | case body: 56 | options = append(options, "param.InBody") 57 | case header: 58 | options = append(options, "param.InHeader") 59 | } 60 | if mp.defaultValue != "" { 61 | options = append(options, fmt.Sprintf(`param.Default("%s")`, mp.defaultValue)) 62 | } 63 | if len(options) > 0 { 64 | result += ", " 65 | } 66 | result += strings.Join(options, ", ") 67 | result += ")" 68 | return result 69 | } 70 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/context/param/options.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // MethodParamOption defines a func which apply options on a MethodParam 8 | type MethodParamOption func(*MethodParam) 9 | 10 | // IsRequired indicates that this param is required and can not be omitted from the http request 11 | var IsRequired MethodParamOption = func(p *MethodParam) { 12 | p.required = true 13 | } 14 | 15 | // InHeader indicates that this param is passed via an http header 16 | var InHeader MethodParamOption = func(p *MethodParam) { 17 | p.in = header 18 | } 19 | 20 | // InPath indicates that this param is part of the URL path 21 | var InPath MethodParamOption = func(p *MethodParam) { 22 | p.in = path 23 | } 24 | 25 | // InBody indicates that this param is passed as an http request body 26 | var InBody MethodParamOption = func(p *MethodParam) { 27 | p.in = body 28 | } 29 | 30 | // Default provides a default value for the http param 31 | func Default(defaultValue interface{}) MethodParamOption { 32 | return func(p *MethodParam) { 33 | if defaultValue != nil { 34 | p.defaultValue = fmt.Sprint(defaultValue) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/context/param/parsers.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "encoding/json" 5 | "reflect" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type paramParser interface { 12 | parse(value string, toType reflect.Type) (interface{}, error) 13 | } 14 | 15 | func getParser(param *MethodParam, t reflect.Type) paramParser { 16 | switch t.Kind() { 17 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 18 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 19 | return intParser{} 20 | case reflect.Slice: 21 | if t.Elem().Kind() == reflect.Uint8 { //treat []byte as string 22 | return stringParser{} 23 | } 24 | if param.in == body { 25 | return jsonParser{} 26 | } 27 | elemParser := getParser(param, t.Elem()) 28 | if elemParser == (jsonParser{}) { 29 | return elemParser 30 | } 31 | return sliceParser(elemParser) 32 | case reflect.Bool: 33 | return boolParser{} 34 | case reflect.String: 35 | return stringParser{} 36 | case reflect.Float32, reflect.Float64: 37 | return floatParser{} 38 | case reflect.Ptr: 39 | elemParser := getParser(param, t.Elem()) 40 | if elemParser == (jsonParser{}) { 41 | return elemParser 42 | } 43 | return ptrParser(elemParser) 44 | default: 45 | if t.PkgPath() == "time" && t.Name() == "Time" { 46 | return timeParser{} 47 | } 48 | return jsonParser{} 49 | } 50 | } 51 | 52 | type parserFunc func(value string, toType reflect.Type) (interface{}, error) 53 | 54 | func (f parserFunc) parse(value string, toType reflect.Type) (interface{}, error) { 55 | return f(value, toType) 56 | } 57 | 58 | type boolParser struct { 59 | } 60 | 61 | func (p boolParser) parse(value string, toType reflect.Type) (interface{}, error) { 62 | return strconv.ParseBool(value) 63 | } 64 | 65 | type stringParser struct { 66 | } 67 | 68 | func (p stringParser) parse(value string, toType reflect.Type) (interface{}, error) { 69 | return value, nil 70 | } 71 | 72 | type intParser struct { 73 | } 74 | 75 | func (p intParser) parse(value string, toType reflect.Type) (interface{}, error) { 76 | return strconv.Atoi(value) 77 | } 78 | 79 | type floatParser struct { 80 | } 81 | 82 | func (p floatParser) parse(value string, toType reflect.Type) (interface{}, error) { 83 | if toType.Kind() == reflect.Float32 { 84 | res, err := strconv.ParseFloat(value, 32) 85 | if err != nil { 86 | return nil, err 87 | } 88 | return float32(res), nil 89 | } 90 | return strconv.ParseFloat(value, 64) 91 | } 92 | 93 | type timeParser struct { 94 | } 95 | 96 | func (p timeParser) parse(value string, toType reflect.Type) (result interface{}, err error) { 97 | result, err = time.Parse(time.RFC3339, value) 98 | if err != nil { 99 | result, err = time.Parse("2006-01-02", value) 100 | } 101 | return 102 | } 103 | 104 | type jsonParser struct { 105 | } 106 | 107 | func (p jsonParser) parse(value string, toType reflect.Type) (interface{}, error) { 108 | pResult := reflect.New(toType) 109 | v := pResult.Interface() 110 | err := json.Unmarshal([]byte(value), v) 111 | if err != nil { 112 | return nil, err 113 | } 114 | return pResult.Elem().Interface(), nil 115 | } 116 | 117 | func sliceParser(elemParser paramParser) paramParser { 118 | return parserFunc(func(value string, toType reflect.Type) (interface{}, error) { 119 | values := strings.Split(value, ",") 120 | result := reflect.MakeSlice(toType, 0, len(values)) 121 | elemType := toType.Elem() 122 | for _, v := range values { 123 | parsedValue, err := elemParser.parse(v, elemType) 124 | if err != nil { 125 | return nil, err 126 | } 127 | result = reflect.Append(result, reflect.ValueOf(parsedValue)) 128 | } 129 | return result.Interface(), nil 130 | }) 131 | } 132 | 133 | func ptrParser(elemParser paramParser) paramParser { 134 | return parserFunc(func(value string, toType reflect.Type) (interface{}, error) { 135 | parsedValue, err := elemParser.parse(value, toType.Elem()) 136 | if err != nil { 137 | return nil, err 138 | } 139 | newValPtr := reflect.New(toType.Elem()) 140 | newVal := reflect.Indirect(newValPtr) 141 | convertedVal, err := safeConvert(reflect.ValueOf(parsedValue), toType.Elem()) 142 | if err != nil { 143 | return nil, err 144 | } 145 | 146 | newVal.Set(convertedVal) 147 | return newValPtr.Interface(), nil 148 | }) 149 | } 150 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/context/renderer.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | // Renderer defines an http response renderer 4 | type Renderer interface { 5 | Render(ctx *Context) 6 | } 7 | 8 | type rendererFunc func(ctx *Context) 9 | 10 | func (f rendererFunc) Render(ctx *Context) { 11 | f(ctx) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/context/response.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | import ( 4 | "strconv" 5 | 6 | "net/http" 7 | ) 8 | 9 | const ( 10 | //BadRequest indicates http error 400 11 | BadRequest StatusCode = http.StatusBadRequest 12 | 13 | //NotFound indicates http error 404 14 | NotFound StatusCode = http.StatusNotFound 15 | ) 16 | 17 | // StatusCode sets the http response status code 18 | type StatusCode int 19 | 20 | func (s StatusCode) Error() string { 21 | return strconv.Itoa(int(s)) 22 | } 23 | 24 | // Render sets the http status code 25 | func (s StatusCode) Render(ctx *Context) { 26 | ctx.Output.SetStatus(int(s)) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package beego provide a MVC framework 3 | beego: an open-source, high-performance, modular, full-stack web framework 4 | 5 | It is used for rapid development of RESTful APIs, web apps and backend services in Go. 6 | beego is inspired by Tornado, Sinatra and Flask with the added benefit of some Go-specific features such as interfaces and struct embedding. 7 | 8 | package main 9 | import "github.com/astaxie/beego" 10 | 11 | func main() { 12 | beego.Run() 13 | } 14 | 15 | more information: http://beego.me 16 | */ 17 | package beego 18 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/filter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package beego 16 | 17 | import "github.com/astaxie/beego/context" 18 | 19 | // FilterFunc defines a filter function which is invoked before the controller handler is executed. 20 | type FilterFunc func(*context.Context) 21 | 22 | // FilterRouter defines a filter operation which is invoked before the controller handler is executed. 23 | // It can match the URL against a pattern, and execute a filter function 24 | // when a request with a matching URL arrives. 25 | type FilterRouter struct { 26 | filterFunc FilterFunc 27 | tree *Tree 28 | pattern string 29 | returnOnOutput bool 30 | resetParams bool 31 | } 32 | 33 | // ValidRouter checks if the current request is matched by this filter. 34 | // If the request is matched, the values of the URL parameters defined 35 | // by the filter pattern are also returned. 36 | func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool { 37 | isOk := f.tree.Match(url, ctx) 38 | if isOk != nil { 39 | if b, ok := isOk.(bool); ok { 40 | return b 41 | } 42 | } 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/flash.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package beego 16 | 17 | import ( 18 | "fmt" 19 | "net/url" 20 | "strings" 21 | ) 22 | 23 | // FlashData is a tools to maintain data when using across request. 24 | type FlashData struct { 25 | Data map[string]string 26 | } 27 | 28 | // NewFlash return a new empty FlashData struct. 29 | func NewFlash() *FlashData { 30 | return &FlashData{ 31 | Data: make(map[string]string), 32 | } 33 | } 34 | 35 | // Set message to flash 36 | func (fd *FlashData) Set(key string, msg string, args ...interface{}) { 37 | if len(args) == 0 { 38 | fd.Data[key] = msg 39 | } else { 40 | fd.Data[key] = fmt.Sprintf(msg, args...) 41 | } 42 | } 43 | 44 | // Success writes success message to flash. 45 | func (fd *FlashData) Success(msg string, args ...interface{}) { 46 | if len(args) == 0 { 47 | fd.Data["success"] = msg 48 | } else { 49 | fd.Data["success"] = fmt.Sprintf(msg, args...) 50 | } 51 | } 52 | 53 | // Notice writes notice message to flash. 54 | func (fd *FlashData) Notice(msg string, args ...interface{}) { 55 | if len(args) == 0 { 56 | fd.Data["notice"] = msg 57 | } else { 58 | fd.Data["notice"] = fmt.Sprintf(msg, args...) 59 | } 60 | } 61 | 62 | // Warning writes warning message to flash. 63 | func (fd *FlashData) Warning(msg string, args ...interface{}) { 64 | if len(args) == 0 { 65 | fd.Data["warning"] = msg 66 | } else { 67 | fd.Data["warning"] = fmt.Sprintf(msg, args...) 68 | } 69 | } 70 | 71 | // Error writes error message to flash. 72 | func (fd *FlashData) Error(msg string, args ...interface{}) { 73 | if len(args) == 0 { 74 | fd.Data["error"] = msg 75 | } else { 76 | fd.Data["error"] = fmt.Sprintf(msg, args...) 77 | } 78 | } 79 | 80 | // Store does the saving operation of flash data. 81 | // the data are encoded and saved in cookie. 82 | func (fd *FlashData) Store(c *Controller) { 83 | c.Data["flash"] = fd.Data 84 | var flashValue string 85 | for key, value := range fd.Data { 86 | flashValue += "\x00" + key + "\x23" + BConfig.WebConfig.FlashSeparator + "\x23" + value + "\x00" 87 | } 88 | c.Ctx.SetCookie(BConfig.WebConfig.FlashName, url.QueryEscape(flashValue), 0, "/") 89 | } 90 | 91 | // ReadFromRequest parsed flash data from encoded values in cookie. 92 | func ReadFromRequest(c *Controller) *FlashData { 93 | flash := NewFlash() 94 | if cookie, err := c.Ctx.Request.Cookie(BConfig.WebConfig.FlashName); err == nil { 95 | v, _ := url.QueryUnescape(cookie.Value) 96 | vals := strings.Split(v, "\x00") 97 | for _, v := range vals { 98 | if len(v) > 0 { 99 | kv := strings.Split(v, "\x23"+BConfig.WebConfig.FlashSeparator+"\x23") 100 | if len(kv) == 2 { 101 | flash.Data[kv[0]] = kv[1] 102 | } 103 | } 104 | } 105 | //read one time then delete it 106 | c.Ctx.SetCookie(BConfig.WebConfig.FlashName, "", -1, "/") 107 | } 108 | c.Data["flash"] = flash.Data 109 | return flash 110 | } 111 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/grace/conn.go: -------------------------------------------------------------------------------- 1 | package grace 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "sync" 7 | ) 8 | 9 | type graceConn struct { 10 | net.Conn 11 | server *Server 12 | m sync.Mutex 13 | closed bool 14 | } 15 | 16 | func (c *graceConn) Close() (err error) { 17 | defer func() { 18 | if r := recover(); r != nil { 19 | switch x := r.(type) { 20 | case string: 21 | err = errors.New(x) 22 | case error: 23 | err = x 24 | default: 25 | err = errors.New("Unknown panic") 26 | } 27 | } 28 | }() 29 | 30 | c.m.Lock() 31 | if c.closed { 32 | c.m.Unlock() 33 | return 34 | } 35 | c.server.wg.Done() 36 | c.closed = true 37 | c.m.Unlock() 38 | return c.Conn.Close() 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/grace/grace.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | // Package grace use to hot reload 16 | // Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/ 17 | // 18 | // Usage: 19 | // 20 | // import( 21 | // "log" 22 | // "net/http" 23 | // "os" 24 | // 25 | // "github.com/astaxie/beego/grace" 26 | // ) 27 | // 28 | // func handler(w http.ResponseWriter, r *http.Request) { 29 | // w.Write([]byte("WORLD!")) 30 | // } 31 | // 32 | // func main() { 33 | // mux := http.NewServeMux() 34 | // mux.HandleFunc("/hello", handler) 35 | // 36 | // err := grace.ListenAndServe("localhost:8080", mux) 37 | // if err != nil { 38 | // log.Println(err) 39 | // } 40 | // log.Println("Server on 8080 stopped") 41 | // os.Exit(0) 42 | // } 43 | package grace 44 | 45 | import ( 46 | "flag" 47 | "net/http" 48 | "os" 49 | "strings" 50 | "sync" 51 | "syscall" 52 | "time" 53 | ) 54 | 55 | const ( 56 | // PreSignal is the position to add filter before signal 57 | PreSignal = iota 58 | // PostSignal is the position to add filter after signal 59 | PostSignal 60 | // StateInit represent the application inited 61 | StateInit 62 | // StateRunning represent the application is running 63 | StateRunning 64 | // StateShuttingDown represent the application is shutting down 65 | StateShuttingDown 66 | // StateTerminate represent the application is killed 67 | StateTerminate 68 | ) 69 | 70 | var ( 71 | regLock *sync.Mutex 72 | runningServers map[string]*Server 73 | runningServersOrder []string 74 | socketPtrOffsetMap map[string]uint 75 | runningServersForked bool 76 | 77 | // DefaultReadTimeOut is the HTTP read timeout 78 | DefaultReadTimeOut time.Duration 79 | // DefaultWriteTimeOut is the HTTP Write timeout 80 | DefaultWriteTimeOut time.Duration 81 | // DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit 82 | DefaultMaxHeaderBytes int 83 | // DefaultTimeout is the shutdown server's timeout. default is 60s 84 | DefaultTimeout = 60 * time.Second 85 | 86 | isChild bool 87 | socketOrder string 88 | 89 | hookableSignals []os.Signal 90 | ) 91 | 92 | func init() { 93 | flag.BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)") 94 | flag.StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started") 95 | 96 | regLock = &sync.Mutex{} 97 | runningServers = make(map[string]*Server) 98 | runningServersOrder = []string{} 99 | socketPtrOffsetMap = make(map[string]uint) 100 | 101 | hookableSignals = []os.Signal{ 102 | syscall.SIGHUP, 103 | syscall.SIGINT, 104 | syscall.SIGTERM, 105 | } 106 | } 107 | 108 | // NewServer returns a new graceServer. 109 | func NewServer(addr string, handler http.Handler) (srv *Server) { 110 | regLock.Lock() 111 | defer regLock.Unlock() 112 | 113 | if !flag.Parsed() { 114 | flag.Parse() 115 | } 116 | if len(socketOrder) > 0 { 117 | for i, addr := range strings.Split(socketOrder, ",") { 118 | socketPtrOffsetMap[addr] = uint(i) 119 | } 120 | } else { 121 | socketPtrOffsetMap[addr] = uint(len(runningServersOrder)) 122 | } 123 | 124 | srv = &Server{ 125 | wg: sync.WaitGroup{}, 126 | sigChan: make(chan os.Signal), 127 | isChild: isChild, 128 | SignalHooks: map[int]map[os.Signal][]func(){ 129 | PreSignal: { 130 | syscall.SIGHUP: {}, 131 | syscall.SIGINT: {}, 132 | syscall.SIGTERM: {}, 133 | }, 134 | PostSignal: { 135 | syscall.SIGHUP: {}, 136 | syscall.SIGINT: {}, 137 | syscall.SIGTERM: {}, 138 | }, 139 | }, 140 | state: StateInit, 141 | Network: "tcp", 142 | } 143 | srv.Server = &http.Server{} 144 | srv.Server.Addr = addr 145 | srv.Server.ReadTimeout = DefaultReadTimeOut 146 | srv.Server.WriteTimeout = DefaultWriteTimeOut 147 | srv.Server.MaxHeaderBytes = DefaultMaxHeaderBytes 148 | srv.Server.Handler = handler 149 | 150 | runningServersOrder = append(runningServersOrder, addr) 151 | runningServers[addr] = srv 152 | 153 | return 154 | } 155 | 156 | // ListenAndServe refer http.ListenAndServe 157 | func ListenAndServe(addr string, handler http.Handler) error { 158 | server := NewServer(addr, handler) 159 | return server.ListenAndServe() 160 | } 161 | 162 | // ListenAndServeTLS refer http.ListenAndServeTLS 163 | func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error { 164 | server := NewServer(addr, handler) 165 | return server.ListenAndServeTLS(certFile, keyFile) 166 | } 167 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/grace/listener.go: -------------------------------------------------------------------------------- 1 | package grace 2 | 3 | import ( 4 | "net" 5 | "os" 6 | "syscall" 7 | "time" 8 | ) 9 | 10 | type graceListener struct { 11 | net.Listener 12 | stop chan error 13 | stopped bool 14 | server *Server 15 | } 16 | 17 | func newGraceListener(l net.Listener, srv *Server) (el *graceListener) { 18 | el = &graceListener{ 19 | Listener: l, 20 | stop: make(chan error), 21 | server: srv, 22 | } 23 | go func() { 24 | <-el.stop 25 | el.stopped = true 26 | el.stop <- el.Listener.Close() 27 | }() 28 | return 29 | } 30 | 31 | func (gl *graceListener) Accept() (c net.Conn, err error) { 32 | tc, err := gl.Listener.(*net.TCPListener).AcceptTCP() 33 | if err != nil { 34 | return 35 | } 36 | 37 | tc.SetKeepAlive(true) 38 | tc.SetKeepAlivePeriod(3 * time.Minute) 39 | 40 | c = &graceConn{ 41 | Conn: tc, 42 | server: gl.server, 43 | } 44 | 45 | gl.server.wg.Add(1) 46 | return 47 | } 48 | 49 | func (gl *graceListener) Close() error { 50 | if gl.stopped { 51 | return syscall.EINVAL 52 | } 53 | gl.stop <- nil 54 | return <-gl.stop 55 | } 56 | 57 | func (gl *graceListener) File() *os.File { 58 | // returns a dup(2) - FD_CLOEXEC flag *not* set 59 | tl := gl.Listener.(*net.TCPListener) 60 | fl, _ := tl.File() 61 | return fl 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/hooks.go: -------------------------------------------------------------------------------- 1 | package beego 2 | 3 | import ( 4 | "encoding/json" 5 | "mime" 6 | "net/http" 7 | "path/filepath" 8 | 9 | "github.com/astaxie/beego/context" 10 | "github.com/astaxie/beego/logs" 11 | "github.com/astaxie/beego/session" 12 | ) 13 | 14 | // 15 | func registerMime() error { 16 | for k, v := range mimemaps { 17 | mime.AddExtensionType(k, v) 18 | } 19 | return nil 20 | } 21 | 22 | // register default error http handlers, 404,401,403,500 and 503. 23 | func registerDefaultErrorHandler() error { 24 | m := map[string]func(http.ResponseWriter, *http.Request){ 25 | "401": unauthorized, 26 | "402": paymentRequired, 27 | "403": forbidden, 28 | "404": notFound, 29 | "405": methodNotAllowed, 30 | "500": internalServerError, 31 | "501": notImplemented, 32 | "502": badGateway, 33 | "503": serviceUnavailable, 34 | "504": gatewayTimeout, 35 | "417": invalidxsrf, 36 | "422": missingxsrf, 37 | } 38 | for e, h := range m { 39 | if _, ok := ErrorMaps[e]; !ok { 40 | ErrorHandler(e, h) 41 | } 42 | } 43 | return nil 44 | } 45 | 46 | func registerSession() error { 47 | if BConfig.WebConfig.Session.SessionOn { 48 | var err error 49 | sessionConfig := AppConfig.String("sessionConfig") 50 | conf := new(session.ManagerConfig) 51 | if sessionConfig == "" { 52 | conf.CookieName = BConfig.WebConfig.Session.SessionName 53 | conf.EnableSetCookie = BConfig.WebConfig.Session.SessionAutoSetCookie 54 | conf.Gclifetime = BConfig.WebConfig.Session.SessionGCMaxLifetime 55 | conf.Secure = BConfig.Listen.EnableHTTPS 56 | conf.CookieLifeTime = BConfig.WebConfig.Session.SessionCookieLifeTime 57 | conf.ProviderConfig = filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig) 58 | conf.DisableHTTPOnly = BConfig.WebConfig.Session.SessionDisableHTTPOnly 59 | conf.Domain = BConfig.WebConfig.Session.SessionDomain 60 | conf.EnableSidInHTTPHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader 61 | conf.SessionNameInHTTPHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader 62 | conf.EnableSidInURLQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery 63 | } else { 64 | if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil { 65 | return err 66 | } 67 | } 68 | if GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, conf); err != nil { 69 | return err 70 | } 71 | go GlobalSessions.GC() 72 | } 73 | return nil 74 | } 75 | 76 | func registerTemplate() error { 77 | defer lockViewPaths() 78 | if err := AddViewPath(BConfig.WebConfig.ViewsPath); err != nil { 79 | if BConfig.RunMode == DEV { 80 | logs.Warn(err) 81 | } 82 | return err 83 | } 84 | return nil 85 | } 86 | 87 | func registerAdmin() error { 88 | if BConfig.Listen.EnableAdmin { 89 | go beeAdminApp.Run() 90 | } 91 | return nil 92 | } 93 | 94 | func registerGzip() error { 95 | if BConfig.EnableGzip { 96 | context.InitGzip( 97 | AppConfig.DefaultInt("gzipMinLength", -1), 98 | AppConfig.DefaultInt("gzipCompressLevel", -1), 99 | AppConfig.DefaultStrings("includedMethods", []string{"GET"}), 100 | ) 101 | } 102 | return nil 103 | } 104 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/httplib/README.md: -------------------------------------------------------------------------------- 1 | # httplib 2 | httplib is an libs help you to curl remote url. 3 | 4 | # How to use? 5 | 6 | ## GET 7 | you can use Get to crawl data. 8 | 9 | import "github.com/astaxie/beego/httplib" 10 | 11 | str, err := httplib.Get("http://beego.me/").String() 12 | if err != nil { 13 | // error 14 | } 15 | fmt.Println(str) 16 | 17 | ## POST 18 | POST data to remote url 19 | 20 | req := httplib.Post("http://beego.me/") 21 | req.Param("username","astaxie") 22 | req.Param("password","123456") 23 | str, err := req.String() 24 | if err != nil { 25 | // error 26 | } 27 | fmt.Println(str) 28 | 29 | ## Set timeout 30 | 31 | The default timeout is `60` seconds, function prototype: 32 | 33 | SetTimeout(connectTimeout, readWriteTimeout time.Duration) 34 | 35 | Example: 36 | 37 | // GET 38 | httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) 39 | 40 | // POST 41 | httplib.Post("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) 42 | 43 | 44 | ## Debug 45 | 46 | If you want to debug the request info, set the debug on 47 | 48 | httplib.Get("http://beego.me/").Debug(true) 49 | 50 | ## Set HTTP Basic Auth 51 | 52 | str, err := Get("http://beego.me/").SetBasicAuth("user", "passwd").String() 53 | if err != nil { 54 | // error 55 | } 56 | fmt.Println(str) 57 | 58 | ## Set HTTPS 59 | 60 | If request url is https, You can set the client support TSL: 61 | 62 | httplib.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) 63 | 64 | More info about the `tls.Config` please visit http://golang.org/pkg/crypto/tls/#Config 65 | 66 | ## Set HTTP Version 67 | 68 | some servers need to specify the protocol version of HTTP 69 | 70 | httplib.Get("http://beego.me/").SetProtocolVersion("HTTP/1.1") 71 | 72 | ## Set Cookie 73 | 74 | some http request need setcookie. So set it like this: 75 | 76 | cookie := &http.Cookie{} 77 | cookie.Name = "username" 78 | cookie.Value = "astaxie" 79 | httplib.Get("http://beego.me/").SetCookie(cookie) 80 | 81 | ## Upload file 82 | 83 | httplib support mutil file upload, use `req.PostFile()` 84 | 85 | req := httplib.Post("http://beego.me/") 86 | req.Param("username","astaxie") 87 | req.PostFile("uploadfile1", "httplib.pdf") 88 | str, err := req.String() 89 | if err != nil { 90 | // error 91 | } 92 | fmt.Println(str) 93 | 94 | 95 | See godoc for further documentation and examples. 96 | 97 | * [godoc.org/github.com/astaxie/beego/httplib](https://godoc.org/github.com/astaxie/beego/httplib) 98 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package beego 16 | 17 | import ( 18 | "strings" 19 | 20 | "github.com/astaxie/beego/logs" 21 | ) 22 | 23 | // Log levels to control the logging output. 24 | const ( 25 | LevelEmergency = iota 26 | LevelAlert 27 | LevelCritical 28 | LevelError 29 | LevelWarning 30 | LevelNotice 31 | LevelInformational 32 | LevelDebug 33 | ) 34 | 35 | // BeeLogger references the used application logger. 36 | var BeeLogger = logs.GetBeeLogger() 37 | 38 | // SetLevel sets the global log level used by the simple logger. 39 | func SetLevel(l int) { 40 | logs.SetLevel(l) 41 | } 42 | 43 | // SetLogFuncCall set the CallDepth, default is 3 44 | func SetLogFuncCall(b bool) { 45 | logs.SetLogFuncCall(b) 46 | } 47 | 48 | // SetLogger sets a new logger. 49 | func SetLogger(adaptername string, config string) error { 50 | return logs.SetLogger(adaptername, config) 51 | } 52 | 53 | // Emergency logs a message at emergency level. 54 | func Emergency(v ...interface{}) { 55 | logs.Emergency(generateFmtStr(len(v)), v...) 56 | } 57 | 58 | // Alert logs a message at alert level. 59 | func Alert(v ...interface{}) { 60 | logs.Alert(generateFmtStr(len(v)), v...) 61 | } 62 | 63 | // Critical logs a message at critical level. 64 | func Critical(v ...interface{}) { 65 | logs.Critical(generateFmtStr(len(v)), v...) 66 | } 67 | 68 | // Error logs a message at error level. 69 | func Error(v ...interface{}) { 70 | logs.Error(generateFmtStr(len(v)), v...) 71 | } 72 | 73 | // Warning logs a message at warning level. 74 | func Warning(v ...interface{}) { 75 | logs.Warning(generateFmtStr(len(v)), v...) 76 | } 77 | 78 | // Warn compatibility alias for Warning() 79 | func Warn(v ...interface{}) { 80 | logs.Warn(generateFmtStr(len(v)), v...) 81 | } 82 | 83 | // Notice logs a message at notice level. 84 | func Notice(v ...interface{}) { 85 | logs.Notice(generateFmtStr(len(v)), v...) 86 | } 87 | 88 | // Informational logs a message at info level. 89 | func Informational(v ...interface{}) { 90 | logs.Informational(generateFmtStr(len(v)), v...) 91 | } 92 | 93 | // Info compatibility alias for Warning() 94 | func Info(v ...interface{}) { 95 | logs.Info(generateFmtStr(len(v)), v...) 96 | } 97 | 98 | // Debug logs a message at debug level. 99 | func Debug(v ...interface{}) { 100 | logs.Debug(generateFmtStr(len(v)), v...) 101 | } 102 | 103 | // Trace logs a message at trace level. 104 | // compatibility alias for Warning() 105 | func Trace(v ...interface{}) { 106 | logs.Trace(generateFmtStr(len(v)), v...) 107 | } 108 | 109 | func generateFmtStr(n int) string { 110 | return strings.Repeat("%v ", n) 111 | } 112 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/README.md: -------------------------------------------------------------------------------- 1 | ## logs 2 | logs is a Go logs manager. It can use many logs adapters. The repo is inspired by `database/sql` . 3 | 4 | 5 | ## How to install? 6 | 7 | go get github.com/astaxie/beego/logs 8 | 9 | 10 | ## What adapters are supported? 11 | 12 | As of now this logs support console, file,smtp and conn. 13 | 14 | 15 | ## How to use it? 16 | 17 | First you must import it 18 | 19 | ```golang 20 | import ( 21 | "github.com/astaxie/beego/logs" 22 | ) 23 | ``` 24 | 25 | Then init a Log (example with console adapter) 26 | 27 | ```golang 28 | log := logs.NewLogger(10000) 29 | log.SetLogger("console", "") 30 | ``` 31 | 32 | > the first params stand for how many channel 33 | 34 | Use it like this: 35 | 36 | ```golang 37 | log.Trace("trace") 38 | log.Info("info") 39 | log.Warn("warning") 40 | log.Debug("debug") 41 | log.Critical("critical") 42 | ``` 43 | 44 | ## File adapter 45 | 46 | Configure file adapter like this: 47 | 48 | ```golang 49 | log := NewLogger(10000) 50 | log.SetLogger("file", `{"filename":"test.log"}`) 51 | ``` 52 | 53 | ## Conn adapter 54 | 55 | Configure like this: 56 | 57 | ```golang 58 | log := NewLogger(1000) 59 | log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`) 60 | log.Info("info") 61 | ``` 62 | 63 | ## Smtp adapter 64 | 65 | Configure like this: 66 | 67 | ```golang 68 | log := NewLogger(10000) 69 | log.SetLogger("smtp", `{"username":"beegotest@gmail.com","password":"xxxxxxxx","host":"smtp.gmail.com:587","sendTos":["xiemengjun@gmail.com"]}`) 70 | log.Critical("sendmail critical") 71 | time.Sleep(time.Second * 30) 72 | ``` 73 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/accesslog.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package logs 16 | 17 | import ( 18 | "bytes" 19 | "strings" 20 | "encoding/json" 21 | "fmt" 22 | "time" 23 | ) 24 | 25 | const ( 26 | apacheFormatPattern = "%s - - [%s] \"%s %d %d\" %f %s %s" 27 | apacheFormat = "APACHE_FORMAT" 28 | jsonFormat = "JSON_FORMAT" 29 | ) 30 | 31 | // AccessLogRecord struct for holding access log data. 32 | type AccessLogRecord struct { 33 | RemoteAddr string `json:"remote_addr"` 34 | RequestTime time.Time `json:"request_time"` 35 | RequestMethod string `json:"request_method"` 36 | Request string `json:"request"` 37 | ServerProtocol string `json:"server_protocol"` 38 | Host string `json:"host"` 39 | Status int `json:"status"` 40 | BodyBytesSent int64 `json:"body_bytes_sent"` 41 | ElapsedTime time.Duration `json:"elapsed_time"` 42 | HTTPReferrer string `json:"http_referrer"` 43 | HTTPUserAgent string `json:"http_user_agent"` 44 | RemoteUser string `json:"remote_user"` 45 | } 46 | 47 | func (r *AccessLogRecord) json() ([]byte, error) { 48 | buffer := &bytes.Buffer{} 49 | encoder := json.NewEncoder(buffer) 50 | disableEscapeHTML(encoder) 51 | 52 | err := encoder.Encode(r) 53 | return buffer.Bytes(), err 54 | } 55 | 56 | func disableEscapeHTML(i interface{}) { 57 | if e, ok := i.(interface { 58 | SetEscapeHTML(bool) 59 | }); ok { 60 | e.SetEscapeHTML(false) 61 | } 62 | } 63 | 64 | // AccessLog - Format and print access log. 65 | func AccessLog(r *AccessLogRecord, format string) { 66 | var msg string 67 | switch format { 68 | case apacheFormat: 69 | timeFormatted := r.RequestTime.Format("02/Jan/2006 03:04:05") 70 | msg = fmt.Sprintf(apacheFormatPattern, r.RemoteAddr, timeFormatted, r.Request, r.Status, r.BodyBytesSent, 71 | r.ElapsedTime.Seconds(), r.HTTPReferrer, r.HTTPUserAgent) 72 | case jsonFormat: 73 | fallthrough 74 | default: 75 | jsonData, err := r.json() 76 | if err != nil { 77 | msg = fmt.Sprintf(`{"Error": "%s"}`, err) 78 | } else { 79 | msg = string(jsonData) 80 | } 81 | } 82 | beeLogger.writeMsg(levelLoggerImpl, strings.TrimSpace(msg)) 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/color.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | // +build !windows 16 | 17 | package logs 18 | 19 | import "io" 20 | 21 | type ansiColorWriter struct { 22 | w io.Writer 23 | mode outputMode 24 | } 25 | 26 | func (cw *ansiColorWriter) Write(p []byte) (int, error) { 27 | return cw.w.Write(p) 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/conn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package logs 16 | 17 | import ( 18 | "encoding/json" 19 | "io" 20 | "net" 21 | "time" 22 | ) 23 | 24 | // connWriter implements LoggerInterface. 25 | // it writes messages in keep-live tcp connection. 26 | type connWriter struct { 27 | lg *logWriter 28 | innerWriter io.WriteCloser 29 | ReconnectOnMsg bool `json:"reconnectOnMsg"` 30 | Reconnect bool `json:"reconnect"` 31 | Net string `json:"net"` 32 | Addr string `json:"addr"` 33 | Level int `json:"level"` 34 | } 35 | 36 | // NewConn create new ConnWrite returning as LoggerInterface. 37 | func NewConn() Logger { 38 | conn := new(connWriter) 39 | conn.Level = LevelTrace 40 | return conn 41 | } 42 | 43 | // Init init connection writer with json config. 44 | // json config only need key "level". 45 | func (c *connWriter) Init(jsonConfig string) error { 46 | return json.Unmarshal([]byte(jsonConfig), c) 47 | } 48 | 49 | // WriteMsg write message in connection. 50 | // if connection is down, try to re-connect. 51 | func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { 52 | if level > c.Level { 53 | return nil 54 | } 55 | if c.needToConnectOnMsg() { 56 | err := c.connect() 57 | if err != nil { 58 | return err 59 | } 60 | } 61 | 62 | if c.ReconnectOnMsg { 63 | defer c.innerWriter.Close() 64 | } 65 | 66 | c.lg.println(when, msg) 67 | return nil 68 | } 69 | 70 | // Flush implementing method. empty. 71 | func (c *connWriter) Flush() { 72 | 73 | } 74 | 75 | // Destroy destroy connection writer and close tcp listener. 76 | func (c *connWriter) Destroy() { 77 | if c.innerWriter != nil { 78 | c.innerWriter.Close() 79 | } 80 | } 81 | 82 | func (c *connWriter) connect() error { 83 | if c.innerWriter != nil { 84 | c.innerWriter.Close() 85 | c.innerWriter = nil 86 | } 87 | 88 | conn, err := net.Dial(c.Net, c.Addr) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | if tcpConn, ok := conn.(*net.TCPConn); ok { 94 | tcpConn.SetKeepAlive(true) 95 | } 96 | 97 | c.innerWriter = conn 98 | c.lg = newLogWriter(conn) 99 | return nil 100 | } 101 | 102 | func (c *connWriter) needToConnectOnMsg() bool { 103 | if c.Reconnect { 104 | c.Reconnect = false 105 | return true 106 | } 107 | 108 | if c.innerWriter == nil { 109 | return true 110 | } 111 | 112 | return c.ReconnectOnMsg 113 | } 114 | 115 | func init() { 116 | Register(AdapterConn, NewConn) 117 | } 118 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/console.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package logs 16 | 17 | import ( 18 | "encoding/json" 19 | "os" 20 | "runtime" 21 | "time" 22 | ) 23 | 24 | // brush is a color join function 25 | type brush func(string) string 26 | 27 | // newBrush return a fix color Brush 28 | func newBrush(color string) brush { 29 | pre := "\033[" 30 | reset := "\033[0m" 31 | return func(text string) string { 32 | return pre + color + "m" + text + reset 33 | } 34 | } 35 | 36 | var colors = []brush{ 37 | newBrush("1;37"), // Emergency white 38 | newBrush("1;36"), // Alert cyan 39 | newBrush("1;35"), // Critical magenta 40 | newBrush("1;31"), // Error red 41 | newBrush("1;33"), // Warning yellow 42 | newBrush("1;32"), // Notice green 43 | newBrush("1;34"), // Informational blue 44 | newBrush("1;44"), // Debug Background blue 45 | } 46 | 47 | // consoleWriter implements LoggerInterface and writes messages to terminal. 48 | type consoleWriter struct { 49 | lg *logWriter 50 | Level int `json:"level"` 51 | Colorful bool `json:"color"` //this filed is useful only when system's terminal supports color 52 | } 53 | 54 | // NewConsole create ConsoleWriter returning as LoggerInterface. 55 | func NewConsole() Logger { 56 | cw := &consoleWriter{ 57 | lg: newLogWriter(os.Stdout), 58 | Level: LevelDebug, 59 | Colorful: runtime.GOOS != "windows", 60 | } 61 | return cw 62 | } 63 | 64 | // Init init console logger. 65 | // jsonConfig like '{"level":LevelTrace}'. 66 | func (c *consoleWriter) Init(jsonConfig string) error { 67 | if len(jsonConfig) == 0 { 68 | return nil 69 | } 70 | err := json.Unmarshal([]byte(jsonConfig), c) 71 | if runtime.GOOS == "windows" { 72 | c.Colorful = false 73 | } 74 | return err 75 | } 76 | 77 | // WriteMsg write message in console. 78 | func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { 79 | if level > c.Level { 80 | return nil 81 | } 82 | if c.Colorful { 83 | msg = colors[level](msg) 84 | } 85 | c.lg.println(when, msg) 86 | return nil 87 | } 88 | 89 | // Destroy implementing method. empty. 90 | func (c *consoleWriter) Destroy() { 91 | 92 | } 93 | 94 | // Flush implementing method. empty. 95 | func (c *consoleWriter) Flush() { 96 | 97 | } 98 | 99 | func init() { 100 | Register(AdapterConsole, NewConsole) 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/jianliao.go: -------------------------------------------------------------------------------- 1 | package logs 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "net/url" 8 | "time" 9 | ) 10 | 11 | // JLWriter implements beego LoggerInterface and is used to send jiaoliao webhook 12 | type JLWriter struct { 13 | AuthorName string `json:"authorname"` 14 | Title string `json:"title"` 15 | WebhookURL string `json:"webhookurl"` 16 | RedirectURL string `json:"redirecturl,omitempty"` 17 | ImageURL string `json:"imageurl,omitempty"` 18 | Level int `json:"level"` 19 | } 20 | 21 | // newJLWriter create jiaoliao writer. 22 | func newJLWriter() Logger { 23 | return &JLWriter{Level: LevelTrace} 24 | } 25 | 26 | // Init JLWriter with json config string 27 | func (s *JLWriter) Init(jsonconfig string) error { 28 | return json.Unmarshal([]byte(jsonconfig), s) 29 | } 30 | 31 | // WriteMsg write message in smtp writer. 32 | // it will send an email with subject and only this message. 33 | func (s *JLWriter) WriteMsg(when time.Time, msg string, level int) error { 34 | if level > s.Level { 35 | return nil 36 | } 37 | 38 | text := fmt.Sprintf("%s %s", when.Format("2006-01-02 15:04:05"), msg) 39 | 40 | form := url.Values{} 41 | form.Add("authorName", s.AuthorName) 42 | form.Add("title", s.Title) 43 | form.Add("text", text) 44 | if s.RedirectURL != "" { 45 | form.Add("redirectUrl", s.RedirectURL) 46 | } 47 | if s.ImageURL != "" { 48 | form.Add("imageUrl", s.ImageURL) 49 | } 50 | 51 | resp, err := http.PostForm(s.WebhookURL, form) 52 | if err != nil { 53 | return err 54 | } 55 | defer resp.Body.Close() 56 | if resp.StatusCode != http.StatusOK { 57 | return fmt.Errorf("Post webhook failed %s %d", resp.Status, resp.StatusCode) 58 | } 59 | return nil 60 | } 61 | 62 | // Flush implementing method. empty. 63 | func (s *JLWriter) Flush() { 64 | } 65 | 66 | // Destroy implementing method. empty. 67 | func (s *JLWriter) Destroy() { 68 | } 69 | 70 | func init() { 71 | Register(AdapterJianLiao, newJLWriter) 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/multifile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package logs 16 | 17 | import ( 18 | "encoding/json" 19 | "time" 20 | ) 21 | 22 | // A filesLogWriter manages several fileLogWriter 23 | // filesLogWriter will write logs to the file in json configuration and write the same level log to correspond file 24 | // means if the file name in configuration is project.log filesLogWriter will create project.error.log/project.debug.log 25 | // and write the error-level logs to project.error.log and write the debug-level logs to project.debug.log 26 | // the rotate attribute also acts like fileLogWriter 27 | type multiFileLogWriter struct { 28 | writers [LevelDebug + 1 + 1]*fileLogWriter // the last one for fullLogWriter 29 | fullLogWriter *fileLogWriter 30 | Separate []string `json:"separate"` 31 | } 32 | 33 | var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"} 34 | 35 | // Init file logger with json config. 36 | // jsonConfig like: 37 | // { 38 | // "filename":"logs/beego.log", 39 | // "maxLines":0, 40 | // "maxsize":0, 41 | // "daily":true, 42 | // "maxDays":15, 43 | // "rotate":true, 44 | // "perm":0600, 45 | // "separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"], 46 | // } 47 | 48 | func (f *multiFileLogWriter) Init(config string) error { 49 | writer := newFileWriter().(*fileLogWriter) 50 | err := writer.Init(config) 51 | if err != nil { 52 | return err 53 | } 54 | f.fullLogWriter = writer 55 | f.writers[LevelDebug+1] = writer 56 | 57 | //unmarshal "separate" field to f.Separate 58 | json.Unmarshal([]byte(config), f) 59 | 60 | jsonMap := map[string]interface{}{} 61 | json.Unmarshal([]byte(config), &jsonMap) 62 | 63 | for i := LevelEmergency; i < LevelDebug+1; i++ { 64 | for _, v := range f.Separate { 65 | if v == levelNames[i] { 66 | jsonMap["filename"] = f.fullLogWriter.fileNameOnly + "." + levelNames[i] + f.fullLogWriter.suffix 67 | jsonMap["level"] = i 68 | bs, _ := json.Marshal(jsonMap) 69 | writer = newFileWriter().(*fileLogWriter) 70 | err := writer.Init(string(bs)) 71 | if err != nil { 72 | return err 73 | } 74 | f.writers[i] = writer 75 | } 76 | } 77 | } 78 | 79 | return nil 80 | } 81 | 82 | func (f *multiFileLogWriter) Destroy() { 83 | for i := 0; i < len(f.writers); i++ { 84 | if f.writers[i] != nil { 85 | f.writers[i].Destroy() 86 | } 87 | } 88 | } 89 | 90 | func (f *multiFileLogWriter) WriteMsg(when time.Time, msg string, level int) error { 91 | if f.fullLogWriter != nil { 92 | f.fullLogWriter.WriteMsg(when, msg, level) 93 | } 94 | for i := 0; i < len(f.writers)-1; i++ { 95 | if f.writers[i] != nil { 96 | if level == f.writers[i].Level { 97 | f.writers[i].WriteMsg(when, msg, level) 98 | } 99 | } 100 | } 101 | return nil 102 | } 103 | 104 | func (f *multiFileLogWriter) Flush() { 105 | for i := 0; i < len(f.writers); i++ { 106 | if f.writers[i] != nil { 107 | f.writers[i].Flush() 108 | } 109 | } 110 | } 111 | 112 | // newFilesWriter create a FileLogWriter returning as LoggerInterface. 113 | func newFilesWriter() Logger { 114 | return &multiFileLogWriter{} 115 | } 116 | 117 | func init() { 118 | Register(AdapterMultiFile, newFilesWriter) 119 | } 120 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/slack.go: -------------------------------------------------------------------------------- 1 | package logs 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "net/url" 8 | "time" 9 | ) 10 | 11 | // SLACKWriter implements beego LoggerInterface and is used to send jiaoliao webhook 12 | type SLACKWriter struct { 13 | WebhookURL string `json:"webhookurl"` 14 | Level int `json:"level"` 15 | } 16 | 17 | // newSLACKWriter create jiaoliao writer. 18 | func newSLACKWriter() Logger { 19 | return &SLACKWriter{Level: LevelTrace} 20 | } 21 | 22 | // Init SLACKWriter with json config string 23 | func (s *SLACKWriter) Init(jsonconfig string) error { 24 | return json.Unmarshal([]byte(jsonconfig), s) 25 | } 26 | 27 | // WriteMsg write message in smtp writer. 28 | // it will send an email with subject and only this message. 29 | func (s *SLACKWriter) WriteMsg(when time.Time, msg string, level int) error { 30 | if level > s.Level { 31 | return nil 32 | } 33 | 34 | text := fmt.Sprintf("{\"text\": \"%s %s\"}", when.Format("2006-01-02 15:04:05"), msg) 35 | 36 | form := url.Values{} 37 | form.Add("payload", text) 38 | 39 | resp, err := http.PostForm(s.WebhookURL, form) 40 | if err != nil { 41 | return err 42 | } 43 | defer resp.Body.Close() 44 | if resp.StatusCode != http.StatusOK { 45 | return fmt.Errorf("Post webhook failed %s %d", resp.Status, resp.StatusCode) 46 | } 47 | return nil 48 | } 49 | 50 | // Flush implementing method. empty. 51 | func (s *SLACKWriter) Flush() { 52 | } 53 | 54 | // Destroy implementing method. empty. 55 | func (s *SLACKWriter) Destroy() { 56 | } 57 | 58 | func init() { 59 | Register(AdapterSlack, newSLACKWriter) 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/logs/smtp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package logs 16 | 17 | import ( 18 | "crypto/tls" 19 | "encoding/json" 20 | "fmt" 21 | "net" 22 | "net/smtp" 23 | "strings" 24 | "time" 25 | ) 26 | 27 | // SMTPWriter implements LoggerInterface and is used to send emails via given SMTP-server. 28 | type SMTPWriter struct { 29 | Username string `json:"username"` 30 | Password string `json:"password"` 31 | Host string `json:"host"` 32 | Subject string `json:"subject"` 33 | FromAddress string `json:"fromAddress"` 34 | RecipientAddresses []string `json:"sendTos"` 35 | Level int `json:"level"` 36 | } 37 | 38 | // NewSMTPWriter create smtp writer. 39 | func newSMTPWriter() Logger { 40 | return &SMTPWriter{Level: LevelTrace} 41 | } 42 | 43 | // Init smtp writer with json config. 44 | // config like: 45 | // { 46 | // "username":"example@gmail.com", 47 | // "password:"password", 48 | // "host":"smtp.gmail.com:465", 49 | // "subject":"email title", 50 | // "fromAddress":"from@example.com", 51 | // "sendTos":["email1","email2"], 52 | // "level":LevelError 53 | // } 54 | func (s *SMTPWriter) Init(jsonconfig string) error { 55 | return json.Unmarshal([]byte(jsonconfig), s) 56 | } 57 | 58 | func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth { 59 | if len(strings.Trim(s.Username, " ")) == 0 && len(strings.Trim(s.Password, " ")) == 0 { 60 | return nil 61 | } 62 | return smtp.PlainAuth( 63 | "", 64 | s.Username, 65 | s.Password, 66 | host, 67 | ) 68 | } 69 | 70 | func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAddress string, recipients []string, msgContent []byte) error { 71 | client, err := smtp.Dial(hostAddressWithPort) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | host, _, _ := net.SplitHostPort(hostAddressWithPort) 77 | tlsConn := &tls.Config{ 78 | InsecureSkipVerify: true, 79 | ServerName: host, 80 | } 81 | if err = client.StartTLS(tlsConn); err != nil { 82 | return err 83 | } 84 | 85 | if auth != nil { 86 | if err = client.Auth(auth); err != nil { 87 | return err 88 | } 89 | } 90 | 91 | if err = client.Mail(fromAddress); err != nil { 92 | return err 93 | } 94 | 95 | for _, rec := range recipients { 96 | if err = client.Rcpt(rec); err != nil { 97 | return err 98 | } 99 | } 100 | 101 | w, err := client.Data() 102 | if err != nil { 103 | return err 104 | } 105 | _, err = w.Write(msgContent) 106 | if err != nil { 107 | return err 108 | } 109 | 110 | err = w.Close() 111 | if err != nil { 112 | return err 113 | } 114 | 115 | return client.Quit() 116 | } 117 | 118 | // WriteMsg write message in smtp writer. 119 | // it will send an email with subject and only this message. 120 | func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error { 121 | if level > s.Level { 122 | return nil 123 | } 124 | 125 | hp := strings.Split(s.Host, ":") 126 | 127 | // Set up authentication information. 128 | auth := s.getSMTPAuth(hp[0]) 129 | 130 | // Connect to the server, authenticate, set the sender and recipient, 131 | // and send the email all in one step. 132 | contentType := "Content-Type: text/plain" + "; charset=UTF-8" 133 | mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress + 134 | ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", when.Format("2006-01-02 15:04:05")) + msg) 135 | 136 | return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg) 137 | } 138 | 139 | // Flush implementing method. empty. 140 | func (s *SMTPWriter) Flush() { 141 | } 142 | 143 | // Destroy implementing method. empty. 144 | func (s *SMTPWriter) Destroy() { 145 | } 146 | 147 | func init() { 148 | Register(AdapterMail, newSMTPWriter) 149 | } 150 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/plugins/auth/basic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | // Package auth provides handlers to enable basic auth support. 16 | // Simple Usage: 17 | // import( 18 | // "github.com/astaxie/beego" 19 | // "github.com/astaxie/beego/plugins/auth" 20 | // ) 21 | // 22 | // func main(){ 23 | // // authenticate every request 24 | // beego.InsertFilter("*", beego.BeforeRouter,auth.Basic("username","secretpassword")) 25 | // beego.Run() 26 | // } 27 | // 28 | // 29 | // Advanced Usage: 30 | // 31 | // func SecretAuth(username, password string) bool { 32 | // return username == "astaxie" && password == "helloBeego" 33 | // } 34 | // authPlugin := auth.NewBasicAuthenticator(SecretAuth, "Authorization Required") 35 | // beego.InsertFilter("*", beego.BeforeRouter,authPlugin) 36 | package auth 37 | 38 | import ( 39 | "encoding/base64" 40 | "net/http" 41 | "strings" 42 | 43 | "github.com/astaxie/beego" 44 | "github.com/astaxie/beego/context" 45 | ) 46 | 47 | var defaultRealm = "Authorization Required" 48 | 49 | // Basic is the http basic auth 50 | func Basic(username string, password string) beego.FilterFunc { 51 | secrets := func(user, pass string) bool { 52 | return user == username && pass == password 53 | } 54 | return NewBasicAuthenticator(secrets, defaultRealm) 55 | } 56 | 57 | // NewBasicAuthenticator return the BasicAuth 58 | func NewBasicAuthenticator(secrets SecretProvider, Realm string) beego.FilterFunc { 59 | return func(ctx *context.Context) { 60 | a := &BasicAuth{Secrets: secrets, Realm: Realm} 61 | if username := a.CheckAuth(ctx.Request); username == "" { 62 | a.RequireAuth(ctx.ResponseWriter, ctx.Request) 63 | } 64 | } 65 | } 66 | 67 | // SecretProvider is the SecretProvider function 68 | type SecretProvider func(user, pass string) bool 69 | 70 | // BasicAuth store the SecretProvider and Realm 71 | type BasicAuth struct { 72 | Secrets SecretProvider 73 | Realm string 74 | } 75 | 76 | // CheckAuth Checks the username/password combination from the request. Returns 77 | // either an empty string (authentication failed) or the name of the 78 | // authenticated user. 79 | // Supports MD5 and SHA1 password entries 80 | func (a *BasicAuth) CheckAuth(r *http.Request) string { 81 | s := strings.SplitN(r.Header.Get("Authorization"), " ", 2) 82 | if len(s) != 2 || s[0] != "Basic" { 83 | return "" 84 | } 85 | 86 | b, err := base64.StdEncoding.DecodeString(s[1]) 87 | if err != nil { 88 | return "" 89 | } 90 | pair := strings.SplitN(string(b), ":", 2) 91 | if len(pair) != 2 { 92 | return "" 93 | } 94 | 95 | if a.Secrets(pair[0], pair[1]) { 96 | return pair[0] 97 | } 98 | return "" 99 | } 100 | 101 | // RequireAuth http.Handler for BasicAuth which initiates the authentication process 102 | // (or requires reauthentication). 103 | func (a *BasicAuth) RequireAuth(w http.ResponseWriter, r *http.Request) { 104 | w.Header().Set("WWW-Authenticate", `Basic realm="`+a.Realm+`"`) 105 | w.WriteHeader(401) 106 | w.Write([]byte("401 Unauthorized\n")) 107 | } 108 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/policy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 beego authors. All Rights Reserved. 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 | package beego 16 | 17 | import ( 18 | "strings" 19 | 20 | "github.com/astaxie/beego/context" 21 | ) 22 | 23 | // PolicyFunc defines a policy function which is invoked before the controller handler is executed. 24 | type PolicyFunc func(*context.Context) 25 | 26 | // FindPolicy Find Router info for URL 27 | func (p *ControllerRegister) FindPolicy(cont *context.Context) []PolicyFunc { 28 | var urlPath = cont.Input.URL() 29 | if !BConfig.RouterCaseSensitive { 30 | urlPath = strings.ToLower(urlPath) 31 | } 32 | httpMethod := cont.Input.Method() 33 | isWildcard := false 34 | // Find policy for current method 35 | t, ok := p.policies[httpMethod] 36 | // If not found - find policy for whole controller 37 | if !ok { 38 | t, ok = p.policies["*"] 39 | isWildcard = true 40 | } 41 | if ok { 42 | runObjects := t.Match(urlPath, cont) 43 | if r, ok := runObjects.([]PolicyFunc); ok { 44 | return r 45 | } else if !isWildcard { 46 | // If no policies found and we checked not for "*" method - try to find it 47 | t, ok = p.policies["*"] 48 | if ok { 49 | runObjects = t.Match(urlPath, cont) 50 | if r, ok = runObjects.([]PolicyFunc); ok { 51 | return r 52 | } 53 | } 54 | } 55 | } 56 | return nil 57 | } 58 | 59 | func (p *ControllerRegister) addToPolicy(method, pattern string, r ...PolicyFunc) { 60 | method = strings.ToUpper(method) 61 | p.enablePolicy = true 62 | if !BConfig.RouterCaseSensitive { 63 | pattern = strings.ToLower(pattern) 64 | } 65 | if t, ok := p.policies[method]; ok { 66 | t.AddRouter(pattern, r) 67 | } else { 68 | t := NewTree() 69 | t.AddRouter(pattern, r) 70 | p.policies[method] = t 71 | } 72 | } 73 | 74 | // Policy Register new policy in beego 75 | func Policy(pattern, method string, policy ...PolicyFunc) { 76 | BeeApp.Handlers.addToPolicy(method, pattern, policy...) 77 | } 78 | 79 | // Find policies and execute if were found 80 | func (p *ControllerRegister) execPolicy(cont *context.Context, urlPath string) (started bool) { 81 | if !p.enablePolicy { 82 | return false 83 | } 84 | // Find Policy for method 85 | policyList := p.FindPolicy(cont) 86 | if len(policyList) > 0 { 87 | // Run policies 88 | for _, runPolicy := range policyList { 89 | runPolicy(cont) 90 | if cont.ResponseWriter.Started { 91 | return true 92 | } 93 | } 94 | return false 95 | } 96 | return false 97 | } 98 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/session/README.md: -------------------------------------------------------------------------------- 1 | session 2 | ============== 3 | 4 | session is a Go session manager. It can use many session providers. Just like the `database/sql` and `database/sql/driver`. 5 | 6 | ## How to install? 7 | 8 | go get github.com/astaxie/beego/session 9 | 10 | 11 | ## What providers are supported? 12 | 13 | As of now this session manager support memory, file, Redis and MySQL. 14 | 15 | 16 | ## How to use it? 17 | 18 | First you must import it 19 | 20 | import ( 21 | "github.com/astaxie/beego/session" 22 | ) 23 | 24 | Then in you web app init the global session manager 25 | 26 | var globalSessions *session.Manager 27 | 28 | * Use **memory** as provider: 29 | 30 | func init() { 31 | globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid","gclifetime":3600}`) 32 | go globalSessions.GC() 33 | } 34 | 35 | * Use **file** as provider, the last param is the path where you want file to be stored: 36 | 37 | func init() { 38 | globalSessions, _ = session.NewManager("file",`{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"./tmp"}`) 39 | go globalSessions.GC() 40 | } 41 | 42 | * Use **Redis** as provider, the last param is the Redis conn address,poolsize,password: 43 | 44 | func init() { 45 | globalSessions, _ = session.NewManager("redis", `{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:6379,100,astaxie"}`) 46 | go globalSessions.GC() 47 | } 48 | 49 | * Use **MySQL** as provider, the last param is the DSN, learn more from [mysql](https://github.com/go-sql-driver/mysql#dsn-data-source-name): 50 | 51 | func init() { 52 | globalSessions, _ = session.NewManager( 53 | "mysql", `{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"username:password@protocol(address)/dbname?param=value"}`) 54 | go globalSessions.GC() 55 | } 56 | 57 | * Use **Cookie** as provider: 58 | 59 | func init() { 60 | globalSessions, _ = session.NewManager( 61 | "cookie", `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`) 62 | go globalSessions.GC() 63 | } 64 | 65 | 66 | Finally in the handlerfunc you can use it like this 67 | 68 | func login(w http.ResponseWriter, r *http.Request) { 69 | sess := globalSessions.SessionStart(w, r) 70 | defer sess.SessionRelease(w) 71 | username := sess.Get("username") 72 | fmt.Println(username) 73 | if r.Method == "GET" { 74 | t, _ := template.ParseFiles("login.gtpl") 75 | t.Execute(w, nil) 76 | } else { 77 | fmt.Println("username:", r.Form["username"]) 78 | sess.Set("username", r.Form["username"]) 79 | fmt.Println("password:", r.Form["password"]) 80 | } 81 | } 82 | 83 | 84 | ## How to write own provider? 85 | 86 | When you develop a web app, maybe you want to write own provider because you must meet the requirements. 87 | 88 | Writing a provider is easy. You only need to define two struct types 89 | (Session and Provider), which satisfy the interface definition. 90 | Maybe you will find the **memory** provider is a good example. 91 | 92 | type SessionStore interface { 93 | Set(key, value interface{}) error //set session value 94 | Get(key interface{}) interface{} //get session value 95 | Delete(key interface{}) error //delete session value 96 | SessionID() string //back current sessionID 97 | SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data 98 | Flush() error //delete all data 99 | } 100 | 101 | type Provider interface { 102 | SessionInit(gclifetime int64, config string) error 103 | SessionRead(sid string) (SessionStore, error) 104 | SessionExist(sid string) bool 105 | SessionRegenerate(oldsid, sid string) (SessionStore, error) 106 | SessionDestroy(sid string) error 107 | SessionAll() int //get all active session 108 | SessionGC() 109 | } 110 | 111 | 112 | ## LICENSE 113 | 114 | BSD License http://creativecommons.org/licenses/BSD/ 115 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/session/sess_cookie.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package session 16 | 17 | import ( 18 | "crypto/aes" 19 | "crypto/cipher" 20 | "encoding/json" 21 | "net/http" 22 | "net/url" 23 | "sync" 24 | ) 25 | 26 | var cookiepder = &CookieProvider{} 27 | 28 | // CookieSessionStore Cookie SessionStore 29 | type CookieSessionStore struct { 30 | sid string 31 | values map[interface{}]interface{} // session data 32 | lock sync.RWMutex 33 | } 34 | 35 | // Set value to cookie session. 36 | // the value are encoded as gob with hash block string. 37 | func (st *CookieSessionStore) Set(key, value interface{}) error { 38 | st.lock.Lock() 39 | defer st.lock.Unlock() 40 | st.values[key] = value 41 | return nil 42 | } 43 | 44 | // Get value from cookie session 45 | func (st *CookieSessionStore) Get(key interface{}) interface{} { 46 | st.lock.RLock() 47 | defer st.lock.RUnlock() 48 | if v, ok := st.values[key]; ok { 49 | return v 50 | } 51 | return nil 52 | } 53 | 54 | // Delete value in cookie session 55 | func (st *CookieSessionStore) Delete(key interface{}) error { 56 | st.lock.Lock() 57 | defer st.lock.Unlock() 58 | delete(st.values, key) 59 | return nil 60 | } 61 | 62 | // Flush Clean all values in cookie session 63 | func (st *CookieSessionStore) Flush() error { 64 | st.lock.Lock() 65 | defer st.lock.Unlock() 66 | st.values = make(map[interface{}]interface{}) 67 | return nil 68 | } 69 | 70 | // SessionID Return id of this cookie session 71 | func (st *CookieSessionStore) SessionID() string { 72 | return st.sid 73 | } 74 | 75 | // SessionRelease Write cookie session to http response cookie 76 | func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { 77 | encodedCookie, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, st.values) 78 | if err == nil { 79 | cookie := &http.Cookie{Name: cookiepder.config.CookieName, 80 | Value: url.QueryEscape(encodedCookie), 81 | Path: "/", 82 | HttpOnly: true, 83 | Secure: cookiepder.config.Secure, 84 | MaxAge: cookiepder.config.Maxage} 85 | http.SetCookie(w, cookie) 86 | } 87 | } 88 | 89 | type cookieConfig struct { 90 | SecurityKey string `json:"securityKey"` 91 | BlockKey string `json:"blockKey"` 92 | SecurityName string `json:"securityName"` 93 | CookieName string `json:"cookieName"` 94 | Secure bool `json:"secure"` 95 | Maxage int `json:"maxage"` 96 | } 97 | 98 | // CookieProvider Cookie session provider 99 | type CookieProvider struct { 100 | maxlifetime int64 101 | config *cookieConfig 102 | block cipher.Block 103 | } 104 | 105 | // SessionInit Init cookie session provider with max lifetime and config json. 106 | // maxlifetime is ignored. 107 | // json config: 108 | // securityKey - hash string 109 | // blockKey - gob encode hash string. it's saved as aes crypto. 110 | // securityName - recognized name in encoded cookie string 111 | // cookieName - cookie name 112 | // maxage - cookie max life time. 113 | func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error { 114 | pder.config = &cookieConfig{} 115 | err := json.Unmarshal([]byte(config), pder.config) 116 | if err != nil { 117 | return err 118 | } 119 | if pder.config.BlockKey == "" { 120 | pder.config.BlockKey = string(generateRandomKey(16)) 121 | } 122 | if pder.config.SecurityName == "" { 123 | pder.config.SecurityName = string(generateRandomKey(20)) 124 | } 125 | pder.block, err = aes.NewCipher([]byte(pder.config.BlockKey)) 126 | if err != nil { 127 | return err 128 | } 129 | pder.maxlifetime = maxlifetime 130 | return nil 131 | } 132 | 133 | // SessionRead Get SessionStore in cooke. 134 | // decode cooke string to map and put into SessionStore with sid. 135 | func (pder *CookieProvider) SessionRead(sid string) (Store, error) { 136 | maps, _ := decodeCookie(pder.block, 137 | pder.config.SecurityKey, 138 | pder.config.SecurityName, 139 | sid, pder.maxlifetime) 140 | if maps == nil { 141 | maps = make(map[interface{}]interface{}) 142 | } 143 | rs := &CookieSessionStore{sid: sid, values: maps} 144 | return rs, nil 145 | } 146 | 147 | // SessionExist Cookie session is always existed 148 | func (pder *CookieProvider) SessionExist(sid string) bool { 149 | return true 150 | } 151 | 152 | // SessionRegenerate Implement method, no used. 153 | func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (Store, error) { 154 | return nil, nil 155 | } 156 | 157 | // SessionDestroy Implement method, no used. 158 | func (pder *CookieProvider) SessionDestroy(sid string) error { 159 | return nil 160 | } 161 | 162 | // SessionGC Implement method, no used. 163 | func (pder *CookieProvider) SessionGC() { 164 | } 165 | 166 | // SessionAll Implement method, return 0. 167 | func (pder *CookieProvider) SessionAll() int { 168 | return 0 169 | } 170 | 171 | // SessionUpdate Implement method, no used. 172 | func (pder *CookieProvider) SessionUpdate(sid string) error { 173 | return nil 174 | } 175 | 176 | func init() { 177 | Register("cookie", cookiepder) 178 | } 179 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/toolbox/healthcheck.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | // Package toolbox healthcheck 16 | // 17 | // type DatabaseCheck struct { 18 | // } 19 | // 20 | // func (dc *DatabaseCheck) Check() error { 21 | // if dc.isConnected() { 22 | // return nil 23 | // } else { 24 | // return errors.New("can't connect database") 25 | // } 26 | // } 27 | // 28 | // AddHealthCheck("database",&DatabaseCheck{}) 29 | // 30 | // more docs: http://beego.me/docs/module/toolbox.md 31 | package toolbox 32 | 33 | // AdminCheckList holds health checker map 34 | var AdminCheckList map[string]HealthChecker 35 | 36 | // HealthChecker health checker interface 37 | type HealthChecker interface { 38 | Check() error 39 | } 40 | 41 | // AddHealthCheck add health checker with name string 42 | func AddHealthCheck(name string, hc HealthChecker) { 43 | AdminCheckList[name] = hc 44 | } 45 | 46 | func init() { 47 | AdminCheckList = make(map[string]HealthChecker) 48 | } 49 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/toolbox/statistics.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package toolbox 16 | 17 | import ( 18 | "fmt" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | // Statistics struct 24 | type Statistics struct { 25 | RequestURL string 26 | RequestController string 27 | RequestNum int64 28 | MinTime time.Duration 29 | MaxTime time.Duration 30 | TotalTime time.Duration 31 | } 32 | 33 | // URLMap contains several statistics struct to log different data 34 | type URLMap struct { 35 | lock sync.RWMutex 36 | LengthLimit int //limit the urlmap's length if it's equal to 0 there's no limit 37 | urlmap map[string]map[string]*Statistics 38 | } 39 | 40 | // AddStatistics add statistics task. 41 | // it needs request method, request url, request controller and statistics time duration 42 | func (m *URLMap) AddStatistics(requestMethod, requestURL, requestController string, requesttime time.Duration) { 43 | m.lock.Lock() 44 | defer m.lock.Unlock() 45 | if method, ok := m.urlmap[requestURL]; ok { 46 | if s, ok := method[requestMethod]; ok { 47 | s.RequestNum++ 48 | if s.MaxTime < requesttime { 49 | s.MaxTime = requesttime 50 | } 51 | if s.MinTime > requesttime { 52 | s.MinTime = requesttime 53 | } 54 | s.TotalTime += requesttime 55 | } else { 56 | nb := &Statistics{ 57 | RequestURL: requestURL, 58 | RequestController: requestController, 59 | RequestNum: 1, 60 | MinTime: requesttime, 61 | MaxTime: requesttime, 62 | TotalTime: requesttime, 63 | } 64 | m.urlmap[requestURL][requestMethod] = nb 65 | } 66 | 67 | } else { 68 | if m.LengthLimit > 0 && m.LengthLimit <= len(m.urlmap) { 69 | return 70 | } 71 | methodmap := make(map[string]*Statistics) 72 | nb := &Statistics{ 73 | RequestURL: requestURL, 74 | RequestController: requestController, 75 | RequestNum: 1, 76 | MinTime: requesttime, 77 | MaxTime: requesttime, 78 | TotalTime: requesttime, 79 | } 80 | methodmap[requestMethod] = nb 81 | m.urlmap[requestURL] = methodmap 82 | } 83 | } 84 | 85 | // GetMap put url statistics result in io.Writer 86 | func (m *URLMap) GetMap() map[string]interface{} { 87 | m.lock.RLock() 88 | defer m.lock.RUnlock() 89 | 90 | var fields = []string{"requestUrl", "method", "times", "used", "max used", "min used", "avg used"} 91 | 92 | var resultLists [][]string 93 | content := make(map[string]interface{}) 94 | content["Fields"] = fields 95 | 96 | for k, v := range m.urlmap { 97 | for kk, vv := range v { 98 | result := []string{ 99 | fmt.Sprintf("% -50s", k), 100 | fmt.Sprintf("% -10s", kk), 101 | fmt.Sprintf("% -16d", vv.RequestNum), 102 | fmt.Sprintf("%d", vv.TotalTime), 103 | fmt.Sprintf("% -16s", toS(vv.TotalTime)), 104 | fmt.Sprintf("%d", vv.MaxTime), 105 | fmt.Sprintf("% -16s", toS(vv.MaxTime)), 106 | fmt.Sprintf("%d", vv.MinTime), 107 | fmt.Sprintf("% -16s", toS(vv.MinTime)), 108 | fmt.Sprintf("%d", time.Duration(int64(vv.TotalTime)/vv.RequestNum)), 109 | fmt.Sprintf("% -16s", toS(time.Duration(int64(vv.TotalTime)/vv.RequestNum))), 110 | } 111 | resultLists = append(resultLists, result) 112 | } 113 | } 114 | content["Data"] = resultLists 115 | return content 116 | } 117 | 118 | // GetMapData return all mapdata 119 | func (m *URLMap) GetMapData() []map[string]interface{} { 120 | m.lock.Lock() 121 | defer m.lock.Unlock() 122 | 123 | var resultLists []map[string]interface{} 124 | 125 | for k, v := range m.urlmap { 126 | for kk, vv := range v { 127 | result := map[string]interface{}{ 128 | "request_url": k, 129 | "method": kk, 130 | "times": vv.RequestNum, 131 | "total_time": toS(vv.TotalTime), 132 | "max_time": toS(vv.MaxTime), 133 | "min_time": toS(vv.MinTime), 134 | "avg_time": toS(time.Duration(int64(vv.TotalTime) / vv.RequestNum)), 135 | } 136 | resultLists = append(resultLists, result) 137 | } 138 | } 139 | return resultLists 140 | } 141 | 142 | // StatisticsMap hosld global statistics data map 143 | var StatisticsMap *URLMap 144 | 145 | func init() { 146 | StatisticsMap = &URLMap{ 147 | urlmap: make(map[string]map[string]*Statistics), 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/utils/caller.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package utils 16 | 17 | import ( 18 | "reflect" 19 | "runtime" 20 | ) 21 | 22 | // GetFuncName get function name 23 | func GetFuncName(i interface{}) string { 24 | return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/utils/file.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package utils 16 | 17 | import ( 18 | "bufio" 19 | "errors" 20 | "io" 21 | "os" 22 | "path/filepath" 23 | "regexp" 24 | ) 25 | 26 | // SelfPath gets compiled executable file absolute path 27 | func SelfPath() string { 28 | path, _ := filepath.Abs(os.Args[0]) 29 | return path 30 | } 31 | 32 | // SelfDir gets compiled executable file directory 33 | func SelfDir() string { 34 | return filepath.Dir(SelfPath()) 35 | } 36 | 37 | // FileExists reports whether the named file or directory exists. 38 | func FileExists(name string) bool { 39 | if _, err := os.Stat(name); err != nil { 40 | if os.IsNotExist(err) { 41 | return false 42 | } 43 | } 44 | return true 45 | } 46 | 47 | // SearchFile Search a file in paths. 48 | // this is often used in search config file in /etc ~/ 49 | func SearchFile(filename string, paths ...string) (fullpath string, err error) { 50 | for _, path := range paths { 51 | if fullpath = filepath.Join(path, filename); FileExists(fullpath) { 52 | return 53 | } 54 | } 55 | err = errors.New(fullpath + " not found in paths") 56 | return 57 | } 58 | 59 | // GrepFile like command grep -E 60 | // for example: GrepFile(`^hello`, "hello.txt") 61 | // \n is striped while read 62 | func GrepFile(patten string, filename string) (lines []string, err error) { 63 | re, err := regexp.Compile(patten) 64 | if err != nil { 65 | return 66 | } 67 | 68 | fd, err := os.Open(filename) 69 | if err != nil { 70 | return 71 | } 72 | lines = make([]string, 0) 73 | reader := bufio.NewReader(fd) 74 | prefix := "" 75 | var isLongLine bool 76 | for { 77 | byteLine, isPrefix, er := reader.ReadLine() 78 | if er != nil && er != io.EOF { 79 | return nil, er 80 | } 81 | if er == io.EOF { 82 | break 83 | } 84 | line := string(byteLine) 85 | if isPrefix { 86 | prefix += line 87 | continue 88 | } else { 89 | isLongLine = true 90 | } 91 | 92 | line = prefix + line 93 | if isLongLine { 94 | prefix = "" 95 | } 96 | if re.MatchString(line) { 97 | lines = append(lines, line) 98 | } 99 | } 100 | return lines, nil 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/utils/rand.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package utils 16 | 17 | import ( 18 | "crypto/rand" 19 | r "math/rand" 20 | "time" 21 | ) 22 | 23 | var alphaNum = []byte(`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`) 24 | 25 | // RandomCreateBytes generate random []byte by specify chars. 26 | func RandomCreateBytes(n int, alphabets ...byte) []byte { 27 | if len(alphabets) == 0 { 28 | alphabets = alphaNum 29 | } 30 | var bytes = make([]byte, n) 31 | var randBy bool 32 | if num, err := rand.Read(bytes); num != n || err != nil { 33 | r.Seed(time.Now().UnixNano()) 34 | randBy = true 35 | } 36 | for i, b := range bytes { 37 | if randBy { 38 | bytes[i] = alphabets[r.Intn(len(alphabets))] 39 | } else { 40 | bytes[i] = alphabets[b%byte(len(alphabets))] 41 | } 42 | } 43 | return bytes 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/utils/safemap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package utils 16 | 17 | import ( 18 | "sync" 19 | ) 20 | 21 | // BeeMap is a map with lock 22 | type BeeMap struct { 23 | lock *sync.RWMutex 24 | bm map[interface{}]interface{} 25 | } 26 | 27 | // NewBeeMap return new safemap 28 | func NewBeeMap() *BeeMap { 29 | return &BeeMap{ 30 | lock: new(sync.RWMutex), 31 | bm: make(map[interface{}]interface{}), 32 | } 33 | } 34 | 35 | // Get from maps return the k's value 36 | func (m *BeeMap) Get(k interface{}) interface{} { 37 | m.lock.RLock() 38 | defer m.lock.RUnlock() 39 | if val, ok := m.bm[k]; ok { 40 | return val 41 | } 42 | return nil 43 | } 44 | 45 | // Set Maps the given key and value. Returns false 46 | // if the key is already in the map and changes nothing. 47 | func (m *BeeMap) Set(k interface{}, v interface{}) bool { 48 | m.lock.Lock() 49 | defer m.lock.Unlock() 50 | if val, ok := m.bm[k]; !ok { 51 | m.bm[k] = v 52 | } else if val != v { 53 | m.bm[k] = v 54 | } else { 55 | return false 56 | } 57 | return true 58 | } 59 | 60 | // Check Returns true if k is exist in the map. 61 | func (m *BeeMap) Check(k interface{}) bool { 62 | m.lock.RLock() 63 | defer m.lock.RUnlock() 64 | _, ok := m.bm[k] 65 | return ok 66 | } 67 | 68 | // Delete the given key and value. 69 | func (m *BeeMap) Delete(k interface{}) { 70 | m.lock.Lock() 71 | defer m.lock.Unlock() 72 | delete(m.bm, k) 73 | } 74 | 75 | // Items returns all items in safemap. 76 | func (m *BeeMap) Items() map[interface{}]interface{} { 77 | m.lock.RLock() 78 | defer m.lock.RUnlock() 79 | r := make(map[interface{}]interface{}) 80 | for k, v := range m.bm { 81 | r[k] = v 82 | } 83 | return r 84 | } 85 | 86 | // Count returns the number of items within the map. 87 | func (m *BeeMap) Count() int { 88 | m.lock.RLock() 89 | defer m.lock.RUnlock() 90 | return len(m.bm) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/utils/slice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 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 | package utils 16 | 17 | import ( 18 | "math/rand" 19 | "time" 20 | ) 21 | 22 | type reducetype func(interface{}) interface{} 23 | type filtertype func(interface{}) bool 24 | 25 | // InSlice checks given string in string slice or not. 26 | func InSlice(v string, sl []string) bool { 27 | for _, vv := range sl { 28 | if vv == v { 29 | return true 30 | } 31 | } 32 | return false 33 | } 34 | 35 | // InSliceIface checks given interface in interface slice. 36 | func InSliceIface(v interface{}, sl []interface{}) bool { 37 | for _, vv := range sl { 38 | if vv == v { 39 | return true 40 | } 41 | } 42 | return false 43 | } 44 | 45 | // SliceRandList generate an int slice from min to max. 46 | func SliceRandList(min, max int) []int { 47 | if max < min { 48 | min, max = max, min 49 | } 50 | length := max - min + 1 51 | t0 := time.Now() 52 | rand.Seed(int64(t0.Nanosecond())) 53 | list := rand.Perm(length) 54 | for index := range list { 55 | list[index] += min 56 | } 57 | return list 58 | } 59 | 60 | // SliceMerge merges interface slices to one slice. 61 | func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) { 62 | c = append(slice1, slice2...) 63 | return 64 | } 65 | 66 | // SliceReduce generates a new slice after parsing every value by reduce function 67 | func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) { 68 | for _, v := range slice { 69 | dslice = append(dslice, a(v)) 70 | } 71 | return 72 | } 73 | 74 | // SliceRand returns random one from slice. 75 | func SliceRand(a []interface{}) (b interface{}) { 76 | randnum := rand.Intn(len(a)) 77 | b = a[randnum] 78 | return 79 | } 80 | 81 | // SliceSum sums all values in int64 slice. 82 | func SliceSum(intslice []int64) (sum int64) { 83 | for _, v := range intslice { 84 | sum += v 85 | } 86 | return 87 | } 88 | 89 | // SliceFilter generates a new slice after filter function. 90 | func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) { 91 | for _, v := range slice { 92 | if a(v) { 93 | ftslice = append(ftslice, v) 94 | } 95 | } 96 | return 97 | } 98 | 99 | // SliceDiff returns diff slice of slice1 - slice2. 100 | func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) { 101 | for _, v := range slice1 { 102 | if !InSliceIface(v, slice2) { 103 | diffslice = append(diffslice, v) 104 | } 105 | } 106 | return 107 | } 108 | 109 | // SliceIntersect returns slice that are present in all the slice1 and slice2. 110 | func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) { 111 | for _, v := range slice1 { 112 | if InSliceIface(v, slice2) { 113 | diffslice = append(diffslice, v) 114 | } 115 | } 116 | return 117 | } 118 | 119 | // SliceChunk separates one slice to some sized slice. 120 | func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) { 121 | if size >= len(slice) { 122 | chunkslice = append(chunkslice, slice) 123 | return 124 | } 125 | end := size 126 | for i := 0; i <= (len(slice) - size); i += size { 127 | chunkslice = append(chunkslice, slice[i:end]) 128 | end += size 129 | } 130 | return 131 | } 132 | 133 | // SliceRange generates a new slice from begin to end with step duration of int64 number. 134 | func SliceRange(start, end, step int64) (intslice []int64) { 135 | for i := start; i <= end; i += step { 136 | intslice = append(intslice, i) 137 | } 138 | return 139 | } 140 | 141 | // SlicePad prepends size number of val into slice. 142 | func SlicePad(slice []interface{}, size int, val interface{}) []interface{} { 143 | if size <= len(slice) { 144 | return slice 145 | } 146 | for i := 0; i < (size - len(slice)); i++ { 147 | slice = append(slice, val) 148 | } 149 | return slice 150 | } 151 | 152 | // SliceUnique cleans repeated values in slice. 153 | func SliceUnique(slice []interface{}) (uniqueslice []interface{}) { 154 | for _, v := range slice { 155 | if !InSliceIface(v, uniqueslice) { 156 | uniqueslice = append(uniqueslice, v) 157 | } 158 | } 159 | return 160 | } 161 | 162 | // SliceShuffle shuffles a slice. 163 | func SliceShuffle(slice []interface{}) []interface{} { 164 | for i := 0; i < len(slice); i++ { 165 | a := rand.Intn(len(slice)) 166 | b := rand.Intn(len(slice)) 167 | slice[a], slice[b] = slice[b], slice[a] 168 | } 169 | return slice 170 | } 171 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | // GetGOPATHs returns all paths in GOPATH variable. 11 | func GetGOPATHs() []string { 12 | gopath := os.Getenv("GOPATH") 13 | if gopath == "" && strings.Compare(runtime.Version(), "go1.8") >= 0 { 14 | gopath = defaultGOPATH() 15 | } 16 | return filepath.SplitList(gopath) 17 | } 18 | 19 | func defaultGOPATH() string { 20 | env := "HOME" 21 | if runtime.GOOS == "windows" { 22 | env = "USERPROFILE" 23 | } else if runtime.GOOS == "plan9" { 24 | env = "home" 25 | } 26 | if home := os.Getenv(env); home != "" { 27 | return filepath.Join(home, "go") 28 | } 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.gitignore: -------------------------------------------------------------------------------- 1 | .db 2 | *.test 3 | *~ 4 | *.swp 5 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | client_configure() { 6 | sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key 7 | } 8 | 9 | pgdg_repository() { 10 | local sourcelist='sources.list.d/postgresql.list' 11 | 12 | curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo apt-key add - 13 | echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist" 14 | sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update 15 | } 16 | 17 | postgresql_configure() { 18 | sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null <<-config 19 | local all all trust 20 | hostnossl all pqgossltest 127.0.0.1/32 reject 21 | hostnossl all pqgosslcert 127.0.0.1/32 reject 22 | hostssl all pqgossltest 127.0.0.1/32 trust 23 | hostssl all pqgosslcert 127.0.0.1/32 cert 24 | host all all 127.0.0.1/32 trust 25 | hostnossl all pqgossltest ::1/128 reject 26 | hostnossl all pqgosslcert ::1/128 reject 27 | hostssl all pqgossltest ::1/128 trust 28 | hostssl all pqgosslcert ::1/128 cert 29 | host all all ::1/128 trust 30 | config 31 | 32 | xargs sudo install -o postgres -g postgres -m 600 -t /var/lib/postgresql/$PGVERSION/main/ <<-certificates 33 | certs/root.crt 34 | certs/server.crt 35 | certs/server.key 36 | certificates 37 | 38 | sort -VCu <<-versions || 39 | $PGVERSION 40 | 9.2 41 | versions 42 | sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null <<-config 43 | ssl_ca_file = 'root.crt' 44 | ssl_cert_file = 'server.crt' 45 | ssl_key_file = 'server.key' 46 | config 47 | 48 | echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null 49 | 50 | sudo service postgresql restart 51 | } 52 | 53 | postgresql_install() { 54 | xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages 55 | postgresql-$PGVERSION 56 | postgresql-server-dev-$PGVERSION 57 | postgresql-contrib-$PGVERSION 58 | packages 59 | } 60 | 61 | postgresql_uninstall() { 62 | sudo service postgresql stop 63 | xargs sudo apt-get -y --purge remove <<-packages 64 | libpq-dev 65 | libpq5 66 | postgresql 67 | postgresql-client-common 68 | postgresql-common 69 | packages 70 | sudo rm -rf /var/lib/postgresql 71 | } 72 | 73 | megacheck_install() { 74 | # Megacheck is Go 1.6+, so skip if Go 1.5. 75 | if [[ "$(go version)" =~ "go1.5" ]] 76 | then 77 | echo "megacheck not supported, skipping installation" 78 | return 0 79 | fi 80 | # Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous 81 | # new error messages in old code. 82 | go get -d honnef.co/go/tools/... 83 | git -C $GOPATH/src/honnef.co/go/tools/ checkout $MEGACHECK_VERSION 84 | go install honnef.co/go/tools/cmd/megacheck 85 | megacheck --version 86 | } 87 | 88 | golint_install() { 89 | # Golint is Go 1.6+, so skip if Go 1.5. 90 | if [[ "$(go version)" =~ "go1.5" ]] 91 | then 92 | echo "golint not supported, skipping installation" 93 | return 0 94 | fi 95 | go get github.com/golang/lint/golint 96 | } 97 | 98 | $1 99 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.5.x 5 | - 1.6.x 6 | - 1.7.x 7 | - 1.8.x 8 | - 1.9.x 9 | - master 10 | 11 | sudo: true 12 | 13 | env: 14 | global: 15 | - PGUSER=postgres 16 | - PQGOSSLTESTS=1 17 | - PQSSLCERTTEST_PATH=$PWD/certs 18 | - PGHOST=127.0.0.1 19 | - MEGACHECK_VERSION=2017.2.1 20 | matrix: 21 | - PGVERSION=10 22 | - PGVERSION=9.6 23 | - PGVERSION=9.5 24 | - PGVERSION=9.4 25 | - PGVERSION=9.3 26 | - PGVERSION=9.2 27 | - PGVERSION=9.1 28 | - PGVERSION=9.0 29 | 30 | before_install: 31 | - ./.travis.sh postgresql_uninstall 32 | - ./.travis.sh pgdg_repository 33 | - ./.travis.sh postgresql_install 34 | - ./.travis.sh postgresql_configure 35 | - ./.travis.sh client_configure 36 | - ./.travis.sh megacheck_install 37 | - ./.travis.sh golint_install 38 | - go get golang.org/x/tools/cmd/goimports 39 | 40 | before_script: 41 | - createdb pqgotest 42 | - createuser -DRS pqgossltest 43 | - createuser -DRS pqgosslcert 44 | 45 | script: 46 | - > 47 | goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' 48 | - go vet ./... 49 | # For compatibility with Go 1.5, launch only if megacheck is present. 50 | - > 51 | which megacheck > /dev/null && megacheck -go 1.5 ./... 52 | || echo 'megacheck is not supported, skipping check' 53 | # For compatibility with Go 1.5, launch only if golint is present. 54 | - > 55 | which golint > /dev/null && golint ./... 56 | || echo 'golint is not supported, skipping check' 57 | - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... 58 | - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... 59 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to pq 2 | 3 | `pq` has a backlog of pull requests, but contributions are still very 4 | much welcome. You can help with patch review, submitting bug reports, 5 | or adding new functionality. There is no formal style guide, but 6 | please conform to the style of existing code and general Go formatting 7 | conventions when submitting patches. 8 | 9 | ### Patch review 10 | 11 | Help review existing open pull requests by commenting on the code or 12 | proposed functionality. 13 | 14 | ### Bug reports 15 | 16 | We appreciate any bug reports, but especially ones with self-contained 17 | (doesn't depend on code outside of pq), minimal (can't be simplified 18 | further) test cases. It's especially helpful if you can submit a pull 19 | request with just the failing test case (you'll probably want to 20 | pattern it after the tests in 21 | [conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). 22 | 23 | ### New functionality 24 | 25 | There are a number of pending patches for new functionality, so 26 | additional feature patches will take a while to merge. Still, patches 27 | are generally reviewed based on usefulness and complexity in addition 28 | to time-in-queue, so if you have a knockout idea, take a shot. Feel 29 | free to open an issue discussion your proposed patch beforehand. 30 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2013, 'pq' Contributors 2 | Portions Copyright (C) 2011 Blake Mizerany 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/README.md: -------------------------------------------------------------------------------- 1 | # pq - A pure Go postgres driver for Go's database/sql package 2 | 3 | [![GoDoc](https://godoc.org/github.com/lib/pq?status.svg)](https://godoc.org/github.com/lib/pq) 4 | [![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq) 5 | 6 | ## Install 7 | 8 | go get github.com/lib/pq 9 | 10 | ## Docs 11 | 12 | For detailed documentation and basic usage examples, please see the package 13 | documentation at . 14 | 15 | ## Tests 16 | 17 | `go test` is used for testing. A running PostgreSQL server is 18 | required, with the ability to log in. The default database to connect 19 | to test with is "pqgotest," but it can be overridden using environment 20 | variables. 21 | 22 | Example: 23 | 24 | PGHOST=/run/postgresql go test github.com/lib/pq 25 | 26 | Optionally, a benchmark suite can be run as part of the tests: 27 | 28 | PGHOST=/run/postgresql go test -bench . 29 | 30 | ## Features 31 | 32 | * SSL 33 | * Handles bad connections for `database/sql` 34 | * Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) 35 | * Scan binary blobs correctly (i.e. `bytea`) 36 | * Package for `hstore` support 37 | * COPY FROM support 38 | * pq.ParseURL for converting urls to connection strings for sql.Open. 39 | * Many libpq compatible environment variables 40 | * Unix socket support 41 | * Notifications: `LISTEN`/`NOTIFY` 42 | * pgpass support 43 | 44 | ## Future / Things you can help with 45 | 46 | * Better COPY FROM / COPY TO (see discussion in #181) 47 | 48 | ## Thank you (alphabetical) 49 | 50 | Some of these contributors are from the original library `bmizerany/pq.go` whose 51 | code still exists in here. 52 | 53 | * Andy Balholm (andybalholm) 54 | * Ben Berkert (benburkert) 55 | * Benjamin Heatwole (bheatwole) 56 | * Bill Mill (llimllib) 57 | * Bjørn Madsen (aeons) 58 | * Blake Gentry (bgentry) 59 | * Brad Fitzpatrick (bradfitz) 60 | * Charlie Melbye (cmelbye) 61 | * Chris Bandy (cbandy) 62 | * Chris Gilling (cgilling) 63 | * Chris Walsh (cwds) 64 | * Dan Sosedoff (sosedoff) 65 | * Daniel Farina (fdr) 66 | * Eric Chlebek (echlebek) 67 | * Eric Garrido (minusnine) 68 | * Eric Urban (hydrogen18) 69 | * Everyone at The Go Team 70 | * Evan Shaw (edsrzf) 71 | * Ewan Chou (coocood) 72 | * Fazal Majid (fazalmajid) 73 | * Federico Romero (federomero) 74 | * Fumin (fumin) 75 | * Gary Burd (garyburd) 76 | * Heroku (heroku) 77 | * James Pozdena (jpoz) 78 | * Jason McVetta (jmcvetta) 79 | * Jeremy Jay (pbnjay) 80 | * Joakim Sernbrant (serbaut) 81 | * John Gallagher (jgallagher) 82 | * Jonathan Rudenberg (titanous) 83 | * Joël Stemmer (jstemmer) 84 | * Kamil Kisiel (kisielk) 85 | * Kelly Dunn (kellydunn) 86 | * Keith Rarick (kr) 87 | * Kir Shatrov (kirs) 88 | * Lann Martin (lann) 89 | * Maciek Sakrejda (uhoh-itsmaciek) 90 | * Marc Brinkmann (mbr) 91 | * Marko Tiikkaja (johto) 92 | * Matt Newberry (MattNewberry) 93 | * Matt Robenolt (mattrobenolt) 94 | * Martin Olsen (martinolsen) 95 | * Mike Lewis (mikelikespie) 96 | * Nicolas Patry (Narsil) 97 | * Oliver Tonnhofer (olt) 98 | * Patrick Hayes (phayes) 99 | * Paul Hammond (paulhammond) 100 | * Ryan Smith (ryandotsmith) 101 | * Samuel Stauffer (samuel) 102 | * Timothée Peignier (cyberdelia) 103 | * Travis Cline (tmc) 104 | * TruongSinh Tran-Nguyen (truongsinh) 105 | * Yaismel Miranda (ympons) 106 | * notedit (notedit) 107 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/buf.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | 7 | "github.com/lib/pq/oid" 8 | ) 9 | 10 | type readBuf []byte 11 | 12 | func (b *readBuf) int32() (n int) { 13 | n = int(int32(binary.BigEndian.Uint32(*b))) 14 | *b = (*b)[4:] 15 | return 16 | } 17 | 18 | func (b *readBuf) oid() (n oid.Oid) { 19 | n = oid.Oid(binary.BigEndian.Uint32(*b)) 20 | *b = (*b)[4:] 21 | return 22 | } 23 | 24 | // N.B: this is actually an unsigned 16-bit integer, unlike int32 25 | func (b *readBuf) int16() (n int) { 26 | n = int(binary.BigEndian.Uint16(*b)) 27 | *b = (*b)[2:] 28 | return 29 | } 30 | 31 | func (b *readBuf) string() string { 32 | i := bytes.IndexByte(*b, 0) 33 | if i < 0 { 34 | errorf("invalid message format; expected string terminator") 35 | } 36 | s := (*b)[:i] 37 | *b = (*b)[i+1:] 38 | return string(s) 39 | } 40 | 41 | func (b *readBuf) next(n int) (v []byte) { 42 | v = (*b)[:n] 43 | *b = (*b)[n:] 44 | return 45 | } 46 | 47 | func (b *readBuf) byte() byte { 48 | return b.next(1)[0] 49 | } 50 | 51 | type writeBuf struct { 52 | buf []byte 53 | pos int 54 | } 55 | 56 | func (b *writeBuf) int32(n int) { 57 | x := make([]byte, 4) 58 | binary.BigEndian.PutUint32(x, uint32(n)) 59 | b.buf = append(b.buf, x...) 60 | } 61 | 62 | func (b *writeBuf) int16(n int) { 63 | x := make([]byte, 2) 64 | binary.BigEndian.PutUint16(x, uint16(n)) 65 | b.buf = append(b.buf, x...) 66 | } 67 | 68 | func (b *writeBuf) string(s string) { 69 | b.buf = append(b.buf, (s + "\000")...) 70 | } 71 | 72 | func (b *writeBuf) byte(c byte) { 73 | b.buf = append(b.buf, c) 74 | } 75 | 76 | func (b *writeBuf) bytes(v []byte) { 77 | b.buf = append(b.buf, v...) 78 | } 79 | 80 | func (b *writeBuf) wrap() []byte { 81 | p := b.buf[b.pos:] 82 | binary.BigEndian.PutUint32(p, uint32(len(p))) 83 | return b.buf 84 | } 85 | 86 | func (b *writeBuf) next(c byte) { 87 | p := b.buf[b.pos:] 88 | binary.BigEndian.PutUint32(p, uint32(len(p))) 89 | b.pos = len(b.buf) + 1 90 | b.buf = append(b.buf, c, 0, 0, 0, 0) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/conn_go18.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package pq 4 | 5 | import ( 6 | "context" 7 | "database/sql" 8 | "database/sql/driver" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | ) 13 | 14 | // Implement the "QueryerContext" interface 15 | func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 16 | list := make([]driver.Value, len(args)) 17 | for i, nv := range args { 18 | list[i] = nv.Value 19 | } 20 | finish := cn.watchCancel(ctx) 21 | r, err := cn.query(query, list) 22 | if err != nil { 23 | if finish != nil { 24 | finish() 25 | } 26 | return nil, err 27 | } 28 | r.finish = finish 29 | return r, nil 30 | } 31 | 32 | // Implement the "ExecerContext" interface 33 | func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 34 | list := make([]driver.Value, len(args)) 35 | for i, nv := range args { 36 | list[i] = nv.Value 37 | } 38 | 39 | if finish := cn.watchCancel(ctx); finish != nil { 40 | defer finish() 41 | } 42 | 43 | return cn.Exec(query, list) 44 | } 45 | 46 | // Implement the "ConnBeginTx" interface 47 | func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 48 | var mode string 49 | 50 | switch sql.IsolationLevel(opts.Isolation) { 51 | case sql.LevelDefault: 52 | // Don't touch mode: use the server's default 53 | case sql.LevelReadUncommitted: 54 | mode = " ISOLATION LEVEL READ UNCOMMITTED" 55 | case sql.LevelReadCommitted: 56 | mode = " ISOLATION LEVEL READ COMMITTED" 57 | case sql.LevelRepeatableRead: 58 | mode = " ISOLATION LEVEL REPEATABLE READ" 59 | case sql.LevelSerializable: 60 | mode = " ISOLATION LEVEL SERIALIZABLE" 61 | default: 62 | return nil, fmt.Errorf("pq: isolation level not supported: %d", opts.Isolation) 63 | } 64 | 65 | if opts.ReadOnly { 66 | mode += " READ ONLY" 67 | } else { 68 | mode += " READ WRITE" 69 | } 70 | 71 | tx, err := cn.begin(mode) 72 | if err != nil { 73 | return nil, err 74 | } 75 | cn.txnFinish = cn.watchCancel(ctx) 76 | return tx, nil 77 | } 78 | 79 | func (cn *conn) watchCancel(ctx context.Context) func() { 80 | if done := ctx.Done(); done != nil { 81 | finished := make(chan struct{}) 82 | go func() { 83 | select { 84 | case <-done: 85 | _ = cn.cancel() 86 | finished <- struct{}{} 87 | case <-finished: 88 | } 89 | }() 90 | return func() { 91 | select { 92 | case <-finished: 93 | case finished <- struct{}{}: 94 | } 95 | } 96 | } 97 | return nil 98 | } 99 | 100 | func (cn *conn) cancel() error { 101 | c, err := dial(cn.dialer, cn.opts) 102 | if err != nil { 103 | return err 104 | } 105 | defer c.Close() 106 | 107 | { 108 | can := conn{ 109 | c: c, 110 | } 111 | can.ssl(cn.opts) 112 | 113 | w := can.writeBuf(0) 114 | w.int32(80877102) // cancel request code 115 | w.int32(cn.processID) 116 | w.int32(cn.secretKey) 117 | 118 | if err := can.sendStartupPacket(w); err != nil { 119 | return err 120 | } 121 | } 122 | 123 | // Read until EOF to ensure that the server received the cancel. 124 | { 125 | _, err := io.Copy(ioutil.Discard, c) 126 | return err 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/doc.go: -------------------------------------------------------------------------------- 1 | // Package oid contains OID constants 2 | // as defined by the Postgres server. 3 | package oid 4 | 5 | // Oid is a Postgres Object ID. 6 | type Oid uint32 7 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Generate the table of OID values 4 | // Run with 'go run gen.go'. 5 | package main 6 | 7 | import ( 8 | "database/sql" 9 | "fmt" 10 | "log" 11 | "os" 12 | "os/exec" 13 | "strings" 14 | 15 | _ "github.com/lib/pq" 16 | ) 17 | 18 | // OID represent a postgres Object Identifier Type. 19 | type OID struct { 20 | ID int 21 | Type string 22 | } 23 | 24 | // Name returns an upper case version of the oid type. 25 | func (o OID) Name() string { 26 | return strings.ToUpper(o.Type) 27 | } 28 | 29 | func main() { 30 | datname := os.Getenv("PGDATABASE") 31 | sslmode := os.Getenv("PGSSLMODE") 32 | 33 | if datname == "" { 34 | os.Setenv("PGDATABASE", "pqgotest") 35 | } 36 | 37 | if sslmode == "" { 38 | os.Setenv("PGSSLMODE", "disable") 39 | } 40 | 41 | db, err := sql.Open("postgres", "") 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | rows, err := db.Query(` 46 | SELECT typname, oid 47 | FROM pg_type WHERE oid < 10000 48 | ORDER BY oid; 49 | `) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | oids := make([]*OID, 0) 54 | for rows.Next() { 55 | var oid OID 56 | if err = rows.Scan(&oid.Type, &oid.ID); err != nil { 57 | log.Fatal(err) 58 | } 59 | oids = append(oids, &oid) 60 | } 61 | if err = rows.Err(); err != nil { 62 | log.Fatal(err) 63 | } 64 | cmd := exec.Command("gofmt") 65 | cmd.Stderr = os.Stderr 66 | w, err := cmd.StdinPipe() 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | f, err := os.Create("types.go") 71 | if err != nil { 72 | log.Fatal(err) 73 | } 74 | cmd.Stdout = f 75 | err = cmd.Start() 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.") 80 | fmt.Fprintln(w, "\npackage oid") 81 | fmt.Fprintln(w, "const (") 82 | for _, oid := range oids { 83 | fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID) 84 | } 85 | fmt.Fprintln(w, ")") 86 | fmt.Fprintln(w, "var TypeName = map[Oid]string{") 87 | for _, oid := range oids { 88 | fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name()) 89 | } 90 | fmt.Fprintln(w, "}") 91 | w.Close() 92 | cmd.Wait() 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/rows.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "math" 5 | "reflect" 6 | "time" 7 | 8 | "github.com/lib/pq/oid" 9 | ) 10 | 11 | const headerSize = 4 12 | 13 | type fieldDesc struct { 14 | // The object ID of the data type. 15 | OID oid.Oid 16 | // The data type size (see pg_type.typlen). 17 | // Note that negative values denote variable-width types. 18 | Len int 19 | // The type modifier (see pg_attribute.atttypmod). 20 | // The meaning of the modifier is type-specific. 21 | Mod int 22 | } 23 | 24 | func (fd fieldDesc) Type() reflect.Type { 25 | switch fd.OID { 26 | case oid.T_int8: 27 | return reflect.TypeOf(int64(0)) 28 | case oid.T_int4: 29 | return reflect.TypeOf(int32(0)) 30 | case oid.T_int2: 31 | return reflect.TypeOf(int16(0)) 32 | case oid.T_varchar, oid.T_text: 33 | return reflect.TypeOf("") 34 | case oid.T_bool: 35 | return reflect.TypeOf(false) 36 | case oid.T_date, oid.T_time, oid.T_timetz, oid.T_timestamp, oid.T_timestamptz: 37 | return reflect.TypeOf(time.Time{}) 38 | case oid.T_bytea: 39 | return reflect.TypeOf([]byte(nil)) 40 | default: 41 | return reflect.TypeOf(new(interface{})).Elem() 42 | } 43 | } 44 | 45 | func (fd fieldDesc) Name() string { 46 | return oid.TypeName[fd.OID] 47 | } 48 | 49 | func (fd fieldDesc) Length() (length int64, ok bool) { 50 | switch fd.OID { 51 | case oid.T_text, oid.T_bytea: 52 | return math.MaxInt64, true 53 | case oid.T_varchar, oid.T_bpchar: 54 | return int64(fd.Mod - headerSize), true 55 | default: 56 | return 0, false 57 | } 58 | } 59 | 60 | func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) { 61 | switch fd.OID { 62 | case oid.T_numeric, oid.T__numeric: 63 | mod := fd.Mod - headerSize 64 | precision = int64((mod >> 16) & 0xffff) 65 | scale = int64(mod & 0xffff) 66 | return precision, scale, true 67 | default: 68 | return 0, 0, false 69 | } 70 | } 71 | 72 | // ColumnTypeScanType returns the value type that can be used to scan types into. 73 | func (rs *rows) ColumnTypeScanType(index int) reflect.Type { 74 | return rs.colTyps[index].Type() 75 | } 76 | 77 | // ColumnTypeDatabaseTypeName return the database system type name. 78 | func (rs *rows) ColumnTypeDatabaseTypeName(index int) string { 79 | return rs.colTyps[index].Name() 80 | } 81 | 82 | // ColumnTypeLength returns the length of the column type if the column is a 83 | // variable length type. If the column is not a variable length type ok 84 | // should return false. 85 | func (rs *rows) ColumnTypeLength(index int) (length int64, ok bool) { 86 | return rs.colTyps[index].Length() 87 | } 88 | 89 | // ColumnTypePrecisionScale should return the precision and scale for decimal 90 | // types. If not applicable, ok should be false. 91 | func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) { 92 | return rs.colTyps[index].PrecisionScale() 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io/ioutil" 7 | "net" 8 | "os" 9 | "os/user" 10 | "path/filepath" 11 | ) 12 | 13 | // ssl generates a function to upgrade a net.Conn based on the "sslmode" and 14 | // related settings. The function is nil when no upgrade should take place. 15 | func ssl(o values) func(net.Conn) net.Conn { 16 | verifyCaOnly := false 17 | tlsConf := tls.Config{} 18 | switch mode := o["sslmode"]; mode { 19 | // "require" is the default. 20 | case "", "require": 21 | // We must skip TLS's own verification since it requires full 22 | // verification since Go 1.3. 23 | tlsConf.InsecureSkipVerify = true 24 | 25 | // From http://www.postgresql.org/docs/current/static/libpq-ssl.html: 26 | // 27 | // Note: For backwards compatibility with earlier versions of 28 | // PostgreSQL, if a root CA file exists, the behavior of 29 | // sslmode=require will be the same as that of verify-ca, meaning the 30 | // server certificate is validated against the CA. Relying on this 31 | // behavior is discouraged, and applications that need certificate 32 | // validation should always use verify-ca or verify-full. 33 | if sslrootcert, ok := o["sslrootcert"]; ok { 34 | if _, err := os.Stat(sslrootcert); err == nil { 35 | verifyCaOnly = true 36 | } else { 37 | delete(o, "sslrootcert") 38 | } 39 | } 40 | case "verify-ca": 41 | // We must skip TLS's own verification since it requires full 42 | // verification since Go 1.3. 43 | tlsConf.InsecureSkipVerify = true 44 | verifyCaOnly = true 45 | case "verify-full": 46 | tlsConf.ServerName = o["host"] 47 | case "disable": 48 | return nil 49 | default: 50 | errorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) 51 | } 52 | 53 | sslClientCertificates(&tlsConf, o) 54 | sslCertificateAuthority(&tlsConf, o) 55 | sslRenegotiation(&tlsConf) 56 | 57 | return func(conn net.Conn) net.Conn { 58 | client := tls.Client(conn, &tlsConf) 59 | if verifyCaOnly { 60 | sslVerifyCertificateAuthority(client, &tlsConf) 61 | } 62 | return client 63 | } 64 | } 65 | 66 | // sslClientCertificates adds the certificate specified in the "sslcert" and 67 | // "sslkey" settings, or if they aren't set, from the .postgresql directory 68 | // in the user's home directory. The configured files must exist and have 69 | // the correct permissions. 70 | func sslClientCertificates(tlsConf *tls.Config, o values) { 71 | // user.Current() might fail when cross-compiling. We have to ignore the 72 | // error and continue without home directory defaults, since we wouldn't 73 | // know from where to load them. 74 | user, _ := user.Current() 75 | 76 | // In libpq, the client certificate is only loaded if the setting is not blank. 77 | // 78 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1036-L1037 79 | sslcert := o["sslcert"] 80 | if len(sslcert) == 0 && user != nil { 81 | sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt") 82 | } 83 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045 84 | if len(sslcert) == 0 { 85 | return 86 | } 87 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054 88 | if _, err := os.Stat(sslcert); os.IsNotExist(err) { 89 | return 90 | } else if err != nil { 91 | panic(err) 92 | } 93 | 94 | // In libpq, the ssl key is only loaded if the setting is not blank. 95 | // 96 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1123-L1222 97 | sslkey := o["sslkey"] 98 | if len(sslkey) == 0 && user != nil { 99 | sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key") 100 | } 101 | 102 | if len(sslkey) > 0 { 103 | if err := sslKeyPermissions(sslkey); err != nil { 104 | panic(err) 105 | } 106 | } 107 | 108 | cert, err := tls.LoadX509KeyPair(sslcert, sslkey) 109 | if err != nil { 110 | panic(err) 111 | } 112 | tlsConf.Certificates = []tls.Certificate{cert} 113 | } 114 | 115 | // sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting. 116 | func sslCertificateAuthority(tlsConf *tls.Config, o values) { 117 | // In libpq, the root certificate is only loaded if the setting is not blank. 118 | // 119 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951 120 | if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 { 121 | tlsConf.RootCAs = x509.NewCertPool() 122 | 123 | cert, err := ioutil.ReadFile(sslrootcert) 124 | if err != nil { 125 | panic(err) 126 | } 127 | 128 | if !tlsConf.RootCAs.AppendCertsFromPEM(cert) { 129 | errorf("couldn't parse pem in sslrootcert") 130 | } 131 | } 132 | } 133 | 134 | // sslVerifyCertificateAuthority carries out a TLS handshake to the server and 135 | // verifies the presented certificate against the CA, i.e. the one specified in 136 | // sslrootcert or the system CA if sslrootcert was not specified. 137 | func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) { 138 | err := client.Handshake() 139 | if err != nil { 140 | panic(err) 141 | } 142 | certs := client.ConnectionState().PeerCertificates 143 | opts := x509.VerifyOptions{ 144 | DNSName: client.ConnectionState().ServerName, 145 | Intermediates: x509.NewCertPool(), 146 | Roots: tlsConf.RootCAs, 147 | } 148 | for i, cert := range certs { 149 | if i == 0 { 150 | continue 151 | } 152 | opts.Intermediates.AddCert(cert) 153 | } 154 | _, err = certs[0].Verify(opts) 155 | if err != nil { 156 | panic(err) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_go1.7.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package pq 4 | 5 | import "crypto/tls" 6 | 7 | // Accept renegotiation requests initiated by the backend. 8 | // 9 | // Renegotiation was deprecated then removed from PostgreSQL 9.5, but 10 | // the default configuration of older versions has it enabled. Redshift 11 | // also initiates renegotiations and cannot be reconfigured. 12 | func sslRenegotiation(conf *tls.Config) { 13 | conf.Renegotiation = tls.RenegotiateFreelyAsClient 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_permissions.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package pq 4 | 5 | import "os" 6 | 7 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 8 | // The key file should have very little access. 9 | // 10 | // libpq does not check key file permissions on Windows. 11 | func sslKeyPermissions(sslkey string) error { 12 | info, err := os.Stat(sslkey) 13 | if err != nil { 14 | return err 15 | } 16 | if info.Mode().Perm()&0077 != 0 { 17 | return ErrSSLKeyHasWorldPermissions 18 | } 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_renegotiation.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package pq 4 | 5 | import "crypto/tls" 6 | 7 | // Renegotiation is not supported by crypto/tls until Go 1.7. 8 | func sslRenegotiation(*tls.Config) {} 9 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package pq 4 | 5 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 6 | // The key file should have very little access. 7 | // 8 | // libpq does not check key file permissions on Windows. 9 | func sslKeyPermissions(string) error { return nil } 10 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/url.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | nurl "net/url" 7 | "sort" 8 | "strings" 9 | ) 10 | 11 | // ParseURL no longer needs to be used by clients of this library since supplying a URL as a 12 | // connection string to sql.Open() is now supported: 13 | // 14 | // sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") 15 | // 16 | // It remains exported here for backwards-compatibility. 17 | // 18 | // ParseURL converts a url to a connection string for driver.Open. 19 | // Example: 20 | // 21 | // "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" 22 | // 23 | // converts to: 24 | // 25 | // "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" 26 | // 27 | // A minimal example: 28 | // 29 | // "postgres://" 30 | // 31 | // This will be blank, causing driver.Open to use all of the defaults 32 | func ParseURL(url string) (string, error) { 33 | u, err := nurl.Parse(url) 34 | if err != nil { 35 | return "", err 36 | } 37 | 38 | if u.Scheme != "postgres" && u.Scheme != "postgresql" { 39 | return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) 40 | } 41 | 42 | var kvs []string 43 | escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) 44 | accrue := func(k, v string) { 45 | if v != "" { 46 | kvs = append(kvs, k+"="+escaper.Replace(v)) 47 | } 48 | } 49 | 50 | if u.User != nil { 51 | v := u.User.Username() 52 | accrue("user", v) 53 | 54 | v, _ = u.User.Password() 55 | accrue("password", v) 56 | } 57 | 58 | if host, port, err := net.SplitHostPort(u.Host); err != nil { 59 | accrue("host", u.Host) 60 | } else { 61 | accrue("host", host) 62 | accrue("port", port) 63 | } 64 | 65 | if u.Path != "" { 66 | accrue("dbname", u.Path[1:]) 67 | } 68 | 69 | q := u.Query() 70 | for k := range q { 71 | accrue(k, q.Get(k)) 72 | } 73 | 74 | sort.Strings(kvs) // Makes testing easier (not a performance concern) 75 | return strings.Join(kvs, " "), nil 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_posix.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | 3 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun 4 | 5 | package pq 6 | 7 | import ( 8 | "os" 9 | "os/user" 10 | ) 11 | 12 | func userCurrent() (string, error) { 13 | u, err := user.Current() 14 | if err == nil { 15 | return u.Username, nil 16 | } 17 | 18 | name := os.Getenv("USER") 19 | if name != "" { 20 | return name, nil 21 | } 22 | 23 | return "", ErrCouldNotDetectUsername 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_windows.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | package pq 3 | 4 | import ( 5 | "path/filepath" 6 | "syscall" 7 | ) 8 | 9 | // Perform Windows user name lookup identically to libpq. 10 | // 11 | // The PostgreSQL code makes use of the legacy Win32 function 12 | // GetUserName, and that function has not been imported into stock Go. 13 | // GetUserNameEx is available though, the difference being that a 14 | // wider range of names are available. To get the output to be the 15 | // same as GetUserName, only the base (or last) component of the 16 | // result is returned. 17 | func userCurrent() (string, error) { 18 | pw_name := make([]uint16, 128) 19 | pwname_size := uint32(len(pw_name)) - 1 20 | err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) 21 | if err != nil { 22 | return "", ErrCouldNotDetectUsername 23 | } 24 | s := syscall.UTF16ToString(pw_name) 25 | u := filepath.Base(s) 26 | return u, nil 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/uuid.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | ) 7 | 8 | // decodeUUIDBinary interprets the binary format of a uuid, returning it in text format. 9 | func decodeUUIDBinary(src []byte) ([]byte, error) { 10 | if len(src) != 16 { 11 | return nil, fmt.Errorf("pq: unable to decode uuid; bad length: %d", len(src)) 12 | } 13 | 14 | dst := make([]byte, 36) 15 | dst[8], dst[13], dst[18], dst[23] = '-', '-', '-', '-' 16 | hex.Encode(dst[0:], src[0:4]) 17 | hex.Encode(dst[9:], src[4:6]) 18 | hex.Encode(dst[14:], src[6:8]) 19 | hex.Encode(dst[19:], src[8:10]) 20 | hex.Encode(dst[24:], src[10:16]) 21 | 22 | return dst, nil 23 | } 24 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at https://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at https://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/acme/autocert/cache.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert 6 | 7 | import ( 8 | "context" 9 | "errors" 10 | "io/ioutil" 11 | "os" 12 | "path/filepath" 13 | ) 14 | 15 | // ErrCacheMiss is returned when a certificate is not found in cache. 16 | var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") 17 | 18 | // Cache is used by Manager to store and retrieve previously obtained certificates 19 | // as opaque data. 20 | // 21 | // The key argument of the methods refers to a domain name but need not be an FQDN. 22 | // Cache implementations should not rely on the key naming pattern. 23 | type Cache interface { 24 | // Get returns a certificate data for the specified key. 25 | // If there's no such key, Get returns ErrCacheMiss. 26 | Get(ctx context.Context, key string) ([]byte, error) 27 | 28 | // Put stores the data in the cache under the specified key. 29 | // Underlying implementations may use any data storage format, 30 | // as long as the reverse operation, Get, results in the original data. 31 | Put(ctx context.Context, key string, data []byte) error 32 | 33 | // Delete removes a certificate data from the cache under the specified key. 34 | // If there's no such key in the cache, Delete returns nil. 35 | Delete(ctx context.Context, key string) error 36 | } 37 | 38 | // DirCache implements Cache using a directory on the local filesystem. 39 | // If the directory does not exist, it will be created with 0700 permissions. 40 | type DirCache string 41 | 42 | // Get reads a certificate data from the specified file name. 43 | func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { 44 | name = filepath.Join(string(d), name) 45 | var ( 46 | data []byte 47 | err error 48 | done = make(chan struct{}) 49 | ) 50 | go func() { 51 | data, err = ioutil.ReadFile(name) 52 | close(done) 53 | }() 54 | select { 55 | case <-ctx.Done(): 56 | return nil, ctx.Err() 57 | case <-done: 58 | } 59 | if os.IsNotExist(err) { 60 | return nil, ErrCacheMiss 61 | } 62 | return data, err 63 | } 64 | 65 | // Put writes the certificate data to the specified file name. 66 | // The file will be created with 0600 permissions. 67 | func (d DirCache) Put(ctx context.Context, name string, data []byte) error { 68 | if err := os.MkdirAll(string(d), 0700); err != nil { 69 | return err 70 | } 71 | 72 | done := make(chan struct{}) 73 | var err error 74 | go func() { 75 | defer close(done) 76 | var tmp string 77 | if tmp, err = d.writeTempFile(name, data); err != nil { 78 | return 79 | } 80 | select { 81 | case <-ctx.Done(): 82 | // Don't overwrite the file if the context was canceled. 83 | default: 84 | newName := filepath.Join(string(d), name) 85 | err = os.Rename(tmp, newName) 86 | } 87 | }() 88 | select { 89 | case <-ctx.Done(): 90 | return ctx.Err() 91 | case <-done: 92 | } 93 | return err 94 | } 95 | 96 | // Delete removes the specified file name. 97 | func (d DirCache) Delete(ctx context.Context, name string) error { 98 | name = filepath.Join(string(d), name) 99 | var ( 100 | err error 101 | done = make(chan struct{}) 102 | ) 103 | go func() { 104 | err = os.Remove(name) 105 | close(done) 106 | }() 107 | select { 108 | case <-ctx.Done(): 109 | return ctx.Err() 110 | case <-done: 111 | } 112 | if err != nil && !os.IsNotExist(err) { 113 | return err 114 | } 115 | return nil 116 | } 117 | 118 | // writeTempFile writes b to a temporary file, closes the file and returns its path. 119 | func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) { 120 | // TempFile uses 0600 permissions 121 | f, err := ioutil.TempFile(string(d), prefix) 122 | if err != nil { 123 | return "", err 124 | } 125 | if _, err := f.Write(b); err != nil { 126 | f.Close() 127 | return "", err 128 | } 129 | return f.Name(), f.Close() 130 | } 131 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/acme/autocert/listener.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert 6 | 7 | import ( 8 | "crypto/tls" 9 | "log" 10 | "net" 11 | "os" 12 | "path/filepath" 13 | "runtime" 14 | "time" 15 | ) 16 | 17 | // NewListener returns a net.Listener that listens on the standard TLS 18 | // port (443) on all interfaces and returns *tls.Conn connections with 19 | // LetsEncrypt certificates for the provided domain or domains. 20 | // 21 | // It enables one-line HTTPS servers: 22 | // 23 | // log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) 24 | // 25 | // NewListener is a convenience function for a common configuration. 26 | // More complex or custom configurations can use the autocert.Manager 27 | // type instead. 28 | // 29 | // Use of this function implies acceptance of the LetsEncrypt Terms of 30 | // Service. If domains is not empty, the provided domains are passed 31 | // to HostWhitelist. If domains is empty, the listener will do 32 | // LetsEncrypt challenges for any requested domain, which is not 33 | // recommended. 34 | // 35 | // Certificates are cached in a "golang-autocert" directory under an 36 | // operating system-specific cache or temp directory. This may not 37 | // be suitable for servers spanning multiple machines. 38 | // 39 | // The returned listener uses a *tls.Config that enables HTTP/2, and 40 | // should only be used with servers that support HTTP/2. 41 | // 42 | // The returned Listener also enables TCP keep-alives on the accepted 43 | // connections. The returned *tls.Conn are returned before their TLS 44 | // handshake has completed. 45 | func NewListener(domains ...string) net.Listener { 46 | m := &Manager{ 47 | Prompt: AcceptTOS, 48 | } 49 | if len(domains) > 0 { 50 | m.HostPolicy = HostWhitelist(domains...) 51 | } 52 | dir := cacheDir() 53 | if err := os.MkdirAll(dir, 0700); err != nil { 54 | log.Printf("warning: autocert.NewListener not using a cache: %v", err) 55 | } else { 56 | m.Cache = DirCache(dir) 57 | } 58 | return m.Listener() 59 | } 60 | 61 | // Listener listens on the standard TLS port (443) on all interfaces 62 | // and returns a net.Listener returning *tls.Conn connections. 63 | // 64 | // The returned listener uses a *tls.Config that enables HTTP/2, and 65 | // should only be used with servers that support HTTP/2. 66 | // 67 | // The returned Listener also enables TCP keep-alives on the accepted 68 | // connections. The returned *tls.Conn are returned before their TLS 69 | // handshake has completed. 70 | // 71 | // Unlike NewListener, it is the caller's responsibility to initialize 72 | // the Manager m's Prompt, Cache, HostPolicy, and other desired options. 73 | func (m *Manager) Listener() net.Listener { 74 | ln := &listener{ 75 | m: m, 76 | conf: &tls.Config{ 77 | GetCertificate: m.GetCertificate, // bonus: panic on nil m 78 | NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2 79 | }, 80 | } 81 | ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") 82 | return ln 83 | } 84 | 85 | type listener struct { 86 | m *Manager 87 | conf *tls.Config 88 | 89 | tcpListener net.Listener 90 | tcpListenErr error 91 | } 92 | 93 | func (ln *listener) Accept() (net.Conn, error) { 94 | if ln.tcpListenErr != nil { 95 | return nil, ln.tcpListenErr 96 | } 97 | conn, err := ln.tcpListener.Accept() 98 | if err != nil { 99 | return nil, err 100 | } 101 | tcpConn := conn.(*net.TCPConn) 102 | 103 | // Because Listener is a convenience function, help out with 104 | // this too. This is not possible for the caller to set once 105 | // we return a *tcp.Conn wrapping an inaccessible net.Conn. 106 | // If callers don't want this, they can do things the manual 107 | // way and tweak as needed. But this is what net/http does 108 | // itself, so copy that. If net/http changes, we can change 109 | // here too. 110 | tcpConn.SetKeepAlive(true) 111 | tcpConn.SetKeepAlivePeriod(3 * time.Minute) 112 | 113 | return tls.Server(tcpConn, ln.conf), nil 114 | } 115 | 116 | func (ln *listener) Addr() net.Addr { 117 | if ln.tcpListener != nil { 118 | return ln.tcpListener.Addr() 119 | } 120 | // net.Listen failed. Return something non-nil in case callers 121 | // call Addr before Accept: 122 | return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443} 123 | } 124 | 125 | func (ln *listener) Close() error { 126 | if ln.tcpListenErr != nil { 127 | return ln.tcpListenErr 128 | } 129 | return ln.tcpListener.Close() 130 | } 131 | 132 | func homeDir() string { 133 | if runtime.GOOS == "windows" { 134 | return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") 135 | } 136 | if h := os.Getenv("HOME"); h != "" { 137 | return h 138 | } 139 | return "/" 140 | } 141 | 142 | func cacheDir() string { 143 | const base = "golang-autocert" 144 | switch runtime.GOOS { 145 | case "darwin": 146 | return filepath.Join(homeDir(), "Library", "Caches", base) 147 | case "windows": 148 | for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} { 149 | if v := os.Getenv(ev); v != "" { 150 | return filepath.Join(v, base) 151 | } 152 | } 153 | // Worst case: 154 | return filepath.Join(homeDir(), base) 155 | } 156 | if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" { 157 | return filepath.Join(xdg, base) 158 | } 159 | return filepath.Join(homeDir(), ".cache", base) 160 | } 161 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/acme/autocert/renewal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert 6 | 7 | import ( 8 | "context" 9 | "crypto" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // renewJitter is the maximum deviation from Manager.RenewBefore. 15 | const renewJitter = time.Hour 16 | 17 | // domainRenewal tracks the state used by the periodic timers 18 | // renewing a single domain's cert. 19 | type domainRenewal struct { 20 | m *Manager 21 | domain string 22 | key crypto.Signer 23 | 24 | timerMu sync.Mutex 25 | timer *time.Timer 26 | } 27 | 28 | // start starts a cert renewal timer at the time 29 | // defined by the certificate expiration time exp. 30 | // 31 | // If the timer is already started, calling start is a noop. 32 | func (dr *domainRenewal) start(exp time.Time) { 33 | dr.timerMu.Lock() 34 | defer dr.timerMu.Unlock() 35 | if dr.timer != nil { 36 | return 37 | } 38 | dr.timer = time.AfterFunc(dr.next(exp), dr.renew) 39 | } 40 | 41 | // stop stops the cert renewal timer. 42 | // If the timer is already stopped, calling stop is a noop. 43 | func (dr *domainRenewal) stop() { 44 | dr.timerMu.Lock() 45 | defer dr.timerMu.Unlock() 46 | if dr.timer == nil { 47 | return 48 | } 49 | dr.timer.Stop() 50 | dr.timer = nil 51 | } 52 | 53 | // renew is called periodically by a timer. 54 | // The first renew call is kicked off by dr.start. 55 | func (dr *domainRenewal) renew() { 56 | dr.timerMu.Lock() 57 | defer dr.timerMu.Unlock() 58 | if dr.timer == nil { 59 | return 60 | } 61 | 62 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) 63 | defer cancel() 64 | // TODO: rotate dr.key at some point? 65 | next, err := dr.do(ctx) 66 | if err != nil { 67 | next = renewJitter / 2 68 | next += time.Duration(pseudoRand.int63n(int64(next))) 69 | } 70 | dr.timer = time.AfterFunc(next, dr.renew) 71 | testDidRenewLoop(next, err) 72 | } 73 | 74 | // updateState locks and replaces the relevant Manager.state item with the given 75 | // state. It additionally updates dr.key with the given state's key. 76 | func (dr *domainRenewal) updateState(state *certState) { 77 | dr.m.stateMu.Lock() 78 | defer dr.m.stateMu.Unlock() 79 | dr.key = state.key 80 | dr.m.state[dr.domain] = state 81 | } 82 | 83 | // do is similar to Manager.createCert but it doesn't lock a Manager.state item. 84 | // Instead, it requests a new certificate independently and, upon success, 85 | // replaces dr.m.state item with a new one and updates cache for the given domain. 86 | // 87 | // It may lock and update the Manager.state if the expiration date of the currently 88 | // cached cert is far enough in the future. 89 | // 90 | // The returned value is a time interval after which the renewal should occur again. 91 | func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { 92 | // a race is likely unavoidable in a distributed environment 93 | // but we try nonetheless 94 | if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil { 95 | next := dr.next(tlscert.Leaf.NotAfter) 96 | if next > dr.m.renewBefore()+renewJitter { 97 | signer, ok := tlscert.PrivateKey.(crypto.Signer) 98 | if ok { 99 | state := &certState{ 100 | key: signer, 101 | cert: tlscert.Certificate, 102 | leaf: tlscert.Leaf, 103 | } 104 | dr.updateState(state) 105 | return next, nil 106 | } 107 | } 108 | } 109 | 110 | der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain) 111 | if err != nil { 112 | return 0, err 113 | } 114 | state := &certState{ 115 | key: dr.key, 116 | cert: der, 117 | leaf: leaf, 118 | } 119 | tlscert, err := state.tlscert() 120 | if err != nil { 121 | return 0, err 122 | } 123 | if err := dr.m.cachePut(ctx, dr.domain, tlscert); err != nil { 124 | return 0, err 125 | } 126 | dr.updateState(state) 127 | return dr.next(leaf.NotAfter), nil 128 | } 129 | 130 | func (dr *domainRenewal) next(expiry time.Time) time.Duration { 131 | d := expiry.Sub(timeNow()) - dr.m.renewBefore() 132 | // add a bit of randomness to renew deadline 133 | n := pseudoRand.int63n(int64(renewJitter)) 134 | d -= time.Duration(n) 135 | if d < 0 { 136 | return 0 137 | } 138 | return d 139 | } 140 | 141 | var testDidRenewLoop = func(next time.Duration, err error) {} 142 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/acme/jws.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package acme 6 | 7 | import ( 8 | "crypto" 9 | "crypto/ecdsa" 10 | "crypto/rand" 11 | "crypto/rsa" 12 | "crypto/sha256" 13 | _ "crypto/sha512" // need for EC keys 14 | "encoding/base64" 15 | "encoding/json" 16 | "fmt" 17 | "math/big" 18 | ) 19 | 20 | // jwsEncodeJSON signs claimset using provided key and a nonce. 21 | // The result is serialized in JSON format. 22 | // See https://tools.ietf.org/html/rfc7515#section-7. 23 | func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) { 24 | jwk, err := jwkEncode(key.Public()) 25 | if err != nil { 26 | return nil, err 27 | } 28 | alg, sha := jwsHasher(key) 29 | if alg == "" || !sha.Available() { 30 | return nil, ErrUnsupportedKey 31 | } 32 | phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce) 33 | phead = base64.RawURLEncoding.EncodeToString([]byte(phead)) 34 | cs, err := json.Marshal(claimset) 35 | if err != nil { 36 | return nil, err 37 | } 38 | payload := base64.RawURLEncoding.EncodeToString(cs) 39 | hash := sha.New() 40 | hash.Write([]byte(phead + "." + payload)) 41 | sig, err := jwsSign(key, sha, hash.Sum(nil)) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | enc := struct { 47 | Protected string `json:"protected"` 48 | Payload string `json:"payload"` 49 | Sig string `json:"signature"` 50 | }{ 51 | Protected: phead, 52 | Payload: payload, 53 | Sig: base64.RawURLEncoding.EncodeToString(sig), 54 | } 55 | return json.Marshal(&enc) 56 | } 57 | 58 | // jwkEncode encodes public part of an RSA or ECDSA key into a JWK. 59 | // The result is also suitable for creating a JWK thumbprint. 60 | // https://tools.ietf.org/html/rfc7517 61 | func jwkEncode(pub crypto.PublicKey) (string, error) { 62 | switch pub := pub.(type) { 63 | case *rsa.PublicKey: 64 | // https://tools.ietf.org/html/rfc7518#section-6.3.1 65 | n := pub.N 66 | e := big.NewInt(int64(pub.E)) 67 | // Field order is important. 68 | // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. 69 | return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, 70 | base64.RawURLEncoding.EncodeToString(e.Bytes()), 71 | base64.RawURLEncoding.EncodeToString(n.Bytes()), 72 | ), nil 73 | case *ecdsa.PublicKey: 74 | // https://tools.ietf.org/html/rfc7518#section-6.2.1 75 | p := pub.Curve.Params() 76 | n := p.BitSize / 8 77 | if p.BitSize%8 != 0 { 78 | n++ 79 | } 80 | x := pub.X.Bytes() 81 | if n > len(x) { 82 | x = append(make([]byte, n-len(x)), x...) 83 | } 84 | y := pub.Y.Bytes() 85 | if n > len(y) { 86 | y = append(make([]byte, n-len(y)), y...) 87 | } 88 | // Field order is important. 89 | // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. 90 | return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, 91 | p.Name, 92 | base64.RawURLEncoding.EncodeToString(x), 93 | base64.RawURLEncoding.EncodeToString(y), 94 | ), nil 95 | } 96 | return "", ErrUnsupportedKey 97 | } 98 | 99 | // jwsSign signs the digest using the given key. 100 | // It returns ErrUnsupportedKey if the key type is unknown. 101 | // The hash is used only for RSA keys. 102 | func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) { 103 | switch key := key.(type) { 104 | case *rsa.PrivateKey: 105 | return key.Sign(rand.Reader, digest, hash) 106 | case *ecdsa.PrivateKey: 107 | r, s, err := ecdsa.Sign(rand.Reader, key, digest) 108 | if err != nil { 109 | return nil, err 110 | } 111 | rb, sb := r.Bytes(), s.Bytes() 112 | size := key.Params().BitSize / 8 113 | if size%8 > 0 { 114 | size++ 115 | } 116 | sig := make([]byte, size*2) 117 | copy(sig[size-len(rb):], rb) 118 | copy(sig[size*2-len(sb):], sb) 119 | return sig, nil 120 | } 121 | return nil, ErrUnsupportedKey 122 | } 123 | 124 | // jwsHasher indicates suitable JWS algorithm name and a hash function 125 | // to use for signing a digest with the provided key. 126 | // It returns ("", 0) if the key is not supported. 127 | func jwsHasher(key crypto.Signer) (string, crypto.Hash) { 128 | switch key := key.(type) { 129 | case *rsa.PrivateKey: 130 | return "RS256", crypto.SHA256 131 | case *ecdsa.PrivateKey: 132 | switch key.Params().Name { 133 | case "P-256": 134 | return "ES256", crypto.SHA256 135 | case "P-384": 136 | return "ES384", crypto.SHA384 137 | case "P-521": 138 | return "ES512", crypto.SHA512 139 | } 140 | } 141 | return "", 0 142 | } 143 | 144 | // JWKThumbprint creates a JWK thumbprint out of pub 145 | // as specified in https://tools.ietf.org/html/rfc7638. 146 | func JWKThumbprint(pub crypto.PublicKey) (string, error) { 147 | jwk, err := jwkEncode(pub) 148 | if err != nil { 149 | return "", err 150 | } 151 | b := sha256.Sum256([]byte(jwk)) 152 | return base64.RawURLEncoding.EncodeToString(b[:]), nil 153 | } 154 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.5 6 | - 1.6 7 | - 1.7 8 | - 1.8 9 | - 1.9 10 | - tip 11 | 12 | go_import_path: gopkg.in/yaml.v2 13 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 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 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v2" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | // Note: struct fields must be public in order for unmarshal to 69 | // correctly populate the data. 70 | type T struct { 71 | A string 72 | B struct { 73 | RenamedC int `yaml:"c"` 74 | D []int `yaml:",flow"` 75 | } 76 | } 77 | 78 | func main() { 79 | t := T{} 80 | 81 | err := yaml.Unmarshal([]byte(data), &t) 82 | if err != nil { 83 | log.Fatalf("error: %v", err) 84 | } 85 | fmt.Printf("--- t:\n%v\n\n", t) 86 | 87 | d, err := yaml.Marshal(&t) 88 | if err != nil { 89 | log.Fatalf("error: %v", err) 90 | } 91 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 92 | 93 | m := make(map[interface{}]interface{}) 94 | 95 | err = yaml.Unmarshal([]byte(data), &m) 96 | if err != nil { 97 | log.Fatalf("error: %v", err) 98 | } 99 | fmt.Printf("--- m:\n%v\n\n", m) 100 | 101 | d, err = yaml.Marshal(&m) 102 | if err != nil { 103 | log.Fatalf("error: %v", err) 104 | } 105 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 106 | } 107 | ``` 108 | 109 | This example will generate the following output: 110 | 111 | ``` 112 | --- t: 113 | {Easy! {2 [3 4]}} 114 | 115 | --- t dump: 116 | a: Easy! 117 | b: 118 | c: 2 119 | d: [3, 4] 120 | 121 | 122 | --- m: 123 | map[a:Easy! b:map[c:2 d:[3 4]]] 124 | 125 | --- m dump: 126 | a: Easy! 127 | b: 128 | c: 2 129 | d: 130 | - 3 131 | - 4 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/go.mod: -------------------------------------------------------------------------------- 1 | module "gopkg.in/yaml.v2" 2 | 3 | require ( 4 | "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 5 | ) 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | if ar[i] == '0' || br[i] == '0' { 55 | for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { 56 | if ar[j] != '0' { 57 | an = 1 58 | bn = 1 59 | break 60 | } 61 | } 62 | } 63 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 64 | an = an*10 + int64(ar[ai]-'0') 65 | } 66 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 67 | bn = bn*10 + int64(br[bi]-'0') 68 | } 69 | if an != bn { 70 | return an < bn 71 | } 72 | if ai != bi { 73 | return ai < bi 74 | } 75 | return ar[i] < br[i] 76 | } 77 | return len(ar) < len(br) 78 | } 79 | 80 | // keyFloat returns a float value for v if it is a number/bool 81 | // and whether it is a number/bool or not. 82 | func keyFloat(v reflect.Value) (f float64, ok bool) { 83 | switch v.Kind() { 84 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 85 | return float64(v.Int()), true 86 | case reflect.Float32, reflect.Float64: 87 | return v.Float(), true 88 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 89 | return float64(v.Uint()), true 90 | case reflect.Bool: 91 | if v.Bool() { 92 | return 1, true 93 | } 94 | return 0, true 95 | } 96 | return 0, false 97 | } 98 | 99 | // numLess returns whether a < b. 100 | // a and b must necessarily have the same kind. 101 | func numLess(a, b reflect.Value) bool { 102 | switch a.Kind() { 103 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 104 | return a.Int() < b.Int() 105 | case reflect.Float32, reflect.Float64: 106 | return a.Float() < b.Float() 107 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 108 | return a.Uint() < b.Uint() 109 | case reflect.Bool: 110 | return !a.Bool() && b.Bool() 111 | } 112 | panic("not a number") 113 | } 114 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 22 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 23 | } 24 | emitter.buffer_pos = 0 25 | return true 26 | } 27 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | const ( 4 | // The size of the input raw buffer. 5 | input_raw_buffer_size = 512 6 | 7 | // The size of the input buffer. 8 | // It should be possible to decode the whole raw buffer. 9 | input_buffer_size = input_raw_buffer_size * 3 10 | 11 | // The size of the output buffer. 12 | output_buffer_size = 128 13 | 14 | // The size of the output raw buffer. 15 | // It should be possible to encode the whole output buffer. 16 | output_raw_buffer_size = (output_buffer_size*2 + 2) 17 | 18 | // The size of other stacks and queues. 19 | initial_stack_size = 16 20 | initial_queue_size = 16 21 | initial_string_size = 16 22 | ) 23 | 24 | // Check if the character at the specified position is an alphabetical 25 | // character, a digit, '_', or '-'. 26 | func is_alpha(b []byte, i int) bool { 27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 28 | } 29 | 30 | // Check if the character at the specified position is a digit. 31 | func is_digit(b []byte, i int) bool { 32 | return b[i] >= '0' && b[i] <= '9' 33 | } 34 | 35 | // Get the value of a digit. 36 | func as_digit(b []byte, i int) int { 37 | return int(b[i]) - '0' 38 | } 39 | 40 | // Check if the character at the specified position is a hex-digit. 41 | func is_hex(b []byte, i int) bool { 42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 43 | } 44 | 45 | // Get the value of a hex-digit. 46 | func as_hex(b []byte, i int) int { 47 | bi := b[i] 48 | if bi >= 'A' && bi <= 'F' { 49 | return int(bi) - 'A' + 10 50 | } 51 | if bi >= 'a' && bi <= 'f' { 52 | return int(bi) - 'a' + 10 53 | } 54 | return int(bi) - '0' 55 | } 56 | 57 | // Check if the character is ASCII. 58 | func is_ascii(b []byte, i int) bool { 59 | return b[i] <= 0x7F 60 | } 61 | 62 | // Check if the character at the start of the buffer can be printed unescaped. 63 | func is_printable(b []byte, i int) bool { 64 | return ((b[i] == 0x0A) || // . == #x0A 65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 67 | (b[i] > 0xC2 && b[i] < 0xED) || 68 | (b[i] == 0xED && b[i+1] < 0xA0) || 69 | (b[i] == 0xEE) || 70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 73 | } 74 | 75 | // Check if the character at the specified position is NUL. 76 | func is_z(b []byte, i int) bool { 77 | return b[i] == 0x00 78 | } 79 | 80 | // Check if the beginning of the buffer is a BOM. 81 | func is_bom(b []byte, i int) bool { 82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 83 | } 84 | 85 | // Check if the character at the specified position is space. 86 | func is_space(b []byte, i int) bool { 87 | return b[i] == ' ' 88 | } 89 | 90 | // Check if the character at the specified position is tab. 91 | func is_tab(b []byte, i int) bool { 92 | return b[i] == '\t' 93 | } 94 | 95 | // Check if the character at the specified position is blank (space or tab). 96 | func is_blank(b []byte, i int) bool { 97 | //return is_space(b, i) || is_tab(b, i) 98 | return b[i] == ' ' || b[i] == '\t' 99 | } 100 | 101 | // Check if the character at the specified position is a line break. 102 | func is_break(b []byte, i int) bool { 103 | return (b[i] == '\r' || // CR (#xD) 104 | b[i] == '\n' || // LF (#xA) 105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 108 | } 109 | 110 | func is_crlf(b []byte, i int) bool { 111 | return b[i] == '\r' && b[i+1] == '\n' 112 | } 113 | 114 | // Check if the character is a line break or NUL. 115 | func is_breakz(b []byte, i int) bool { 116 | //return is_break(b, i) || is_z(b, i) 117 | return ( // is_break: 118 | b[i] == '\r' || // CR (#xD) 119 | b[i] == '\n' || // LF (#xA) 120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 123 | // is_z: 124 | b[i] == 0) 125 | } 126 | 127 | // Check if the character is a line break, space, or NUL. 128 | func is_spacez(b []byte, i int) bool { 129 | //return is_space(b, i) || is_breakz(b, i) 130 | return ( // is_space: 131 | b[i] == ' ' || 132 | // is_breakz: 133 | b[i] == '\r' || // CR (#xD) 134 | b[i] == '\n' || // LF (#xA) 135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 138 | b[i] == 0) 139 | } 140 | 141 | // Check if the character is a line break, space, tab, or NUL. 142 | func is_blankz(b []byte, i int) bool { 143 | //return is_blank(b, i) || is_breakz(b, i) 144 | return ( // is_blank: 145 | b[i] == ' ' || b[i] == '\t' || 146 | // is_breakz: 147 | b[i] == '\r' || // CR (#xD) 148 | b[i] == '\n' || // LF (#xA) 149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 152 | b[i] == 0) 153 | } 154 | 155 | // Determine the width of the character. 156 | func width(b byte) int { 157 | // Don't replace these by a switch without first 158 | // confirming that it is being inlined. 159 | if b&0x80 == 0x00 { 160 | return 1 161 | } 162 | if b&0xE0 == 0xC0 { 163 | return 2 164 | } 165 | if b&0xF0 == 0xE0 { 166 | return 3 167 | } 168 | if b&0xF8 == 0xF0 { 169 | return 4 170 | } 171 | return 0 172 | 173 | } 174 | -------------------------------------------------------------------------------- /views/chart.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ template "head.tpl" . }} 6 |
7 | 8 |
9 | {{ template "header.tpl" . }} 10 |
11 | 12 |
13 |
14 |
15 | {{ if (index .chart 0).Icon }} 16 |
default avatar
17 | {{else}} 18 |
default avatar
19 | {{end}} 20 | 21 |

{{ (index .chart 0).Name }}

22 | 23 | 29 | 30 |
31 |

{{ (index .chart 0).Description }}

32 |
33 | 34 | 43 | 44 |
45 | 46 |
47 |
48 | 49 |
50 | {{ template "footer.tpl" . }} 51 |
52 | 53 |
54 | 55 | 87 | 88 | -------------------------------------------------------------------------------- /views/footer.tpl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/header.tpl: -------------------------------------------------------------------------------- 1 |
2 |

Welcome to ChartMuseumUI

3 |
4 |
-------------------------------------------------------------------------------- /views/index.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ChartMuseumUI 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 162 | 163 | 164 | 165 | {{ template "main.tpl" . }} 166 | 167 | 168 | -------------------------------------------------------------------------------- /views/login.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "head.tpl" . }} 5 | 14 | 15 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /views/main.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "head.tpl" . }} 5 |
6 | 7 |
8 | {{ template "header.tpl" . }} 9 |
10 | 11 |
12 | 13 | 48 | 49 |
50 | 51 |
52 | {{ template "footer.tpl" . }} 53 |
54 | 55 |
56 | 57 | 101 | 102 | 103 | 104 | 105 | 106 | --------------------------------------------------------------------------------