diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 298999d99..0594ea60c 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -532,6 +532,8 @@ func startRpc(server *utils.Server, internalRaterChan, go server.ServeGOB(cfg.RPCGOBListen) go server.ServeHTTP( cfg.HTTPListen, + cfg.HTTPJsonRPCURL, + cfg.HTTPWSURL, cfg.HTTPUseBasicAuth, cfg.HTTPAuthUsers, ) diff --git a/config/config.go b/config/config.go index 7485a7395..63e33de3e 100644 --- a/config/config.go +++ b/config/config.go @@ -203,6 +203,8 @@ type CGRConfig struct { RPCJSONListen string // RPC JSON listening address RPCGOBListen string // RPC GOB listening address HTTPListen string // HTTP listening address + HTTPJsonRPCURL string // JSON RPC relative URL ("" to disable) + HTTPWSURL string // WebSocket relative URL ("" to disable) HTTPUseBasicAuth bool // Use basic auth for HTTP API HTTPAuthUsers map[string]string // Basic auth user:password map (base64 passwords) DefaultReqType string // Use this request type if not defined on top @@ -787,6 +789,12 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { } if jsnHttpCfg != nil { + if jsnHttpCfg.Json_rpc_url != nil { + self.HTTPJsonRPCURL = *jsnHttpCfg.Json_rpc_url + } + if jsnHttpCfg.Ws_url != nil { + self.HTTPWSURL = *jsnHttpCfg.Ws_url + } if jsnHttpCfg.Use_basic_auth != nil { self.HTTPUseBasicAuth = *jsnHttpCfg.Use_basic_auth } diff --git a/config/config_defaults.go b/config/config_defaults.go index 280002de6..ce0b5b7cd 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -72,9 +72,11 @@ const CGRATES_CFG_JSON = ` }, -"http": { // HTTP API configuration - "use_basic_auth": false, // use basic authentication - "auth_users": {} // basic authentication usernames and base64-encoded passwords (eg: { "username1": "cGFzc3dvcmQ=", "username2": "cGFzc3dvcmQy "}) +"http": { // HTTP API configuration + "json_rpc_url": "/jsonrpc", // JSON RPC relative URL ("" to disable) + "ws_url": "/ws", // WebSockets relative URL ("" to disable) + "use_basic_auth": false, // use basic authentication + "auth_users": {} // basic authentication usernames and base64-encoded passwords (eg: { "username1": "cGFzc3dvcmQ=", "username2": "cGFzc3dvcmQy "}) }, diff --git a/config/libconfig_json.go b/config/libconfig_json.go index c2aee8e17..37890fe97 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -48,6 +48,8 @@ type ListenJsonCfg struct { // HTTP config section type HTTPJsonCfg struct { + Json_rpc_url *string + Ws_url *string Use_basic_auth *bool Auth_users *map[string]string } diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index 710f062d8..5cd043eb3 100644 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -51,9 +51,11 @@ // }, -// "http": { // HTTP API configuration -// "use_basic_auth": false, // use basic authentication -// "auth_users": {} // basic authentication usernames and base64-encoded passwords (eg: { "username1": "cGFzc3dvcmQ=", "username2": "cGFzc3dvcmQy "}) +// "http": { // HTTP API configuration +// "json_rpc_url": "/jsonrpc", // JSON RPC relative URL ("" to disable) +// "ws_url": "/ws", // WebSockets relative URL ("" to disable) +// "use_basic_auth": false, // use basic authentication +// "auth_users": {} // basic authentication usernames and base64-encoded passwords (eg: { "username1": "cGFzc3dvcmQ=", "username2": "cGFzc3dvcmQy "}) // }, diff --git a/utils/server.go b/utils/server.go index 14d510485..6b506256c 100644 --- a/utils/server.go +++ b/utils/server.go @@ -29,9 +29,12 @@ import ( "reflect" "time" + "golang.org/x/net/websocket" + "github.com/cenk/rpc2" + + _ "net/http/pprof" ) -import _ "net/http/pprof" type Server struct { rpcEnabled bool @@ -146,19 +149,36 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { io.Copy(w, res) } -func (s *Server) ServeHTTP(addr string, useBasicAuth bool, userList map[string]string) { - if s.rpcEnabled { +func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, useBasicAuth bool, userList map[string]string) { + if s.rpcEnabled && jsonRPCURL != "" { + s.httpEnabled = true if useBasicAuth { Logger.Info("Configuring CGRateS HTTP server to use basic auth") - http.HandleFunc("/jsonrpc", use(handleRequest, basicAuth(userList))) + http.HandleFunc(jsonRPCURL, use(handleRequest, basicAuth(userList))) } else { - http.HandleFunc("/jsonrpc", handleRequest) + http.HandleFunc(jsonRPCURL, handleRequest) } - s.httpEnabled = true } + + if s.rpcEnabled && wsRPCURL != "" { + s.httpEnabled = true + Logger.Info("Configuring CGRateS HTTP server to handle WebSocket connections") + wsHandler := websocket.Handler(func(ws *websocket.Conn) { + jsonrpc.ServeConn(ws) + }) + if useBasicAuth { + http.HandleFunc(wsRPCURL, use(func(w http.ResponseWriter, r *http.Request) { + wsHandler.ServeHTTP(w, r) + }, basicAuth(userList))) + } else { + http.Handle(wsRPCURL, wsHandler) + } + } + if !s.httpEnabled { return } + Logger.Info(fmt.Sprintf("Starting CGRateS HTTP server at %s.", addr)) http.ListenAndServe(addr, nil) }