From b1e4ee4196aacc50b639f8d1fa2698212c2adbc2 Mon Sep 17 00:00:00 2001 From: Chakib Benziane Date: Fri, 29 Mar 2019 13:10:06 +0100 Subject: [PATCH] Wip websocket + use caddy + fix CSP and CORS --- api.go | 18 +++- docker-compose.yml | 3 +- go.mod | 6 +- go.sum | 9 +- ln/charge.go | 4 +- package.json | 5 + storage/shortid.go | 26 +++++ storage/upload_ctrl.go | 12 ++- storage/upload_model.go | 17 ++- web/Caddyfile | 19 ++++ web/package.json | 4 +- web/src/Websocket.js | 19 ++++ web/src/api.js | 23 +--- web/src/index.js | 5 +- web/src/pay.vue | 23 ++-- web/src/workerInterface.js | 3 + web/yarn.lock | 216 ++++++++++++++++++++++++++++++++++++- websocket.go | 108 +++++++++++++++++++ 18 files changed, 469 insertions(+), 51 deletions(-) create mode 100644 package.json create mode 100644 storage/shortid.go create mode 100644 web/Caddyfile create mode 100644 web/src/Websocket.js create mode 100644 websocket.go diff --git a/api.go b/api.go index 38c59cb..c410223 100644 --- a/api.go +++ b/api.go @@ -16,20 +16,32 @@ type API struct { func (api *API) Run() { - uploadRoute := api.router.Group("/upload") + uploadRoute := api.router.Group("/api/upload") { - uploadRoute.POST("/", UploadCtrl.New) - uploadRoute.PUT("/:id", UploadCtrl.Upload) + uploadRoute.POST("", UploadCtrl.New) + uploadRoute.PUT(":id", UploadCtrl.Upload) } + websocket := api.router.Group("/ws") + { + websocket.GET("/", serveWebsocket) + websocket.GET("/WS", serveWebsocket) + websocket.GET("/WSS", serveWebsocket) + } + api.router.Run(":8880") } func NewAPI() *API { router := gin.Default() router.Use(cors.Default()) + // + //router.Use(secure.New(secure.Config{ + //ContentSecurityPolicy: "default-src 'self'; script-src *; worker-src *", + ////IsDevelopment: true, + //})) return &API{ router: router, diff --git a/docker-compose.yml b/docker-compose.yml index 40ba6c7..71c4621 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,7 +30,8 @@ services: volumes: - $PWD:/src - - gocache:/go + #- gocache:/go + - /fastData/go:/go #- ./db-storage:/sqlite - file-storage:/storage diff --git a/go.mod b/go.mod index 098cdb7..a35ac7b 100644 --- a/go.mod +++ b/go.mod @@ -4,17 +4,19 @@ go 1.12 require ( github.com/gin-contrib/cors v0.0.0-20190301062745-f9e10995c85a + github.com/gin-contrib/secure v0.0.0-20190301062601-f9a5befa6106 github.com/gin-gonic/gin v1.3.0 - github.com/go-sql-driver/mysql v1.4.1 + github.com/go-sql-driver/mysql v1.4.1 // indirect github.com/golang/protobuf v1.3.1 // indirect + github.com/gorilla/websocket v1.4.0 github.com/jmoiron/sqlx v1.2.0 github.com/kr/pretty v0.1.0 // indirect github.com/lib/pq v1.0.0 github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-sqlite3 v1.10.0 github.com/mediocregopher/radix/v3 v3.2.3 - github.com/segmentio/ksuid v1.0.2 github.com/stretchr/testify v1.3.0 // indirect + github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 // indirect golang.org/x/net v0.0.0-20190322120337-addf6b3196f6 // indirect golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc // indirect diff --git a/go.sum b/go.sum index 4ceeca4..e9fdb72 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/cors v0.0.0-20190301062745-f9e10995c85a h1:zBycVvXa03SIX+jdMv8wGu9TMDMWdN8EhaR1FoeKHNo= github.com/gin-contrib/cors v0.0.0-20190301062745-f9e10995c85a/go.mod h1:pL2kNE+DgDU+eQ+dary5bX0Z6LPP8nR6Mqs1iejILw4= +github.com/gin-contrib/secure v0.0.0-20190301062601-f9a5befa6106 h1:EvzHcDe2j4sFRLhCJR6sE1cwmt9LtrMMDdejcdjQ1Dg= +github.com/gin-contrib/secure v0.0.0-20190301062601-f9a5befa6106/go.mod h1:l2I5UUSmHxQp81CF1EmB6RIo22QgZx7yIa8bwgFwq3k= github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cougNAV9szl6CVoj2RYwzS3DpUQNtlY= github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= @@ -14,6 +16,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= @@ -42,12 +46,12 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc= -github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ75iPqWZc0HeJWFYNCvKsfpQwFpRNTA= +github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 h1:EICbibRW4JNKMcY+LsWmuwob+CRS1BmdRdjphAm9mH4= @@ -61,6 +65,7 @@ golang.org/x/net v0.0.0-20190322120337-addf6b3196f6 h1:78jEq2G3J16aXneH23HSnTQQT golang.org/x/net v0.0.0-20190322120337-addf6b3196f6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/ln/charge.go b/ln/charge.go index 0c46fb7..ece3f18 100644 --- a/ln/charge.go +++ b/ln/charge.go @@ -67,11 +67,11 @@ func (c *Charge) Info() (gin.H, error) { return result, nil } -func (c *Charge) Invoice(amount int, id string) (gin.H, error) { +func (c *Charge) Invoice(amount float32, id string) (gin.H, error) { result := make(gin.H) reqData := gin.H{ - "amount": 10, + "amount": amount, "currency": "USD", "description": fmt.Sprintf("bit4sat upload: %s", id), } diff --git a/package.json b/package.json new file mode 100644 index 0000000..6960c8a --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "socket.io": "^2.2.0" + } +} diff --git a/storage/shortid.go b/storage/shortid.go new file mode 100644 index 0000000..84618e8 --- /dev/null +++ b/storage/shortid.go @@ -0,0 +1,26 @@ +package storage + +import ( + "log" + + "github.com/teris-io/shortid" +) + +const ( + Seed = 8562913 +) + +var SID *shortid.Shortid + +func GetSIDGenerator() *shortid.Shortid { + return SID +} + +func init() { + var err error + SID, err = shortid.New(1, shortid.DefaultABC, Seed) + if err != nil { + log.Fatal(err) + } + +} diff --git a/storage/upload_ctrl.go b/storage/upload_ctrl.go index 12415c0..87db633 100644 --- a/storage/upload_ctrl.go +++ b/storage/upload_ctrl.go @@ -13,11 +13,11 @@ import ( "git.sp4ke.com/sp4ke/bit4sat/ln" "git.sp4ke.com/sp4ke/bit4sat/utils" "github.com/gin-gonic/gin" - "github.com/segmentio/ksuid" ) type UploadCtrl struct{} +//TODO: tell client to avoid sending duplicate if we already have hash func (ctrl UploadCtrl) New(c *gin.Context) { uploadForm := UploadForm{} @@ -28,7 +28,11 @@ func (ctrl UploadCtrl) New(c *gin.Context) { } // Create unique id - id := ksuid.New() + id, err := GetSIDGenerator().Generate() + if err != nil { + utils.JSONErrPriv(c, http.StatusInternalServerError, err) + return + } tx, err := db.DB.Sql.Beginx() if err != nil { @@ -61,7 +65,7 @@ func (ctrl UploadCtrl) New(c *gin.Context) { return } - err = CacheSetUploadStatus(id.String(), UpNew) + err = CacheSetUploadStatus(id, UpNew) if err != nil { utils.JSONErrPriv(c, http.StatusInternalServerError, err) return @@ -197,7 +201,7 @@ func (ctrl UploadCtrl) Upload(c *gin.Context) { charge := ln.NewCharge() // New invoice for 10$ - invoice, err := charge.Invoice(10, id) + invoice, err := charge.Invoice(float32(0.01), id) //info, err := ln.Info() if err != nil { diff --git a/storage/upload_model.go b/storage/upload_model.go index 089175c..58251c8 100644 --- a/storage/upload_model.go +++ b/storage/upload_model.go @@ -10,7 +10,6 @@ import ( "github.com/jmoiron/sqlx" "github.com/mattn/go-sqlite3" "github.com/mediocregopher/radix/v3" - "github.com/segmentio/ksuid" ) var DB = db.DB @@ -19,7 +18,7 @@ const ( DBUploadSchema = ` CREATE TABLE IF NOT EXISTS upload ( id serial PRIMARY KEY, - upload_id varchar(27) NOT NULL, + upload_id varchar(9) NOT NULL, sha256 varchar(64) NOT NULL, file_name varchar(255) NOT NULL, file_type varchar(255) DEFAULT '', @@ -89,13 +88,13 @@ var ( ) type Upload struct { - ID ksuid.KSUID `db:"upload_id"` - SHA256 string `db:"sha256"` - FileName string `db:"file_name"` - FileType string `db:"file_type"` - FileSize int64 `db:"file_size"` - FileExt string `db:"file_ext"` - Status int `db:"status"` + ID string `db:"upload_id"` + SHA256 string `db:"sha256"` + FileName string `db:"file_name"` + FileType string `db:"file_type"` + FileSize int64 `db:"file_size"` + FileExt string `db:"file_ext"` + Status int `db:"status"` } func CacheSetUploadStatus(id string, status int) error { diff --git a/web/Caddyfile b/web/Caddyfile new file mode 100644 index 0000000..d01da91 --- /dev/null +++ b/web/Caddyfile @@ -0,0 +1,19 @@ +localhost + +root dist +ext .html + +header / { + Content-Security-Policy "default-src * 'unsafe-eval' 'unsafe-inline';" +} + +proxy /api localhost:8880 + +log /api stdout + +proxy /ws localhost:8880 { + websocket + transparent +} + +proxy /wss localhost:8880 diff --git a/web/package.json b/web/package.json index e1cf720..2624961 100644 --- a/web/package.json +++ b/web/package.json @@ -19,6 +19,7 @@ "dependencies": { "babel-polyfill": "^6.26.0", "qrcode": "^1.3.3", + "socket.io-client": "^1.4.0", "vue": "^2.6.8", "vue-hot-reload-api": "^2.3.3" }, @@ -26,6 +27,7 @@ "vue": "./node_modules/vue/dist/vue.common.js" }, "scripts": { - "start": "parcel index.html" + "start": "parcel index.html", + "watch": "parcel watch index.html" } } diff --git a/web/src/Websocket.js b/web/src/Websocket.js new file mode 100644 index 0000000..f051a92 --- /dev/null +++ b/web/src/Websocket.js @@ -0,0 +1,19 @@ +import { apiPort } from './api.js'; + +let singleton = false + +export class WS { + + constructor(){ + if (singleton) { + return singleton; + } + + const endpoint = `ws://localhost:2015/ws/`; + console.log(`endpoint is ${endpoint}`); + this.conn = new WebSocket(endpoint); + singleton = this; + } + +} + diff --git a/web/src/api.js b/web/src/api.js index 1fb2979..b7e2902 100644 --- a/web/src/api.js +++ b/web/src/api.js @@ -1,29 +1,15 @@ import 'babel-polyfill'; -let apiPort = '8880' -if (process.env.API_PORT !== undefined) { - apiPort = process.env.API_PORT; -} -function getEndpoint (path) { - return new URL(path, apiEndpoint).toString() -} + const endPoints = { get upload () { - return getEndpoint('upload/') + return '/api/upload' } } -const apiEndpoint = function() { - let currentLoc = self.location; - let endpoint = new URL(currentLoc); - - endpoint.port = apiPort; - - return endpoint.toString() -}() class Upload { @@ -72,7 +58,7 @@ class Upload { } - let req = new Request(endPoints.upload + this.uploadId, { + let req = new Request(endPoints.upload + '/' + this.uploadId, { method: 'PUT', body: formData }) @@ -89,7 +75,6 @@ class Upload { } export default { - endpoint: apiEndpoint, endPoints: endPoints, - Upload: Upload + Upload: Upload, } diff --git a/web/src/index.js b/web/src/index.js index 4bd297f..e637612 100644 --- a/web/src/index.js +++ b/web/src/index.js @@ -2,8 +2,11 @@ import './styles/index.css'; import Vue from 'vue'; import App from './App.vue'; -import GetWorker from './workerInterface.js' +import GetWorker from './workerInterface.js'; +import { WS } from './Websocket.js'; +window.ws = new WS() +new WS() window.app = new Vue({ diff --git a/web/src/pay.vue b/web/src/pay.vue index 90eece2..f9bf569 100644 --- a/web/src/pay.vue +++ b/web/src/pay.vue @@ -25,15 +25,22 @@ export default { let self = this this.worker = Worker; - let canvas = this.$el.querySelector('#canvas') + //let canvas = this.$el.querySelector('#canvas') this.worker.listenTo('upload-invoice', (e) => { console.log("received invoice ", e.data) self.invoice = e.data.invoice - QRCode.toDataURL(canvas, self.invoice.payreq, { - margin: 2, + + }) + }, + methods:{ + makeLnQR(payreq) { + let canvas = this.$el.querySelector('#canvas') + + QRCode.toDataURL(canvas, payreq.toUpperCase(), { + margin: 4, width: 340, errorCorrectionLevel: 'H', type: 'png', @@ -42,13 +49,17 @@ export default { } }) .then(url => { - self.payreqURI = url; + this.payreqURI = url; }) .catch(err =>{ console.error(err); }) - - }) + } + }, + watch: { + invoice: function(val) { + this.makeLnQR(val.payreq) + } }, } diff --git a/web/src/workerInterface.js b/web/src/workerInterface.js index edddb39..ef0c63c 100644 --- a/web/src/workerInterface.js +++ b/web/src/workerInterface.js @@ -10,6 +10,9 @@ class Worker { this.post({ msg: 'init' }) + + + } } diff --git a/web/yarn.lock b/web/yarn.lock index 95ef1d1..36ff131 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -755,6 +755,11 @@ acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.7: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +after@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + ajv@^6.5.5, ajv@^6.9.1: version "6.10.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" @@ -862,6 +867,11 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +arraybuffer.slice@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" + integrity sha1-8zshWfBTKj8xB6JywMz70a0peco= + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1459,11 +1469,21 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== +backo2@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-arraybuffer@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= + base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" @@ -1489,6 +1509,13 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +better-assert@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" + integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= + dependencies: + callsite "1.0.0" + binary-extensions@^1.0.0: version "1.13.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" @@ -1499,6 +1526,11 @@ bindings@~1.2.1: resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" integrity sha1-FK1hE4EtLTfXLme0ystLtyZQXxE= +blob@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" + integrity sha1-vPEwUspURj8w+fx+lbmkdjCpSSE= + bluebird@^3.1.1: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" @@ -1697,6 +1729,11 @@ caller-path@^2.0.0: dependencies: caller-callsite "^2.0.0" +callsite@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -1924,11 +1961,26 @@ commander@^2.11.0, commander@^2.19.0, commander@^2.9.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== -component-emitter@^1.2.1: +component-bind@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" + integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= + +component-emitter@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" + integrity sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM= + +component-emitter@1.2.1, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= +component-inherit@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" + integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2279,6 +2331,20 @@ deasync@^0.1.14: bindings "~1.2.1" node-addon-api "^1.6.0" +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= + dependencies: + ms "0.7.1" + +debug@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" + integrity sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w= + dependencies: + ms "0.7.2" + debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2532,6 +2598,36 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +engine.io-client@~1.8.4: + version "1.8.5" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.5.tgz#fe7fb60cb0dcf2fa2859489329cb5968dedeb11f" + integrity sha512-AYTgHyeVUPitsseqjoedjhYJapNVoSPShbZ+tEUX9/73jgZ/Z3sUlJf9oYgdEBBdVhupUpUqSxH0kBCXlQnmZg== + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "2.3.3" + engine.io-parser "1.3.2" + has-cors "1.1.0" + indexof "0.0.1" + parsejson "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + ws "~1.1.5" + xmlhttprequest-ssl "1.5.3" + yeast "0.1.2" + +engine.io-parser@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" + integrity sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo= + dependencies: + after "0.8.2" + arraybuffer.slice "0.0.6" + base64-arraybuffer "0.1.5" + blob "0.0.4" + has-binary "0.1.7" + wtf-8 "1.0.0" + entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -3146,6 +3242,18 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-binary@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" + integrity sha1-aOYesWIQyVRaClzOBqhzkS/h5ow= + dependencies: + isarray "0.0.1" + +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -3823,6 +3931,11 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= + json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -4144,6 +4257,16 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + integrity sha1-riXPJRKziFodldfwN4aNhDESR2U= + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -4349,6 +4472,11 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +object-component@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= + object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -4440,6 +4568,11 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= + ora@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" @@ -4634,6 +4767,27 @@ parse5@4.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== +parsejson@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" + integrity sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs= + dependencies: + better-assert "~1.0.0" + +parseqs@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" + integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= + dependencies: + better-assert "~1.0.0" + +parseuri@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" + integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= + dependencies: + better-assert "~1.0.0" + parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" @@ -5711,6 +5865,33 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +socket.io-client@^1.4.0: + version "1.7.4" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.4.tgz#ec9f820356ed99ef6d357f0756d648717bdd4281" + integrity sha1-7J+CA1btme9tNX8HVtZIcXvdQoE= + dependencies: + backo2 "1.0.2" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "2.3.3" + engine.io-client "~1.8.4" + has-binary "0.1.7" + indexof "0.0.1" + object-component "0.0.3" + parseuri "0.0.5" + socket.io-parser "2.3.1" + to-array "0.1.4" + +socket.io-parser@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" + integrity sha1-3VMgJRA85Clpcya+/WQAX8/ltKA= + dependencies: + component-emitter "1.1.2" + debug "2.2.0" + isarray "0.0.1" + json3 "3.3.2" + source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" @@ -6058,6 +6239,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +to-array@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -6160,6 +6346,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po= + uncss@^0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/uncss/-/uncss-0.16.2.tgz#3b2269c59012da7c66cbe98fbedddeef94f0649c" @@ -6477,11 +6668,29 @@ ws@^5.1.1, ws@^5.2.0: dependencies: async-limiter "~1.0.0" +ws@~1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w== + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +wtf-8@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" + integrity sha1-OS2LotDxw00e4tYw8V0O+2jhBIo= + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== +xmlhttprequest-ssl@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" + integrity sha1-GFqIjATspGw+QHDZn3tJ3jUomS0= + xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -6527,3 +6736,8 @@ yargs@^12.0.5: which-module "^2.0.0" y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" + +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= diff --git a/websocket.go b/websocket.go new file mode 100644 index 0000000..dac7f93 --- /dev/null +++ b/websocket.go @@ -0,0 +1,108 @@ +package main + +import ( + "bytes" + "log" + "net/http" + "time" + + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" +) + +const ( + // Time allowed to write message to peer + writeWait = 10 * time.Second + + // Time allowed to read the next pong message from the client. + pongWait = 5 * time.Second + + // Send pings to client with this period. Must be less than pongWait. + pingPeriod = (pongWait * 9) / 10 + //pingPeriod = 5 * time.Second + + // Maximum message size + maxMessageSize = 512 +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { + return true + }, +} + +var ( + conn *websocket.Conn +) + +var ( + newline = []byte{'\n'} + space = []byte{' '} +) + +func reader() { + defer conn.Close() + conn.SetReadLimit(maxMessageSize) + conn.SetReadDeadline(time.Now().Add(pongWait)) + conn.SetPongHandler(func(string) error { + //log.Println("pong") + conn.SetReadDeadline(time.Now().Add(pongWait)) + return nil + }) + + for { + _, message, err := conn.ReadMessage() + if err != nil { + if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, + websocket.CloseAbnormalClosure) { + log.Printf("error: %v", err) + } + break + } + message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1)) + } +} + +func writer() { + pingTicker := time.NewTicker(pingPeriod) + defer func() { + log.Println("quit ws server") + + pingTicker.Stop() + conn.Close() + }() + + for { + select { + case <-pingTicker.C: + //log.Println("ping") + + conn.SetWriteDeadline(time.Now().Add(writeWait)) + if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil { + log.Println(err) + return + } + + } + } +} + +func serveWebsocket(c *gin.Context) { + var err error + log.Println("websocket request") + + conn, err = upgrader.Upgrade(c.Writer, c.Request, nil) + if err != nil { + if _, ok := err.(websocket.HandshakeError); !ok { + log.Printf("handshake error: %s", err) + } + + log.Println(err) + return + } + + go writer() + reader() +}