HttpPoster implementation in CDR replication and actions with call_url, new configuration parameters added: http_failed_dir, replication attempts, fixes #201, Rated bug fix in CDRC, Cost imported via CDRC in templates now

This commit is contained in:
DanB
2015-10-02 18:13:29 +02:00
parent f75afcea33
commit 2e61fcf5bb
15 changed files with 120 additions and 51 deletions

View File

@@ -124,7 +124,8 @@ const (
RATED_SUBJECT = "RatedSubject"
COST = "Cost"
COST_DETAILS = "CostDetails"
RATED = "Rated"
RATED = "rated"
RATED_FLD = "Rated"
DEFAULT_RUNID = "*default"
META_DEFAULT = "*default"
STATIC_VALUE_PREFIX = "^"

View File

@@ -21,14 +21,33 @@ package utils
import (
"bytes"
"crypto/tls"
"encoding/gob"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"time"
)
var (
CONTENT_JSON = "json"
CONTENT_FORM = "form"
CONTENT_TEXT = "text"
)
// Converts interface to []byte
func GetBytes(content interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(content)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Post without automatic failover
func HttpJsonPost(url string, skipTlsVerify bool, content interface{}) ([]byte, error) {
body, err := json.Marshal(content)
@@ -55,8 +74,20 @@ func HttpJsonPost(url string, skipTlsVerify bool, content interface{}) ([]byte,
}
// Post with built-in failover
func HttpJsonPoster(url string, skipTlsVerify bool, content interface{}, retries int, fallbackFilePath string) ([]byte, error) {
body, err := json.Marshal(content)
func HttpPoster(addr string, skipTlsVerify bool, content interface{}, contentType string, attempts int, fallbackFilePath string) ([]byte, error) {
var body []byte
var urlData url.Values
var err error
switch contentType {
case CONTENT_JSON:
body, err = json.Marshal(content)
case CONTENT_FORM:
urlData = content.(url.Values)
case CONTENT_TEXT:
body = content.([]byte)
default:
err = fmt.Errorf("Unsupported ContentType: %s", contentType)
}
if err != nil {
return nil, err
}
@@ -65,22 +96,31 @@ func HttpJsonPoster(url string, skipTlsVerify bool, content interface{}, retries
}
client := &http.Client{Transport: tr}
delay := Fib()
for i := 0; i < retries; i++ {
resp, err := client.Post(url, "application/json", bytes.NewBuffer(body))
bodyType := "application/x-www-form-urlencoded"
if contentType == CONTENT_JSON {
bodyType = "application/json"
}
for i := 0; i < attempts; i++ {
var resp *http.Response
if IsSliceMember([]string{CONTENT_JSON, CONTENT_TEXT}, contentType) {
resp, err = client.Post(addr, bodyType, bytes.NewBuffer(body))
} else if contentType == CONTENT_FORM {
resp, err = client.PostForm(addr, urlData)
}
if err != nil {
Logger.Warning(fmt.Sprintf("<HttpPoster> Posting to : <%s>, error: <%s>", url, err.Error()))
Logger.Warning(fmt.Sprintf("<HttpPoster> Posting to : <%s>, error: <%s>", addr, err.Error()))
time.Sleep(delay())
continue
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
Logger.Warning(fmt.Sprintf("<HttpPoster> Posting to : <%s>, error: <%s>", url, err.Error()))
Logger.Warning(fmt.Sprintf("<HttpPoster> Posting to : <%s>, error: <%s>", addr, err.Error()))
time.Sleep(delay())
continue
}
if resp.StatusCode > 299 {
Logger.Warning(fmt.Sprintf("<HttpPoster> Posting to : <%s>, unexpected status code received: <%d>", url, resp.StatusCode))
Logger.Warning(fmt.Sprintf("<HttpPoster> Posting to : <%s>, unexpected status code received: <%d>", addr, resp.StatusCode))
time.Sleep(delay())
continue
}

View File

@@ -22,6 +22,7 @@ import (
"encoding/json"
"flag"
"io/ioutil"
"os"
"reflect"
"testing"
)
@@ -38,8 +39,8 @@ func TestHttpJsonPoster(t *testing.T) {
return
}
content := &TestContent{Var1: "Val1", Var2: "Val2"}
filePath := "/tmp/test_http_poster.cgr"
if _, err := HttpJsonPoster("http://localhost:8080/invalid", true, content, 3, filePath); err != nil {
filePath := "/tmp/cgr_test_http_poster.json"
if _, err := HttpPoster("http://localhost:8080/invalid", true, content, true, 3, filePath); err != nil {
t.Error(err)
}
jsnContent, _ := json.Marshal(content)
@@ -48,4 +49,28 @@ func TestHttpJsonPoster(t *testing.T) {
} else if !reflect.DeepEqual(jsnContent, readBytes) {
t.Errorf("Expecting: %q, received: %q", string(jsnContent), string(readBytes))
}
if err := os.Remove(filePath); err != nil {
t.Error("Failed removing file: ", filePath)
}
}
func TestHttpBytesPoster(t *testing.T) {
if !*testLocal {
return
}
content := []byte(`Test
Test2
`)
filePath := "/tmp/test_http_poster.http"
if _, err := HttpPoster("http://localhost:8080/invalid", true, content, false, 3, filePath); err != nil {
t.Error(err)
}
if readBytes, err := ioutil.ReadFile(filePath); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(content, readBytes) {
t.Errorf("Expecting: %q, received: %q", string(content), string(readBytes))
}
if err := os.Remove(filePath); err != nil {
t.Error("Failed removing file: ", filePath)
}
}