123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package v1
- import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "strings"
- "devt.de/krotik/common/cryptutil"
- "devt.de/krotik/common/errorutil"
- "devt.de/krotik/common/stringutil"
- "devt.de/krotik/ecal/engine"
- "devt.de/krotik/ecal/scope"
- "devt.de/krotik/eliasdb/api"
- "devt.de/krotik/eliasdb/ecal"
- "github.com/gorilla/websocket"
- )
- /*
- EndpointECALSock is the ECAL endpoint URL (rooted) for websocket operations. Handles everything under sock/...
- */
- const EndpointECALSock = api.APIRoot + "/sock/"
- /*
- upgrader can upgrade normal requests to websocket communications
- */
- var sockUpgrader = websocket.Upgrader{
- Subprotocols: []string{"ecal-sock"},
- ReadBufferSize: 1024,
- WriteBufferSize: 1024,
- }
- var sockCallbackError error
- /*
- ECALSockEndpointInst creates a new endpoint handler.
- */
- func ECALSockEndpointInst() api.RestEndpointHandler {
- return &ecalSockEndpoint{}
- }
- /*
- Handler object for ECAL websocket operations.
- */
- type ecalSockEndpoint struct {
- *api.DefaultEndpointHandler
- }
- /*
- HandleGET handles ECAL websocket operations.
- */
- func (e *ecalSockEndpoint) HandleGET(w http.ResponseWriter, r *http.Request, resources []string) {
- if api.SI != nil {
- var body []byte
- // Update the incomming connection to a websocket
- // If the upgrade fails then the client gets an HTTP error response.
- conn, err := sockUpgrader.Upgrade(w, r, nil)
- if err != nil {
- // We give details here on what went wrong
- w.Write([]byte(err.Error()))
- return
- }
- commID := fmt.Sprintf("%x", cryptutil.GenerateUUID())
- wc := ecal.NewWebsocketConnection(commID, conn)
- wc.Init()
- if body, err = ioutil.ReadAll(r.Body); err == nil {
- var data interface{}
- json.Unmarshal(body, &data)
- query := map[interface{}]interface{}{}
- for k, v := range r.URL.Query() {
- values := make([]interface{}, 0)
- for _, val := range v {
- values = append(values, val)
- }
- query[k] = values
- }
- header := map[interface{}]interface{}{}
- for k, v := range r.Header {
- header[k] = scope.ConvertJSONToECALObject(v)
- }
- proc := api.SI.Interpreter.RuntimeProvider.Processor
- event := engine.NewEvent(fmt.Sprintf("WebSocketRequest"), []string{"db", "web", "sock"},
- map[interface{}]interface{}{
- "commID": commID,
- "path": strings.Join(resources, "/"),
- "pathList": resources,
- "bodyString": string(body),
- "bodyJSON": scope.ConvertJSONToECALObject(data),
- "query": query,
- "method": r.Method,
- "header": header,
- })
- // Add event that the websocket has been registered
- if _, err = proc.AddEventAndWait(event, nil); err == nil {
- api.SI.RegisterECALSock(wc)
- defer func() {
- api.SI.DeregisterECALSock(wc)
- }()
- for {
- var fatal bool
- var data map[string]interface{}
- // Read websocket message
- if data, fatal, err = wc.ReadData(); err != nil {
- wc.WriteData(map[string]interface{}{
- "error": err.Error(),
- })
- if fatal {
- break
- }
- continue
- }
- if val, ok := data["close"]; ok && stringutil.IsTrueValue(fmt.Sprint(val)) {
- wc.Close("")
- break
- }
- event = engine.NewEvent(fmt.Sprintf("WebSocketRequest"), []string{"db", "web", "sock", "data"},
- map[interface{}]interface{}{
- "commID": commID,
- "path": strings.Join(resources, "/"),
- "pathList": resources,
- "query": query,
- "method": r.Method,
- "header": header,
- "data": scope.ConvertJSONToECALObject(data),
- })
- _, err = proc.AddEvent(event, nil)
- errorutil.AssertOk(err)
- }
- }
- }
- if err != nil {
- wc.Close(err.Error())
- api.SI.Interpreter.RuntimeProvider.Logger.LogDebug(err)
- }
- return
- }
- http.Error(w, "Resource was not found", http.StatusNotFound)
- }
- /*
- SwaggerDefs is used to describe the endpoint in swagger.
- */
- func (e *ecalSockEndpoint) SwaggerDefs(s map[string]interface{}) {
- // No swagger definitions for this endpoint as it only handles websocket requests
- }
|