mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Skel of HTTPAgent with interfaces for both request and reply decoder/encoders
This commit is contained in:
@@ -19,22 +19,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package agents
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/cgrates/rpcclient"
|
||||
)
|
||||
|
||||
// NewHttpAgent will construct a HttpAgent
|
||||
func NewHttpAgent(sessionS rpcclient.RpcClientConnection,
|
||||
// NewHttpAgent will construct a HTTPAgent
|
||||
func NewHTTPAgent(sessionS rpcclient.RpcClientConnection,
|
||||
timezone, reqPayload, rplyPayload string,
|
||||
reqProcessors []*config.HttpAgntProcCfg) *HttpAgent {
|
||||
return &HttpAgent{sessionS: sessionS, timezone: timezone,
|
||||
reqProcessors []*config.HttpAgntProcCfg) *HTTPAgent {
|
||||
return &HTTPAgent{sessionS: sessionS, timezone: timezone,
|
||||
reqPayload: reqPayload, rplyPayload: rplyPayload,
|
||||
reqProcessors: reqProcessors}
|
||||
}
|
||||
|
||||
type HttpAgent struct {
|
||||
// HTTPAgent is a handler for HTTP requests
|
||||
type HTTPAgent struct {
|
||||
sessionS rpcclient.RpcClientConnection
|
||||
timezone,
|
||||
reqPayload,
|
||||
@@ -43,5 +46,40 @@ type HttpAgent struct {
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler interface
|
||||
func (ha *HttpAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
_, err := newHAReqDecoder(ha.reqPayload, req) // dcdr
|
||||
if err != nil {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> error creating decoder: %s",
|
||||
utils.HTTPAgent, err.Error()))
|
||||
}
|
||||
var processed bool
|
||||
procVars := make(processorVars)
|
||||
rpl := newHTTPReplyFields()
|
||||
for _, reqProcessor := range ha.reqProcessors {
|
||||
var lclProcessed bool
|
||||
if lclProcessed, err = ha.processRequest(reqProcessor, req,
|
||||
procVars, rpl); lclProcessed {
|
||||
processed = lclProcessed
|
||||
}
|
||||
if err != nil || (lclProcessed && !reqProcessor.ContinueOnSuccess) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
utils.Logger.Warning(fmt.Sprintf("<%s> error: %s processing request: %s, process vars: %+v",
|
||||
utils.HTTPAgent, err.Error(), utils.ToJSON(req), procVars))
|
||||
return // FixMe with returning some error on HTTP level
|
||||
} else if !processed {
|
||||
utils.Logger.Warning(fmt.Sprintf("<%s> no request processor enabled, ignoring request %s, process vars: %+v",
|
||||
utils.RadiusAgent, utils.ToJSON(req), procVars))
|
||||
return // FixMe with returning some error on HTTP level
|
||||
}
|
||||
}
|
||||
|
||||
// processRequest represents one processor processing the request
|
||||
func (ha *HTTPAgent) processRequest(reqProc *config.HttpAgntProcCfg,
|
||||
req *http.Request, procVars processorVars,
|
||||
reply *httpReplyFields) (processed bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
71
agents/libhttpagent.go
Normal file
71
agents/libhttpagent.go
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package agents
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// httpReplyField is one field written in HTTP reply
|
||||
type httpReplyField struct {
|
||||
fldPath,
|
||||
fldVal string
|
||||
}
|
||||
|
||||
func newHTTPReplyFields() *httpReplyFields {
|
||||
return &httpReplyFields{indexed: make(map[string]*httpReplyField),
|
||||
ordered: make([]*httpReplyField, 0)}
|
||||
}
|
||||
|
||||
// httpReplyFields is the reply which will be written to HTTP
|
||||
// both flds and ordered are pointig towards same httpReplyField
|
||||
type httpReplyFields struct {
|
||||
indexed map[string]*httpReplyField // map[fldPath]*httpReplyField
|
||||
ordered []*httpReplyField // keep order for export
|
||||
}
|
||||
|
||||
// newHAReqDecoder produces decoders
|
||||
func newHAReqDecoder(dcdType string,
|
||||
req *http.Request) (rD httpAgentReqDecoder, err error) {
|
||||
switch dcdType {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported decoder type <%s>", dcdType)
|
||||
}
|
||||
}
|
||||
|
||||
// httpAgentReqDecoder will decode request values
|
||||
type httpAgentReqDecoder interface {
|
||||
getFieldVal(fldPath string) (interface{}, error)
|
||||
}
|
||||
|
||||
// newHAReplyEncoder constructs a httpAgentReqDecoder based on encoder type
|
||||
func newHAReplyEncoder(encType string,
|
||||
w http.ResponseWriter) (rE httpAgentReplyEncoder, err error) {
|
||||
switch encType {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported encoder type <%s>", encType)
|
||||
}
|
||||
}
|
||||
|
||||
// httpAgentReplyEncoder will encode fields from httpReplyFields
|
||||
// and write content to http writer
|
||||
type httpAgentReplyEncoder interface {
|
||||
encode(*httpReplyFields) error
|
||||
}
|
||||
@@ -368,7 +368,7 @@ func startHTTPAgent(internalSMGChan chan rpcclient.RpcClientConnection, exitChan
|
||||
}
|
||||
}
|
||||
server.RegisterHttpHandler(agntCfg.Url,
|
||||
agents.NewHttpAgent(sSConn, agntCfg.Timezone, agntCfg.RequestPayload,
|
||||
agents.NewHTTPAgent(sSConn, agntCfg.Timezone, agntCfg.RequestPayload,
|
||||
agntCfg.ReplyPayload, agntCfg.RequestProcessors))
|
||||
}
|
||||
exitChan <- true
|
||||
|
||||
@@ -77,12 +77,13 @@ func (ca *HttpAgentCfg) loadFromJsonCfg(jsnCfg *HttpAgentJsonCfg) error {
|
||||
}
|
||||
|
||||
type HttpAgntProcCfg struct {
|
||||
Id string
|
||||
DryRun bool
|
||||
Filters []string
|
||||
Flags utils.StringMap
|
||||
RequestFields []*CfgCdrField
|
||||
ReplyFields []*CfgCdrField
|
||||
Id string
|
||||
DryRun bool
|
||||
Filters []string
|
||||
Flags utils.StringMap
|
||||
ContinueOnSuccess bool
|
||||
RequestFields []*CfgCdrField
|
||||
ReplyFields []*CfgCdrField
|
||||
}
|
||||
|
||||
func (ha *HttpAgntProcCfg) loadFromJsonCfg(jsnCfg *HttpAgentProcessorJsnCfg) (err error) {
|
||||
@@ -104,6 +105,9 @@ func (ha *HttpAgntProcCfg) loadFromJsonCfg(jsnCfg *HttpAgentProcessorJsnCfg) (er
|
||||
if jsnCfg.Flags != nil {
|
||||
ha.Flags = utils.StringMapFromSlice(*jsnCfg.Flags)
|
||||
}
|
||||
if jsnCfg.Continue_on_success != nil {
|
||||
ha.ContinueOnSuccess = *jsnCfg.Continue_on_success
|
||||
}
|
||||
if jsnCfg.Request_fields != nil {
|
||||
if ha.RequestFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Request_fields); err != nil {
|
||||
return
|
||||
|
||||
@@ -383,12 +383,13 @@ type HttpAgentJsonCfg struct {
|
||||
}
|
||||
|
||||
type HttpAgentProcessorJsnCfg struct {
|
||||
Id *string
|
||||
Dry_run *bool
|
||||
Filters *[]string
|
||||
Flags *[]string
|
||||
Request_fields *[]*CdrFieldJsonCfg
|
||||
Reply_fields *[]*CdrFieldJsonCfg
|
||||
Id *string
|
||||
Dry_run *bool
|
||||
Filters *[]string
|
||||
Flags *[]string
|
||||
Continue_on_success *bool
|
||||
Request_fields *[]*CdrFieldJsonCfg
|
||||
Reply_fields *[]*CdrFieldJsonCfg
|
||||
}
|
||||
|
||||
// History server config section
|
||||
|
||||
Reference in New Issue
Block a user