├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── codecov.yml ├── gulpfile.js ├── npm-debug.log ├── package.json ├── screenshot.png ├── src ├── app │ ├── index.html │ ├── main.js │ └── src │ │ ├── components │ │ ├── manager.jsx │ │ ├── notification.jsx │ │ └── websocket.jsx │ │ ├── container.jsx │ │ ├── less │ │ ├── alerts.less │ │ ├── blocks.less │ │ ├── breadcrumbs.less │ │ ├── buttons.less │ │ ├── coffer.less │ │ ├── forms.less │ │ ├── grid.less │ │ ├── helpers.less │ │ ├── kube.less │ │ ├── labels.less │ │ ├── messages.less │ │ ├── mixins.less │ │ ├── pagination.less │ │ ├── reset.less │ │ ├── tables.less │ │ ├── typography.less │ │ └── variables.less │ │ ├── main.jsx │ │ └── pages │ │ ├── about.jsx │ │ ├── login.jsx │ │ └── manager.jsx └── service │ ├── main.go │ ├── router │ ├── handlers.go │ ├── handlers_test.go │ ├── model.go │ └── router.go │ └── store │ ├── encryption.go │ ├── encryption_test.go │ ├── model.go │ └── store.go └── vendor ├── manifest ├── pkg └── linux_amd64 │ ├── github.com │ ├── boltdb │ │ └── bolt.a │ ├── gin-gonic │ │ ├── gin.a │ │ └── gin │ │ │ ├── binding.a │ │ │ └── render.a │ ├── golang │ │ └── protobuf │ │ │ └── proto.a │ ├── gorilla │ │ └── websocket.a │ ├── manucorporat │ │ └── sse.a │ └── sirupsen │ │ └── logrus.a │ ├── golang.org │ └── x │ │ └── net │ │ ├── context.a │ │ └── websocket.a │ └── gopkg.in │ ├── go-playground │ └── validator.v8.a │ └── yaml.v2.a └── src ├── github.com ├── boltdb │ └── bolt │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── appveyor.yml │ │ ├── bolt_386.go │ │ ├── bolt_amd64.go │ │ ├── bolt_arm.go │ │ ├── bolt_arm64.go │ │ ├── bolt_linux.go │ │ ├── bolt_openbsd.go │ │ ├── bolt_ppc.go │ │ ├── bolt_ppc64.go │ │ ├── bolt_ppc64le.go │ │ ├── bolt_s390x.go │ │ ├── bolt_unix.go │ │ ├── bolt_unix_solaris.go │ │ ├── bolt_windows.go │ │ ├── boltsync_unix.go │ │ ├── bucket.go │ │ ├── bucket_test.go │ │ ├── cmd │ │ └── bolt │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── cursor.go │ │ ├── cursor_test.go │ │ ├── db.go │ │ ├── db_test.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── freelist.go │ │ ├── freelist_test.go │ │ ├── node.go │ │ ├── node_test.go │ │ ├── page.go │ │ ├── page_test.go │ │ ├── quick_test.go │ │ ├── simulation_test.go │ │ ├── tx.go │ │ └── tx_test.go ├── dustin │ └── go-broadcast │ │ ├── LICENSE │ │ ├── README.markdown │ │ ├── broadcaster.go │ │ ├── broadcaster_test.go │ │ ├── mux_observer.go │ │ └── mux_observer_test.go ├── gin-gonic │ └── gin │ │ ├── AUTHORS.md │ │ ├── BENCHMARKS.md │ │ ├── CHANGELOG.md │ │ ├── Godeps │ │ └── Godeps.json │ │ ├── LICENSE │ │ ├── README.md │ │ ├── auth.go │ │ ├── auth_test.go │ │ ├── benchmarks_test.go │ │ ├── binding │ │ ├── binding.go │ │ ├── binding_test.go │ │ ├── default_validator.go │ │ ├── example │ │ │ ├── test.pb.go │ │ │ └── test.proto │ │ ├── form.go │ │ ├── form_mapping.go │ │ ├── json.go │ │ ├── protobuf.go │ │ ├── validate_test.go │ │ └── xml.go │ │ ├── context.go │ │ ├── context_test.go │ │ ├── debug.go │ │ ├── debug_test.go │ │ ├── deprecated.go │ │ ├── errors.go │ │ ├── errors_test.go │ │ ├── fs.go │ │ ├── gin.go │ │ ├── ginS │ │ ├── README.md │ │ └── gins.go │ │ ├── gin_integration_test.go │ │ ├── gin_test.go │ │ ├── githubapi_test.go │ │ ├── helpers_test.go │ │ ├── logger.go │ │ ├── logger_test.go │ │ ├── logo.jpg │ │ ├── middleware_test.go │ │ ├── mode.go │ │ ├── mode_test.go │ │ ├── path.go │ │ ├── path_test.go │ │ ├── recovery.go │ │ ├── recovery_test.go │ │ ├── render │ │ ├── data.go │ │ ├── html.go │ │ ├── json.go │ │ ├── redirect.go │ │ ├── render.go │ │ ├── render_test.go │ │ ├── text.go │ │ ├── xml.go │ │ └── yaml.go │ │ ├── response_writer.go │ │ ├── response_writer_test.go │ │ ├── routergroup.go │ │ ├── routergroup_test.go │ │ ├── routes_test.go │ │ ├── tree.go │ │ ├── tree_test.go │ │ ├── utils.go │ │ ├── utils_test.go │ │ └── wercker.yml ├── golang │ └── protobuf │ │ └── proto │ │ ├── Makefile │ │ ├── all_test.go │ │ ├── any_test.go │ │ ├── clone.go │ │ ├── clone_test.go │ │ ├── decode.go │ │ ├── encode.go │ │ ├── equal.go │ │ ├── equal_test.go │ │ ├── extensions.go │ │ ├── extensions_test.go │ │ ├── lib.go │ │ ├── message_set.go │ │ ├── message_set_test.go │ │ ├── pointer_reflect.go │ │ ├── pointer_unsafe.go │ │ ├── properties.go │ │ ├── proto3_proto │ │ ├── proto3.pb.go │ │ └── proto3.proto │ │ ├── proto3_test.go │ │ ├── size2_test.go │ │ ├── size_test.go │ │ ├── testdata │ │ ├── Makefile │ │ ├── golden_test.go │ │ ├── test.pb.go │ │ └── test.proto │ │ ├── text.go │ │ ├── text_parser.go │ │ ├── text_parser_test.go │ │ └── text_test.go ├── gorilla │ └── websocket │ │ ├── AUTHORS │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bench_test.go │ │ ├── client.go │ │ ├── client_server_test.go │ │ ├── client_test.go │ │ ├── conn.go │ │ ├── conn_test.go │ │ ├── doc.go │ │ ├── example_test.go │ │ ├── examples │ │ ├── autobahn │ │ │ ├── README.md │ │ │ ├── fuzzingclient.json │ │ │ └── server.go │ │ ├── chat │ │ │ ├── README.md │ │ │ ├── conn.go │ │ │ ├── home.html │ │ │ ├── hub.go │ │ │ └── main.go │ │ ├── command │ │ │ ├── README.md │ │ │ ├── home.html │ │ │ └── main.go │ │ ├── echo │ │ │ ├── README.md │ │ │ ├── client.go │ │ │ └── server.go │ │ └── filewatch │ │ │ ├── README.md │ │ │ └── main.go │ │ ├── json.go │ │ ├── json_test.go │ │ ├── server.go │ │ ├── server_test.go │ │ ├── util.go │ │ └── util_test.go ├── manucorporat │ ├── sse │ │ ├── LICENSE │ │ ├── README.md │ │ ├── sse-decoder.go │ │ ├── sse-decoder_test.go │ │ ├── sse-encoder.go │ │ ├── sse_test.go │ │ └── writer.go │ └── stats │ │ └── stats.go └── sirupsen │ └── logrus │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── doc.go │ ├── entry.go │ ├── entry_test.go │ ├── examples │ ├── basic │ │ └── basic.go │ └── hook │ │ └── hook.go │ ├── exported.go │ ├── formatter.go │ ├── formatter_bench_test.go │ ├── formatters │ └── logstash │ │ ├── logstash.go │ │ └── logstash_test.go │ ├── hook_test.go │ ├── hooks.go │ ├── hooks │ ├── syslog │ │ ├── README.md │ │ ├── syslog.go │ │ └── syslog_test.go │ └── test │ │ ├── test.go │ │ └── test_test.go │ ├── json_formatter.go │ ├── json_formatter_test.go │ ├── logger.go │ ├── logrus.go │ ├── logrus_test.go │ ├── terminal_bsd.go │ ├── terminal_linux.go │ ├── terminal_notwindows.go │ ├── terminal_solaris.go │ ├── terminal_windows.go │ ├── text_formatter.go │ ├── text_formatter_test.go │ └── writer.go ├── golang.org └── x │ └── net │ └── context │ ├── context.go │ ├── context_test.go │ ├── ctxhttp │ ├── ctxhttp.go │ └── ctxhttp_test.go │ ├── go17.go │ ├── pre_go17.go │ └── withtimeout_test.go └── gopkg.in ├── airbrake └── gobrake.v2 │ ├── LICENSE │ ├── README.md │ ├── bench_test.go │ ├── circle.yml │ ├── gobrake.go │ ├── notice.go │ ├── notifier.go │ ├── notifier_test.go │ └── util.go ├── gemnasium └── logrus-airbrake-hook.v2 │ ├── LICENSE │ ├── README.md │ ├── airbrake.go │ └── airbrake_test.go ├── go-playground └── validator.v8 │ ├── LICENSE │ ├── README.md │ ├── baked_in.go │ ├── benchmarks_test.go │ ├── cache.go │ ├── doc.go │ ├── examples │ ├── custom │ │ └── custom.go │ ├── simple │ │ └── simple.go │ └── struct-level │ │ └── struct_level.go │ ├── examples_test.go │ ├── logo.png │ ├── regexes.go │ ├── util.go │ ├── validator.go │ └── validator_test.go └── yaml.v2 ├── LICENSE ├── LICENSE.libyaml ├── README.md ├── apic.go ├── decode.go ├── decode_test.go ├── emitterc.go ├── encode.go ├── encode_test.go ├── parserc.go ├── readerc.go ├── resolve.go ├── scannerc.go ├── sorter.go ├── suite_test.go ├── writerc.go ├── yaml.go ├── yamlh.go └── yamlprivateh.go /.gitignore: -------------------------------------------------------------------------------- 1 | store.bolt 2 | node_modules/ 3 | pkg/ 4 | bin/ 5 | 6 | dist/ 7 | coffer-*/ 8 | 9 | *.asar 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | deps: 2 | rm -rf node_modules 3 | npm i 4 | npm i -g electron-packager electron 5 | 6 | go get github.com/constabulary/gb/... 7 | gb vendor restore 8 | 9 | test: 10 | gb test 11 | 12 | build-app: clean 13 | gulp build 14 | gb build 15 | 16 | cp package.json dist/coffer/ 17 | 18 | build-linux: build-app 19 | GOOS=linux GOARCH=amd64 gb build -P 1 -f -F 20 | cp bin/service-linux-amd64 dist/coffer/service 21 | electron-packager dist/coffer --platform=linux --arch=x64 --asar 22 | 23 | build-win: build-app 24 | GOOS=windows GOARCH=amd64 gb build -P 1 -f -F 25 | cp bin/service-windows-amd64.exe dist/coffer/service.exe 26 | electron-packager dist/coffer --platform=win32 --arch=x64 --asar 27 | 28 | clean: 29 | rm -rf coffer-* 30 | rm -rf dist/ 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *Coffer is very much in development - and should not be used to store import information* 2 | 3 | ![](screenshot.png) 4 | 5 | Coffer is a light weight password manager built with Go, React, and Electron. 6 | 7 | # Install (TBC) 8 | To install Coffer you can download the pre-compiled binary from the ['releases'](https://github.com/spaceshuttl/coffer/releases/latest) section of GitHub, just select the version for your OS and architecture and download Coffer. 9 | 10 | # Development 11 | We actively welcome PRs and love to see the community contributing to Coffer. If you want to open a PR for a feature, or just want to hack on it, follow the intstructions below. 12 | 13 | ## Install dependencies 14 | - Install GB, the vendoring Go vendoring tool 15 | ```bash 16 | go get github.com/constabulary/gb/... 17 | ``` 18 | - Install Electron + electron-packager globally for your OS 19 | ```bash 20 | npm install -g electron electron-packager 21 | ``` 22 | 23 | ## Setting up coffer 24 | - Clone the repo, `git clone https://github.com/spaceshuttl/coffer.git` 25 | - cd into the directory, install dependencies, 26 | ```bash 27 | cd coffer && npm install 28 | ``` 29 | - Build the repo, `make build` 30 | - Run the backend `./bin/service` 31 | - Run the front end, `npm run app` 32 | 33 | *Note: There is a unison build system coming soon, hopefully there will be a single binary you can run.* 34 | 35 | # Data retention 36 | Coffer stores all passwords within a local file (`~/.coffer/store.bolt` by default.) All writes to the disk are encrypted with AES-256. 37 | 38 | # TODO 39 | 40 | ### Backend 41 | - [X] Rewrite endpoints in gorilla/websocket 42 | - [X] Rewrite backend into neat unison API to be used. 43 | - [X] Encrypt disk transaction 44 | - [ ] Add SSL support to the WS connection 45 | - [-] Write tests 46 | 47 | ### Frontend 48 | - [X] Write up HTML structure 49 | - [X] Write React components 50 | - [X] Implement WebSockets 51 | - [X] Automatically hide passwords, show on click/hover 52 | - [ ] Implement some store to hold the WS connection 53 | 54 | ### Meta 55 | - [X] Create build + packing system 56 | - [ ] Add bower dependency management system 57 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | token: 6a1b93c3-8088-42a9-afa6-86eaf0c8aa05 3 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const gulp = require('gulp'); 3 | const less = require('gulp-less'); 4 | const react = require('gulp-react'); 5 | const cleanCSS = require('gulp-clean-css'); 6 | const uglify = require('gulp-uglify') 7 | const path = require('path'); 8 | const browserify = require('browserify'); 9 | const babelify = require('babelify'); 10 | const source = require('vinyl-source-stream'); 11 | 12 | gulp.task('less', function () { 13 | return gulp.src(__dirname + '/src/app/src/less/kube.less') 14 | .pipe(less()) 15 | .pipe(cleanCSS()) 16 | .pipe(gulp.dest(__dirname + '/dist/coffer/css')) 17 | }); 18 | 19 | gulp.task('react', function () { 20 | browserify({ 21 | entries: __dirname + '/src/app/src/main.jsx', 22 | extensions: ['.jsx'], 23 | debug: true 24 | }) 25 | .transform(babelify, {presets: ["es2015", "react"]}) 26 | .bundle() 27 | .pipe(source('bundle.js')) 28 | .pipe(gulp.dest(__dirname + '/dist/coffer/js')); 29 | }); 30 | 31 | 32 | gulp.task('default', ['less', 'react', 'build'], function () { 33 | gulp.watch("./src/app/src/less/**/*.less", ['less']) 34 | gulp.watch("./src/app/src/**/*.jsx", ['react']) 35 | }) 36 | 37 | gulp.task('build', ['less', 'react'], function() { 38 | gulp.src(__dirname + '/src/app/main.js') 39 | .pipe(gulp.dest('dist/coffer')) 40 | 41 | gulp.src(__dirname + '/src/app/index.html') 42 | .pipe(gulp.dest('dist/coffer')) 43 | return 44 | }) 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coffer", 3 | "productName": "coffer", 4 | "version": "0.0.1", 5 | "description": "A simple go-backed password store", 6 | "main": "main.js", 7 | "scripts": { 8 | "app": "electron dist/coffer", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "github.com/spaceshuttl/coffer" 14 | }, 15 | "keywords": [ 16 | "password", 17 | "manager", 18 | "store" 19 | ], 20 | "author": "MNZT ", 21 | "license": "ISC", 22 | "devDependencies": { 23 | "babel-preset-es2015": "^6.6.0", 24 | "babel-preset-react": "^6.5.0", 25 | "babelify": "^7.3.0", 26 | "browserify": "^13.0.0", 27 | "classnames": "^2.2.5", 28 | "gulp": "^3.9.1", 29 | "gulp-clean-css": "^2.0.7", 30 | "gulp-less": "^3.0.5", 31 | "gulp-react": "^3.1.0", 32 | "gulp-uglify": "^1.5.3", 33 | "install": "^0.7.3", 34 | "npm": "^3.9.0", 35 | "path": "^0.12.7", 36 | "react": "^15.0.1", 37 | "react-dom": "^15.0.1", 38 | "react-router": "^2.5.1", 39 | "reactify": "^1.1.1", 40 | "vinyl-source-stream": "^1.1.0" 41 | }, 42 | "dependencies": { 43 | "electron-prebuilt": "^1.0.2" 44 | }, 45 | "browserify": { 46 | "transform": [ 47 | [ 48 | "reactify", 49 | { 50 | "es6": true 51 | } 52 | ] 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/screenshot.png -------------------------------------------------------------------------------- /src/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Coffer 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/main.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const electron = require('electron') 3 | const {BrowserWindow, app} = require('electron') 4 | const {execFile} = require('child_process') 5 | const os = require('os') 6 | const fs = require('fs') 7 | const path = require('path') 8 | const cwd = path.join(__dirname, '..') 9 | 10 | var win = null 11 | 12 | // Quit when all windows are closed. 13 | app.on('window-all-closed', function() { 14 | app.quit() 15 | }) 16 | 17 | // This method will be called when Electron has finished 18 | // initialization and is ready to create browser windows. 19 | app.on('ready', function() { 20 | let binName = "" 21 | 22 | // get the operating system 23 | if (os.type() == 'Linux') { 24 | binName = "service" 25 | } else if (os.type() == 'Darwin') { 26 | binName = "service" 27 | } else if (os.type() == 'Windows_NT') { 28 | binName = "service.exe" 29 | } 30 | 31 | // start the backend 32 | var service = execFile(`${__dirname}/${binName}`, { 33 | env: { 34 | "LEVEL": "debug" 35 | } 36 | }, (error, stdout, stderr) => { 37 | if(error) { 38 | console.error(error) 39 | app.quit 40 | } 41 | }) 42 | 43 | 44 | // Create the browser window. 45 | win = new BrowserWindow({ 46 | title: "Coffer", 47 | width: 800, 48 | height: 600, 49 | frame: true, 50 | center: true, 51 | }) 52 | 53 | win.on('closed', function() { 54 | win = null 55 | }) 56 | 57 | win.once('ready-to-show', () => { 58 | win.show() 59 | }) 60 | 61 | // Remove the app menu 62 | win.setMenuBarVisibility(false) 63 | 64 | // load the application page 65 | win.loadURL(`file://${__dirname}/index.html`); 66 | 67 | // Open the DevTools. 68 | 69 | if (process.env.DEBUG === "true") { 70 | win.webContents.openDevTools() 71 | } 72 | 73 | }) 74 | -------------------------------------------------------------------------------- /src/app/src/components/notification.jsx: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | import React, { PropTypes } from 'react' 3 | 4 | class Notification extends React.Component { 5 | constructor(props) { 6 | super(props) 7 | } 8 | 9 | open() { 10 | inst.open() 11 | } 12 | 13 | 14 | render(){ 15 | // TODO: Modal structure 16 | return ( 17 |
18 |
19 | ) 20 | } 21 | } 22 | 23 | export default Notification 24 | -------------------------------------------------------------------------------- /src/app/src/components/websocket.jsx: -------------------------------------------------------------------------------- 1 | export default class websocket { 2 | constructor() { 3 | this.ws = new WebSocket("ws://localhost:5050") 4 | } 5 | 6 | send(payload) { 7 | console.debug(payload) 8 | this.ws.send(JSON.stringify(payload)) 9 | } 10 | 11 | listen() { 12 | return new Promise((resolve, reject) => { 13 | 14 | this.ws.addEventListener('message', (event) => { 15 | let response = JSON.parse(event.data) 16 | 17 | if (response.error) { 18 | reject(response.error) 19 | } 20 | 21 | console.debug(response) 22 | resolve(response) 23 | }) 24 | 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/src/container.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'react-router' 3 | 4 | class Container extends React.Component { 5 | render() { 6 | return ( 7 |
8 | {this.props.children} 9 |
10 | ) 11 | } 12 | } 13 | 14 | export default Container 15 | -------------------------------------------------------------------------------- /src/app/src/less/alerts.less: -------------------------------------------------------------------------------- 1 | /* =Alerts 2 | -----------------------------------------------------------------------------*/ 3 | .alert { 4 | position: relative; 5 | padding: @base-line / 2 @base-line; 6 | padding-right: 32px; 7 | line-height: @base-line; 8 | font-size: 94%; 9 | color: rgba(0, 0, 0, 1); 10 | display: block; 11 | font-weight: normal; 12 | border-radius: @global-radius; 13 | margin-bottom: @base-line; 14 | &.alert-primary { 15 | color: @color-primary; 16 | & a, 17 | & h5 { 18 | color: @color-primary; 19 | } 20 | background-color: rgba(red(@color-primary), green(@color-primary), blue(@color-primary), .15); 21 | } 22 | &.alert-error { 23 | color: @color-error; 24 | & a, 25 | & h5 { 26 | color: @color-error; 27 | } 28 | background-color: rgba(red(@color-error), green(@color-error), blue(@color-error), .15); 29 | } 30 | &.alert-warning { 31 | color: darken(@color-warning, 15); 32 | & a, 33 | & h5 { 34 | color: darken(@color-warning, 15); 35 | } 36 | background-color: rgba(red(@color-warning), green(@color-warning), blue(@color-warning), .23); 37 | } 38 | &.alert-success { 39 | color: @color-success; 40 | & a, 41 | & h5 { 42 | color: @color-success; 43 | } 44 | background-color: rgba(red(@color-success), green(@color-success), blue(@color-success), .13); 45 | } 46 | & a { 47 | font-weight: bold; 48 | &:hover { 49 | color: #000; 50 | } 51 | } 52 | & span.close { 53 | position: absolute; 54 | top: 0; 55 | right: 0; 56 | padding: .5rem 1rem; 57 | opacity: .6; 58 | cursor: pointer; 59 | &:hover { 60 | opacity: 1; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/app/src/less/blocks.less: -------------------------------------------------------------------------------- 1 | /* =Blocks 2 | -----------------------------------------------------------------------------*/ 3 | blocks { 4 | display: -webkit-box; 5 | display: -moz-box; 6 | display: -ms-flexbox; 7 | display: -webkit-flex; 8 | display: flex; 9 | -webkit-flex-wrap: wrap; 10 | -ms-flex-wrap: wrap; 11 | flex-wrap: wrap; 12 | margin-left: -@grid-gap; 13 | 14 | & > div { 15 | margin-left: @grid-gap; 16 | margin-bottom: @base-line; 17 | } 18 | 19 | &[cols="2"] > div { width: 50% - @grid-gap; } 20 | &[cols="3"] > div { width: 33.3% - @grid-gap; } 21 | &[cols="4"] > div { width: 25% - @grid-gap; } 22 | &[cols="5"] > div { width: 20% - @grid-gap; } 23 | &[cols="6"] > div { width: 16.6% - @grid-gap; } 24 | } 25 | 26 | @media (max-width: @breakpoint-small) { 27 | 28 | blocks { 29 | 30 | display: block; 31 | margin-left: 0; 32 | 33 | &[cols="2"] > div, 34 | &[cols="3"] > div, 35 | &[cols="4"] > div, 36 | &[cols="5"] > div, 37 | &[cols="6"] > div { 38 | width: 100%; 39 | margin-left: 0; 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/app/src/less/breadcrumbs.less: -------------------------------------------------------------------------------- 1 | /* =Breadcrumbs 2 | -----------------------------------------------------------------------------*/ 3 | .breadcrumb { 4 | 5 | margin: 0; 6 | list-style: none; 7 | margin-bottom: @base-line; 8 | font-size: @font-size-small; 9 | color: rgba(0, 0, 0, .5); 10 | .clearfix; 11 | & li { 12 | float: left; 13 | } 14 | & a { 15 | position: relative; 16 | margin-right: 8px; 17 | padding-right: 13px; 18 | color: #000; 19 | text-decoration: none; 20 | &:hover { 21 | .transition(); 22 | color: rgba(0, 0, 0, .6); 23 | text-decoration: underline; 24 | } 25 | } 26 | & a:before { 27 | position: absolute; 28 | top: -5px; 29 | right: 0; 30 | content: " > "; 31 | color: rgba(0, 0, 0, .4); 32 | font-size: 12px; 33 | } 34 | &.breadcrumb-path a:before { 35 | content: " / "; 36 | top: -4px; 37 | } 38 | 39 | & span, 40 | & a.active:hover { 41 | text-decoration: none; 42 | cursor: text; 43 | color: rgba(0, 0, 0, .4); 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/app/src/less/coffer.less: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | height: .33em; 3 | } 4 | 5 | ::-webkit-scrollbar-track { 6 | // -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); 7 | } 8 | 9 | ::-webkit-scrollbar-thumb { 10 | background-color: #e3e3e3; 11 | outline: 1px solid slategrey; 12 | } 13 | 14 | 15 | .password { 16 | max-width: 30rem; 17 | overflow-x: hidden; 18 | white-space: nowrap; 19 | 20 | -webkit-text-security: disc; 21 | -mos-text-security: disc; 22 | text-security: disc; 23 | 24 | &:hover{ 25 | overflow-x: auto; 26 | 27 | -webkit-text-security: none; 28 | -mos-text-security: none; 29 | text-security: none; 30 | } 31 | 32 | } 33 | 34 | .btn[type="red"], 35 | button[type="red"] { 36 | .make-btn(#f23d3d, 10); 37 | .transition(all .17s ease-in-out); 38 | } 39 | 40 | .confirmed { 41 | .transition(all .17s ease-in-out); 42 | background: @color-success !important; 43 | border-color: @color-success !important; 44 | color: rgba(255, 255, 255, .9) !important; 45 | } 46 | -------------------------------------------------------------------------------- /src/app/src/less/helpers.less: -------------------------------------------------------------------------------- 1 | /* =Helpers 2 | -----------------------------------------------------------------------------*/ 3 | .group { 4 | .clearfix; 5 | } 6 | .hide { 7 | display: none; 8 | } 9 | .visible { 10 | visibility: visible; 11 | } 12 | .hidden { 13 | visibility: hidden; 14 | } 15 | .centered { 16 | margin: auto; 17 | } 18 | .highlight { 19 | background-color: @color-highlighted-background; 20 | } 21 | .big { 22 | font-size: @font-size-big; 23 | } 24 | .small { 25 | font-size: @font-size-small; 26 | } 27 | .smaller { 28 | font-size: @font-size-smaller; 29 | } 30 | p, 31 | ul, 32 | ol, 33 | dl, 34 | blockquote, 35 | hr, 36 | pre, 37 | table, 38 | form, 39 | fieldset, 40 | figure, 41 | address { 42 | &.small { 43 | line-height: @base-line-small; 44 | } 45 | &.smaller { 46 | line-height: @base-line-smaller; 47 | } 48 | &.big { 49 | line-height: @base-line-big; 50 | } 51 | } 52 | .nowrap, 53 | .nowrap td { 54 | white-space: nowrap; 55 | } 56 | .req { 57 | font-weight: bold; 58 | color: @color-error; 59 | font-size: 1.1em; 60 | text-transform: none; 61 | } 62 | .error { 63 | color: @color-error; 64 | } 65 | .success { 66 | color: @color-success; 67 | } 68 | .text-centered { 69 | text-align: center; 70 | } 71 | .text-right { 72 | text-align: right; 73 | } 74 | .text-left { 75 | text-align: left !important; 76 | } 77 | .start { 78 | margin-top: 0 !important; 79 | } 80 | .last { 81 | margin-right: 0 !important; 82 | } 83 | .end { 84 | margin-bottom: 0 !important; 85 | } 86 | .normal { 87 | font-weight: normal !important; 88 | } 89 | .light { 90 | font-weight: 300 !important; 91 | } 92 | .thin { 93 | font-weight: 100 !important; 94 | } 95 | .bold { 96 | font-weight: bold !important; 97 | } 98 | .italic { 99 | font-style: italic !important; 100 | } 101 | .upper { 102 | text-transform: uppercase; 103 | } 104 | .list-flat { 105 | margin-left: 0; 106 | list-style: none; 107 | } 108 | .muted { 109 | color: rgba(0, 0, 0, .5); 110 | } 111 | .soft-muted { 112 | color: rgba(0, 0, 0, .7); 113 | } 114 | .color-black { 115 | color: rgba(0, 0, 0, 1); 116 | } 117 | a.color-black:hover { 118 | color: rgba(0, 0, 0, .6); 119 | } 120 | .color-white { 121 | color: rgba(255, 255, 255, 1); 122 | } 123 | a.color-white:hover { 124 | color: rgba(255, 255, 255, .6); 125 | } 126 | 127 | // Responsive Utilities 128 | @media (max-width: @breakpoint-small) { 129 | .hide-for-small { 130 | display: none; 131 | } 132 | } 133 | @media (min-width: @breakpoint-small) { 134 | .show-for-small { 135 | display: none; 136 | } 137 | .left { 138 | float: none; 139 | float: left; 140 | } 141 | .right { 142 | float: none; 143 | float: right; 144 | } 145 | } 146 | 147 | @media print { 148 | .hide-for-print { 149 | display: none !important; 150 | } 151 | .show-for-print { 152 | display: block !important; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/app/src/less/kube.less: -------------------------------------------------------------------------------- 1 | /* 2 | Kube Framework 5 3 | */ 4 | 5 | @import "mixins.less"; 6 | @import "variables.less"; 7 | 8 | // Base 9 | @import "reset.less"; 10 | @import "typography.less"; 11 | 12 | @import "grid.less"; 13 | @import "blocks.less"; 14 | 15 | @import "tables.less"; 16 | @import "forms.less"; 17 | 18 | @import "buttons.less"; 19 | @import "labels.less"; 20 | 21 | @import "messages.less"; 22 | @import "alerts.less"; 23 | 24 | // Navigation 25 | @import "breadcrumbs.less"; 26 | @import "pagination.less"; 27 | 28 | // Helpers 29 | @import "helpers.less"; 30 | 31 | // Custom 32 | @import "coffer.less"; 33 | -------------------------------------------------------------------------------- /src/app/src/less/labels.less: -------------------------------------------------------------------------------- 1 | /* =Labels 2 | -----------------------------------------------------------------------------*/ 3 | 4 | @tag-padding-y: .2rem; 5 | @tag-padding-x: .7rem; 6 | 7 | .label, 8 | .badge { 9 | font-size: @font-size-label; 10 | font-weight: normal; 11 | display: inline; 12 | line-height: 1; 13 | color: #000; 14 | text-align: center; 15 | text-transform: uppercase; 16 | text-decoration: none; 17 | border-radius: @global-radius; 18 | padding: @tag-padding-y @tag-padding-x; 19 | position: relative; 20 | & a { 21 | color: #000; 22 | text-decoration: none; 23 | &:hover { 24 | .transition; 25 | color: rgba(0, 0, 0, .6); 26 | } 27 | } 28 | &:empty { 29 | display: none; 30 | } 31 | &[bold] { 32 | font-weight: bold; 33 | } 34 | &[outline] { 35 | background: none; 36 | color: rgba(0, 0, 0, .7); 37 | border: 1px solid rgba(0, 0, 0, .5); 38 | padding: @tag-padding-y - .1rem @tag-padding-x - .1rem; 39 | &[bold] { 40 | border-width: 2px; 41 | padding: @tag-padding-y - .2rem @tag-padding-x - .2rem; 42 | } 43 | } 44 | &.label-default, 45 | &.badge-default { 46 | .make-label(#e4e4e4, #000); 47 | } 48 | &.label-primary, 49 | &.badge-primary { 50 | .make-label(@color-primary, #fff); 51 | } 52 | &.label-error, 53 | &.badge-error { 54 | .make-label(@color-error, #fff); 55 | } 56 | &.label-success, 57 | &.badge-success { 58 | .make-label(@color-success, #fff); 59 | } 60 | &.label-warning, 61 | &.badge-warning { 62 | .make-label(@color-warning, #000); 63 | } 64 | &.label-black, 65 | &.badge-black { 66 | .make-label(#000, #fff); 67 | } 68 | &.label-white, 69 | &.badge-white { 70 | .make-label(#fff, #000); 71 | } 72 | } 73 | .badge { 74 | border-radius: 30px; 75 | min-width: 17px; 76 | } 77 | 78 | .title, 79 | .large, 80 | h1, 81 | h2, 82 | h3, 83 | h4, 84 | h5, 85 | h6 { 86 | & .label, 87 | & .badge { 88 | vertical-align: middle; 89 | } 90 | } 91 | h3, 92 | h4, 93 | h5 { 94 | & .label, 95 | & .badge { 96 | top: -1px; 97 | } 98 | } 99 | h6 { 100 | & .label, 101 | & .badge { 102 | top: -2px; 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /src/app/src/less/messages.less: -------------------------------------------------------------------------------- 1 | /* =Messages 2 | -----------------------------------------------------------------------------*/ 3 | .message { 4 | 5 | border-radius: @global-radius; 6 | display: none; 7 | position: fixed; 8 | z-index: 2000; 9 | top: @margin-half; 10 | right: @margin-half; 11 | max-width: 360px; 12 | line-height: 1.45; 13 | font-size: 94%; 14 | padding: @base-line (@base-line * 1.5); 15 | color: rgba(0, 0, 0, .9); 16 | &.message-line { 17 | top: 0; 18 | right: 0; 19 | left: 0; 20 | width: 100%; 21 | padding-right: 200px; 22 | max-width: none; 23 | border-radius: 0; 24 | & footer { 25 | position: absolute; 26 | top: 0; 27 | right: 2rem; 28 | } 29 | } 30 | & ul, 31 | & ol { 32 | margin-top: 8px; 33 | margin-bottom: 0; 34 | } 35 | & footer { 36 | margin-top: 8px; 37 | } 38 | & a { 39 | font-weight: bold; 40 | } 41 | &.message-primary, 42 | &.message-error, 43 | &.message-success { 44 | color: rgba(255, 255, 255, .9); 45 | & a { 46 | color: rgba(255, 255, 255, .9); 47 | &:hover { 48 | color: rgba(255, 255, 255, .7); 49 | } 50 | } 51 | } 52 | &.message-primary { 53 | background: @color-primary; 54 | } 55 | &.message-error { 56 | background: @color-error; 57 | } 58 | &.message-warning { 59 | background: @color-warning; 60 | } 61 | &.message-success { 62 | background: @color-success; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/app/src/less/pagination.less: -------------------------------------------------------------------------------- 1 | /* =Pagination 2 | -----------------------------------------------------------------------------*/ 3 | .pagination { 4 | list-style: none; 5 | margin: 0; 6 | margin-left: 2px; 7 | margin-bottom: @base-line; 8 | font-size: @font-size-tools; 9 | .clearfix; 10 | & li { 11 | float: left; 12 | } 13 | & a, 14 | & span { 15 | padding: 4px 8px; 16 | line-height: @base-line; 17 | margin-right: 2px; 18 | border-radius: 2px; 19 | color: #000; 20 | text-decoration: none; 21 | } 22 | & span, 23 | & a.active, 24 | & a.active:hover { 25 | color: rgba(0, 0, 0, .6); 26 | background-color: rgba(0, 0, 0, .1); 27 | cursor: text; 28 | } 29 | & a:focus, 30 | & a:hover { 31 | .transition(); 32 | text-decoration: none; 33 | background-color: rgba(0, 0, 0, .1); 34 | color: rgba(0, 0, 0, .6); 35 | } 36 | &.centered { 37 | 38 | & li { 39 | float: none; 40 | display: inline-block; 41 | } 42 | text-align: center; 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/app/src/less/tables.less: -------------------------------------------------------------------------------- 1 | /* =Tables 2 | -----------------------------------------------------------------------------*/ 3 | table { 4 | max-width: 100%; 5 | width: 100%; 6 | empty-cells: show; 7 | 8 | caption { 9 | text-transform: uppercase; 10 | padding: 0; 11 | color: #000; 12 | font-size: 11px; 13 | font-weight: bold; 14 | } 15 | 16 | th, 17 | td { 18 | font-size: @font-size-table; 19 | border-bottom: 1px solid rgba(0, 0, 0, .04); 20 | padding: 16px; 21 | padding-bottom: 15px; 22 | &:first-child { 23 | padding-left: 0; 24 | } 25 | &:last-child { 26 | padding-right: 0; 27 | } 28 | } 29 | 30 | tfoot th, 31 | tfoot td { 32 | color: rgba(0, 0, 0, .5); 33 | } 34 | } 35 | 36 | table.table-bordered { 37 | 38 | margin-top: -1px; 39 | 40 | & td, 41 | & th { 42 | border: 1px solid rgba(0, 0, 0, .03); 43 | } 44 | & caption { 45 | padding-left: 16px; 46 | } 47 | } 48 | table.table-bordered, 49 | table.table-stripped { 50 | & td, 51 | & th { 52 | &:first-child { 53 | padding-left: 16px; 54 | } 55 | &:last-child { 56 | padding-right: 16px; 57 | } 58 | } 59 | } 60 | table.table-simple { 61 | & td, 62 | & th, 63 | & caption { 64 | border: none; 65 | padding-left: 0; 66 | } 67 | & td, 68 | & th { 69 | padding-bottom: 16px; 70 | } 71 | } 72 | table.table-flat { 73 | & td, 74 | & th, 75 | & caption { 76 | border: none; 77 | padding: 0; 78 | } 79 | } 80 | table.table-stroked { 81 | & td, 82 | & th { 83 | border-bottom: 1px solid rgba(0, 0, 0, .03); 84 | } 85 | } 86 | table.table-stripped tbody tr:nth-child(odd) td { 87 | background: @color-table-stripped; 88 | } 89 | 90 | @media (max-width: @breakpoint-small) { 91 | 92 | table.table-responsive { 93 | 94 | border: 0; 95 | 96 | & thead { 97 | display: none; 98 | } 99 | & tr { 100 | display: block; 101 | border-bottom: 2px solid rgba(0, 0, 0, .1); 102 | } 103 | 104 | & td, 105 | & td:last-child, 106 | & td:first-child { 107 | display: block; 108 | text-align: right; 109 | padding: 10px; 110 | } 111 | 112 | &.table-flat td { 113 | padding: 0; 114 | } 115 | 116 | &.table-bordered td:last-child, 117 | & td:last-child { 118 | border-bottom: 0; 119 | } 120 | 121 | & td:before { 122 | content: attr(data-label); 123 | float: left; 124 | text-transform: uppercase; 125 | font-size: @font-size-small; 126 | font-weight: bold; 127 | line-height: 2; 128 | } 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /src/app/src/main.jsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom' 2 | import { Router, hashHistory, Route, IndexRoute } from 'react-router' 3 | 4 | import Container from './container' 5 | 6 | import Login from './pages/login' 7 | import Manager from './pages/manager' 8 | import About from './pages/about' 9 | 10 | ReactDOM.render( 11 | 12 | 13 | 14 | 15 | 16 | 17 | , 18 | document.getElementById('app') 19 | ) 20 | -------------------------------------------------------------------------------- /src/app/src/pages/about.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react' 2 | import { Router, Route, IndexRoute, Link, hashHistory } from 'react-router' 3 | 4 | class About extends React.Component { 5 | render () { 6 | return ( 7 |
8 |

About

9 |

Some about

10 |
11 | ) 12 | } 13 | } 14 | 15 | export default About 16 | -------------------------------------------------------------------------------- /src/app/src/pages/login.jsx: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react' 2 | import { Link } from 'react-router' 3 | import websocket from '../components/websocket.jsx' 4 | 5 | class Login extends React.Component { 6 | constructor(props) { 7 | super(props) 8 | 9 | this.ws = new websocket() 10 | this.props = props 11 | this.state = { 12 | master: "", 13 | } 14 | } 15 | 16 | handleMaster(e) { 17 | e.preventDefault() 18 | this.setState({master: e.target.value}); 19 | } 20 | 21 | handleKeypress(e) { 22 | if (e.key == 'Enter') { 23 | this.handleSubmit(e) 24 | } 25 | } 26 | 27 | // handleSubmit inserts the data into store 28 | handleSubmit(e) { 29 | e.preventDefault() 30 | 31 | let request = { 32 | action: "LOGIN", 33 | payload: { 34 | password: this.state.master, 35 | } 36 | } 37 | 38 | console.log(request); 39 | this.ws.send(JSON.stringify(request)) 40 | 41 | // on success coninue to the manager 42 | this.props.history.push('manager'); 43 | } 44 | 45 | render () { 46 | return ( 47 |
48 | 49 | 50 |

Login

51 |
52 |
53 | 54 | 55 |
56 |
57 | 63 |
64 |
65 | 66 | 67 | 68 |
69 |
70 |
71 |
72 |
73 | ) 74 | } 75 | 76 | } 77 | 78 | export default Login 79 | -------------------------------------------------------------------------------- /src/app/src/pages/manager.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Notification from '../components/notification' 3 | import { PasswordList, PasswordListAdd } from '../components/manager' 4 | 5 | class Manager extends React.Component { 6 | render () { 7 | return ( 8 |
9 | { /* Greeting */ } 10 | 11 | 12 |

Coffer

13 |

Your light-weight, easy to use, secure, password manager

14 |
15 |
16 | 17 | 18 | 19 |
20 | ) 21 | } 22 | } 23 | 24 | export default Manager 25 | -------------------------------------------------------------------------------- /src/service/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "service/router" 6 | "service/store" 7 | 8 | "github.com/sirupsen/logrus" 9 | ) 10 | 11 | var ( 12 | level = os.Getenv("LOG_LEVEL") 13 | ) 14 | 15 | func main() { 16 | 17 | switch level { 18 | case "debug": 19 | logrus.SetLevel(logrus.DebugLevel) 20 | case "info": 21 | logrus.SetLevel(logrus.InfoLevel) 22 | default: 23 | logrus.SetLevel(logrus.ErrorLevel) 24 | } 25 | 26 | dataStore, err := store.Start() 27 | if err != nil { 28 | logrus.WithFields(logrus.Fields{ 29 | "realm": "start store", 30 | }).Error(err) 31 | os.Exit(-1) 32 | } 33 | 34 | err = router.Start("5050", dataStore) 35 | if err != nil { 36 | logrus.Error(err) 37 | os.Exit(-1) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/service/router/handlers.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "service/store" 5 | 6 | "github.com/sirupsen/logrus" 7 | ) 8 | 9 | // TODO: implement 10 | func handleLogin(m *Message) error { 11 | // logrus.WithFields(logrus.Fields{ 12 | // "action": m.Action, 13 | // "password": m.Payload.Password, 14 | // }).Debug("received websocket request") 15 | // 16 | // // Initialise our crypter 17 | // crypter, err := store.InitaliaseCrypter(m.Payload.Password) 18 | // if err != nil { 19 | // logrus.Error(err) 20 | // return err 21 | // } 22 | // 23 | // dataStore.AddCrypter(crypter) 24 | return nil 25 | } 26 | 27 | func handleAll(m *Message) ([]*store.Entry, error) { 28 | logrus.WithFields(logrus.Fields{ 29 | "action": m.Action, 30 | }).Debug("received websocket request") 31 | 32 | return dataStore.All() 33 | } 34 | 35 | func handleAdd(m *Message) ([]*store.Entry, error) { 36 | logrus.WithFields(logrus.Fields{ 37 | "action": m.Action, 38 | }).Debug("received websocket request") 39 | 40 | if err := dataStore.Put(m.Payload); err != nil { 41 | return nil, err 42 | } 43 | 44 | // Resend the updated store 45 | return dataStore.All() 46 | } 47 | 48 | func handleDelete(m *Message) ([]*store.Entry, error) { 49 | logrus.WithFields(logrus.Fields{ 50 | "action": m.Action, 51 | }).Debug("received websocket request") 52 | 53 | if err := dataStore.Delete(m.Payload); err != nil { 54 | return nil, err 55 | } 56 | 57 | // Resend the updated store 58 | return dataStore.All() 59 | } 60 | -------------------------------------------------------------------------------- /src/service/router/handlers_test.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "service/store" 5 | "testing" 6 | ) 7 | 8 | type MockStore struct{} 9 | 10 | func (ms *MockStore) All() ([]*store.Entry, error) { 11 | return []*store.Entry{ 12 | &store.Entry{ 13 | ID: []byte("the id"), 14 | Key: []byte("the key"), 15 | Value: []byte("the value"), 16 | }, 17 | }, nil 18 | } 19 | func (ms *MockStore) Put(e *store.Entry) error { return nil } 20 | func (ms *MockStore) Delete(e *store.Entry) error { return nil } 21 | func (ms *MockStore) AddCrypter(c *store.Crypter) { return } 22 | func init() { 23 | dataStore = &MockStore{} 24 | } 25 | 26 | func TestHandleAll(t *testing.T) { 27 | msg := &Message{} 28 | resp, err := handleAll(msg) 29 | if err != nil { 30 | t.Error(err) 31 | } 32 | 33 | if len(resp) != 1 { 34 | t.Errorf("exptect respose length of %v got %v", 1, len(resp)) 35 | } 36 | 37 | for _, entry := range resp { 38 | if recv := string(entry.ID); recv != "the id" { 39 | t.Errorf("expected %v got %v", "the id", recv) 40 | } 41 | if recv := string(entry.Key); recv != "the key" { 42 | t.Errorf("expected %v got %v", "the key", recv) 43 | } 44 | if recv := string(entry.Value); recv != "the value" { 45 | t.Errorf("expected %v got %v", "the value", recv) 46 | } 47 | } 48 | } 49 | 50 | func TestHandleAdd(t *testing.T) { 51 | msg := &Message{} 52 | resp, err := handleAdd(msg) 53 | if err != nil { 54 | t.Error(err) 55 | } 56 | 57 | if len(resp) != 1 { 58 | t.Errorf("exptect respose length of %v got %v", 1, len(resp)) 59 | } 60 | 61 | for _, entry := range resp { 62 | if recv := string(entry.ID); recv != "the id" { 63 | t.Errorf("expected %v got %v", "the id", recv) 64 | } 65 | if recv := string(entry.Key); recv != "the key" { 66 | t.Errorf("expected %v got %v", "the key", recv) 67 | } 68 | if recv := string(entry.Value); recv != "the value" { 69 | t.Errorf("expected %v got %v", "the value", recv) 70 | } 71 | } 72 | } 73 | 74 | func TestHandleDelete(t *testing.T) { 75 | msg := &Message{} 76 | resp, err := handleDelete(msg) 77 | if err != nil { 78 | t.Error(err) 79 | } 80 | 81 | if len(resp) != 1 { 82 | t.Errorf("exptect respose length of %v got %v", 1, len(resp)) 83 | } 84 | 85 | for _, entry := range resp { 86 | if recv := string(entry.ID); recv != "the id" { 87 | t.Errorf("expected %v got %v", "the id", recv) 88 | } 89 | if recv := string(entry.Key); recv != "the key" { 90 | t.Errorf("expected %v got %v", "the key", recv) 91 | } 92 | if recv := string(entry.Value); recv != "the value" { 93 | t.Errorf("expected %v got %v", "the value", recv) 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/service/router/model.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import "service/store" 4 | 5 | // Message is the structure of a message we will send and receive over websocket 6 | type Message struct { 7 | Action string `json:"action"` 8 | Payload *store.Entry `json:"payload"` 9 | } 10 | 11 | // Response is the strict message structure in which we send responses to the client 12 | type Response struct { 13 | Error error `json:"error"` 14 | Message []*store.Entry `json:"message"` 15 | } 16 | -------------------------------------------------------------------------------- /src/service/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "net/http" 7 | "os/user" 8 | "sync" 9 | 10 | "service/store" 11 | 12 | "github.com/gorilla/websocket" 13 | "github.com/sirupsen/logrus" 14 | ) 15 | 16 | // Websocket actions 17 | const ( 18 | LOGIN = "LOGIN" 19 | ADD = "ADD" 20 | ALL = "ALL" 21 | GET = "GET" 22 | DELETE = "DELETE" 23 | ) 24 | 25 | var ( 26 | upgrader = websocket.Upgrader{ 27 | ReadBufferSize: 2048, 28 | WriteBufferSize: 2048, 29 | CheckOrigin: func(r *http.Request) bool { return true }, 30 | } 31 | 32 | wg sync.WaitGroup 33 | 34 | dataStore store.Datastore 35 | 36 | usr, _ = user.Current() 37 | baseDir = usr.HomeDir + "/.coffer" 38 | ) 39 | 40 | // Start initialises the routes and started a listener 41 | func Start(port string, ds *store.Store) error { 42 | dataStore = ds 43 | 44 | logrus.Debugf("starting router on port %s", port) 45 | 46 | http.HandleFunc("/", handler) 47 | http.ListenAndServe(":"+port, nil) 48 | 49 | return nil 50 | } 51 | 52 | func handler(w http.ResponseWriter, r *http.Request) { 53 | conn, err := upgrader.Upgrade(w, r, nil) 54 | if err != nil { 55 | log.Println(err) 56 | return 57 | } 58 | 59 | defer conn.Close() 60 | for { 61 | var ( 62 | m *Message 63 | ) 64 | 65 | if err := conn.ReadJSON(&m); err != nil { 66 | if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) { 67 | logrus.Error(err) 68 | } 69 | break 70 | } 71 | 72 | switch m.Action { 73 | case LOGIN: 74 | err := handleLogin(m) 75 | if err != nil { 76 | logrus.Error(err) 77 | } 78 | 79 | conn.WriteJSON(Response{ 80 | Error: err, 81 | }) 82 | 83 | case ALL: 84 | resp, err := handleAll(m) 85 | if err != nil { 86 | logrus.Error(err) 87 | } 88 | 89 | conn.WriteJSON(Response{ 90 | Error: err, 91 | Message: resp, 92 | }) 93 | case ADD: 94 | resp, err := handleAdd(m) 95 | if err != nil { 96 | logrus.Error(err) 97 | } 98 | 99 | conn.WriteJSON(Response{ 100 | Error: err, 101 | Message: resp, 102 | }) 103 | case DELETE: 104 | resp, err := handleDelete(m) 105 | if err != nil { 106 | logrus.Error(err) 107 | } 108 | 109 | conn.WriteJSON(Response{ 110 | Error: err, 111 | Message: resp, 112 | }) 113 | default: 114 | conn.WriteJSON(Response{ 115 | Error: ErrInvalidAction, 116 | }) 117 | } 118 | } 119 | } 120 | 121 | // List of error messages 122 | var ( 123 | ErrInvalidAction = errors.New("invalid action") 124 | ) 125 | -------------------------------------------------------------------------------- /src/service/store/encryption_test.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import "testing" 4 | 5 | var ( 6 | key = "something that satisifies 32...." 7 | cipherText string 8 | ) 9 | 10 | func TestEncrypt(t *testing.T) { 11 | crypter, err := InitaliaseCrypter(key) 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | // Test for 32 byte strings 16 | c, err := crypter.Encrypt([]byte("something that satisifies 32....")) 17 | if err != nil { 18 | t.Error(err) 19 | } 20 | 21 | // Test for sub-32 bytes with padding 22 | _, err = crypter.Encrypt([]byte("this is odd")) 23 | if err != nil { 24 | t.Error(err) 25 | } 26 | 27 | /* 28 | * Test the key generation 29 | */ 30 | 31 | _, err = InitaliaseCrypter("") 32 | if err == nil { 33 | t.Errorf("expected %v got %v", err, nil) 34 | } 35 | 36 | // Push out cipher to a varible to decrypt 37 | cipherText = c 38 | } 39 | 40 | func TestDecrypt(t *testing.T) { 41 | crypter, err := InitaliaseCrypter(key) 42 | if err != nil { 43 | t.Error(err) 44 | } 45 | 46 | plaintext, err := crypter.Decrypt([]byte(cipherText)) 47 | if err != nil { 48 | t.Error(err) 49 | } 50 | 51 | expected := "something that satisifies 32...." 52 | if string(plaintext) != expected { 53 | t.Errorf("error expected %s got %s", expected, plaintext) 54 | } 55 | 56 | } 57 | 58 | func TestPad(t *testing.T) { 59 | in := []byte("memes") 60 | resp := pad(in) 61 | if string(resp) != "memes000000000000000000000000000" { 62 | t.Errorf("got incorrect padding length of %v", len(resp)) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/service/store/model.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import "github.com/boltdb/bolt" 4 | 5 | // Datastore is the interface for a store 6 | type Datastore interface { 7 | All() ([]*Entry, error) 8 | Put(e *Entry) error 9 | Delete(e *Entry) error 10 | AddCrypter(c *Crypter) 11 | } 12 | 13 | // Store holds the Bolt database and our Crypter. It should satisfy the 14 | // Datastore interface 15 | type Store struct { 16 | DB *bolt.DB 17 | Crypter *Crypter 18 | } 19 | 20 | // Entry is the format of a database entry 21 | type Entry struct { 22 | ID []byte `json:"key"` 23 | Key []byte `json:"identifier"` 24 | Value []byte `json:"value"` 25 | 26 | Password string `json:"password,omitempty"` 27 | } 28 | 29 | // LoginRequest is the request we receive when a user enters their master 30 | // password into the front end 31 | type LoginRequest struct { 32 | Master string `json:"master"` 33 | } 34 | -------------------------------------------------------------------------------- /vendor/manifest: -------------------------------------------------------------------------------- 1 | { 2 | "version": 0, 3 | "dependencies": [ 4 | { 5 | "importpath": "github.com/boltdb/bolt", 6 | "repository": "https://github.com/boltdb/bolt", 7 | "revision": "d97499360d1ecebc492ea66c7447ea948f417620", 8 | "branch": "master" 9 | }, 10 | { 11 | "importpath": "github.com/dustin/go-broadcast", 12 | "repository": "https://github.com/dustin/go-broadcast", 13 | "revision": "3bdf6d4a7164a50bc19d5f230e2981d87d2584f1", 14 | "branch": "master" 15 | }, 16 | { 17 | "importpath": "github.com/golang/protobuf/proto", 18 | "repository": "https://github.com/golang/protobuf", 19 | "revision": "7cc19b78d562895b13596ddce7aafb59dd789318", 20 | "branch": "master", 21 | "path": "/proto" 22 | }, 23 | { 24 | "importpath": "github.com/gorilla/websocket", 25 | "repository": "https://github.com/gorilla/websocket", 26 | "revision": "1f512fc3f05332ba7117626cdfb4e07474e58e60", 27 | "branch": "master" 28 | }, 29 | { 30 | "importpath": "github.com/manucorporat/sse", 31 | "repository": "https://github.com/manucorporat/sse", 32 | "revision": "ee05b128a739a0fb76c7ebd3ae4810c1de808d6d", 33 | "branch": "master" 34 | }, 35 | { 36 | "importpath": "github.com/manucorporat/stats", 37 | "repository": "https://github.com/manucorporat/stats", 38 | "revision": "8f2d6ace262eba462e9beb552382c98be51d807b", 39 | "branch": "master" 40 | }, 41 | { 42 | "importpath": "github.com/sirupsen/logrus", 43 | "repository": "https://github.com/sirupsen/logrus", 44 | "revision": "cd7d1bbe41066b6c1f19780f895901052150a575", 45 | "branch": "master" 46 | }, 47 | { 48 | "importpath": "golang.org/x/net/context", 49 | "repository": "https://go.googlesource.com/net", 50 | "revision": "1aafd77e1e7f6849ad16a7bdeb65e3589a10b2bb", 51 | "branch": "master", 52 | "path": "/context" 53 | }, 54 | { 55 | "importpath": "gopkg.in/airbrake/gobrake.v2", 56 | "repository": "https://gopkg.in/airbrake/gobrake.v2", 57 | "revision": "31c8ff1fb8b79a6947e6565e9a6df535f98a6b94", 58 | "branch": "master" 59 | }, 60 | { 61 | "importpath": "gopkg.in/gemnasium/logrus-airbrake-hook.v2", 62 | "repository": "https://gopkg.in/gemnasium/logrus-airbrake-hook.v2", 63 | "revision": "31e6fd4bd5a98d8ee7673d24bc54ec73c31810dd", 64 | "branch": "master" 65 | }, 66 | { 67 | "importpath": "gopkg.in/go-playground/validator.v8", 68 | "repository": "https://gopkg.in/go-playground/validator.v8", 69 | "revision": "014792cf3e266caff1e916876be12282b33059e0", 70 | "branch": "master" 71 | }, 72 | { 73 | "importpath": "gopkg.in/yaml.v2", 74 | "repository": "https://gopkg.in/yaml.v2", 75 | "revision": "a83829b6f1293c91addabc89d0571c246397bbf4", 76 | "branch": "v2" 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/boltdb/bolt.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/boltdb/bolt.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/gin-gonic/gin.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/gin-gonic/gin.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/gin-gonic/gin/binding.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/gin-gonic/gin/binding.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/gin-gonic/gin/render.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/gin-gonic/gin/render.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/golang/protobuf/proto.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/golang/protobuf/proto.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/gorilla/websocket.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/gorilla/websocket.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/manucorporat/sse.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/manucorporat/sse.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/github.com/sirupsen/logrus.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/github.com/sirupsen/logrus.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/golang.org/x/net/context.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/golang.org/x/net/context.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/golang.org/x/net/websocket.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/golang.org/x/net/websocket.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/gopkg.in/go-playground/validator.v8.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/gopkg.in/go-playground/validator.v8.a -------------------------------------------------------------------------------- /vendor/pkg/linux_amd64/gopkg.in/yaml.v2.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/pkg/linux_amd64/gopkg.in/yaml.v2.a -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ben Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/Makefile: -------------------------------------------------------------------------------- 1 | BRANCH=`git rev-parse --abbrev-ref HEAD` 2 | COMMIT=`git rev-parse --short HEAD` 3 | GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" 4 | 5 | default: build 6 | 7 | race: 8 | @go test -v -race -test.run="TestSimulate_(100op|1000op)" 9 | 10 | # go get github.com/kisielk/errcheck 11 | errcheck: 12 | @errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt 13 | 14 | test: 15 | @go test -v -cover . 16 | @go test -v ./cmd/bolt 17 | 18 | .PHONY: fmt test 19 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\boltdb\bolt 6 | 7 | environment: 8 | GOPATH: c:\gopath 9 | 10 | install: 11 | - echo %PATH% 12 | - echo %GOPATH% 13 | - go version 14 | - go env 15 | - go get -v -t ./... 16 | 17 | build_script: 18 | - go test -v ./... 19 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_386.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_amd64.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0x7FFFFFFF 8 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_arm.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_arm64.go: -------------------------------------------------------------------------------- 1 | // +build arm64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_linux.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // fdatasync flushes written data to a file descriptor. 8 | func fdatasync(db *DB) error { 9 | return syscall.Fdatasync(int(db.file.Fd())) 10 | } 11 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_openbsd.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | msAsync = 1 << iota // perform asynchronous writes 10 | msSync // perform synchronous writes 11 | msInvalidate // invalidate cached data 12 | ) 13 | 14 | func msync(db *DB) error { 15 | _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) 16 | if errno != 0 { 17 | return errno 18 | } 19 | return nil 20 | } 21 | 22 | func fdatasync(db *DB) error { 23 | if db.data != nil { 24 | return msync(db) 25 | } 26 | return db.file.Sync() 27 | } 28 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_ppc.go: -------------------------------------------------------------------------------- 1 | // +build ppc 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0x7FFFFFFF // 2GB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0xFFFFFFF 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_ppc64.go: -------------------------------------------------------------------------------- 1 | // +build ppc64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_ppc64le.go: -------------------------------------------------------------------------------- 1 | // +build ppc64le 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_s390x.go: -------------------------------------------------------------------------------- 1 | // +build s390x 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!solaris 2 | 3 | package bolt 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "syscall" 9 | "time" 10 | "unsafe" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | flag := syscall.LOCK_SH 25 | if exclusive { 26 | flag = syscall.LOCK_EX 27 | } 28 | 29 | // Otherwise attempt to obtain an exclusive lock. 30 | err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB) 31 | if err == nil { 32 | return nil 33 | } else if err != syscall.EWOULDBLOCK { 34 | return err 35 | } 36 | 37 | // Wait for a bit and try again. 38 | time.Sleep(50 * time.Millisecond) 39 | } 40 | } 41 | 42 | // funlock releases an advisory lock on a file descriptor. 43 | func funlock(db *DB) error { 44 | return syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN) 45 | } 46 | 47 | // mmap memory maps a DB's data file. 48 | func mmap(db *DB, sz int) error { 49 | // Map the data file to memory. 50 | b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) 51 | if err != nil { 52 | return err 53 | } 54 | 55 | // Advise the kernel that the mmap is accessed randomly. 56 | if err := madvise(b, syscall.MADV_RANDOM); err != nil { 57 | return fmt.Errorf("madvise: %s", err) 58 | } 59 | 60 | // Save the original byte slice and convert to a byte array pointer. 61 | db.dataref = b 62 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 63 | db.datasz = sz 64 | return nil 65 | } 66 | 67 | // munmap unmaps a DB's data file from memory. 68 | func munmap(db *DB) error { 69 | // Ignore the unmap if we have no mapped data. 70 | if db.dataref == nil { 71 | return nil 72 | } 73 | 74 | // Unmap using the original byte slice. 75 | err := syscall.Munmap(db.dataref) 76 | db.dataref = nil 77 | db.data = nil 78 | db.datasz = 0 79 | return err 80 | } 81 | 82 | // NOTE: This function is copied from stdlib because it is not available on darwin. 83 | func madvise(b []byte, advice int) (err error) { 84 | _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) 85 | if e1 != 0 { 86 | err = e1 87 | } 88 | return 89 | } 90 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/bolt_unix_solaris.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | "unsafe" 9 | 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | var lock syscall.Flock_t 25 | lock.Start = 0 26 | lock.Len = 0 27 | lock.Pid = 0 28 | lock.Whence = 0 29 | lock.Pid = 0 30 | if exclusive { 31 | lock.Type = syscall.F_WRLCK 32 | } else { 33 | lock.Type = syscall.F_RDLCK 34 | } 35 | err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock) 36 | if err == nil { 37 | return nil 38 | } else if err != syscall.EAGAIN { 39 | return err 40 | } 41 | 42 | // Wait for a bit and try again. 43 | time.Sleep(50 * time.Millisecond) 44 | } 45 | } 46 | 47 | // funlock releases an advisory lock on a file descriptor. 48 | func funlock(db *DB) error { 49 | var lock syscall.Flock_t 50 | lock.Start = 0 51 | lock.Len = 0 52 | lock.Type = syscall.F_UNLCK 53 | lock.Whence = 0 54 | return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock) 55 | } 56 | 57 | // mmap memory maps a DB's data file. 58 | func mmap(db *DB, sz int) error { 59 | // Map the data file to memory. 60 | b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | // Advise the kernel that the mmap is accessed randomly. 66 | if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { 67 | return fmt.Errorf("madvise: %s", err) 68 | } 69 | 70 | // Save the original byte slice and convert to a byte array pointer. 71 | db.dataref = b 72 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 73 | db.datasz = sz 74 | return nil 75 | } 76 | 77 | // munmap unmaps a DB's data file from memory. 78 | func munmap(db *DB) error { 79 | // Ignore the unmap if we have no mapped data. 80 | if db.dataref == nil { 81 | return nil 82 | } 83 | 84 | // Unmap using the original byte slice. 85 | err := unix.Munmap(db.dataref) 86 | db.dataref = nil 87 | db.data = nil 88 | db.datasz = 0 89 | return err 90 | } 91 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/boltsync_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!linux,!openbsd 2 | 3 | package bolt 4 | 5 | // fdatasync flushes written data to a file descriptor. 6 | func fdatasync(db *DB) error { 7 | return db.file.Sync() 8 | } 9 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package bolt implements a low-level key/value store in pure Go. It supports 3 | fully serializable transactions, ACID semantics, and lock-free MVCC with 4 | multiple readers and a single writer. Bolt can be used for projects that 5 | want a simple data store without the need to add large dependencies such as 6 | Postgres or MySQL. 7 | 8 | Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is 9 | optimized for fast read access and does not require recovery in the event of a 10 | system crash. Transactions which have not finished committing will simply be 11 | rolled back in the event of a crash. 12 | 13 | The design of Bolt is based on Howard Chu's LMDB database project. 14 | 15 | Bolt currently works on Windows, Mac OS X, and Linux. 16 | 17 | 18 | Basics 19 | 20 | There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is 21 | a collection of buckets and is represented by a single file on disk. A bucket is 22 | a collection of unique keys that are associated with values. 23 | 24 | Transactions provide either read-only or read-write access to the database. 25 | Read-only transactions can retrieve key/value pairs and can use Cursors to 26 | iterate over the dataset sequentially. Read-write transactions can create and 27 | delete buckets and can insert and remove keys. Only one read-write transaction 28 | is allowed at a time. 29 | 30 | 31 | Caveats 32 | 33 | The database uses a read-only, memory-mapped data file to ensure that 34 | applications cannot corrupt the database, however, this means that keys and 35 | values returned from Bolt cannot be changed. Writing to a read-only byte slice 36 | will cause Go to panic. 37 | 38 | Keys and values retrieved from the database are only valid for the life of 39 | the transaction. When used outside the transaction, these byte slices can 40 | point to different data or can point to invalid memory which will cause a panic. 41 | 42 | 43 | */ 44 | package bolt 45 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/errors.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import "errors" 4 | 5 | // These errors can be returned when opening or calling methods on a DB. 6 | var ( 7 | // ErrDatabaseNotOpen is returned when a DB instance is accessed before it 8 | // is opened or after it is closed. 9 | ErrDatabaseNotOpen = errors.New("database not open") 10 | 11 | // ErrDatabaseOpen is returned when opening a database that is 12 | // already open. 13 | ErrDatabaseOpen = errors.New("database already open") 14 | 15 | // ErrInvalid is returned when both meta pages on a database are invalid. 16 | // This typically occurs when a file is not a bolt database. 17 | ErrInvalid = errors.New("invalid database") 18 | 19 | // ErrVersionMismatch is returned when the data file was created with a 20 | // different version of Bolt. 21 | ErrVersionMismatch = errors.New("version mismatch") 22 | 23 | // ErrChecksum is returned when either meta page checksum does not match. 24 | ErrChecksum = errors.New("checksum error") 25 | 26 | // ErrTimeout is returned when a database cannot obtain an exclusive lock 27 | // on the data file after the timeout passed to Open(). 28 | ErrTimeout = errors.New("timeout") 29 | ) 30 | 31 | // These errors can occur when beginning or committing a Tx. 32 | var ( 33 | // ErrTxNotWritable is returned when performing a write operation on a 34 | // read-only transaction. 35 | ErrTxNotWritable = errors.New("tx not writable") 36 | 37 | // ErrTxClosed is returned when committing or rolling back a transaction 38 | // that has already been committed or rolled back. 39 | ErrTxClosed = errors.New("tx closed") 40 | 41 | // ErrDatabaseReadOnly is returned when a mutating transaction is started on a 42 | // read-only database. 43 | ErrDatabaseReadOnly = errors.New("database is in read-only mode") 44 | ) 45 | 46 | // These errors can occur when putting or deleting a value or a bucket. 47 | var ( 48 | // ErrBucketNotFound is returned when trying to access a bucket that has 49 | // not been created yet. 50 | ErrBucketNotFound = errors.New("bucket not found") 51 | 52 | // ErrBucketExists is returned when creating a bucket that already exists. 53 | ErrBucketExists = errors.New("bucket already exists") 54 | 55 | // ErrBucketNameRequired is returned when creating a bucket with a blank name. 56 | ErrBucketNameRequired = errors.New("bucket name required") 57 | 58 | // ErrKeyRequired is returned when inserting a zero-length key. 59 | ErrKeyRequired = errors.New("key required") 60 | 61 | // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. 62 | ErrKeyTooLarge = errors.New("key too large") 63 | 64 | // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. 65 | ErrValueTooLarge = errors.New("value too large") 66 | 67 | // ErrIncompatibleValue is returned when trying create or delete a bucket 68 | // on an existing non-bucket key or when trying to create or delete a 69 | // non-bucket key on an existing bucket key. 70 | ErrIncompatibleValue = errors.New("incompatible value") 71 | ) 72 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/page_test.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "reflect" 5 | "sort" 6 | "testing" 7 | "testing/quick" 8 | ) 9 | 10 | // Ensure that the page type can be returned in human readable format. 11 | func TestPage_typ(t *testing.T) { 12 | if typ := (&page{flags: branchPageFlag}).typ(); typ != "branch" { 13 | t.Fatalf("exp=branch; got=%v", typ) 14 | } 15 | if typ := (&page{flags: leafPageFlag}).typ(); typ != "leaf" { 16 | t.Fatalf("exp=leaf; got=%v", typ) 17 | } 18 | if typ := (&page{flags: metaPageFlag}).typ(); typ != "meta" { 19 | t.Fatalf("exp=meta; got=%v", typ) 20 | } 21 | if typ := (&page{flags: freelistPageFlag}).typ(); typ != "freelist" { 22 | t.Fatalf("exp=freelist; got=%v", typ) 23 | } 24 | if typ := (&page{flags: 20000}).typ(); typ != "unknown<4e20>" { 25 | t.Fatalf("exp=unknown<4e20>; got=%v", typ) 26 | } 27 | } 28 | 29 | // Ensure that the hexdump debugging function doesn't blow up. 30 | func TestPage_dump(t *testing.T) { 31 | (&page{id: 256}).hexdump(16) 32 | } 33 | 34 | func TestPgids_merge(t *testing.T) { 35 | a := pgids{4, 5, 6, 10, 11, 12, 13, 27} 36 | b := pgids{1, 3, 8, 9, 25, 30} 37 | c := a.merge(b) 38 | if !reflect.DeepEqual(c, pgids{1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30}) { 39 | t.Errorf("mismatch: %v", c) 40 | } 41 | 42 | a = pgids{4, 5, 6, 10, 11, 12, 13, 27, 35, 36} 43 | b = pgids{8, 9, 25, 30} 44 | c = a.merge(b) 45 | if !reflect.DeepEqual(c, pgids{4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30, 35, 36}) { 46 | t.Errorf("mismatch: %v", c) 47 | } 48 | } 49 | 50 | func TestPgids_merge_quick(t *testing.T) { 51 | if err := quick.Check(func(a, b pgids) bool { 52 | // Sort incoming lists. 53 | sort.Sort(a) 54 | sort.Sort(b) 55 | 56 | // Merge the two lists together. 57 | got := a.merge(b) 58 | 59 | // The expected value should be the two lists combined and sorted. 60 | exp := append(a, b...) 61 | sort.Sort(exp) 62 | 63 | if !reflect.DeepEqual(exp, got) { 64 | t.Errorf("\nexp=%+v\ngot=%+v\n", exp, got) 65 | return false 66 | } 67 | 68 | return true 69 | }, nil); err != nil { 70 | t.Fatal(err) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /vendor/src/github.com/boltdb/bolt/quick_test.go: -------------------------------------------------------------------------------- 1 | package bolt_test 2 | 3 | import ( 4 | "bytes" 5 | "flag" 6 | "fmt" 7 | "math/rand" 8 | "os" 9 | "reflect" 10 | "testing/quick" 11 | "time" 12 | ) 13 | 14 | // testing/quick defaults to 5 iterations and a random seed. 15 | // You can override these settings from the command line: 16 | // 17 | // -quick.count The number of iterations to perform. 18 | // -quick.seed The seed to use for randomizing. 19 | // -quick.maxitems The maximum number of items to insert into a DB. 20 | // -quick.maxksize The maximum size of a key. 21 | // -quick.maxvsize The maximum size of a value. 22 | // 23 | 24 | var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int 25 | 26 | func init() { 27 | flag.IntVar(&qcount, "quick.count", 5, "") 28 | flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "") 29 | flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "") 30 | flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "") 31 | flag.IntVar(&qmaxvsize, "quick.maxvsize", 1024, "") 32 | flag.Parse() 33 | fmt.Fprintln(os.Stderr, "seed:", qseed) 34 | fmt.Fprintf(os.Stderr, "quick settings: count=%v, items=%v, ksize=%v, vsize=%v\n", qcount, qmaxitems, qmaxksize, qmaxvsize) 35 | } 36 | 37 | func qconfig() *quick.Config { 38 | return &quick.Config{ 39 | MaxCount: qcount, 40 | Rand: rand.New(rand.NewSource(int64(qseed))), 41 | } 42 | } 43 | 44 | type testdata []testdataitem 45 | 46 | func (t testdata) Len() int { return len(t) } 47 | func (t testdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] } 48 | func (t testdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == -1 } 49 | 50 | func (t testdata) Generate(rand *rand.Rand, size int) reflect.Value { 51 | n := rand.Intn(qmaxitems-1) + 1 52 | items := make(testdata, n) 53 | for i := 0; i < n; i++ { 54 | item := &items[i] 55 | item.Key = randByteSlice(rand, 1, qmaxksize) 56 | item.Value = randByteSlice(rand, 0, qmaxvsize) 57 | } 58 | return reflect.ValueOf(items) 59 | } 60 | 61 | type revtestdata []testdataitem 62 | 63 | func (t revtestdata) Len() int { return len(t) } 64 | func (t revtestdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] } 65 | func (t revtestdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == 1 } 66 | 67 | type testdataitem struct { 68 | Key []byte 69 | Value []byte 70 | } 71 | 72 | func randByteSlice(rand *rand.Rand, minSize, maxSize int) []byte { 73 | n := rand.Intn(maxSize-minSize) + minSize 74 | b := make([]byte, n) 75 | for i := 0; i < n; i++ { 76 | b[i] = byte(rand.Intn(255)) 77 | } 78 | return b 79 | } 80 | -------------------------------------------------------------------------------- /vendor/src/github.com/dustin/go-broadcast/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Dustin Sallings 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/src/github.com/dustin/go-broadcast/README.markdown: -------------------------------------------------------------------------------- 1 | pubsubbing channels. 2 | 3 | This project primarily exists because I've been copying and pasting 4 | the exact same two files into numerous projects. It does work well, 5 | though. 6 | -------------------------------------------------------------------------------- /vendor/src/github.com/dustin/go-broadcast/broadcaster.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package broadcast provides pubsub of messages over channels. 3 | 4 | A provider has a Broadcaster into which it Submits messages and into 5 | which subscribers Register to pick up those messages. 6 | 7 | */ 8 | package broadcast 9 | 10 | type broadcaster struct { 11 | input chan interface{} 12 | reg chan chan<- interface{} 13 | unreg chan chan<- interface{} 14 | 15 | outputs map[chan<- interface{}]bool 16 | } 17 | 18 | // The Broadcaster interface describes the main entry points to 19 | // broadcasters. 20 | type Broadcaster interface { 21 | // Register a new channel to receive broadcasts 22 | Register(chan<- interface{}) 23 | // Unregister a channel so that it no longer receives broadcasts. 24 | Unregister(chan<- interface{}) 25 | // Shut this broadcaster down. 26 | Close() error 27 | // Submit a new object to all subscribers 28 | Submit(interface{}) 29 | } 30 | 31 | func (b *broadcaster) broadcast(m interface{}) { 32 | for ch := range b.outputs { 33 | ch <- m 34 | } 35 | } 36 | 37 | func (b *broadcaster) run() { 38 | for { 39 | select { 40 | case m := <-b.input: 41 | b.broadcast(m) 42 | case ch, ok := <-b.reg: 43 | if ok { 44 | b.outputs[ch] = true 45 | } else { 46 | return 47 | } 48 | case ch := <-b.unreg: 49 | delete(b.outputs, ch) 50 | } 51 | } 52 | } 53 | 54 | // NewBroadcaster creates a new broadcaster with the given input 55 | // channel buffer length. 56 | func NewBroadcaster(buflen int) Broadcaster { 57 | b := &broadcaster{ 58 | input: make(chan interface{}, buflen), 59 | reg: make(chan chan<- interface{}), 60 | unreg: make(chan chan<- interface{}), 61 | outputs: make(map[chan<- interface{}]bool), 62 | } 63 | 64 | go b.run() 65 | 66 | return b 67 | } 68 | 69 | func (b *broadcaster) Register(newch chan<- interface{}) { 70 | b.reg <- newch 71 | } 72 | 73 | func (b *broadcaster) Unregister(newch chan<- interface{}) { 74 | b.unreg <- newch 75 | } 76 | 77 | func (b *broadcaster) Close() error { 78 | close(b.reg) 79 | return nil 80 | } 81 | 82 | func (b *broadcaster) Submit(m interface{}) { 83 | if b != nil { 84 | b.input <- m 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /vendor/src/github.com/dustin/go-broadcast/broadcaster_test.go: -------------------------------------------------------------------------------- 1 | package broadcast 2 | 3 | import ( 4 | "sync" 5 | "testing" 6 | ) 7 | 8 | func TestBroadcast(t *testing.T) { 9 | wg := sync.WaitGroup{} 10 | 11 | b := NewBroadcaster(100) 12 | defer b.Close() 13 | 14 | for i := 0; i < 5; i++ { 15 | wg.Add(1) 16 | 17 | cch := make(chan interface{}) 18 | 19 | b.Register(cch) 20 | 21 | go func() { 22 | defer wg.Done() 23 | defer b.Unregister(cch) 24 | <-cch 25 | }() 26 | 27 | } 28 | 29 | b.Submit(1) 30 | 31 | wg.Wait() 32 | } 33 | 34 | func TestBroadcastCleanup(t *testing.T) { 35 | b := NewBroadcaster(100) 36 | b.Register(make(chan interface{})) 37 | b.Close() 38 | } 39 | 40 | func echoer(chin, chout chan interface{}) { 41 | for m := range chin { 42 | chout <- m 43 | } 44 | } 45 | 46 | func BenchmarkDirectSend(b *testing.B) { 47 | chout := make(chan interface{}) 48 | chin := make(chan interface{}) 49 | defer close(chin) 50 | 51 | go echoer(chin, chout) 52 | 53 | for i := 0; i < b.N; i++ { 54 | chin <- nil 55 | <-chout 56 | } 57 | } 58 | 59 | func BenchmarkBrodcast(b *testing.B) { 60 | chout := make(chan interface{}) 61 | 62 | bc := NewBroadcaster(0) 63 | defer bc.Close() 64 | bc.Register(chout) 65 | 66 | for i := 0; i < b.N; i++ { 67 | bc.Submit(nil) 68 | <-chout 69 | } 70 | } 71 | 72 | func BenchmarkParallelDirectSend(b *testing.B) { 73 | chout := make(chan interface{}) 74 | chin := make(chan interface{}) 75 | defer close(chin) 76 | 77 | go echoer(chin, chout) 78 | 79 | b.RunParallel(func(pb *testing.PB) { 80 | for pb.Next() { 81 | chin <- nil 82 | <-chout 83 | } 84 | }) 85 | } 86 | 87 | func BenchmarkParallelBrodcast(b *testing.B) { 88 | chout := make(chan interface{}) 89 | 90 | bc := NewBroadcaster(0) 91 | defer bc.Close() 92 | bc.Register(chout) 93 | 94 | b.RunParallel(func(pb *testing.PB) { 95 | for pb.Next() { 96 | bc.Submit(nil) 97 | <-chout 98 | } 99 | }) 100 | } 101 | -------------------------------------------------------------------------------- /vendor/src/github.com/dustin/go-broadcast/mux_observer_test.go: -------------------------------------------------------------------------------- 1 | package broadcast 2 | 3 | import ( 4 | "sync" 5 | "testing" 6 | ) 7 | 8 | func TestMuxBroadcast(t *testing.T) { 9 | wg := sync.WaitGroup{} 10 | 11 | mo := NewMuxObserver(0, 0) 12 | defer mo.Close() 13 | 14 | b1 := mo.Sub() 15 | defer b1.Close() 16 | 17 | b2 := mo.Sub() 18 | defer b2.Close() 19 | 20 | for i := 0; i < 5; i++ { 21 | wg.Add(2) 22 | 23 | cch1 := make(chan interface{}) 24 | b1.Register(cch1) 25 | cch2 := make(chan interface{}) 26 | b2.Register(cch2) 27 | 28 | go func() { 29 | defer wg.Done() 30 | defer b1.Unregister(cch1) 31 | <-cch1 32 | }() 33 | go func() { 34 | defer wg.Done() 35 | defer b2.Unregister(cch2) 36 | <-cch2 37 | }() 38 | 39 | } 40 | 41 | go b1.Submit(1) 42 | go b2.Submit(1) 43 | 44 | wg.Wait() 45 | } 46 | 47 | func TestMuxBroadcastCleanup(t *testing.T) { 48 | mo := NewMuxObserver(0, 0) 49 | b := mo.Sub() 50 | b.Register(make(chan interface{})) 51 | b.Close() 52 | mo.Close() 53 | } 54 | 55 | func BenchmarkMuxBrodcast(b *testing.B) { 56 | chout := make(chan interface{}) 57 | 58 | mo := NewMuxObserver(0, 0) 59 | defer mo.Close() 60 | bc := mo.Sub() 61 | bc.Register(chout) 62 | 63 | for i := 0; i < b.N; i++ { 64 | bc.Submit(nil) 65 | <-chout 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/gin-gonic/gin", 3 | "GoVersion": "go1.5.1", 4 | "Deps": [ 5 | { 6 | "ImportPath": "github.com/davecgh/go-spew/spew", 7 | "Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d" 8 | }, 9 | { 10 | "ImportPath": "github.com/golang/protobuf/proto", 11 | "Rev": "2402d76f3d41f928c7902a765dfc872356dd3aad" 12 | }, 13 | { 14 | "ImportPath": "github.com/manucorporat/sse", 15 | "Rev": "ee05b128a739a0fb76c7ebd3ae4810c1de808d6d" 16 | }, 17 | { 18 | "ImportPath": "github.com/pmezard/go-difflib/difflib", 19 | "Rev": "792786c7400a136282c1664665ae0a8db921c6c2" 20 | }, 21 | { 22 | "ImportPath": "github.com/stretchr/testify/assert", 23 | "Comment": "v1.1.3", 24 | "Rev": "f390dcf405f7b83c997eac1b06768bb9f44dec18" 25 | }, 26 | { 27 | "ImportPath": "golang.org/x/net/context", 28 | "Rev": "f315505cf3349909cdf013ea56690da34e96a451" 29 | }, 30 | { 31 | "ImportPath": "gopkg.in/go-playground/validator.v8", 32 | "Comment": "v8.15.1", 33 | "Rev": "c193cecd124b5cc722d7ee5538e945bdb3348435" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Manuel Martínez-Almeida 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/binding.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binding 6 | 7 | import "net/http" 8 | 9 | const ( 10 | MIMEJSON = "application/json" 11 | MIMEHTML = "text/html" 12 | MIMEXML = "application/xml" 13 | MIMEXML2 = "text/xml" 14 | MIMEPlain = "text/plain" 15 | MIMEPOSTForm = "application/x-www-form-urlencoded" 16 | MIMEMultipartPOSTForm = "multipart/form-data" 17 | MIMEPROTOBUF = "application/x-protobuf" 18 | ) 19 | 20 | type Binding interface { 21 | Name() string 22 | Bind(*http.Request, interface{}) error 23 | } 24 | 25 | type StructValidator interface { 26 | // ValidateStruct can receive any kind of type and it should never panic, even if the configuration is not right. 27 | // If the received type is not a struct, any validation should be skipped and nil must be returned. 28 | // If the received type is a struct or pointer to a struct, the validation should be performed. 29 | // If the struct is not valid or the validation itself fails, a descriptive error should be returned. 30 | // Otherwise nil must be returned. 31 | ValidateStruct(interface{}) error 32 | } 33 | 34 | var Validator StructValidator = &defaultValidator{} 35 | 36 | var ( 37 | JSON = jsonBinding{} 38 | XML = xmlBinding{} 39 | Form = formBinding{} 40 | FormPost = formPostBinding{} 41 | FormMultipart = formMultipartBinding{} 42 | ProtoBuf = protobufBinding{} 43 | ) 44 | 45 | func Default(method, contentType string) Binding { 46 | if method == "GET" { 47 | return Form 48 | } else { 49 | switch contentType { 50 | case MIMEJSON: 51 | return JSON 52 | case MIMEXML, MIMEXML2: 53 | return XML 54 | case MIMEPROTOBUF: 55 | return ProtoBuf 56 | default: //case MIMEPOSTForm, MIMEMultipartPOSTForm: 57 | return Form 58 | } 59 | } 60 | } 61 | 62 | func validate(obj interface{}) error { 63 | if Validator == nil { 64 | return nil 65 | } 66 | return Validator.ValidateStruct(obj) 67 | } 68 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/default_validator.go: -------------------------------------------------------------------------------- 1 | package binding 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | 7 | "gopkg.in/go-playground/validator.v8" 8 | ) 9 | 10 | type defaultValidator struct { 11 | once sync.Once 12 | validate *validator.Validate 13 | } 14 | 15 | var _ StructValidator = &defaultValidator{} 16 | 17 | func (v *defaultValidator) ValidateStruct(obj interface{}) error { 18 | if kindOfData(obj) == reflect.Struct { 19 | v.lazyinit() 20 | if err := v.validate.Struct(obj); err != nil { 21 | return error(err) 22 | } 23 | } 24 | return nil 25 | } 26 | 27 | func (v *defaultValidator) lazyinit() { 28 | v.once.Do(func() { 29 | config := &validator.Config{TagName: "binding"} 30 | v.validate = validator.New(config) 31 | }) 32 | } 33 | 34 | func kindOfData(data interface{}) reflect.Kind { 35 | value := reflect.ValueOf(data) 36 | valueType := value.Kind() 37 | if valueType == reflect.Ptr { 38 | valueType = value.Elem().Kind() 39 | } 40 | return valueType 41 | } 42 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/example/test.proto: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | enum FOO {X=17;}; 4 | 5 | message Test { 6 | required string label = 1; 7 | optional int32 type = 2[default=77]; 8 | repeated int64 reps = 3; 9 | optional group OptionalGroup = 4{ 10 | required string RequiredField = 5; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/form.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binding 6 | 7 | import "net/http" 8 | 9 | type formBinding struct{} 10 | type formPostBinding struct{} 11 | type formMultipartBinding struct{} 12 | 13 | func (formBinding) Name() string { 14 | return "form" 15 | } 16 | 17 | func (formBinding) Bind(req *http.Request, obj interface{}) error { 18 | if err := req.ParseForm(); err != nil { 19 | return err 20 | } 21 | req.ParseMultipartForm(32 << 10) // 32 MB 22 | if err := mapForm(obj, req.Form); err != nil { 23 | return err 24 | } 25 | return validate(obj) 26 | } 27 | 28 | func (formPostBinding) Name() string { 29 | return "form-urlencoded" 30 | } 31 | 32 | func (formPostBinding) Bind(req *http.Request, obj interface{}) error { 33 | if err := req.ParseForm(); err != nil { 34 | return err 35 | } 36 | if err := mapForm(obj, req.PostForm); err != nil { 37 | return err 38 | } 39 | return validate(obj) 40 | } 41 | 42 | func (formMultipartBinding) Name() string { 43 | return "multipart/form-data" 44 | } 45 | 46 | func (formMultipartBinding) Bind(req *http.Request, obj interface{}) error { 47 | if err := req.ParseMultipartForm(32 << 10); err != nil { 48 | return err 49 | } 50 | if err := mapForm(obj, req.MultipartForm.Value); err != nil { 51 | return err 52 | } 53 | return validate(obj) 54 | } 55 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binding 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "net/http" 11 | ) 12 | 13 | type jsonBinding struct{} 14 | 15 | func (jsonBinding) Name() string { 16 | return "json" 17 | } 18 | 19 | func (jsonBinding) Bind(req *http.Request, obj interface{}) error { 20 | decoder := json.NewDecoder(req.Body) 21 | if err := decoder.Decode(obj); err != nil { 22 | return err 23 | } 24 | return validate(obj) 25 | } 26 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/protobuf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binding 6 | 7 | import ( 8 | "github.com/golang/protobuf/proto" 9 | 10 | "io/ioutil" 11 | "net/http" 12 | ) 13 | 14 | type protobufBinding struct{} 15 | 16 | func (protobufBinding) Name() string { 17 | return "protobuf" 18 | } 19 | 20 | func (protobufBinding) Bind(req *http.Request, obj interface{}) error { 21 | 22 | buf, err := ioutil.ReadAll(req.Body) 23 | if err != nil { 24 | return err 25 | } 26 | 27 | if err = proto.Unmarshal(buf, obj.(proto.Message)); err != nil { 28 | return err 29 | } 30 | 31 | //Here it's same to return validate(obj), but util now we cann't add `binding:""` to the struct 32 | //which automatically generate by gen-proto 33 | return nil 34 | //return validate(obj) 35 | } 36 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/binding/xml.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binding 6 | 7 | import ( 8 | "encoding/xml" 9 | "net/http" 10 | ) 11 | 12 | type xmlBinding struct{} 13 | 14 | func (xmlBinding) Name() string { 15 | return "xml" 16 | } 17 | 18 | func (xmlBinding) Bind(req *http.Request, obj interface{}) error { 19 | decoder := xml.NewDecoder(req.Body) 20 | if err := decoder.Decode(obj); err != nil { 21 | return err 22 | } 23 | return validate(obj) 24 | } 25 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/debug.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gin 6 | 7 | import ( 8 | "bytes" 9 | "html/template" 10 | "log" 11 | ) 12 | 13 | func init() { 14 | log.SetFlags(0) 15 | } 16 | 17 | // IsDebugging returns true if the framework is running in debug mode. 18 | // Use SetMode(gin.Release) to switch to disable the debug mode. 19 | func IsDebugging() bool { 20 | return ginMode == debugCode 21 | } 22 | 23 | func debugPrintRoute(httpMethod, absolutePath string, handlers HandlersChain) { 24 | if IsDebugging() { 25 | nuHandlers := len(handlers) 26 | handlerName := nameOfFunction(handlers.Last()) 27 | debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers) 28 | } 29 | } 30 | 31 | func debugPrintLoadTemplate(tmpl *template.Template) { 32 | if IsDebugging() { 33 | var buf bytes.Buffer 34 | for _, tmpl := range tmpl.Templates() { 35 | buf.WriteString("\t- ") 36 | buf.WriteString(tmpl.Name()) 37 | buf.WriteString("\n") 38 | } 39 | debugPrint("Loaded HTML Templates (%d): \n%s\n", len(tmpl.Templates()), buf.String()) 40 | } 41 | } 42 | 43 | func debugPrint(format string, values ...interface{}) { 44 | if IsDebugging() { 45 | log.Printf("[GIN-debug] "+format, values...) 46 | } 47 | } 48 | 49 | func debugPrintWARNINGNew() { 50 | debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production. 51 | - using env: export GIN_MODE=release 52 | - using code: gin.SetMode(gin.ReleaseMode) 53 | 54 | `) 55 | } 56 | 57 | func debugPrintWARNINGSetHTMLTemplate() { 58 | debugPrint(`[WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called 59 | at initialization. ie. before any route is registered or the router is listening in a socket: 60 | 61 | router := gin.Default() 62 | router.SetHTMLTemplate(template) // << good place 63 | 64 | `) 65 | } 66 | 67 | func debugPrintError(err error) { 68 | if err != nil { 69 | debugPrint("[ERROR] %v\n", err) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/debug_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gin 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "io" 11 | "log" 12 | "os" 13 | "testing" 14 | 15 | "github.com/stretchr/testify/assert" 16 | ) 17 | 18 | // TODO 19 | // func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) { 20 | // func debugPrint(format string, values ...interface{}) { 21 | 22 | func TestIsDebugging(t *testing.T) { 23 | SetMode(DebugMode) 24 | assert.True(t, IsDebugging()) 25 | SetMode(ReleaseMode) 26 | assert.False(t, IsDebugging()) 27 | SetMode(TestMode) 28 | assert.False(t, IsDebugging()) 29 | } 30 | 31 | func TestDebugPrint(t *testing.T) { 32 | var w bytes.Buffer 33 | setup(&w) 34 | defer teardown() 35 | 36 | SetMode(ReleaseMode) 37 | debugPrint("DEBUG this!") 38 | SetMode(TestMode) 39 | debugPrint("DEBUG this!") 40 | assert.Empty(t, w.String()) 41 | 42 | SetMode(DebugMode) 43 | debugPrint("these are %d %s\n", 2, "error messages") 44 | assert.Equal(t, w.String(), "[GIN-debug] these are 2 error messages\n") 45 | } 46 | 47 | func TestDebugPrintError(t *testing.T) { 48 | var w bytes.Buffer 49 | setup(&w) 50 | defer teardown() 51 | 52 | SetMode(DebugMode) 53 | debugPrintError(nil) 54 | assert.Empty(t, w.String()) 55 | 56 | debugPrintError(errors.New("this is an error")) 57 | assert.Equal(t, w.String(), "[GIN-debug] [ERROR] this is an error\n") 58 | } 59 | 60 | func TestDebugPrintRoutes(t *testing.T) { 61 | var w bytes.Buffer 62 | setup(&w) 63 | defer teardown() 64 | 65 | debugPrintRoute("GET", "/path/to/route/:param", HandlersChain{func(c *Context) {}, handlerNameTest}) 66 | assert.Regexp(t, `^\[GIN-debug\] GET /path/to/route/:param --> (.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest \(2 handlers\)\n$`, w.String()) 67 | } 68 | 69 | func setup(w io.Writer) { 70 | SetMode(DebugMode) 71 | log.SetOutput(w) 72 | } 73 | 74 | func teardown() { 75 | SetMode(TestMode) 76 | log.SetOutput(os.Stdout) 77 | } 78 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/deprecated.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gin 6 | 7 | import "log" 8 | 9 | func (c *Context) GetCookie(name string) (string, error) { 10 | log.Println("GetCookie() method is deprecated. Use Cookie() instead.") 11 | return c.Cookie(name) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/fs.go: -------------------------------------------------------------------------------- 1 | package gin 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | ) 7 | 8 | type ( 9 | onlyfilesFS struct { 10 | fs http.FileSystem 11 | } 12 | neuteredReaddirFile struct { 13 | http.File 14 | } 15 | ) 16 | 17 | // Dir returns a http.Filesystem that can be used by http.FileServer(). It is used interally 18 | // in router.Static(). 19 | // if listDirectory == true, then it works the same as http.Dir() otherwise it returns 20 | // a filesystem that prevents http.FileServer() to list the directory files. 21 | func Dir(root string, listDirectory bool) http.FileSystem { 22 | fs := http.Dir(root) 23 | if listDirectory { 24 | return fs 25 | } 26 | return &onlyfilesFS{fs} 27 | } 28 | 29 | // Conforms to http.Filesystem 30 | func (fs onlyfilesFS) Open(name string) (http.File, error) { 31 | f, err := fs.fs.Open(name) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return neuteredReaddirFile{f}, nil 36 | } 37 | 38 | // Overrides the http.File default implementation 39 | func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { 40 | // this disables directory listing 41 | return nil, nil 42 | } 43 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/ginS/README.md: -------------------------------------------------------------------------------- 1 | #Gin Default Server 2 | 3 | This is API experiment for Gin. 4 | 5 | ```go 6 | package main 7 | 8 | import ( 9 | "github.com/gin-gonic/gin" 10 | "github.com/gin-gonic/gin/ginS" 11 | ) 12 | 13 | func main() { 14 | ginS.GET("/", func(c *gin.Context) { c.String("Hello World") }) 15 | ginS.Run() 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/helpers_test.go: -------------------------------------------------------------------------------- 1 | package gin 2 | 3 | import ( 4 | "net/http/httptest" 5 | ) 6 | 7 | func CreateTestContext() (c *Context, w *httptest.ResponseRecorder, r *Engine) { 8 | w = httptest.NewRecorder() 9 | r = New() 10 | c = r.allocateContext() 11 | c.reset() 12 | c.writermem.reset(w) 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/src/github.com/gin-gonic/gin/logo.jpg -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/mode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gin 6 | 7 | import ( 8 | "io" 9 | "os" 10 | 11 | "github.com/gin-gonic/gin/binding" 12 | ) 13 | 14 | const ENV_GIN_MODE = "GIN_MODE" 15 | 16 | const ( 17 | DebugMode string = "debug" 18 | ReleaseMode string = "release" 19 | TestMode string = "test" 20 | ) 21 | const ( 22 | debugCode = iota 23 | releaseCode = iota 24 | testCode = iota 25 | ) 26 | 27 | // DefaultWriter is the default io.Writer used the Gin for debug output and 28 | // middleware output like Logger() or Recovery(). 29 | // Note that both Logger and Recovery provides custom ways to configure their 30 | // output io.Writer. 31 | // To support coloring in Windows use: 32 | // import "github.com/mattn/go-colorable" 33 | // gin.DefaultWriter = colorable.NewColorableStdout() 34 | var DefaultWriter io.Writer = os.Stdout 35 | var DefaultErrorWriter io.Writer = os.Stderr 36 | 37 | var ginMode = debugCode 38 | var modeName = DebugMode 39 | 40 | func init() { 41 | mode := os.Getenv(ENV_GIN_MODE) 42 | if len(mode) == 0 { 43 | SetMode(DebugMode) 44 | } else { 45 | SetMode(mode) 46 | } 47 | } 48 | 49 | func SetMode(value string) { 50 | switch value { 51 | case DebugMode: 52 | ginMode = debugCode 53 | case ReleaseMode: 54 | ginMode = releaseCode 55 | case TestMode: 56 | ginMode = testCode 57 | default: 58 | panic("gin mode unknown: " + value) 59 | } 60 | modeName = value 61 | } 62 | 63 | func DisableBindValidation() { 64 | binding.Validator = nil 65 | } 66 | 67 | func Mode() string { 68 | return modeName 69 | } 70 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/mode_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gin 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func init() { 14 | SetMode(TestMode) 15 | } 16 | 17 | func TestSetMode(t *testing.T) { 18 | SetMode(DebugMode) 19 | assert.Equal(t, ginMode, debugCode) 20 | assert.Equal(t, Mode(), DebugMode) 21 | 22 | SetMode(ReleaseMode) 23 | assert.Equal(t, ginMode, releaseCode) 24 | assert.Equal(t, Mode(), ReleaseMode) 25 | 26 | SetMode(TestMode) 27 | assert.Equal(t, ginMode, testCode) 28 | assert.Equal(t, Mode(), TestMode) 29 | 30 | assert.Panics(t, func() { SetMode("unknown") }) 31 | } 32 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/path_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Julien Schmidt. All rights reserved. 2 | // Based on the path package, Copyright 2009 The Go Authors. 3 | // Use of this source code is governed by a BSD-style license that can be found 4 | // in the LICENSE file. 5 | 6 | package gin 7 | 8 | import ( 9 | "runtime" 10 | "testing" 11 | 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | var cleanTests = []struct { 16 | path, result string 17 | }{ 18 | // Already clean 19 | {"/", "/"}, 20 | {"/abc", "/abc"}, 21 | {"/a/b/c", "/a/b/c"}, 22 | {"/abc/", "/abc/"}, 23 | {"/a/b/c/", "/a/b/c/"}, 24 | 25 | // missing root 26 | {"", "/"}, 27 | {"abc", "/abc"}, 28 | {"abc/def", "/abc/def"}, 29 | {"a/b/c", "/a/b/c"}, 30 | 31 | // Remove doubled slash 32 | {"//", "/"}, 33 | {"/abc//", "/abc/"}, 34 | {"/abc/def//", "/abc/def/"}, 35 | {"/a/b/c//", "/a/b/c/"}, 36 | {"/abc//def//ghi", "/abc/def/ghi"}, 37 | {"//abc", "/abc"}, 38 | {"///abc", "/abc"}, 39 | {"//abc//", "/abc/"}, 40 | 41 | // Remove . elements 42 | {".", "/"}, 43 | {"./", "/"}, 44 | {"/abc/./def", "/abc/def"}, 45 | {"/./abc/def", "/abc/def"}, 46 | {"/abc/.", "/abc/"}, 47 | 48 | // Remove .. elements 49 | {"..", "/"}, 50 | {"../", "/"}, 51 | {"../../", "/"}, 52 | {"../..", "/"}, 53 | {"../../abc", "/abc"}, 54 | {"/abc/def/ghi/../jkl", "/abc/def/jkl"}, 55 | {"/abc/def/../ghi/../jkl", "/abc/jkl"}, 56 | {"/abc/def/..", "/abc"}, 57 | {"/abc/def/../..", "/"}, 58 | {"/abc/def/../../..", "/"}, 59 | {"/abc/def/../../..", "/"}, 60 | {"/abc/def/../../../ghi/jkl/../../../mno", "/mno"}, 61 | 62 | // Combinations 63 | {"abc/./../def", "/def"}, 64 | {"abc//./../def", "/def"}, 65 | {"abc/../../././../def", "/def"}, 66 | } 67 | 68 | func TestPathClean(t *testing.T) { 69 | for _, test := range cleanTests { 70 | assert.Equal(t, cleanPath(test.path), test.result) 71 | assert.Equal(t, cleanPath(test.result), test.result) 72 | } 73 | } 74 | 75 | func TestPathCleanMallocs(t *testing.T) { 76 | if testing.Short() { 77 | t.Skip("skipping malloc count in short mode") 78 | } 79 | if runtime.GOMAXPROCS(0) > 1 { 80 | t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1") 81 | return 82 | } 83 | 84 | for _, test := range cleanTests { 85 | allocs := testing.AllocsPerRun(100, func() { cleanPath(test.result) }) 86 | assert.EqualValues(t, allocs, 0) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/recovery_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gin 6 | 7 | import ( 8 | "bytes" 9 | "testing" 10 | 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | // TestPanicInHandler assert that panic has been recovered. 15 | func TestPanicInHandler(t *testing.T) { 16 | buffer := new(bytes.Buffer) 17 | router := New() 18 | router.Use(RecoveryWithWriter(buffer)) 19 | router.GET("/recovery", func(_ *Context) { 20 | panic("Oupps, Houston, we have a problem") 21 | }) 22 | // RUN 23 | w := performRequest(router, "GET", "/recovery") 24 | // TEST 25 | assert.Equal(t, w.Code, 500) 26 | assert.Contains(t, buffer.String(), "GET /recovery") 27 | assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem") 28 | assert.Contains(t, buffer.String(), "TestPanicInHandler") 29 | } 30 | 31 | // TestPanicWithAbort assert that panic has been recovered even if context.Abort was used. 32 | func TestPanicWithAbort(t *testing.T) { 33 | router := New() 34 | router.Use(RecoveryWithWriter(nil)) 35 | router.GET("/recovery", func(c *Context) { 36 | c.AbortWithStatus(400) 37 | panic("Oupps, Houston, we have a problem") 38 | }) 39 | // RUN 40 | w := performRequest(router, "GET", "/recovery") 41 | // TEST 42 | assert.Equal(t, w.Code, 400) 43 | } 44 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/data.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import "net/http" 8 | 9 | type Data struct { 10 | ContentType string 11 | Data []byte 12 | } 13 | 14 | func (r Data) Render(w http.ResponseWriter) error { 15 | if len(r.ContentType) > 0 { 16 | w.Header()["Content-Type"] = []string{r.ContentType} 17 | } 18 | w.Write(r.Data) 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/html.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import ( 8 | "html/template" 9 | "net/http" 10 | ) 11 | 12 | type ( 13 | HTMLRender interface { 14 | Instance(string, interface{}) Render 15 | } 16 | 17 | HTMLProduction struct { 18 | Template *template.Template 19 | } 20 | 21 | HTMLDebug struct { 22 | Files []string 23 | Glob string 24 | } 25 | 26 | HTML struct { 27 | Template *template.Template 28 | Name string 29 | Data interface{} 30 | } 31 | ) 32 | 33 | var htmlContentType = []string{"text/html; charset=utf-8"} 34 | 35 | func (r HTMLProduction) Instance(name string, data interface{}) Render { 36 | return HTML{ 37 | Template: r.Template, 38 | Name: name, 39 | Data: data, 40 | } 41 | } 42 | 43 | func (r HTMLDebug) Instance(name string, data interface{}) Render { 44 | return HTML{ 45 | Template: r.loadTemplate(), 46 | Name: name, 47 | Data: data, 48 | } 49 | } 50 | func (r HTMLDebug) loadTemplate() *template.Template { 51 | if len(r.Files) > 0 { 52 | return template.Must(template.ParseFiles(r.Files...)) 53 | } 54 | if len(r.Glob) > 0 { 55 | return template.Must(template.ParseGlob(r.Glob)) 56 | } 57 | panic("the HTML debug render was created without files or glob pattern") 58 | } 59 | 60 | func (r HTML) Render(w http.ResponseWriter) error { 61 | writeContentType(w, htmlContentType) 62 | if len(r.Name) == 0 { 63 | return r.Template.Execute(w, r.Data) 64 | } 65 | return r.Template.ExecuteTemplate(w, r.Name, r.Data) 66 | } 67 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import ( 8 | "encoding/json" 9 | "net/http" 10 | ) 11 | 12 | type ( 13 | JSON struct { 14 | Data interface{} 15 | } 16 | 17 | IndentedJSON struct { 18 | Data interface{} 19 | } 20 | ) 21 | 22 | var jsonContentType = []string{"application/json; charset=utf-8"} 23 | 24 | func (r JSON) Render(w http.ResponseWriter) error { 25 | return WriteJSON(w, r.Data) 26 | } 27 | 28 | func (r IndentedJSON) Render(w http.ResponseWriter) error { 29 | writeContentType(w, jsonContentType) 30 | jsonBytes, err := json.MarshalIndent(r.Data, "", " ") 31 | if err != nil { 32 | return err 33 | } 34 | w.Write(jsonBytes) 35 | return nil 36 | } 37 | 38 | func WriteJSON(w http.ResponseWriter, obj interface{}) error { 39 | writeContentType(w, jsonContentType) 40 | return json.NewEncoder(w).Encode(obj) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/redirect.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import ( 8 | "fmt" 9 | "net/http" 10 | ) 11 | 12 | type Redirect struct { 13 | Code int 14 | Request *http.Request 15 | Location string 16 | } 17 | 18 | func (r Redirect) Render(w http.ResponseWriter) error { 19 | if (r.Code < 300 || r.Code > 308) && r.Code != 201 { 20 | panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code)) 21 | } 22 | http.Redirect(w, r.Request, r.Location, r.Code) 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/render.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import "net/http" 8 | 9 | type Render interface { 10 | Render(http.ResponseWriter) error 11 | } 12 | 13 | var ( 14 | _ Render = JSON{} 15 | _ Render = IndentedJSON{} 16 | _ Render = XML{} 17 | _ Render = String{} 18 | _ Render = Redirect{} 19 | _ Render = Data{} 20 | _ Render = HTML{} 21 | _ HTMLRender = HTMLDebug{} 22 | _ HTMLRender = HTMLProduction{} 23 | _ Render = YAML{} 24 | ) 25 | 26 | func writeContentType(w http.ResponseWriter, value []string) { 27 | header := w.Header() 28 | if val := header["Content-Type"]; len(val) == 0 { 29 | header["Content-Type"] = value 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/text.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "net/http" 11 | ) 12 | 13 | type String struct { 14 | Format string 15 | Data []interface{} 16 | } 17 | 18 | var plainContentType = []string{"text/plain; charset=utf-8"} 19 | 20 | func (r String) Render(w http.ResponseWriter) error { 21 | WriteString(w, r.Format, r.Data) 22 | return nil 23 | } 24 | 25 | func WriteString(w http.ResponseWriter, format string, data []interface{}) { 26 | writeContentType(w, plainContentType) 27 | 28 | if len(data) > 0 { 29 | fmt.Fprintf(w, format, data...) 30 | } else { 31 | io.WriteString(w, format) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/xml.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import ( 8 | "encoding/xml" 9 | "net/http" 10 | ) 11 | 12 | type XML struct { 13 | Data interface{} 14 | } 15 | 16 | var xmlContentType = []string{"application/xml; charset=utf-8"} 17 | 18 | func (r XML) Render(w http.ResponseWriter) error { 19 | writeContentType(w, xmlContentType) 20 | return xml.NewEncoder(w).Encode(r.Data) 21 | } 22 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/render/yaml.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package render 6 | 7 | import ( 8 | "net/http" 9 | 10 | "gopkg.in/yaml.v2" 11 | ) 12 | 13 | type YAML struct { 14 | Data interface{} 15 | } 16 | 17 | var yamlContentType = []string{"application/x-yaml; charset=utf-8"} 18 | 19 | func (r YAML) Render(w http.ResponseWriter) error { 20 | writeContentType(w, yamlContentType) 21 | 22 | bytes, err := yaml.Marshal(r.Data) 23 | if err != nil { 24 | return err 25 | } 26 | 27 | w.Write(bytes) 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /vendor/src/github.com/gin-gonic/gin/wercker.yml: -------------------------------------------------------------------------------- 1 | box: wercker/default -------------------------------------------------------------------------------- /vendor/src/github.com/golang/protobuf/proto/Makefile: -------------------------------------------------------------------------------- 1 | # Go support for Protocol Buffers - Google's data interchange format 2 | # 3 | # Copyright 2010 The Go Authors. All rights reserved. 4 | # https://github.com/golang/protobuf 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following disclaimer 14 | # in the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Google Inc. nor the names of its 17 | # contributors may be used to endorse or promote products derived from 18 | # this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | install: 33 | go install 34 | 35 | test: install generate-test-pbs 36 | go test 37 | 38 | 39 | generate-test-pbs: 40 | make install 41 | make -C testdata 42 | protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto 43 | make 44 | -------------------------------------------------------------------------------- /vendor/src/github.com/golang/protobuf/proto/message_set_test.go: -------------------------------------------------------------------------------- 1 | // Go support for Protocol Buffers - Google's data interchange format 2 | // 3 | // Copyright 2014 The Go Authors. All rights reserved. 4 | // https://github.com/golang/protobuf 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | package proto 33 | 34 | import ( 35 | "bytes" 36 | "testing" 37 | ) 38 | 39 | func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { 40 | // Check that a repeated message set entry will be concatenated. 41 | in := &messageSet{ 42 | Item: []*_MessageSet_Item{ 43 | {TypeId: Int32(12345), Message: []byte("hoo")}, 44 | {TypeId: Int32(12345), Message: []byte("hah")}, 45 | }, 46 | } 47 | b, err := Marshal(in) 48 | if err != nil { 49 | t.Fatalf("Marshal: %v", err) 50 | } 51 | t.Logf("Marshaled bytes: %q", b) 52 | 53 | m := make(map[int32]Extension) 54 | if err := UnmarshalMessageSet(b, m); err != nil { 55 | t.Fatalf("UnmarshalMessageSet: %v", err) 56 | } 57 | ext, ok := m[12345] 58 | if !ok { 59 | t.Fatalf("Didn't retrieve extension 12345; map is %v", m) 60 | } 61 | // Skip wire type/field number and length varints. 62 | got := skipVarint(skipVarint(ext.enc)) 63 | if want := []byte("hoohah"); !bytes.Equal(got, want) { 64 | t.Errorf("Combined extension is %q, want %q", got, want) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /vendor/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto: -------------------------------------------------------------------------------- 1 | // Go support for Protocol Buffers - Google's data interchange format 2 | // 3 | // Copyright 2014 The Go Authors. All rights reserved. 4 | // https://github.com/golang/protobuf 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | syntax = "proto3"; 33 | 34 | import "google/protobuf/any.proto"; 35 | import "testdata/test.proto"; 36 | 37 | package proto3_proto; 38 | 39 | message Message { 40 | enum Humour { 41 | UNKNOWN = 0; 42 | PUNS = 1; 43 | SLAPSTICK = 2; 44 | BILL_BAILEY = 3; 45 | } 46 | 47 | string name = 1; 48 | Humour hilarity = 2; 49 | uint32 height_in_cm = 3; 50 | bytes data = 4; 51 | int64 result_count = 7; 52 | bool true_scotsman = 8; 53 | float score = 9; 54 | 55 | repeated uint64 key = 5; 56 | Nested nested = 6; 57 | repeated Humour r_funny = 16; 58 | 59 | map terrain = 10; 60 | testdata.SubDefaults proto2_field = 11; 61 | map proto2_value = 13; 62 | 63 | google.protobuf.Any anything = 14; 64 | repeated google.protobuf.Any many_things = 15; 65 | } 66 | 67 | message Nested { 68 | string bunny = 1; 69 | } 70 | 71 | message MessageWithMap { 72 | map byte_mapping = 1; 73 | } 74 | -------------------------------------------------------------------------------- /vendor/src/github.com/golang/protobuf/proto/size2_test.go: -------------------------------------------------------------------------------- 1 | // Go support for Protocol Buffers - Google's data interchange format 2 | // 3 | // Copyright 2012 The Go Authors. All rights reserved. 4 | // https://github.com/golang/protobuf 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | package proto 33 | 34 | import ( 35 | "testing" 36 | ) 37 | 38 | // This is a separate file and package from size_test.go because that one uses 39 | // generated messages and thus may not be in package proto without having a circular 40 | // dependency, whereas this file tests unexported details of size.go. 41 | 42 | func TestVarintSize(t *testing.T) { 43 | // Check the edge cases carefully. 44 | testCases := []struct { 45 | n uint64 46 | size int 47 | }{ 48 | {0, 1}, 49 | {1, 1}, 50 | {127, 1}, 51 | {128, 2}, 52 | {16383, 2}, 53 | {16384, 3}, 54 | {1<<63 - 1, 9}, 55 | {1 << 63, 10}, 56 | } 57 | for _, tc := range testCases { 58 | size := sizeVarint(tc.n) 59 | if size != tc.size { 60 | t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vendor/src/github.com/golang/protobuf/proto/testdata/Makefile: -------------------------------------------------------------------------------- 1 | # Go support for Protocol Buffers - Google's data interchange format 2 | # 3 | # Copyright 2010 The Go Authors. All rights reserved. 4 | # https://github.com/golang/protobuf 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following disclaimer 14 | # in the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Google Inc. nor the names of its 17 | # contributors may be used to endorse or promote products derived from 18 | # this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | 33 | include ../../Make.protobuf 34 | 35 | all: regenerate 36 | 37 | regenerate: 38 | rm -f test.pb.go 39 | make test.pb.go 40 | 41 | # The following rules are just aids to development. Not needed for typical testing. 42 | 43 | diff: regenerate 44 | git diff test.pb.go 45 | 46 | restore: 47 | cp test.pb.go.golden test.pb.go 48 | 49 | preserve: 50 | cp test.pb.go test.pb.go.golden 51 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Gorilla WebSocket authors for copyright 2 | # purposes. 3 | # 4 | # Please keep the list sorted. 5 | 6 | Gary Burd 7 | Joachim Bauch 8 | 9 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla WebSocket 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 met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/bench_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func BenchmarkMaskBytes(b *testing.B) { 12 | var key [4]byte 13 | data := make([]byte, 1024) 14 | pos := 0 15 | for i := 0; i < b.N; i++ { 16 | pos = maskBytes(key, pos, data) 17 | } 18 | b.SetBytes(int64(len(data))) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/client_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "net/url" 9 | "reflect" 10 | "testing" 11 | ) 12 | 13 | var parseURLTests = []struct { 14 | s string 15 | u *url.URL 16 | rui string 17 | }{ 18 | {"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"}, 19 | {"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"}, 20 | {"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}, "/"}, 21 | {"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}, "/"}, 22 | {"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}, "/a/b"}, 23 | {"ss://example.com/a/b", nil, ""}, 24 | {"ws://webmaster@example.com/", nil, ""}, 25 | {"wss://example.com/a/b?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b", RawQuery: "x=y"}, "/a/b?x=y"}, 26 | {"wss://example.com?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/", RawQuery: "x=y"}, "/?x=y"}, 27 | } 28 | 29 | func TestParseURL(t *testing.T) { 30 | for _, tt := range parseURLTests { 31 | u, err := parseURL(tt.s) 32 | if tt.u != nil && err != nil { 33 | t.Errorf("parseURL(%q) returned error %v", tt.s, err) 34 | continue 35 | } 36 | if tt.u == nil { 37 | if err == nil { 38 | t.Errorf("parseURL(%q) did not return error", tt.s) 39 | } 40 | continue 41 | } 42 | if !reflect.DeepEqual(u, tt.u) { 43 | t.Errorf("parseURL(%q) = %v, want %v", tt.s, u, tt.u) 44 | continue 45 | } 46 | if u.RequestURI() != tt.rui { 47 | t.Errorf("parseURL(%q).RequestURI() = %v, want %v", tt.s, u.RequestURI(), tt.rui) 48 | } 49 | } 50 | } 51 | 52 | var hostPortNoPortTests = []struct { 53 | u *url.URL 54 | hostPort, hostNoPort string 55 | }{ 56 | {&url.URL{Scheme: "ws", Host: "example.com"}, "example.com:80", "example.com"}, 57 | {&url.URL{Scheme: "wss", Host: "example.com"}, "example.com:443", "example.com"}, 58 | {&url.URL{Scheme: "ws", Host: "example.com:7777"}, "example.com:7777", "example.com"}, 59 | {&url.URL{Scheme: "wss", Host: "example.com:7777"}, "example.com:7777", "example.com"}, 60 | } 61 | 62 | func TestHostPortNoPort(t *testing.T) { 63 | for _, tt := range hostPortNoPortTests { 64 | hostPort, hostNoPort := hostPortNoPort(tt.u) 65 | if hostPort != tt.hostPort { 66 | t.Errorf("hostPortNoPort(%v) returned hostPort %q, want %q", tt.u, hostPort, tt.hostPort) 67 | } 68 | if hostNoPort != tt.hostNoPort { 69 | t.Errorf("hostPortNoPort(%v) returned hostNoPort %q, want %q", tt.u, hostNoPort, tt.hostNoPort) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Gorilla WebSocket 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 websocket_test 6 | 7 | import ( 8 | "log" 9 | "net/http" 10 | "testing" 11 | 12 | "github.com/gorilla/websocket" 13 | ) 14 | 15 | var ( 16 | c *websocket.Conn 17 | req *http.Request 18 | ) 19 | 20 | // The websocket.IsUnexpectedCloseError function is useful for identifying 21 | // application and protocol errors. 22 | // 23 | // This server application works with a client application running in the 24 | // browser. The client application does not explicitly close the websocket. The 25 | // only expected close message from the client has the code 26 | // websocket.CloseGoingAway. All other other close messages are likely the 27 | // result of an application or protocol error and are logged to aid debugging. 28 | func ExampleIsUnexpectedCloseError() { 29 | 30 | for { 31 | messageType, p, err := c.ReadMessage() 32 | if err != nil { 33 | if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) { 34 | log.Printf("error: %v, user-agent: %v", err, req.Header.Get("User-Agent")) 35 | } 36 | return 37 | } 38 | processMesage(messageType, p) 39 | } 40 | } 41 | 42 | func processMesage(mt int, p []byte) {} 43 | 44 | // TestX prevents godoc from showing this entire file in the example. Remove 45 | // this function when a second example is added. 46 | func TestX(t *testing.T) {} 47 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/autobahn/README.md: -------------------------------------------------------------------------------- 1 | # Test Server 2 | 3 | This package contains a server for the [Autobahn WebSockets Test Suite](http://autobahn.ws/testsuite). 4 | 5 | To test the server, run 6 | 7 | go run server.go 8 | 9 | and start the client test driver 10 | 11 | wstest -m fuzzingclient -s fuzzingclient.json 12 | 13 | When the client completes, it writes a report to reports/clients/index.html. 14 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "options": {"failByDrop": false}, 4 | "outdir": "./reports/clients", 5 | "servers": [ 6 | {"agent": "ReadAllWriteMessage", "url": "ws://localhost:9000/m", "options": {"version": 18}}, 7 | {"agent": "ReadAllWrite", "url": "ws://localhost:9000/r", "options": {"version": 18}}, 8 | {"agent": "CopyFull", "url": "ws://localhost:9000/f", "options": {"version": 18}}, 9 | {"agent": "CopyWriterOnly", "url": "ws://localhost:9000/c", "options": {"version": 18}} 10 | ], 11 | "cases": ["*"], 12 | "exclude-cases": [], 13 | "exclude-agent-cases": {} 14 | } 15 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/chat/README.md: -------------------------------------------------------------------------------- 1 | # Chat Example 2 | 3 | This application shows how to use use the 4 | [websocket](https://github.com/gorilla/websocket) package and 5 | [jQuery](http://jquery.com) to implement a simple web chat application. 6 | 7 | ## Running the example 8 | 9 | The example requires a working Go development environment. The [Getting 10 | Started](http://golang.org/doc/install) page describes how to install the 11 | development environment. 12 | 13 | Once you have Go up and running, you can download, build and run the example 14 | using the following commands. 15 | 16 | $ go get github.com/gorilla/websocket 17 | $ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/chat` 18 | $ go run *.go 19 | 20 | To use the chat example, open http://localhost:8080/ in your browser. 21 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/chat/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Chat Example 5 | 6 | 47 | 84 | 85 | 86 |
87 |
88 | 89 | 90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/chat/hub.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket 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 main 6 | 7 | // hub maintains the set of active connections and broadcasts messages to the 8 | // connections. 9 | type hub struct { 10 | // Registered connections. 11 | connections map[*connection]bool 12 | 13 | // Inbound messages from the connections. 14 | broadcast chan []byte 15 | 16 | // Register requests from the connections. 17 | register chan *connection 18 | 19 | // Unregister requests from connections. 20 | unregister chan *connection 21 | } 22 | 23 | var h = hub{ 24 | broadcast: make(chan []byte), 25 | register: make(chan *connection), 26 | unregister: make(chan *connection), 27 | connections: make(map[*connection]bool), 28 | } 29 | 30 | func (h *hub) run() { 31 | for { 32 | select { 33 | case c := <-h.register: 34 | h.connections[c] = true 35 | case c := <-h.unregister: 36 | if _, ok := h.connections[c]; ok { 37 | delete(h.connections, c) 38 | close(c.send) 39 | } 40 | case m := <-h.broadcast: 41 | for c := range h.connections { 42 | select { 43 | case c.send <- m: 44 | default: 45 | close(c.send) 46 | delete(h.connections, c) 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/chat/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket 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 main 6 | 7 | import ( 8 | "flag" 9 | "log" 10 | "net/http" 11 | "text/template" 12 | ) 13 | 14 | var addr = flag.String("addr", ":8080", "http service address") 15 | var homeTempl = template.Must(template.ParseFiles("home.html")) 16 | 17 | func serveHome(w http.ResponseWriter, r *http.Request) { 18 | if r.URL.Path != "/" { 19 | http.Error(w, "Not found", 404) 20 | return 21 | } 22 | if r.Method != "GET" { 23 | http.Error(w, "Method not allowed", 405) 24 | return 25 | } 26 | w.Header().Set("Content-Type", "text/html; charset=utf-8") 27 | homeTempl.Execute(w, r.Host) 28 | } 29 | 30 | func main() { 31 | flag.Parse() 32 | go h.run() 33 | http.HandleFunc("/", serveHome) 34 | http.HandleFunc("/ws", serveWs) 35 | err := http.ListenAndServe(*addr, nil) 36 | if err != nil { 37 | log.Fatal("ListenAndServe: ", err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/command/README.md: -------------------------------------------------------------------------------- 1 | # Command example 2 | 3 | This example connects a websocket connection to stdin and stdout of a command. 4 | Received messages are written to stdin followed by a `\n`. Each line read from 5 | from standard out is sent as a message to the client. 6 | 7 | $ go get github.com/gorilla/websocket 8 | $ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/command` 9 | $ go run main.go 10 | # Open http://localhost:8080/ . 11 | 12 | Try the following commands. 13 | 14 | # Echo sent messages to the output area. 15 | $ go run main.go cat 16 | 17 | # Run a shell.Try sending "ls" and "cat main.go". 18 | $ go run main.go sh 19 | 20 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/command/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Command Example 5 | 6 | 47 | 88 | 89 | 90 |
91 |
92 | 93 | 94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/echo/README.md: -------------------------------------------------------------------------------- 1 | # Client and server example 2 | 3 | This example shows a simple client and server. 4 | 5 | The server echoes messages sent to it. The client sends a message every second 6 | and prints all messages received. 7 | 8 | To run the example, start the server: 9 | 10 | $ go run server.go 11 | 12 | Next, start the client: 13 | 14 | $ go run client.go 15 | 16 | The server includes a simple web client. To use the client, open 17 | http://127.0.0.1:8080 in the browser and follow the instructions on the page. 18 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/echo/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Gorilla WebSocket 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 | // +build ignore 6 | 7 | package main 8 | 9 | import ( 10 | "flag" 11 | "log" 12 | "net/url" 13 | "os" 14 | "os/signal" 15 | "time" 16 | 17 | "github.com/gorilla/websocket" 18 | ) 19 | 20 | var addr = flag.String("addr", "localhost:8080", "http service address") 21 | 22 | func main() { 23 | flag.Parse() 24 | log.SetFlags(0) 25 | 26 | interrupt := make(chan os.Signal, 1) 27 | signal.Notify(interrupt, os.Interrupt) 28 | 29 | u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"} 30 | log.Printf("connecting to %s", u.String()) 31 | 32 | c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) 33 | if err != nil { 34 | log.Fatal("dial:", err) 35 | } 36 | defer c.Close() 37 | 38 | done := make(chan struct{}) 39 | 40 | go func() { 41 | defer c.Close() 42 | defer close(done) 43 | for { 44 | _, message, err := c.ReadMessage() 45 | if err != nil { 46 | log.Println("read:", err) 47 | return 48 | } 49 | log.Printf("recv: %s", message) 50 | } 51 | }() 52 | 53 | ticker := time.NewTicker(time.Second) 54 | defer ticker.Stop() 55 | 56 | for { 57 | select { 58 | case t := <-ticker.C: 59 | err := c.WriteMessage(websocket.TextMessage, []byte(t.String())) 60 | if err != nil { 61 | log.Println("write:", err) 62 | return 63 | } 64 | case <-interrupt: 65 | log.Println("interrupt") 66 | // To cleanly close a connection, a client should send a close 67 | // frame and wait for the server to close the connection. 68 | err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) 69 | if err != nil { 70 | log.Println("write close:", err) 71 | return 72 | } 73 | select { 74 | case <-done: 75 | case <-time.After(time.Second): 76 | } 77 | c.Close() 78 | return 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/examples/filewatch/README.md: -------------------------------------------------------------------------------- 1 | # File Watch example. 2 | 3 | This example sends a file to the browser client for display whenever the file is modified. 4 | 5 | $ go get github.com/gorilla/websocket 6 | $ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/filewatch` 7 | $ go run main.go 8 | # Open http://localhost:8080/ . 9 | # Modify the file to see it update in the browser. 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "encoding/json" 9 | "io" 10 | ) 11 | 12 | // WriteJSON is deprecated, use c.WriteJSON instead. 13 | func WriteJSON(c *Conn, v interface{}) error { 14 | return c.WriteJSON(v) 15 | } 16 | 17 | // WriteJSON writes the JSON encoding of v to the connection. 18 | // 19 | // See the documentation for encoding/json Marshal for details about the 20 | // conversion of Go values to JSON. 21 | func (c *Conn) WriteJSON(v interface{}) error { 22 | w, err := c.NextWriter(TextMessage) 23 | if err != nil { 24 | return err 25 | } 26 | err1 := json.NewEncoder(w).Encode(v) 27 | err2 := w.Close() 28 | if err1 != nil { 29 | return err1 30 | } 31 | return err2 32 | } 33 | 34 | // ReadJSON is deprecated, use c.ReadJSON instead. 35 | func ReadJSON(c *Conn, v interface{}) error { 36 | return c.ReadJSON(v) 37 | } 38 | 39 | // ReadJSON reads the next JSON-encoded message from the connection and stores 40 | // it in the value pointed to by v. 41 | // 42 | // See the documentation for the encoding/json Unmarshal function for details 43 | // about the conversion of JSON to a Go value. 44 | func (c *Conn) ReadJSON(v interface{}) error { 45 | _, r, err := c.NextReader() 46 | if err != nil { 47 | return err 48 | } 49 | err = json.NewDecoder(r).Decode(v) 50 | if err == io.EOF { 51 | // One value is expected in the message. 52 | err = io.ErrUnexpectedEOF 53 | } 54 | return err 55 | } 56 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/json_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "bytes" 9 | "encoding/json" 10 | "io" 11 | "reflect" 12 | "testing" 13 | ) 14 | 15 | func TestJSON(t *testing.T) { 16 | var buf bytes.Buffer 17 | c := fakeNetConn{&buf, &buf} 18 | wc := newConn(c, true, 1024, 1024) 19 | rc := newConn(c, false, 1024, 1024) 20 | 21 | var actual, expect struct { 22 | A int 23 | B string 24 | } 25 | expect.A = 1 26 | expect.B = "hello" 27 | 28 | if err := wc.WriteJSON(&expect); err != nil { 29 | t.Fatal("write", err) 30 | } 31 | 32 | if err := rc.ReadJSON(&actual); err != nil { 33 | t.Fatal("read", err) 34 | } 35 | 36 | if !reflect.DeepEqual(&actual, &expect) { 37 | t.Fatal("equal", actual, expect) 38 | } 39 | } 40 | 41 | func TestPartialJSONRead(t *testing.T) { 42 | var buf bytes.Buffer 43 | c := fakeNetConn{&buf, &buf} 44 | wc := newConn(c, true, 1024, 1024) 45 | rc := newConn(c, false, 1024, 1024) 46 | 47 | var v struct { 48 | A int 49 | B string 50 | } 51 | v.A = 1 52 | v.B = "hello" 53 | 54 | messageCount := 0 55 | 56 | // Partial JSON values. 57 | 58 | data, err := json.Marshal(v) 59 | if err != nil { 60 | t.Fatal(err) 61 | } 62 | for i := len(data) - 1; i >= 0; i-- { 63 | if err := wc.WriteMessage(TextMessage, data[:i]); err != nil { 64 | t.Fatal(err) 65 | } 66 | messageCount++ 67 | } 68 | 69 | // Whitespace. 70 | 71 | if err := wc.WriteMessage(TextMessage, []byte(" ")); err != nil { 72 | t.Fatal(err) 73 | } 74 | messageCount++ 75 | 76 | // Close. 77 | 78 | if err := wc.WriteMessage(CloseMessage, FormatCloseMessage(CloseNormalClosure, "")); err != nil { 79 | t.Fatal(err) 80 | } 81 | 82 | for i := 0; i < messageCount; i++ { 83 | err := rc.ReadJSON(&v) 84 | if err != io.ErrUnexpectedEOF { 85 | t.Error("read", i, err) 86 | } 87 | } 88 | 89 | err = rc.ReadJSON(&v) 90 | if _, ok := err.(*CloseError); !ok { 91 | t.Error("final", err) 92 | } 93 | } 94 | 95 | func TestDeprecatedJSON(t *testing.T) { 96 | var buf bytes.Buffer 97 | c := fakeNetConn{&buf, &buf} 98 | wc := newConn(c, true, 1024, 1024) 99 | rc := newConn(c, false, 1024, 1024) 100 | 101 | var actual, expect struct { 102 | A int 103 | B string 104 | } 105 | expect.A = 1 106 | expect.B = "hello" 107 | 108 | if err := WriteJSON(wc, &expect); err != nil { 109 | t.Fatal("write", err) 110 | } 111 | 112 | if err := ReadJSON(rc, &actual); err != nil { 113 | t.Fatal("read", err) 114 | } 115 | 116 | if !reflect.DeepEqual(&actual, &expect) { 117 | t.Fatal("equal", actual, expect) 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/server_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "net/http" 9 | "reflect" 10 | "testing" 11 | ) 12 | 13 | var subprotocolTests = []struct { 14 | h string 15 | protocols []string 16 | }{ 17 | {"", nil}, 18 | {"foo", []string{"foo"}}, 19 | {"foo,bar", []string{"foo", "bar"}}, 20 | {"foo, bar", []string{"foo", "bar"}}, 21 | {" foo, bar", []string{"foo", "bar"}}, 22 | {" foo, bar ", []string{"foo", "bar"}}, 23 | } 24 | 25 | func TestSubprotocols(t *testing.T) { 26 | for _, st := range subprotocolTests { 27 | r := http.Request{Header: http.Header{"Sec-Websocket-Protocol": {st.h}}} 28 | protocols := Subprotocols(&r) 29 | if !reflect.DeepEqual(st.protocols, protocols) { 30 | t.Errorf("SubProtocols(%q) returned %#v, want %#v", st.h, protocols, st.protocols) 31 | } 32 | } 33 | } 34 | 35 | var isWebSocketUpgradeTests = []struct { 36 | ok bool 37 | h http.Header 38 | }{ 39 | {false, http.Header{"Upgrade": {"websocket"}}}, 40 | {false, http.Header{"Connection": {"upgrade"}}}, 41 | {true, http.Header{"Connection": {"upgRade"}, "Upgrade": {"WebSocket"}}}, 42 | } 43 | 44 | func TestIsWebSocketUpgrade(t *testing.T) { 45 | for _, tt := range isWebSocketUpgradeTests { 46 | ok := IsWebSocketUpgrade(&http.Request{Header: tt.h}) 47 | if tt.ok != ok { 48 | t.Errorf("IsWebSocketUpgrade(%v) returned %v, want %v", tt.h, ok, tt.ok) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "crypto/rand" 9 | "crypto/sha1" 10 | "encoding/base64" 11 | "io" 12 | "net/http" 13 | "strings" 14 | ) 15 | 16 | // tokenListContainsValue returns true if the 1#token header with the given 17 | // name contains token. 18 | func tokenListContainsValue(header http.Header, name string, value string) bool { 19 | for _, v := range header[name] { 20 | for _, s := range strings.Split(v, ",") { 21 | if strings.EqualFold(value, strings.TrimSpace(s)) { 22 | return true 23 | } 24 | } 25 | } 26 | return false 27 | } 28 | 29 | var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") 30 | 31 | func computeAcceptKey(challengeKey string) string { 32 | h := sha1.New() 33 | h.Write([]byte(challengeKey)) 34 | h.Write(keyGUID) 35 | return base64.StdEncoding.EncodeToString(h.Sum(nil)) 36 | } 37 | 38 | func generateChallengeKey() (string, error) { 39 | p := make([]byte, 16) 40 | if _, err := io.ReadFull(rand.Reader, p); err != nil { 41 | return "", err 42 | } 43 | return base64.StdEncoding.EncodeToString(p), nil 44 | } 45 | -------------------------------------------------------------------------------- /vendor/src/github.com/gorilla/websocket/util_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Gorilla WebSocket 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 websocket 6 | 7 | import ( 8 | "net/http" 9 | "testing" 10 | ) 11 | 12 | var tokenListContainsValueTests = []struct { 13 | value string 14 | ok bool 15 | }{ 16 | {"WebSocket", true}, 17 | {"WEBSOCKET", true}, 18 | {"websocket", true}, 19 | {"websockets", false}, 20 | {"x websocket", false}, 21 | {"websocket x", false}, 22 | {"other,websocket,more", true}, 23 | {"other, websocket, more", true}, 24 | } 25 | 26 | func TestTokenListContainsValue(t *testing.T) { 27 | for _, tt := range tokenListContainsValueTests { 28 | h := http.Header{"Upgrade": {tt.value}} 29 | ok := tokenListContainsValue(h, "Upgrade", "websocket") 30 | if ok != tt.ok { 31 | t.Errorf("tokenListContainsValue(h, n, %q) = %v, want %v", tt.value, ok, tt.ok) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vendor/src/github.com/manucorporat/sse/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Manuel Martínez-Almeida 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/src/github.com/manucorporat/sse/README.md: -------------------------------------------------------------------------------- 1 | #Server-Sent Events [![GoDoc](https://godoc.org/github.com/manucorporat/sse?status.svg)](https://godoc.org/github.com/manucorporat/sse) [![Build Status](https://travis-ci.org/manucorporat/sse.svg)](https://travis-ci.org/manucorporat/sse) 2 | 3 | Server-sent events (SSE) is a technology where a browser receives automatic updates from a server via HTTP connection. The Server-Sent Events EventSource API is [standardized as part of HTML5[1] by the W3C](http://www.w3.org/TR/2009/WD-eventsource-20091029/). 4 | 5 | - [Real world demostration using Gin](http://sse.getgin.io/) 6 | - [Read this great SSE introduction by the HTML5Rocks guys](http://www.html5rocks.com/en/tutorials/eventsource/basics/) 7 | - [Browser support](http://caniuse.com/#feat=eventsource) 8 | 9 | ##Sample code 10 | 11 | ```go 12 | import "github.com/manucorporat/sse" 13 | 14 | func httpHandler(w http.ResponseWriter, req *http.Request) { 15 | // data can be a primitive like a string, an integer or a float 16 | sse.Encode(w, sse.Event{ 17 | Event: "message", 18 | Data: "some data\nmore data", 19 | }) 20 | 21 | // also a complex type, like a map, a struct or a slice 22 | sse.Encode(w, sse.Event{ 23 | Id: "124", 24 | Event: "message", 25 | Data: map[string]interface{}{ 26 | "user": "manu", 27 | "date": time.Now().Unix(), 28 | "content": "hi!", 29 | }, 30 | }) 31 | } 32 | ``` 33 | ``` 34 | event: message 35 | data: some data\\nmore data 36 | 37 | id: 124 38 | event: message 39 | data: {"content":"hi!","date":1431540810,"user":"manu"} 40 | 41 | ``` 42 | 43 | ##Content-Type 44 | 45 | ```go 46 | fmt.Println(sse.ContentType) 47 | ``` 48 | ``` 49 | text/event-stream 50 | ``` 51 | 52 | ##Decoding support 53 | 54 | There is a client-side implementation of SSE coming soon. -------------------------------------------------------------------------------- /vendor/src/github.com/manucorporat/sse/sse-decoder_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sse 6 | 7 | import ( 8 | "bytes" 9 | "testing" 10 | 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | func TestDecodeSingle1(t *testing.T) { 15 | events, err := Decode(bytes.NewBufferString( 16 | `data: this is a text 17 | event: message 18 | fake: 19 | id: 123456789010 20 | : we can append data 21 | : and multiple comments should not break it 22 | data: a very nice one`)) 23 | 24 | assert.NoError(t, err) 25 | assert.Len(t, events, 1) 26 | assert.Equal(t, events[0].Event, "message") 27 | assert.Equal(t, events[0].Id, "123456789010") 28 | } 29 | 30 | func TestDecodeSingle2(t *testing.T) { 31 | events, err := Decode(bytes.NewBufferString( 32 | `: starting with a comment 33 | fake: 34 | 35 | data:this is a \ntext 36 | event:a message\n\n 37 | fake 38 | :and multiple comments\n should not break it\n\n 39 | id:1234567890\n10 40 | :we can append data 41 | data:a very nice one\n! 42 | 43 | 44 | `)) 45 | assert.NoError(t, err) 46 | assert.Len(t, events, 1) 47 | assert.Equal(t, events[0].Event, "a message\\n\\n") 48 | assert.Equal(t, events[0].Id, "1234567890\\n10") 49 | } 50 | 51 | func TestDecodeSingle3(t *testing.T) { 52 | events, err := Decode(bytes.NewBufferString( 53 | ` 54 | id:123456ABCabc789010 55 | event: message123 56 | : we can append data 57 | data:this is a text 58 | data: a very nice one 59 | data: 60 | data 61 | : ending with a comment`)) 62 | 63 | assert.NoError(t, err) 64 | assert.Len(t, events, 1) 65 | assert.Equal(t, events[0].Event, "message123") 66 | assert.Equal(t, events[0].Id, "123456ABCabc789010") 67 | } 68 | 69 | func TestDecodeMulti1(t *testing.T) { 70 | events, err := Decode(bytes.NewBufferString( 71 | ` 72 | id: 73 | event: weird event 74 | data:this is a text 75 | :data: this should NOT APER 76 | data: second line 77 | 78 | : a comment 79 | event: message 80 | id:123 81 | data:this is a text 82 | :data: this should NOT APER 83 | data: second line 84 | 85 | 86 | : a comment 87 | event: message 88 | id:123 89 | data:this is a text 90 | data: second line 91 | 92 | :hola 93 | 94 | data 95 | 96 | event: 97 | 98 | id`)) 99 | assert.NoError(t, err) 100 | assert.Len(t, events, 3) 101 | assert.Equal(t, events[0].Event, "weird event") 102 | assert.Equal(t, events[0].Id, "") 103 | } 104 | 105 | func TestDecodeW3C(t *testing.T) { 106 | events, err := Decode(bytes.NewBufferString( 107 | `data 108 | 109 | data 110 | data 111 | 112 | data: 113 | `)) 114 | assert.NoError(t, err) 115 | assert.Len(t, events, 1) 116 | } 117 | -------------------------------------------------------------------------------- /vendor/src/github.com/manucorporat/sse/sse-encoder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 | // Use of this source code is governed by a MIT style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sse 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "io" 11 | "net/http" 12 | "reflect" 13 | "strconv" 14 | "strings" 15 | ) 16 | 17 | // Server-Sent Events 18 | // W3C Working Draft 29 October 2009 19 | // http://www.w3.org/TR/2009/WD-eventsource-20091029/ 20 | 21 | const ContentType = "text/event-stream" 22 | 23 | var contentType = []string{ContentType} 24 | var noCache = []string{"no-cache"} 25 | 26 | var fieldReplacer = strings.NewReplacer( 27 | "\n", "\\n", 28 | "\r", "\\r") 29 | 30 | var dataReplacer = strings.NewReplacer( 31 | "\n", "\ndata:", 32 | "\r", "\\r") 33 | 34 | type Event struct { 35 | Event string 36 | Id string 37 | Retry uint 38 | Data interface{} 39 | } 40 | 41 | func Encode(writer io.Writer, event Event) error { 42 | w := checkWriter(writer) 43 | writeId(w, event.Id) 44 | writeEvent(w, event.Event) 45 | writeRetry(w, event.Retry) 46 | return writeData(w, event.Data) 47 | } 48 | 49 | func writeId(w stringWriter, id string) { 50 | if len(id) > 0 { 51 | w.WriteString("id:") 52 | fieldReplacer.WriteString(w, id) 53 | w.WriteString("\n") 54 | } 55 | } 56 | 57 | func writeEvent(w stringWriter, event string) { 58 | if len(event) > 0 { 59 | w.WriteString("event:") 60 | fieldReplacer.WriteString(w, event) 61 | w.WriteString("\n") 62 | } 63 | } 64 | 65 | func writeRetry(w stringWriter, retry uint) { 66 | if retry > 0 { 67 | w.WriteString("retry:") 68 | w.WriteString(strconv.FormatUint(uint64(retry), 10)) 69 | w.WriteString("\n") 70 | } 71 | } 72 | 73 | func writeData(w stringWriter, data interface{}) error { 74 | w.WriteString("data:") 75 | switch kindOfData(data) { 76 | case reflect.Struct, reflect.Slice, reflect.Map: 77 | err := json.NewEncoder(w).Encode(data) 78 | if err != nil { 79 | return err 80 | } 81 | w.WriteString("\n") 82 | default: 83 | dataReplacer.WriteString(w, fmt.Sprint(data)) 84 | w.WriteString("\n\n") 85 | } 86 | return nil 87 | } 88 | 89 | func (r Event) Render(w http.ResponseWriter) error { 90 | header := w.Header() 91 | header["Content-Type"] = contentType 92 | 93 | if _, exist := header["Cache-Control"]; !exist { 94 | header["Cache-Control"] = noCache 95 | } 96 | return Encode(w, r) 97 | } 98 | 99 | func kindOfData(data interface{}) reflect.Kind { 100 | value := reflect.ValueOf(data) 101 | valueType := value.Kind() 102 | if valueType == reflect.Ptr { 103 | valueType = value.Elem().Kind() 104 | } 105 | return valueType 106 | } 107 | -------------------------------------------------------------------------------- /vendor/src/github.com/manucorporat/sse/writer.go: -------------------------------------------------------------------------------- 1 | package sse 2 | 3 | import "io" 4 | 5 | type stringWriter interface { 6 | io.Writer 7 | WriteString(string) (int, error) 8 | } 9 | 10 | type stringWrapper struct { 11 | io.Writer 12 | } 13 | 14 | func (w stringWrapper) WriteString(str string) (int, error) { 15 | return w.Writer.Write([]byte(str)) 16 | } 17 | 18 | func checkWriter(writer io.Writer) stringWriter { 19 | if w, ok := writer.(stringWriter); ok { 20 | return w 21 | } else { 22 | return stringWrapper{writer} 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /vendor/src/github.com/manucorporat/stats/stats.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import "sync" 4 | 5 | type ValueType float64 6 | type StatsType map[string]ValueType 7 | 8 | type StatsCollector struct { 9 | lock sync.RWMutex 10 | stats StatsType 11 | } 12 | 13 | func New() *StatsCollector { 14 | s := new(StatsCollector) 15 | s.Reset() 16 | return s 17 | } 18 | 19 | func (s *StatsCollector) Reset() { 20 | s.lock.Lock() 21 | s.stats = make(StatsType) 22 | s.lock.Unlock() 23 | } 24 | 25 | func (s *StatsCollector) Set(key string, value ValueType) { 26 | s.lock.Lock() 27 | s.stats[key] = value 28 | s.lock.Unlock() 29 | } 30 | 31 | func (s *StatsCollector) Add(key string, delta ValueType) (v ValueType) { 32 | s.lock.Lock() 33 | v = s.stats[key] 34 | v += delta 35 | s.stats[key] = v 36 | s.lock.Unlock() 37 | return 38 | } 39 | 40 | func (s *StatsCollector) Get(key string) (v ValueType) { 41 | s.lock.RLock() 42 | v = s.stats[key] 43 | s.lock.RUnlock() 44 | return 45 | } 46 | 47 | func (s *StatsCollector) Del(key string) { 48 | s.lock.Lock() 49 | delete(s.stats, key) 50 | s.lock.Unlock() 51 | } 52 | 53 | func (s *StatsCollector) Data() StatsType { 54 | cp := make(StatsType) 55 | s.lock.RLock() 56 | for key, value := range s.stats { 57 | cp[key] = value 58 | } 59 | s.lock.RUnlock() 60 | return cp 61 | } 62 | 63 | var defaultCollector = New() 64 | 65 | func Reset() { 66 | defaultCollector.Reset() 67 | } 68 | 69 | func Set(key string, value ValueType) { 70 | defaultCollector.Set(key, value) 71 | } 72 | 73 | func Del(key string) { 74 | defaultCollector.Del(key) 75 | } 76 | 77 | func Add(key string, delta ValueType) ValueType { 78 | return defaultCollector.Add(key, delta) 79 | } 80 | 81 | func Get(key string) ValueType { 82 | return defaultCollector.Get(key) 83 | } 84 | 85 | func Data() StatsType { 86 | return defaultCollector.Data() 87 | } 88 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.10.0 2 | 3 | * feature: Add a test hook (#180) 4 | * feature: `ParseLevel` is now case-insensitive (#326) 5 | * feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) 6 | * performance: avoid re-allocations on `WithFields` (#335) 7 | 8 | # 0.9.0 9 | 10 | * logrus/text_formatter: don't emit empty msg 11 | * logrus/hooks/airbrake: move out of main repository 12 | * logrus/hooks/sentry: move out of main repository 13 | * logrus/hooks/papertrail: move out of main repository 14 | * logrus/hooks/bugsnag: move out of main repository 15 | * logrus/core: run tests with `-race` 16 | * logrus/core: detect TTY based on `stderr` 17 | * logrus/core: support `WithError` on logger 18 | * logrus/core: Solaris support 19 | 20 | # 0.8.7 21 | 22 | * logrus/core: fix possible race (#216) 23 | * logrus/doc: small typo fixes and doc improvements 24 | 25 | 26 | # 0.8.6 27 | 28 | * hooks/raven: allow passing an initialized client 29 | 30 | # 0.8.5 31 | 32 | * logrus/core: revert #208 33 | 34 | # 0.8.4 35 | 36 | * formatter/text: fix data race (#218) 37 | 38 | # 0.8.3 39 | 40 | * logrus/core: fix entry log level (#208) 41 | * logrus/core: improve performance of text formatter by 40% 42 | * logrus/core: expose `LevelHooks` type 43 | * logrus/core: add support for DragonflyBSD and NetBSD 44 | * formatter/text: print structs more verbosely 45 | 46 | # 0.8.2 47 | 48 | * logrus: fix more Fatal family functions 49 | 50 | # 0.8.1 51 | 52 | * logrus: fix not exiting on `Fatalf` and `Fatalln` 53 | 54 | # 0.8.0 55 | 56 | * logrus: defaults to stderr instead of stdout 57 | * hooks/sentry: add special field for `*http.Request` 58 | * formatter/text: ignore Windows for colors 59 | 60 | # 0.7.3 61 | 62 | * formatter/\*: allow configuration of timestamp layout 63 | 64 | # 0.7.2 65 | 66 | * formatter/text: Add configuration option for time format (#158) 67 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Simon Eskildsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package logrus is a structured logger for Go, completely API compatible with the standard library logger. 3 | 4 | 5 | The simplest way to use Logrus is simply the package-level exported logger: 6 | 7 | package main 8 | 9 | import ( 10 | log "github.com/Sirupsen/logrus" 11 | ) 12 | 13 | func main() { 14 | log.WithFields(log.Fields{ 15 | "animal": "walrus", 16 | "number": 1, 17 | "size": 10, 18 | }).Info("A walrus appears") 19 | } 20 | 21 | Output: 22 | time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 23 | 24 | For a full guide visit https://github.com/Sirupsen/logrus 25 | */ 26 | package logrus 27 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/entry_test.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestEntryWithError(t *testing.T) { 12 | 13 | assert := assert.New(t) 14 | 15 | defer func() { 16 | ErrorKey = "error" 17 | }() 18 | 19 | err := fmt.Errorf("kaboom at layer %d", 4711) 20 | 21 | assert.Equal(err, WithError(err).Data["error"]) 22 | 23 | logger := New() 24 | logger.Out = &bytes.Buffer{} 25 | entry := NewEntry(logger) 26 | 27 | assert.Equal(err, entry.WithError(err).Data["error"]) 28 | 29 | ErrorKey = "err" 30 | 31 | assert.Equal(err, entry.WithError(err).Data["err"]) 32 | 33 | } 34 | 35 | func TestEntryPanicln(t *testing.T) { 36 | errBoom := fmt.Errorf("boom time") 37 | 38 | defer func() { 39 | p := recover() 40 | assert.NotNil(t, p) 41 | 42 | switch pVal := p.(type) { 43 | case *Entry: 44 | assert.Equal(t, "kaboom", pVal.Message) 45 | assert.Equal(t, errBoom, pVal.Data["err"]) 46 | default: 47 | t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal) 48 | } 49 | }() 50 | 51 | logger := New() 52 | logger.Out = &bytes.Buffer{} 53 | entry := NewEntry(logger) 54 | entry.WithField("err", errBoom).Panicln("kaboom") 55 | } 56 | 57 | func TestEntryPanicf(t *testing.T) { 58 | errBoom := fmt.Errorf("boom again") 59 | 60 | defer func() { 61 | p := recover() 62 | assert.NotNil(t, p) 63 | 64 | switch pVal := p.(type) { 65 | case *Entry: 66 | assert.Equal(t, "kaboom true", pVal.Message) 67 | assert.Equal(t, errBoom, pVal.Data["err"]) 68 | default: 69 | t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal) 70 | } 71 | }() 72 | 73 | logger := New() 74 | logger.Out = &bytes.Buffer{} 75 | entry := NewEntry(logger) 76 | entry.WithField("err", errBoom).Panicf("kaboom %v", true) 77 | } 78 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/examples/basic/basic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | ) 6 | 7 | var log = logrus.New() 8 | 9 | func init() { 10 | log.Formatter = new(logrus.JSONFormatter) 11 | log.Formatter = new(logrus.TextFormatter) // default 12 | log.Level = logrus.DebugLevel 13 | } 14 | 15 | func main() { 16 | defer func() { 17 | err := recover() 18 | if err != nil { 19 | log.WithFields(logrus.Fields{ 20 | "omg": true, 21 | "err": err, 22 | "number": 100, 23 | }).Fatal("The ice breaks!") 24 | } 25 | }() 26 | 27 | log.WithFields(logrus.Fields{ 28 | "animal": "walrus", 29 | "number": 8, 30 | }).Debug("Started observing beach") 31 | 32 | log.WithFields(logrus.Fields{ 33 | "animal": "walrus", 34 | "size": 10, 35 | }).Info("A group of walrus emerges from the ocean") 36 | 37 | log.WithFields(logrus.Fields{ 38 | "omg": true, 39 | "number": 122, 40 | }).Warn("The group's number increased tremendously!") 41 | 42 | log.WithFields(logrus.Fields{ 43 | "temperature": -4, 44 | }).Debug("Temperature changes") 45 | 46 | log.WithFields(logrus.Fields{ 47 | "animal": "orca", 48 | "size": 9009, 49 | }).Panic("It's over 9000!") 50 | } 51 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/examples/hook/hook.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | "gopkg.in/gemnasium/logrus-airbrake-hook.v2" 6 | ) 7 | 8 | var log = logrus.New() 9 | 10 | func init() { 11 | log.Formatter = new(logrus.TextFormatter) // default 12 | log.Hooks.Add(airbrake.NewHook(123, "xyz", "development")) 13 | } 14 | 15 | func main() { 16 | log.WithFields(logrus.Fields{ 17 | "animal": "walrus", 18 | "size": 10, 19 | }).Info("A group of walrus emerges from the ocean") 20 | 21 | log.WithFields(logrus.Fields{ 22 | "omg": true, 23 | "number": 122, 24 | }).Warn("The group's number increased tremendously!") 25 | 26 | log.WithFields(logrus.Fields{ 27 | "omg": true, 28 | "number": 100, 29 | }).Fatal("The ice breaks!") 30 | } 31 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import "time" 4 | 5 | const DefaultTimestampFormat = time.RFC3339 6 | 7 | // The Formatter interface is used to implement a custom Formatter. It takes an 8 | // `Entry`. It exposes all the fields, including the default ones: 9 | // 10 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. 11 | // * `entry.Data["time"]`. The timestamp. 12 | // * `entry.Data["level"]. The level the entry was logged at. 13 | // 14 | // Any additional fields added with `WithField` or `WithFields` are also in 15 | // `entry.Data`. Format is expected to return an array of bytes which are then 16 | // logged to `logger.Out`. 17 | type Formatter interface { 18 | Format(*Entry) ([]byte, error) 19 | } 20 | 21 | // This is to not silently overwrite `time`, `msg` and `level` fields when 22 | // dumping it. If this code wasn't there doing: 23 | // 24 | // logrus.WithField("level", 1).Info("hello") 25 | // 26 | // Would just silently drop the user provided level. Instead with this code 27 | // it'll logged as: 28 | // 29 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} 30 | // 31 | // It's not exported because it's still using Data in an opinionated way. It's to 32 | // avoid code duplication between the two default formatters. 33 | func prefixFieldClashes(data Fields) { 34 | if t, ok := data["time"]; ok { 35 | data["fields.time"] = t 36 | } 37 | 38 | if m, ok := data["msg"]; ok { 39 | data["fields.msg"] = m 40 | } 41 | 42 | if l, ok := data["level"]; ok { 43 | data["fields.level"] = l 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/formatter_bench_test.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | // smallFields is a small size data set for benchmarking 10 | var smallFields = Fields{ 11 | "foo": "bar", 12 | "baz": "qux", 13 | "one": "two", 14 | "three": "four", 15 | } 16 | 17 | // largeFields is a large size data set for benchmarking 18 | var largeFields = Fields{ 19 | "foo": "bar", 20 | "baz": "qux", 21 | "one": "two", 22 | "three": "four", 23 | "five": "six", 24 | "seven": "eight", 25 | "nine": "ten", 26 | "eleven": "twelve", 27 | "thirteen": "fourteen", 28 | "fifteen": "sixteen", 29 | "seventeen": "eighteen", 30 | "nineteen": "twenty", 31 | "a": "b", 32 | "c": "d", 33 | "e": "f", 34 | "g": "h", 35 | "i": "j", 36 | "k": "l", 37 | "m": "n", 38 | "o": "p", 39 | "q": "r", 40 | "s": "t", 41 | "u": "v", 42 | "w": "x", 43 | "y": "z", 44 | "this": "will", 45 | "make": "thirty", 46 | "entries": "yeah", 47 | } 48 | 49 | var errorFields = Fields{ 50 | "foo": fmt.Errorf("bar"), 51 | "baz": fmt.Errorf("qux"), 52 | } 53 | 54 | func BenchmarkErrorTextFormatter(b *testing.B) { 55 | doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields) 56 | } 57 | 58 | func BenchmarkSmallTextFormatter(b *testing.B) { 59 | doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields) 60 | } 61 | 62 | func BenchmarkLargeTextFormatter(b *testing.B) { 63 | doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields) 64 | } 65 | 66 | func BenchmarkSmallColoredTextFormatter(b *testing.B) { 67 | doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields) 68 | } 69 | 70 | func BenchmarkLargeColoredTextFormatter(b *testing.B) { 71 | doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields) 72 | } 73 | 74 | func BenchmarkSmallJSONFormatter(b *testing.B) { 75 | doBenchmark(b, &JSONFormatter{}, smallFields) 76 | } 77 | 78 | func BenchmarkLargeJSONFormatter(b *testing.B) { 79 | doBenchmark(b, &JSONFormatter{}, largeFields) 80 | } 81 | 82 | func doBenchmark(b *testing.B, formatter Formatter, fields Fields) { 83 | entry := &Entry{ 84 | Time: time.Time{}, 85 | Level: InfoLevel, 86 | Message: "message", 87 | Data: fields, 88 | } 89 | var d []byte 90 | var err error 91 | for i := 0; i < b.N; i++ { 92 | d, err = formatter.Format(entry) 93 | if err != nil { 94 | b.Fatal(err) 95 | } 96 | b.SetBytes(int64(len(d))) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/formatters/logstash/logstash.go: -------------------------------------------------------------------------------- 1 | package logstash 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/Sirupsen/logrus" 8 | ) 9 | 10 | // Formatter generates json in logstash format. 11 | // Logstash site: http://logstash.net/ 12 | type LogstashFormatter struct { 13 | Type string // if not empty use for logstash type field. 14 | 15 | // TimestampFormat sets the format used for timestamps. 16 | TimestampFormat string 17 | } 18 | 19 | func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) { 20 | fields := make(logrus.Fields) 21 | for k, v := range entry.Data { 22 | fields[k] = v 23 | } 24 | 25 | fields["@version"] = 1 26 | 27 | timeStampFormat := f.TimestampFormat 28 | 29 | if timeStampFormat == "" { 30 | timeStampFormat = logrus.DefaultTimestampFormat 31 | } 32 | 33 | fields["@timestamp"] = entry.Time.Format(timeStampFormat) 34 | 35 | // set message field 36 | v, ok := entry.Data["message"] 37 | if ok { 38 | fields["fields.message"] = v 39 | } 40 | fields["message"] = entry.Message 41 | 42 | // set level field 43 | v, ok = entry.Data["level"] 44 | if ok { 45 | fields["fields.level"] = v 46 | } 47 | fields["level"] = entry.Level.String() 48 | 49 | // set type field 50 | if f.Type != "" { 51 | v, ok = entry.Data["type"] 52 | if ok { 53 | fields["fields.type"] = v 54 | } 55 | fields["type"] = f.Type 56 | } 57 | 58 | serialized, err := json.Marshal(fields) 59 | if err != nil { 60 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 61 | } 62 | return append(serialized, '\n'), nil 63 | } 64 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/formatters/logstash/logstash_test.go: -------------------------------------------------------------------------------- 1 | package logstash 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "github.com/Sirupsen/logrus" 7 | "github.com/stretchr/testify/assert" 8 | "testing" 9 | ) 10 | 11 | func TestLogstashFormatter(t *testing.T) { 12 | assert := assert.New(t) 13 | 14 | lf := LogstashFormatter{Type: "abc"} 15 | 16 | fields := logrus.Fields{ 17 | "message": "def", 18 | "level": "ijk", 19 | "type": "lmn", 20 | "one": 1, 21 | "pi": 3.14, 22 | "bool": true, 23 | } 24 | 25 | entry := logrus.WithFields(fields) 26 | entry.Message = "msg" 27 | entry.Level = logrus.InfoLevel 28 | 29 | b, _ := lf.Format(entry) 30 | 31 | var data map[string]interface{} 32 | dec := json.NewDecoder(bytes.NewReader(b)) 33 | dec.UseNumber() 34 | dec.Decode(&data) 35 | 36 | // base fields 37 | assert.Equal(json.Number("1"), data["@version"]) 38 | assert.NotEmpty(data["@timestamp"]) 39 | assert.Equal("abc", data["type"]) 40 | assert.Equal("msg", data["message"]) 41 | assert.Equal("info", data["level"]) 42 | 43 | // substituted fields 44 | assert.Equal("def", data["fields.message"]) 45 | assert.Equal("ijk", data["fields.level"]) 46 | assert.Equal("lmn", data["fields.type"]) 47 | 48 | // formats 49 | assert.Equal(json.Number("1"), data["one"]) 50 | assert.Equal(json.Number("3.14"), data["pi"]) 51 | assert.Equal(true, data["bool"]) 52 | } 53 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hook_test.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | type TestHook struct { 10 | Fired bool 11 | } 12 | 13 | func (hook *TestHook) Fire(entry *Entry) error { 14 | hook.Fired = true 15 | return nil 16 | } 17 | 18 | func (hook *TestHook) Levels() []Level { 19 | return []Level{ 20 | DebugLevel, 21 | InfoLevel, 22 | WarnLevel, 23 | ErrorLevel, 24 | FatalLevel, 25 | PanicLevel, 26 | } 27 | } 28 | 29 | func TestHookFires(t *testing.T) { 30 | hook := new(TestHook) 31 | 32 | LogAndAssertJSON(t, func(log *Logger) { 33 | log.Hooks.Add(hook) 34 | assert.Equal(t, hook.Fired, false) 35 | 36 | log.Print("test") 37 | }, func(fields Fields) { 38 | assert.Equal(t, hook.Fired, true) 39 | }) 40 | } 41 | 42 | type ModifyHook struct { 43 | } 44 | 45 | func (hook *ModifyHook) Fire(entry *Entry) error { 46 | entry.Data["wow"] = "whale" 47 | return nil 48 | } 49 | 50 | func (hook *ModifyHook) Levels() []Level { 51 | return []Level{ 52 | DebugLevel, 53 | InfoLevel, 54 | WarnLevel, 55 | ErrorLevel, 56 | FatalLevel, 57 | PanicLevel, 58 | } 59 | } 60 | 61 | func TestHookCanModifyEntry(t *testing.T) { 62 | hook := new(ModifyHook) 63 | 64 | LogAndAssertJSON(t, func(log *Logger) { 65 | log.Hooks.Add(hook) 66 | log.WithField("wow", "elephant").Print("test") 67 | }, func(fields Fields) { 68 | assert.Equal(t, fields["wow"], "whale") 69 | }) 70 | } 71 | 72 | func TestCanFireMultipleHooks(t *testing.T) { 73 | hook1 := new(ModifyHook) 74 | hook2 := new(TestHook) 75 | 76 | LogAndAssertJSON(t, func(log *Logger) { 77 | log.Hooks.Add(hook1) 78 | log.Hooks.Add(hook2) 79 | 80 | log.WithField("wow", "elephant").Print("test") 81 | }, func(fields Fields) { 82 | assert.Equal(t, fields["wow"], "whale") 83 | assert.Equal(t, hook2.Fired, true) 84 | }) 85 | } 86 | 87 | type ErrorHook struct { 88 | Fired bool 89 | } 90 | 91 | func (hook *ErrorHook) Fire(entry *Entry) error { 92 | hook.Fired = true 93 | return nil 94 | } 95 | 96 | func (hook *ErrorHook) Levels() []Level { 97 | return []Level{ 98 | ErrorLevel, 99 | } 100 | } 101 | 102 | func TestErrorHookShouldntFireOnInfo(t *testing.T) { 103 | hook := new(ErrorHook) 104 | 105 | LogAndAssertJSON(t, func(log *Logger) { 106 | log.Hooks.Add(hook) 107 | log.Info("test") 108 | }, func(fields Fields) { 109 | assert.Equal(t, hook.Fired, false) 110 | }) 111 | } 112 | 113 | func TestErrorHookShouldFireOnError(t *testing.T) { 114 | hook := new(ErrorHook) 115 | 116 | LogAndAssertJSON(t, func(log *Logger) { 117 | log.Hooks.Add(hook) 118 | log.Error("test") 119 | }, func(fields Fields) { 120 | assert.Equal(t, hook.Fired, true) 121 | }) 122 | } 123 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hooks.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // A hook to be fired when logging on the logging levels returned from 4 | // `Levels()` on your implementation of the interface. Note that this is not 5 | // fired in a goroutine or a channel with workers, you should handle such 6 | // functionality yourself if your call is non-blocking and you don't wish for 7 | // the logging calls for levels returned from `Levels()` to block. 8 | type Hook interface { 9 | Levels() []Level 10 | Fire(*Entry) error 11 | } 12 | 13 | // Internal type for storing the hooks on a logger instance. 14 | type LevelHooks map[Level][]Hook 15 | 16 | // Add a hook to an instance of logger. This is called with 17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. 18 | func (hooks LevelHooks) Add(hook Hook) { 19 | for _, level := range hook.Levels() { 20 | hooks[level] = append(hooks[level], hook) 21 | } 22 | } 23 | 24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire 25 | // appropriate hooks for a log entry. 26 | func (hooks LevelHooks) Fire(level Level, entry *Entry) error { 27 | for _, hook := range hooks[level] { 28 | if err := hook.Fire(entry); err != nil { 29 | return err 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hooks/syslog/README.md: -------------------------------------------------------------------------------- 1 | # Syslog Hooks for Logrus :walrus: 2 | 3 | ## Usage 4 | 5 | ```go 6 | import ( 7 | "log/syslog" 8 | "github.com/Sirupsen/logrus" 9 | logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" 10 | ) 11 | 12 | func main() { 13 | log := logrus.New() 14 | hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") 15 | 16 | if err == nil { 17 | log.Hooks.Add(hook) 18 | } 19 | } 20 | ``` 21 | 22 | If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following. 23 | 24 | ```go 25 | import ( 26 | "log/syslog" 27 | "github.com/Sirupsen/logrus" 28 | logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" 29 | ) 30 | 31 | func main() { 32 | log := logrus.New() 33 | hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") 34 | 35 | if err == nil { 36 | log.Hooks.Add(hook) 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hooks/syslog/syslog.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!nacl,!plan9 2 | 3 | package logrus_syslog 4 | 5 | import ( 6 | "fmt" 7 | "github.com/Sirupsen/logrus" 8 | "log/syslog" 9 | "os" 10 | ) 11 | 12 | // SyslogHook to send logs via syslog. 13 | type SyslogHook struct { 14 | Writer *syslog.Writer 15 | SyslogNetwork string 16 | SyslogRaddr string 17 | } 18 | 19 | // Creates a hook to be added to an instance of logger. This is called with 20 | // `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` 21 | // `if err == nil { log.Hooks.Add(hook) }` 22 | func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { 23 | w, err := syslog.Dial(network, raddr, priority, tag) 24 | return &SyslogHook{w, network, raddr}, err 25 | } 26 | 27 | func (hook *SyslogHook) Fire(entry *logrus.Entry) error { 28 | line, err := entry.String() 29 | if err != nil { 30 | fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) 31 | return err 32 | } 33 | 34 | switch entry.Level { 35 | case logrus.PanicLevel: 36 | return hook.Writer.Crit(line) 37 | case logrus.FatalLevel: 38 | return hook.Writer.Crit(line) 39 | case logrus.ErrorLevel: 40 | return hook.Writer.Err(line) 41 | case logrus.WarnLevel: 42 | return hook.Writer.Warning(line) 43 | case logrus.InfoLevel: 44 | return hook.Writer.Info(line) 45 | case logrus.DebugLevel: 46 | return hook.Writer.Debug(line) 47 | default: 48 | return nil 49 | } 50 | } 51 | 52 | func (hook *SyslogHook) Levels() []logrus.Level { 53 | return logrus.AllLevels 54 | } 55 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go: -------------------------------------------------------------------------------- 1 | package logrus_syslog 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | "log/syslog" 6 | "testing" 7 | ) 8 | 9 | func TestLocalhostAddAndPrint(t *testing.T) { 10 | log := logrus.New() 11 | hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") 12 | 13 | if err != nil { 14 | t.Errorf("Unable to connect to local syslog.") 15 | } 16 | 17 | log.Hooks.Add(hook) 18 | 19 | for _, level := range hook.Levels() { 20 | if len(log.Hooks[level]) != 1 { 21 | t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level])) 22 | } 23 | } 24 | 25 | log.Info("Congratulations!") 26 | } 27 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hooks/test/test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "io/ioutil" 5 | 6 | "github.com/Sirupsen/logrus" 7 | ) 8 | 9 | // test.Hook is a hook designed for dealing with logs in test scenarios. 10 | type Hook struct { 11 | Entries []*logrus.Entry 12 | } 13 | 14 | // Installs a test hook for the global logger. 15 | func NewGlobal() *Hook { 16 | 17 | hook := new(Hook) 18 | logrus.AddHook(hook) 19 | 20 | return hook 21 | 22 | } 23 | 24 | // Installs a test hook for a given local logger. 25 | func NewLocal(logger *logrus.Logger) *Hook { 26 | 27 | hook := new(Hook) 28 | logger.Hooks.Add(hook) 29 | 30 | return hook 31 | 32 | } 33 | 34 | // Creates a discarding logger and installs the test hook. 35 | func NewNullLogger() (*logrus.Logger, *Hook) { 36 | 37 | logger := logrus.New() 38 | logger.Out = ioutil.Discard 39 | 40 | return logger, NewLocal(logger) 41 | 42 | } 43 | 44 | func (t *Hook) Fire(e *logrus.Entry) error { 45 | t.Entries = append(t.Entries, e) 46 | return nil 47 | } 48 | 49 | func (t *Hook) Levels() []logrus.Level { 50 | return logrus.AllLevels 51 | } 52 | 53 | // LastEntry returns the last entry that was logged or nil. 54 | func (t *Hook) LastEntry() (l *logrus.Entry) { 55 | 56 | if i := len(t.Entries) - 1; i < 0 { 57 | return nil 58 | } else { 59 | return t.Entries[i] 60 | } 61 | 62 | } 63 | 64 | // Reset removes all Entries from this test hook. 65 | func (t *Hook) Reset() { 66 | t.Entries = make([]*logrus.Entry, 0) 67 | } 68 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/hooks/test/test_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/Sirupsen/logrus" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestAllHooks(t *testing.T) { 11 | 12 | assert := assert.New(t) 13 | 14 | logger, hook := NewNullLogger() 15 | assert.Nil(hook.LastEntry()) 16 | assert.Equal(0, len(hook.Entries)) 17 | 18 | logger.Error("Hello error") 19 | assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level) 20 | assert.Equal("Hello error", hook.LastEntry().Message) 21 | assert.Equal(1, len(hook.Entries)) 22 | 23 | logger.Warn("Hello warning") 24 | assert.Equal(logrus.WarnLevel, hook.LastEntry().Level) 25 | assert.Equal("Hello warning", hook.LastEntry().Message) 26 | assert.Equal(2, len(hook.Entries)) 27 | 28 | hook.Reset() 29 | assert.Nil(hook.LastEntry()) 30 | assert.Equal(0, len(hook.Entries)) 31 | 32 | hook = NewGlobal() 33 | 34 | logrus.Error("Hello error") 35 | assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level) 36 | assert.Equal("Hello error", hook.LastEntry().Message) 37 | assert.Equal(1, len(hook.Entries)) 38 | 39 | } 40 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/json_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type JSONFormatter struct { 9 | // TimestampFormat sets the format used for marshaling timestamps. 10 | TimestampFormat string 11 | } 12 | 13 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { 14 | data := make(Fields, len(entry.Data)+3) 15 | for k, v := range entry.Data { 16 | switch v := v.(type) { 17 | case error: 18 | // Otherwise errors are ignored by `encoding/json` 19 | // https://github.com/Sirupsen/logrus/issues/137 20 | data[k] = v.Error() 21 | default: 22 | data[k] = v 23 | } 24 | } 25 | prefixFieldClashes(data) 26 | 27 | timestampFormat := f.TimestampFormat 28 | if timestampFormat == "" { 29 | timestampFormat = DefaultTimestampFormat 30 | } 31 | 32 | data["time"] = entry.Time.Format(timestampFormat) 33 | data["msg"] = entry.Message 34 | data["level"] = entry.Level.String() 35 | 36 | serialized, err := json.Marshal(data) 37 | if err != nil { 38 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 39 | } 40 | return append(serialized, '\n'), nil 41 | } 42 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/terminal_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd openbsd netbsd dragonfly 2 | 3 | package logrus 4 | 5 | import "syscall" 6 | 7 | const ioctlReadTermios = syscall.TIOCGETA 8 | 9 | type Termios syscall.Termios 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/terminal_linux.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2013 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package logrus 7 | 8 | import "syscall" 9 | 10 | const ioctlReadTermios = syscall.TCGETS 11 | 12 | type Termios syscall.Termios 13 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/terminal_notwindows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build linux darwin freebsd openbsd netbsd dragonfly 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | // IsTerminal returns true if stderr's file descriptor is a terminal. 16 | func IsTerminal() bool { 17 | fd := syscall.Stderr 18 | var termios Termios 19 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 20 | return err == 0 21 | } 22 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/terminal_solaris.go: -------------------------------------------------------------------------------- 1 | // +build solaris 2 | 3 | package logrus 4 | 5 | import ( 6 | "os" 7 | 8 | "golang.org/x/sys/unix" 9 | ) 10 | 11 | // IsTerminal returns true if the given file descriptor is a terminal. 12 | func IsTerminal() bool { 13 | _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) 14 | return err == nil 15 | } 16 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/terminal_windows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build windows 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 16 | 17 | var ( 18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 19 | ) 20 | 21 | // IsTerminal returns true if stderr's file descriptor is a terminal. 22 | func IsTerminal() bool { 23 | fd := syscall.Stderr 24 | var st uint32 25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 26 | return r != 0 && e == 0 27 | } 28 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/text_formatter_test.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestQuoting(t *testing.T) { 11 | tf := &TextFormatter{DisableColors: true} 12 | 13 | checkQuoting := func(q bool, value interface{}) { 14 | b, _ := tf.Format(WithField("test", value)) 15 | idx := bytes.Index(b, ([]byte)("test=")) 16 | cont := bytes.Contains(b[idx+5:], []byte{'"'}) 17 | if cont != q { 18 | if q { 19 | t.Errorf("quoting expected for: %#v", value) 20 | } else { 21 | t.Errorf("quoting not expected for: %#v", value) 22 | } 23 | } 24 | } 25 | 26 | checkQuoting(false, "abcd") 27 | checkQuoting(false, "v1.0") 28 | checkQuoting(false, "1234567890") 29 | checkQuoting(true, "/foobar") 30 | checkQuoting(true, "x y") 31 | checkQuoting(true, "x,y") 32 | checkQuoting(false, errors.New("invalid")) 33 | checkQuoting(true, errors.New("invalid argument")) 34 | } 35 | 36 | func TestTimestampFormat(t *testing.T) { 37 | checkTimeStr := func(format string) { 38 | customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format} 39 | customStr, _ := customFormatter.Format(WithField("test", "test")) 40 | timeStart := bytes.Index(customStr, ([]byte)("time=")) 41 | timeEnd := bytes.Index(customStr, ([]byte)("level=")) 42 | timeStr := customStr[timeStart+5 : timeEnd-1] 43 | if timeStr[0] == '"' && timeStr[len(timeStr)-1] == '"' { 44 | timeStr = timeStr[1 : len(timeStr)-1] 45 | } 46 | if format == "" { 47 | format = time.RFC3339 48 | } 49 | _, e := time.Parse(format, (string)(timeStr)) 50 | if e != nil { 51 | t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e) 52 | } 53 | } 54 | 55 | checkTimeStr("2006-01-02T15:04:05.000000000Z07:00") 56 | checkTimeStr("Mon Jan _2 15:04:05 2006") 57 | checkTimeStr("") 58 | } 59 | 60 | // TODO add tests for sorting etc., this requires a parser for the text 61 | // formatter output. 62 | -------------------------------------------------------------------------------- /vendor/src/github.com/sirupsen/logrus/writer.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "runtime" 7 | ) 8 | 9 | func (logger *Logger) Writer() *io.PipeWriter { 10 | return logger.WriterLevel(InfoLevel) 11 | } 12 | 13 | func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { 14 | reader, writer := io.Pipe() 15 | 16 | var printFunc func(args ...interface{}) 17 | switch level { 18 | case DebugLevel: 19 | printFunc = logger.Debug 20 | case InfoLevel: 21 | printFunc = logger.Info 22 | case WarnLevel: 23 | printFunc = logger.Warn 24 | case ErrorLevel: 25 | printFunc = logger.Error 26 | case FatalLevel: 27 | printFunc = logger.Fatal 28 | case PanicLevel: 29 | printFunc = logger.Panic 30 | default: 31 | printFunc = logger.Print 32 | } 33 | 34 | go logger.writerScanner(reader, printFunc) 35 | runtime.SetFinalizer(writer, writerFinalizer) 36 | 37 | return writer 38 | } 39 | 40 | func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { 41 | scanner := bufio.NewScanner(reader) 42 | for scanner.Scan() { 43 | printFunc(scanner.Text()) 44 | } 45 | if err := scanner.Err(); err != nil { 46 | logger.Errorf("Error while reading from Writer: %s", err) 47 | } 48 | reader.Close() 49 | } 50 | 51 | func writerFinalizer(writer *io.PipeWriter) { 52 | writer.Close() 53 | } 54 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/net/context/withtimeout_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 context_test 6 | 7 | import ( 8 | "fmt" 9 | "time" 10 | 11 | "golang.org/x/net/context" 12 | ) 13 | 14 | func ExampleWithTimeout() { 15 | // Pass a context with a timeout to tell a blocking function that it 16 | // should abandon its work after the timeout elapses. 17 | ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) 18 | select { 19 | case <-time.After(200 * time.Millisecond): 20 | fmt.Println("overslept") 21 | case <-ctx.Done(): 22 | fmt.Println(ctx.Err()) // prints "context deadline exceeded" 23 | } 24 | // Output: 25 | // context deadline exceeded 26 | } 27 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/airbrake/gobrake.v2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 The Gobrake 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/src/gopkg.in/airbrake/gobrake.v2/README.md: -------------------------------------------------------------------------------- 1 | # Airbrake Golang Notifier [![Build Status](https://circleci.com/gh/airbrake/gobrake.png?circle-token=4cbcbf1a58fa8275217247351a2db7250c1ef976)](https://circleci.com/gh/airbrake/gobrake) 2 | 3 | 4 | 5 | # Example 6 | 7 | ```go 8 | package main 9 | 10 | import ( 11 | "errors" 12 | 13 | "gopkg.in/airbrake/gobrake.v2" 14 | ) 15 | 16 | var airbrake = gobrake.NewNotifier(1234567, "FIXME") 17 | 18 | func init() { 19 | airbrake.AddFilter(func(notice *gobrake.Notice) *gobrake.Notice { 20 | notice.Context["environment"] = "production" 21 | return notice 22 | }) 23 | } 24 | 25 | func main() { 26 | defer airbrake.WaitAndClose(5*time.Second) 27 | defer airbrake.NotifyOnPanic() 28 | 29 | airbrake.Notify(errors.New("operation failed"), nil) 30 | } 31 | ``` 32 | 33 | ## Ignoring notices 34 | 35 | ```go 36 | airbrake.AddFilter(func(notice *gobrake.Notice) *gobrake.Notice { 37 | if notice.Context["environment"] == "development" { 38 | // Ignore notices in development environment. 39 | return nil 40 | } 41 | return notice 42 | }) 43 | ``` 44 | 45 | ## Logging 46 | 47 | You can use [glog fork](https://github.com/airbrake/glog) to send your logs to Airbrake. 48 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/airbrake/gobrake.v2/bench_test.go: -------------------------------------------------------------------------------- 1 | package gobrake_test 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "net/http/httptest" 7 | "testing" 8 | 9 | "gopkg.in/airbrake/gobrake.v2" 10 | ) 11 | 12 | func BenchmarkSendNotice(b *testing.B) { 13 | handler := func(w http.ResponseWriter, req *http.Request) { 14 | w.WriteHeader(http.StatusCreated) 15 | w.Write([]byte(`{"id":"123"}`)) 16 | } 17 | server := httptest.NewServer(http.HandlerFunc(handler)) 18 | 19 | notifier := gobrake.NewNotifier(1, "key") 20 | notifier.SetHost(server.URL) 21 | 22 | notice := notifier.Notice(errors.New("benchmark"), nil, 0) 23 | 24 | b.ResetTimer() 25 | 26 | b.RunParallel(func(pb *testing.PB) { 27 | for pb.Next() { 28 | id, err := notifier.SendNotice(notice) 29 | if err != nil { 30 | b.Fatal(err) 31 | } 32 | if id != "123" { 33 | b.Fatalf("got %q, wanted 123", id) 34 | } 35 | } 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/airbrake/gobrake.v2/circle.yml: -------------------------------------------------------------------------------- 1 | checkout: 2 | post: 3 | - rm -rf /home/ubuntu/.go_workspace/src/gopkg.in/airbrake/gobrake.v2 4 | - mkdir -p /home/ubuntu/.go_workspace/src/gopkg.in/airbrake 5 | - mv /home/ubuntu/gobrake /home/ubuntu/.go_workspace/src/gopkg.in/airbrake/gobrake.v2 6 | 7 | dependencies: 8 | override: 9 | - go get github.com/onsi/ginkgo 10 | - go get github.com/onsi/gomega 11 | 12 | test: 13 | override: 14 | - go test gopkg.in/airbrake/gobrake.v2 15 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/airbrake/gobrake.v2/gobrake.go: -------------------------------------------------------------------------------- 1 | package gobrake 2 | 3 | import ( 4 | "log" 5 | "os" 6 | ) 7 | 8 | var logger *log.Logger 9 | 10 | func init() { 11 | SetLogger(log.New(os.Stderr, "gobrake: ", log.LstdFlags)) 12 | } 13 | 14 | func SetLogger(l *log.Logger) { 15 | logger = l 16 | } 17 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/airbrake/gobrake.v2/notice.go: -------------------------------------------------------------------------------- 1 | package gobrake 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | type Error struct { 9 | Type string `json:"type"` 10 | Message string `json:"message"` 11 | Backtrace []StackFrame `json:"backtrace"` 12 | } 13 | 14 | type Notice struct { 15 | Errors []Error `json:"errors"` 16 | Context map[string]interface{} `json:"context"` 17 | Env map[string]interface{} `json:"environment"` 18 | Session map[string]interface{} `json:"session"` 19 | Params map[string]interface{} `json:"params"` 20 | } 21 | 22 | func (n *Notice) String() string { 23 | if len(n.Errors) == 0 { 24 | return fmt.Sprint(n) 25 | } 26 | e := n.Errors[0] 27 | return fmt.Sprintf("%s: %s", e.Type, e.Message) 28 | } 29 | 30 | func NewNotice(e interface{}, req *http.Request, depth int) *Notice { 31 | stack := stack(depth) 32 | notice := &Notice{ 33 | Errors: []Error{ 34 | { 35 | Type: fmt.Sprintf("%T", e), 36 | Message: fmt.Sprint(e), 37 | Backtrace: stack, 38 | }, 39 | }, 40 | Context: map[string]interface{}{ 41 | "notifier": map[string]interface{}{ 42 | "name": "gobrake", 43 | "version": "2.0.3", 44 | "url": "https://github.com/airbrake/gobrake", 45 | }, 46 | }, 47 | Env: map[string]interface{}{}, 48 | Session: map[string]interface{}{}, 49 | Params: map[string]interface{}{}, 50 | } 51 | 52 | if req != nil { 53 | notice.Context["url"] = req.URL.String() 54 | if ua := req.Header.Get("User-Agent"); ua != "" { 55 | notice.Context["userAgent"] = ua 56 | } 57 | 58 | for k, v := range req.Header { 59 | if len(v) == 1 { 60 | notice.Env[k] = v[0] 61 | } else { 62 | notice.Env[k] = v 63 | } 64 | } 65 | 66 | if err := req.ParseForm(); err == nil { 67 | for k, v := range req.Form { 68 | if len(v) == 1 { 69 | notice.Params[k] = v[0] 70 | } else { 71 | notice.Params[k] = v 72 | } 73 | } 74 | } 75 | } 76 | 77 | return notice 78 | } 79 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/airbrake/gobrake.v2/util.go: -------------------------------------------------------------------------------- 1 | package gobrake 2 | 3 | import ( 4 | "runtime" 5 | "strings" 6 | ) 7 | 8 | func stackFilter(packageName, funcName string, file string, line int) bool { 9 | return packageName == "runtime" && funcName == "panic" 10 | } 11 | 12 | type StackFrame struct { 13 | File string `json:"file"` 14 | Line int `json:"line"` 15 | Func string `json:"function"` 16 | } 17 | 18 | func stack(depth int) []StackFrame { 19 | stack := []StackFrame{} 20 | for i := depth; ; i++ { 21 | pc, file, line, ok := runtime.Caller(i) 22 | if !ok { 23 | break 24 | } 25 | packageName, funcName := packageFuncName(pc) 26 | if stackFilter(packageName, funcName, file, line) { 27 | stack = stack[:0] 28 | continue 29 | } 30 | stack = append(stack, StackFrame{ 31 | File: file, 32 | Line: line, 33 | Func: funcName, 34 | }) 35 | } 36 | 37 | return stack 38 | } 39 | 40 | func packageFuncName(pc uintptr) (string, string) { 41 | f := runtime.FuncForPC(pc) 42 | if f == nil { 43 | return "", "" 44 | } 45 | 46 | packageName := "" 47 | funcName := f.Name() 48 | 49 | if ind := strings.LastIndex(funcName, "/"); ind > 0 { 50 | packageName += funcName[:ind+1] 51 | funcName = funcName[ind+1:] 52 | } 53 | if ind := strings.Index(funcName, "."); ind > 0 { 54 | packageName += funcName[:ind] 55 | funcName = funcName[ind+1:] 56 | } 57 | 58 | return packageName, funcName 59 | } 60 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/gemnasium/logrus-airbrake-hook.v2/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Gemnasium 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/gemnasium/logrus-airbrake-hook.v2/README.md: -------------------------------------------------------------------------------- 1 | # Airbrake Hook for Logrus :walrus: 2 | 3 | Use this hook to send your errors to [Airbrake](https://airbrake.io/). 4 | This hook is using the [official airbrake go package](https://github.com/airbrake/gobrake), and will hit the api V3. 5 | The hook is async for `log.Error`, but blocking for the notice to be sent with `log.Fatal` and `log.Panic`. 6 | 7 | All logrus fields will be sent as context fields on Airbrake. 8 | 9 | ## Usage 10 | 11 | The hook must be configured with: 12 | 13 | * A project ID (found in your your Airbrake project settings) 14 | * An API key ID (found in your your Airbrake project settings) 15 | * The name of the current environment ("development", "staging", "production", ...) 16 | 17 | ```go 18 | import ( 19 | "log/syslog" 20 | "github.com/Sirupsen/logrus" 21 | "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" 22 | ) 23 | 24 | func main() { 25 | log := logrus.New() 26 | log.AddHook(airbrake.NewHook(123, "xyz", "development")) 27 | log.Error("some logging message") // The error is sent to airbrake in background 28 | } 29 | ``` 30 | 31 | Note that if environment == "development", the hook will not send anything to airbrake. 32 | 33 | 34 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/gemnasium/logrus-airbrake-hook.v2/airbrake.go: -------------------------------------------------------------------------------- 1 | package airbrake // import "gopkg.in/gemnasium/logrus-airbrake-hook.v2" 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/Sirupsen/logrus" 9 | "gopkg.in/airbrake/gobrake.v2" 10 | ) 11 | 12 | // Set airbrake.BufSize = _before_ calling NewHook 13 | var BufSize uint = 1024 14 | 15 | // AirbrakeHook to send exceptions to an exception-tracking service compatible 16 | // with the Airbrake API. 17 | type airbrakeHook struct { 18 | Airbrake *gobrake.Notifier 19 | noticeChan chan *gobrake.Notice 20 | } 21 | 22 | func NewHook(projectID int64, apiKey, env string) *airbrakeHook { 23 | airbrake := gobrake.NewNotifier(projectID, apiKey) 24 | airbrake.AddFilter(func(notice *gobrake.Notice) *gobrake.Notice { 25 | if env == "development" { 26 | return nil 27 | } 28 | notice.Context["environment"] = env 29 | return notice 30 | }) 31 | hook := &airbrakeHook{ 32 | Airbrake: airbrake, 33 | noticeChan: make(chan *gobrake.Notice, BufSize), 34 | } 35 | go hook.fire() 36 | return hook 37 | } 38 | 39 | func (hook *airbrakeHook) Fire(entry *logrus.Entry) error { 40 | var notifyErr error 41 | err, ok := entry.Data["error"].(error) 42 | if ok { 43 | notifyErr = err 44 | } else { 45 | notifyErr = errors.New(entry.Message) 46 | } 47 | notice := hook.Airbrake.Notice(notifyErr, nil, 3) 48 | for k, v := range entry.Data { 49 | notice.Context[k] = fmt.Sprintf("%s", v) 50 | } 51 | // Don't exit before sending the exception 52 | if entry.Level == logrus.ErrorLevel || entry.Level == logrus.PanicLevel { 53 | hook.sendNotice(notice) 54 | return nil 55 | } 56 | hook.noticeChan <- notice 57 | return nil 58 | } 59 | 60 | // fire sends errors to airbrake when an entry is available on entryChan 61 | func (hook *airbrakeHook) fire() { 62 | for { 63 | notice := <-hook.noticeChan 64 | hook.sendNotice(notice) 65 | } 66 | } 67 | 68 | func (hook *airbrakeHook) sendNotice(notice *gobrake.Notice) { 69 | if _, err := hook.Airbrake.SendNotice(notice); err != nil { 70 | fmt.Fprintf(os.Stderr, "Failed to send error to Airbrake: %v\n", err) 71 | } 72 | } 73 | 74 | func (hook *airbrakeHook) Levels() []logrus.Level { 75 | return []logrus.Level{ 76 | logrus.ErrorLevel, 77 | logrus.FatalLevel, 78 | logrus.PanicLevel, 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/go-playground/validator.v8/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dean Karn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/go-playground/validator.v8/cache.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | ) 7 | 8 | type cachedField struct { 9 | Idx int 10 | Name string 11 | AltName string 12 | CachedTag *cachedTag 13 | } 14 | 15 | type cachedStruct struct { 16 | Name string 17 | fields map[int]cachedField 18 | } 19 | 20 | type structCacheMap struct { 21 | lock sync.RWMutex 22 | m map[reflect.Type]*cachedStruct 23 | } 24 | 25 | func (s *structCacheMap) Get(key reflect.Type) (*cachedStruct, bool) { 26 | s.lock.RLock() 27 | value, ok := s.m[key] 28 | s.lock.RUnlock() 29 | return value, ok 30 | } 31 | 32 | func (s *structCacheMap) Set(key reflect.Type, value *cachedStruct) { 33 | s.lock.Lock() 34 | s.m[key] = value 35 | s.lock.Unlock() 36 | } 37 | 38 | type cachedTag struct { 39 | tag string 40 | isOmitEmpty bool 41 | isNoStructLevel bool 42 | isStructOnly bool 43 | diveTag string 44 | tags []*tagVals 45 | } 46 | 47 | type tagVals struct { 48 | tagVals [][]string 49 | isOrVal bool 50 | isAlias bool 51 | tag string 52 | } 53 | 54 | type tagCacheMap struct { 55 | lock sync.RWMutex 56 | m map[string]*cachedTag 57 | } 58 | 59 | func (s *tagCacheMap) Get(key string) (*cachedTag, bool) { 60 | s.lock.RLock() 61 | value, ok := s.m[key] 62 | s.lock.RUnlock() 63 | 64 | return value, ok 65 | } 66 | 67 | func (s *tagCacheMap) Set(key string, value *cachedTag) { 68 | s.lock.Lock() 69 | s.m[key] = value 70 | s.lock.Unlock() 71 | } 72 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/go-playground/validator.v8/examples/custom/custom.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "database/sql/driver" 6 | "fmt" 7 | "reflect" 8 | 9 | "gopkg.in/go-playground/validator.v8" 10 | ) 11 | 12 | // DbBackedUser User struct 13 | type DbBackedUser struct { 14 | Name sql.NullString `validate:"required"` 15 | Age sql.NullInt64 `validate:"required"` 16 | } 17 | 18 | func main() { 19 | 20 | config := &validator.Config{TagName: "validate"} 21 | 22 | validate := validator.New(config) 23 | 24 | // register all sql.Null* types to use the ValidateValuer CustomTypeFunc 25 | validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) 26 | 27 | x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}} 28 | errs := validate.Struct(x) 29 | 30 | if errs != nil { 31 | fmt.Printf("Errs:\n%+v\n", errs) 32 | } 33 | } 34 | 35 | // ValidateValuer implements validator.CustomTypeFunc 36 | func ValidateValuer(field reflect.Value) interface{} { 37 | if valuer, ok := field.Interface().(driver.Valuer); ok { 38 | val, err := valuer.Value() 39 | if err == nil { 40 | return val 41 | } 42 | // handle the error how you want 43 | } 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/go-playground/validator.v8/examples_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | "gopkg.in/go-playground/validator.v8" 7 | ) 8 | 9 | func ExampleValidate_new() { 10 | config := &validator.Config{TagName: "validate"} 11 | 12 | validator.New(config) 13 | } 14 | 15 | func ExampleValidate_field() { 16 | // This should be stored somewhere globally 17 | var validate *validator.Validate 18 | 19 | config := &validator.Config{TagName: "validate"} 20 | 21 | validate = validator.New(config) 22 | 23 | i := 0 24 | errs := validate.Field(i, "gt=1,lte=10") 25 | err := errs.(validator.ValidationErrors)[""] 26 | fmt.Println(err.Field) 27 | fmt.Println(err.Tag) 28 | fmt.Println(err.Kind) // NOTE: Kind and Type can be different i.e. time Kind=struct and Type=time.Time 29 | fmt.Println(err.Type) 30 | fmt.Println(err.Param) 31 | fmt.Println(err.Value) 32 | //Output: 33 | // 34 | //gt 35 | //int 36 | //int 37 | //1 38 | //0 39 | } 40 | 41 | func ExampleValidate_struct() { 42 | // This should be stored somewhere globally 43 | var validate *validator.Validate 44 | 45 | config := &validator.Config{TagName: "validate"} 46 | 47 | validate = validator.New(config) 48 | 49 | type ContactInformation struct { 50 | Phone string `validate:"required"` 51 | Street string `validate:"required"` 52 | City string `validate:"required"` 53 | } 54 | 55 | type User struct { 56 | Name string `validate:"required,excludesall=!@#$%^&*()_+-=:;?/0x2C"` // 0x2C = comma (,) 57 | Age int8 `validate:"required,gt=0,lt=150"` 58 | Email string `validate:"email"` 59 | ContactInformation []*ContactInformation 60 | } 61 | 62 | contactInfo := &ContactInformation{ 63 | Street: "26 Here Blvd.", 64 | City: "Paradeso", 65 | } 66 | 67 | user := &User{ 68 | Name: "Joey Bloggs", 69 | Age: 31, 70 | Email: "joeybloggs@gmail.com", 71 | ContactInformation: []*ContactInformation{contactInfo}, 72 | } 73 | 74 | errs := validate.Struct(user) 75 | for _, v := range errs.(validator.ValidationErrors) { 76 | fmt.Println(v.Field) // Phone 77 | fmt.Println(v.Tag) // required 78 | //... and so forth 79 | //Output: 80 | //Phone 81 | //required 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /vendor/src/gopkg.in/go-playground/validator.v8/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaceshuttl/coffer/a8613fbc0acf79f7c0efda0242ef3c8593808676/vendor/src/gopkg.in/go-playground/validator.v8/logo.png -------------------------------------------------------------------------------- /vendor/src/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/src/gopkg.in/yaml.v2/suite_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { TestingT(t) } 9 | 10 | type S struct{} 11 | 12 | var _ = Suite(&S{}) 13 | -------------------------------------------------------------------------------- /vendor/src/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 the output encoding is UTF-8, we don't need to recode the buffer. 22 | if emitter.encoding == yaml_UTF8_ENCODING { 23 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 24 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 25 | } 26 | emitter.buffer_pos = 0 27 | return true 28 | } 29 | 30 | // Recode the buffer into the raw buffer. 31 | var low, high int 32 | if emitter.encoding == yaml_UTF16LE_ENCODING { 33 | low, high = 0, 1 34 | } else { 35 | high, low = 1, 0 36 | } 37 | 38 | pos := 0 39 | for pos < emitter.buffer_pos { 40 | // See the "reader.c" code for more details on UTF-8 encoding. Note 41 | // that we assume that the buffer contains a valid UTF-8 sequence. 42 | 43 | // Read the next UTF-8 character. 44 | octet := emitter.buffer[pos] 45 | 46 | var w int 47 | var value rune 48 | switch { 49 | case octet&0x80 == 0x00: 50 | w, value = 1, rune(octet&0x7F) 51 | case octet&0xE0 == 0xC0: 52 | w, value = 2, rune(octet&0x1F) 53 | case octet&0xF0 == 0xE0: 54 | w, value = 3, rune(octet&0x0F) 55 | case octet&0xF8 == 0xF0: 56 | w, value = 4, rune(octet&0x07) 57 | } 58 | for k := 1; k < w; k++ { 59 | octet = emitter.buffer[pos+k] 60 | value = (value << 6) + (rune(octet) & 0x3F) 61 | } 62 | pos += w 63 | 64 | // Write the character. 65 | if value < 0x10000 { 66 | var b [2]byte 67 | b[high] = byte(value >> 8) 68 | b[low] = byte(value & 0xFF) 69 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1]) 70 | } else { 71 | // Write the character using a surrogate pair (check "reader.c"). 72 | var b [4]byte 73 | value -= 0x10000 74 | b[high] = byte(0xD8 + (value >> 18)) 75 | b[low] = byte((value >> 10) & 0xFF) 76 | b[high+2] = byte(0xDC + ((value >> 8) & 0xFF)) 77 | b[low+2] = byte(value & 0xFF) 78 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3]) 79 | } 80 | } 81 | 82 | // Write the raw buffer. 83 | if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil { 84 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 85 | } 86 | emitter.buffer_pos = 0 87 | emitter.raw_buffer = emitter.raw_buffer[:0] 88 | return true 89 | } 90 | --------------------------------------------------------------------------------