|
@@ -0,0 +1,271 @@
|
|
|
|
+package rest
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "bytes"
|
|
|
|
+ "fmt"
|
|
|
|
+ "io"
|
|
|
|
+ "io/ioutil"
|
|
|
|
+ "log"
|
|
|
|
+ "mime/multipart"
|
|
|
|
+ "net/http"
|
|
|
|
+ "net/textproto"
|
|
|
|
+ "testing"
|
|
|
|
+ "time"
|
|
|
|
+
|
|
|
|
+ "git.ali33.ru/fcg-xvii/go-tools/json"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+var (
|
|
|
|
+ AddrCorrect = "localhost:7000"
|
|
|
|
+ AddrIncorrect = "1.1.1.1:7000"
|
|
|
|
+ Secret = []byte("itsMyWay")
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+func URL(path string) string {
|
|
|
|
+ return fmt.Sprintf("http://%s%s", AddrCorrect, path)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func sendRequest(uri string, data json.Map, files map[string]io.ReadCloser, auth string) ([]byte, error) {
|
|
|
|
+ log.Println(uri)
|
|
|
|
+ body := &bytes.Buffer{}
|
|
|
|
+ var contentType string
|
|
|
|
+
|
|
|
|
+ if len(files) == 0 {
|
|
|
|
+ // Если файлов нет, используем application/json
|
|
|
|
+ contentType = "application/json"
|
|
|
|
+ jsonData, err := json.Marshal(data)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ body.Write(jsonData)
|
|
|
|
+ } else {
|
|
|
|
+ // Если есть файлы, используем multipart/form-data
|
|
|
|
+ writer := multipart.NewWriter(body)
|
|
|
|
+
|
|
|
|
+ // Прикрепление файлов
|
|
|
|
+ for fieldName, file := range files {
|
|
|
|
+ part, err := writer.CreateFormFile(fieldName, fieldName)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ _, err = io.Copy(part, file)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ file.Close()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Прикрепление JSON как части с Content-Type application/json
|
|
|
|
+ jsonHeader := make(textproto.MIMEHeader)
|
|
|
|
+ jsonHeader.Set("Content-Disposition", `form-data; name="data"`)
|
|
|
|
+ jsonHeader.Set("Content-Type", "application/json")
|
|
|
|
+ jsonPart, err := writer.CreatePart(jsonHeader)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ jsonPart.Write(data.JSON())
|
|
|
|
+
|
|
|
|
+ err = writer.Close()
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ contentType = writer.FormDataContentType()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req, err := http.NewRequest("POST", uri, body)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if len(auth) > 0 {
|
|
|
|
+ req.Header.Add("Authorization", "Bearer "+auth)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req.Header.Add("Content-Type", contentType)
|
|
|
|
+
|
|
|
|
+ client := &http.Client{}
|
|
|
|
+ resp, err := client.Do(req)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ defer resp.Body.Close()
|
|
|
|
+
|
|
|
|
+ rBody, _ := ioutil.ReadAll(resp.Body)
|
|
|
|
+
|
|
|
|
+ if resp.StatusCode != http.StatusOK {
|
|
|
|
+ err = fmt.Errorf("failed sending request: %s", resp.Status)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return rBody, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func initFile(data []byte) io.ReadCloser {
|
|
|
|
+ buf := bytes.NewBuffer(data)
|
|
|
|
+ return io.NopCloser(buf)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TestListen(t *testing.T) {
|
|
|
|
+ commands := NewCommandStore()
|
|
|
|
+ rest := NewRest(AddrCorrect, Secret, commands)
|
|
|
|
+ err := rest.Listen(time.Second)
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Log("open", err, rest.opened.Load())
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ t.Log("close", rest.Close(), rest.opened.Load())
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TestRequest(t *testing.T) {
|
|
|
|
+ command := new(ObjectDemo)
|
|
|
|
+ commands := NewCommandStore()
|
|
|
|
+ commands.AddCommand("/demo", command)
|
|
|
|
+ commands.AddCommand("/json-debug", &JSONDebug{})
|
|
|
|
+ rest := NewRest(AddrCorrect, Secret, commands)
|
|
|
|
+ err := rest.Listen(time.Second)
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Log("open", err, rest.opened.Load())
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ defer rest.Close()
|
|
|
|
+ body, err := sendRequest(
|
|
|
|
+ URL("/demo"),
|
|
|
|
+ json.Map{
|
|
|
|
+ "get-one": true,
|
|
|
|
+ "get-two": false,
|
|
|
|
+ },
|
|
|
|
+ map[string]io.ReadCloser{
|
|
|
|
+ "test-file.txt": initFile([]byte("test file contents...")),
|
|
|
|
+ },
|
|
|
|
+ "",
|
|
|
|
+ )
|
|
|
|
+ t.Log(string(body), err)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TestToken(t *testing.T) {
|
|
|
|
+ commands := NewCommandStore()
|
|
|
|
+ auth := &AuthDebug{}
|
|
|
|
+ commands.AddCommand("/register", auth)
|
|
|
|
+ commands.AddCommand("/login", auth)
|
|
|
|
+ rest := NewRest(AddrCorrect, Secret, commands)
|
|
|
|
+ err := rest.Listen(time.Second)
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Log("open", err, rest.opened.Load())
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ defer rest.Close()
|
|
|
|
+
|
|
|
|
+ // register
|
|
|
|
+ body, err := sendRequest(
|
|
|
|
+ URL("/register"),
|
|
|
|
+ json.Map{
|
|
|
|
+ "login": "test",
|
|
|
|
+ },
|
|
|
|
+ nil,
|
|
|
|
+ "",
|
|
|
|
+ )
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Fatal(err, string(body))
|
|
|
|
+ }
|
|
|
|
+ var jm json.Map
|
|
|
|
+ json.Unmarshal(body, &jm)
|
|
|
|
+ token := jm.StringVal("token", "")
|
|
|
|
+ t.Log("token", token)
|
|
|
|
+
|
|
|
|
+ // auth
|
|
|
|
+ body, err = sendRequest(
|
|
|
|
+ URL("/login"),
|
|
|
|
+ json.Map{},
|
|
|
|
+ nil,
|
|
|
|
+ token,
|
|
|
|
+ )
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Fatal(err, string(body))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func NewFielderTest(id, parentID int64, name string, price float64, child *FielderTest) *FielderTest {
|
|
|
|
+ f := &FielderTest{
|
|
|
|
+ ID: id,
|
|
|
|
+ Password: "top-secret",
|
|
|
|
+ ParentID: parentID,
|
|
|
|
+ Name: name,
|
|
|
|
+ Price: price,
|
|
|
|
+ }
|
|
|
|
+ f.Fielder = NewFielder(f)
|
|
|
|
+ return f
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type FielderTest struct {
|
|
|
|
+ *Fielder
|
|
|
|
+ ID int64
|
|
|
|
+ Password string
|
|
|
|
+ ParentID int64
|
|
|
|
+ Name string
|
|
|
|
+ Price float64
|
|
|
|
+ Child *FielderTest
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (s *FielderTest) FieldCheck(name string) bool {
|
|
|
|
+ if name == "password" {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TestFielder(t *testing.T) {
|
|
|
|
+ f := NewFielderTest(1, 10, "VTBR", 100, nil)
|
|
|
|
+ f1 := NewFielderTest(10, 100, "SBER", 1000, nil)
|
|
|
|
+ f.Child = f1
|
|
|
|
+
|
|
|
|
+ fm, err := f.Fields(
|
|
|
|
+ "id",
|
|
|
|
+ "name",
|
|
|
|
+ "parent_id",
|
|
|
|
+ "price",
|
|
|
|
+ "password",
|
|
|
|
+ )
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ fm.LogPretty()
|
|
|
|
+
|
|
|
|
+ f.ID = 11
|
|
|
|
+
|
|
|
|
+ fm, err = f.Fields(
|
|
|
|
+ "id",
|
|
|
|
+ "name",
|
|
|
|
+ "parent_id",
|
|
|
|
+ "price",
|
|
|
|
+ map[string]any{
|
|
|
|
+ "name": "child",
|
|
|
|
+ "fields": []any{
|
|
|
|
+ "id",
|
|
|
|
+ "name",
|
|
|
|
+ "parent_id",
|
|
|
|
+ map[string]any{
|
|
|
|
+ "name": "child",
|
|
|
|
+ "fields": []any{
|
|
|
|
+ "id",
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ )
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ fm.LogPretty()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TestCase(t *testing.T) {
|
|
|
|
+ // Тестирование функций
|
|
|
|
+ testCamel := "ParentID"
|
|
|
|
+ testSnake := "parent_id"
|
|
|
|
+
|
|
|
|
+ snake := CamelToSnake(testCamel)
|
|
|
|
+ camel := SnakeToCamel(testSnake)
|
|
|
|
+
|
|
|
|
+ println(testCamel, "->", snake)
|
|
|
|
+ println(testSnake, "->", camel)
|
|
|
|
+}
|