func TestMicroplatformHandler(t *testing.T) { server, _ := getServer(testPortMicro) connectionManager := platform.NewAmqpConnectionManager(rabbitUser, rabbitPass, rabbitAddr+":"+rabbitPort, "") publisher = getDefaultPublisher(connectionManager) subscriber = getDefaultSubscriber(connectionManager, server.GetRouterURI()) router := platform.NewStandardRouter(publisher, subscriber) server.SetRouter(router) Convey("By accessing / with hex encoded string we should get back proper endpoint response", t, func() { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(200) w.Header().Set("Content-Type", "text/plain") contents, err := ioutil.ReadAll(req.Body) if err != nil { w.Write(ErrorResponse(fmt.Sprintf("Failed to read body: %s", err))) return } platformRequestBytes, err := hex.DecodeString(fmt.Sprintf("%s", contents)) if err != nil { w.Write(ErrorResponse(fmt.Sprintf("Failed to decode body: %s", err))) return } platformRequest := &platform.Request{} if err := platform.Unmarshal(platformRequestBytes, platformRequest); err != nil { w.Write(ErrorResponse(fmt.Sprintf("Failed to unmarshal platform request: %s", err))) return } if platformRequest.Routing == nil { platformRequest.Routing = &platform.Routing{} } if platformRequest.Routing.RouteFrom != nil { platformRequest.Routing.RouteFrom = []*platform.Route{} } if !platform.RouteToSchemeMatches(platformRequest, "microservice") { w.Write(ErrorResponse(fmt.Sprintf("Unsupported scheme provided: %s", platformRequest.Routing.RouteTo))) return } w.Header().Set("Content-Type", "text/plain") mainReq := platform.Request{ Routing: &platform.Routing{ RouteTo: []*platform.Route{&platform.Route{Uri: teltech.String("resource:///testing/reply/http-router")}}, }, } w.Write([]byte(hex.EncodeToString(GetProtoBytes(platform.GenerateResponse(&mainReq, &mainReq))))) return })) defer server.Close() // Give it time to start the listener time.Sleep(300 * time.Millisecond) client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, } Convey("By passing valid / we should get back valid response", func() { req := &platform.Request{ Routing: &platform.Routing{ RouteTo: []*platform.Route{&platform.Route{Uri: teltech.String("microservice:///testing/get/http-router")}}, }, Completed: teltech.Bool(true), } responseBytes, err := platform.Marshal(req) So(err, ShouldBeNil) reqHex := []byte(hex.EncodeToString(responseBytes)) request, err := http.NewRequest("POST", server.URL, bytes.NewBuffer(reqHex)) So(err, ShouldBeNil) request.Header.Set("Content-Type", "text/plain") resp, err := client.Do(request) So(err, ShouldBeNil) defer resp.Body.Close() contents, err := ioutil.ReadAll(resp.Body) So(err, ShouldBeNil) platformResponseBytes, err := hex.DecodeString(string(contents)) So(err, ShouldBeNil) response := &platform.Request{} err = platform.Unmarshal(platformResponseBytes, response) So(err, ShouldBeNil) So(response.GetRouting().GetRouteTo()[0].GetUri(), ShouldNotEqual, "resource:///meta/reply/error") So(response.GetRouting().GetRouteTo()[0].GetUri(), ShouldEqual, "resource:///testing/reply/http-router") }) Convey("By passing invalid hex message towards / we should get back hex decode errors", func() { reqHex := []byte("I am not valid request") request, err := http.NewRequest("POST", server.URL, bytes.NewBuffer(reqHex)) So(err, ShouldBeNil) request.Header.Set("Content-Type", "text/plain") resp, err := client.Do(request) So(err, ShouldBeNil) defer resp.Body.Close() contents, err := ioutil.ReadAll(resp.Body) So(err, ShouldBeNil) platformResponseBytes, err := hex.DecodeString(string(contents)) So(err, ShouldBeNil) response := &platform.Request{} err = platform.Unmarshal(platformResponseBytes, response) So(err, ShouldBeNil) So(response.GetRouting().GetRouteTo()[0].GetUri(), ShouldNotEqual, "resource:///meta/reply/error") responseErr := &platform.Error{} err = platform.Unmarshal(response.GetPayload(), responseErr) So(err, ShouldBeNil) So(responseErr.GetMessage(), ShouldContainSubstring, "Failed to decode body") }) Convey("By passing invalid hex request towards / we should get back unmarshal errors", func() { reqHex := []byte(hex.EncodeToString([]byte("Somewhere over the rainbow..."))) request, err := http.NewRequest("POST", server.URL, bytes.NewBuffer(reqHex)) So(err, ShouldBeNil) request.Header.Set("Content-Type", "text/plain") resp, err := client.Do(request) So(err, ShouldBeNil) defer resp.Body.Close() contents, err := ioutil.ReadAll(resp.Body) So(err, ShouldBeNil) platformResponseBytes, err := hex.DecodeString(string(contents)) So(err, ShouldBeNil) response := &platform.Request{} err = platform.Unmarshal(platformResponseBytes, response) So(err, ShouldBeNil) So(response.GetRouting().GetRouteTo()[0].GetUri(), ShouldNotEqual, "resource:///meta/reply/error") responseErr := &platform.Error{} err = platform.Unmarshal(response.GetPayload(), responseErr) So(err, ShouldBeNil) So(responseErr.GetMessage(), ShouldContainSubstring, "Failed to unmarshal platform request") }) Convey("By passing valid hex and request but invalid router scheme we should see invald scheme error", func() { req := &platform.Request{ Routing: &platform.Routing{ RouteTo: []*platform.Route{&platform.Route{Uri: teltech.String("microservice-invalid:///testing/get/http-router")}}, }, Completed: teltech.Bool(true), } responseBytes, err := platform.Marshal(req) So(err, ShouldBeNil) reqHex := []byte(hex.EncodeToString(responseBytes)) request, err := http.NewRequest("POST", server.URL, bytes.NewBuffer(reqHex)) So(err, ShouldBeNil) request.Header.Set("Content-Type", "text/plain") resp, err := client.Do(request) So(err, ShouldBeNil) defer resp.Body.Close() contents, err := ioutil.ReadAll(resp.Body) So(err, ShouldBeNil) platformResponseBytes, err := hex.DecodeString(string(contents)) So(err, ShouldBeNil) response := &platform.Request{} err = platform.Unmarshal(platformResponseBytes, response) So(err, ShouldBeNil) So(response.GetRouting().GetRouteTo()[0].GetUri(), ShouldNotEqual, "resource:///meta/reply/error") responseErr := &platform.Error{} err = platform.Unmarshal(response.GetPayload(), responseErr) So(err, ShouldBeNil) So(responseErr.GetMessage(), ShouldContainSubstring, "Unsupported scheme provided") }) }) }
// MicroplatformEndpointHandler - HTTP proxy request towards gRPC router func MicroplatformEndpointHandler(server *Server) func(w http.ResponseWriter, req *http.Request) { return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "text/plain") contents, err := ioutil.ReadAll(req.Body) if err != nil { w.Write(ErrorResponse(fmt.Sprintf("Failed to read body: %s", err))) return } platformRequestBytes, err := hex.DecodeString(fmt.Sprintf("%s", contents)) if err != nil { w.Write(ErrorResponse(fmt.Sprintf("Failed to decode body: %s", err))) return } platformRequest := &platform.Request{} if err := platform.Unmarshal(platformRequestBytes, platformRequest); err != nil { w.Write(ErrorResponse(fmt.Sprintf("Failed to unmarshal platform request: %s", err))) return } if platformRequest.Routing == nil { platformRequest.Routing = &platform.Routing{} } if platformRequest.Routing.RouteFrom != nil { platformRequest.Routing.RouteFrom = []*platform.Route{} } if !platform.RouteToSchemeMatches(platformRequest, "microservice") { w.Write(ErrorResponse(fmt.Sprintf("Unsupported scheme provided: %s", platformRequest.Routing.RouteTo))) return } responses, timeout := server.Router.Route(platformRequest) for { select { case response := <-responses: logger.Printf("Got a response for request:", platformRequest.GetUuid()) if response.GetRouting().GetRouteTo()[0].GetUri() != "resource:///heartbeat" { responseBytes, err := platform.Marshal(response) if err != nil { w.Write(ErrorResponse(fmt.Sprintf( "failed to marshal platform request: %s - err: %s", platformRequest.GetUuid(), err, ))) return } w.Write([]byte(hex.EncodeToString(responseBytes))) return } case <-timeout: w.Write(ErrorResponse(fmt.Sprintf("Got a timeout for request: %s", platformRequest.GetUuid()))) return } } return } }