github.com/oam-dev/kubevela@v1.9.11/pkg/builtin/http/http_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package http
    18  
    19  import (
    20  	"crypto/tls"
    21  	"crypto/x509"
    22  	"encoding/base64"
    23  	"encoding/json"
    24  	"fmt"
    25  	"net"
    26  	"net/http"
    27  	"net/http/httptest"
    28  	"testing"
    29  
    30  	"cuelang.org/go/cue"
    31  	"cuelang.org/go/cue/cuecontext"
    32  	"github.com/stretchr/testify/assert"
    33  
    34  	"github.com/kubevela/workflow/pkg/cue/model/value"
    35  
    36  	"github.com/oam-dev/kubevela/pkg/builtin/http/testdata"
    37  	"github.com/oam-dev/kubevela/pkg/builtin/registry"
    38  )
    39  
    40  const (
    41  	Req = `
    42  {
    43    method: *"GET" | string
    44    url: "http://127.0.0.1:8090/api/v1/token?val=test-token"
    45    request: {
    46      body ?: bytes
    47      header: {
    48      "Accept-Language": "en,nl"
    49      }
    50      trailer: {
    51      "Accept-Language": "en,nl"
    52      User: "foo"
    53      }
    54    }
    55  }
    56  `
    57  	ReqWithoutHeader = `
    58  {
    59    method: *"GET" | string
    60    url: "http://127.0.0.1:8090/api/v1/token?val=test-token-no-header"
    61    request: {
    62      body ?: bytes
    63      trailer: {
    64        "Accept-Language": "en,nl"
    65        User: "foo"
    66      }
    67    }
    68  }
    69  `
    70  )
    71  
    72  func TestHTTPCmdRun(t *testing.T) {
    73  	s := NewMock()
    74  	defer s.Close()
    75  
    76  	reqInst := cuecontext.New().CompileString(Req)
    77  
    78  	runner, _ := newHTTPCmd(cue.Value{})
    79  	got, err := runner.Run(&registry.Meta{Obj: reqInst.Value()})
    80  	if err != nil {
    81  		t.Error(err)
    82  	}
    83  	body := (got.(map[string]interface{}))["body"].(string)
    84  
    85  	assert.Equal(t, "{\"token\":\"test-token\"}", body)
    86  
    87  	reqNoHeaderInst := cuecontext.New().CompileString(ReqWithoutHeader)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  
    92  	got, err = runner.Run(&registry.Meta{Obj: reqNoHeaderInst.Value()})
    93  	if err != nil {
    94  		t.Error(err)
    95  	}
    96  	body = (got.(map[string]interface{}))["body"].(string)
    97  
    98  	assert.Equal(t, "{\"token\":\"test-token-no-header\"}", body)
    99  
   100  }
   101  
   102  func TestHTTPSRun(t *testing.T) {
   103  	s := newMockHttpsServer()
   104  	defer s.Close()
   105  	reqInst := cuecontext.New().CompileString(`method: "GET"
   106  url: "https://127.0.0.1:8443/api/v1/token?val=test-token"`)
   107  	reqInst = reqInst.FillPath(value.FieldPath("tls_config", "ca"), decodeCert(testdata.MockCerts.Ca))
   108  	reqInst = reqInst.FillPath(value.FieldPath("tls_config", "client_crt"), decodeCert(testdata.MockCerts.ClientCrt))
   109  	reqInst = reqInst.FillPath(value.FieldPath("tls_config", "client_key"), decodeCert(testdata.MockCerts.ClientKey))
   110  
   111  	runner, _ := newHTTPCmd(cue.Value{})
   112  	got, err := runner.Run(&registry.Meta{Obj: reqInst.Value()})
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	body := (got.(map[string]interface{}))["body"].(string)
   117  
   118  	assert.Equal(t, "{\"token\":\"test-token\"}", body)
   119  }
   120  
   121  // NewMock mock the http server
   122  func NewMock() *httptest.Server {
   123  	ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   124  		if r.Method != "GET" {
   125  			fmt.Printf("Expected 'GET' request, got '%s'", r.Method)
   126  		}
   127  		if r.URL.EscapedPath() != "/api/v1/token" {
   128  			fmt.Printf("Expected request to '/person', got '%s'", r.URL.EscapedPath())
   129  		}
   130  		r.ParseForm()
   131  		token := r.Form.Get("val")
   132  		tokenBytes, _ := json.Marshal(map[string]interface{}{"token": token})
   133  
   134  		w.WriteHeader(http.StatusOK)
   135  		w.Write(tokenBytes)
   136  	}))
   137  	l, _ := net.Listen("tcp", "127.0.0.1:8090")
   138  	ts.Listener.Close()
   139  	ts.Listener = l
   140  	ts.Start()
   141  	return ts
   142  }
   143  
   144  func newMockHttpsServer() *httptest.Server {
   145  	ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   146  		if r.Method != "GET" {
   147  			fmt.Printf("Expected 'GET' request, got '%s'", r.Method)
   148  		}
   149  		if r.URL.EscapedPath() != "/api/v1/token" {
   150  			fmt.Printf("Expected request to '/person', got '%s'", r.URL.EscapedPath())
   151  		}
   152  		r.ParseForm()
   153  		token := r.Form.Get("val")
   154  		tokenBytes, _ := json.Marshal(map[string]interface{}{"token": token})
   155  
   156  		w.WriteHeader(http.StatusOK)
   157  		w.Write(tokenBytes)
   158  	}))
   159  	l, _ := net.Listen("tcp", "127.0.0.1:8443")
   160  	ts.Listener.Close()
   161  	ts.Listener = l
   162  
   163  	pool := x509.NewCertPool()
   164  	pool.AppendCertsFromPEM([]byte(decodeCert(testdata.MockCerts.Ca)))
   165  	cert, err := tls.X509KeyPair([]byte(decodeCert(testdata.MockCerts.ServerCrt)), []byte(decodeCert(testdata.MockCerts.ServerKey)))
   166  	if err != nil {
   167  		panic(err)
   168  	}
   169  	ts.TLS = &tls.Config{
   170  		ClientCAs:    pool,
   171  		ClientAuth:   tls.RequireAndVerifyClientCert,
   172  		Certificates: []tls.Certificate{cert},
   173  		NextProtos:   []string{"http/1.1"},
   174  	}
   175  	ts.StartTLS()
   176  	return ts
   177  }
   178  
   179  func decodeCert(in string) string {
   180  	out, _ := base64.StdEncoding.DecodeString(in)
   181  	return string(out)
   182  }