func (w *Worker) handleRequest(writer http.ResponseWriter, request *http.Request) { contentType := request.Header.Get("Content-Type") if contentType == "" { contentType = w.defaultContentType } var unmarshaller gototo.UnmarshalFunction if unmarshaller = w.unmarshalMap[contentType]; unmarshaller == nil { unmarshaller = w.unmarshal contentType = w.defaultContentType } defer w.handlePanic(writer, contentType) body, err := ioutil.ReadAll(request.Body) if err != nil { w.writeResponse(writer, contentType, gototo.CreateErrorResponse(fmt.Errorf("Failed to read request body: %s", err)), 500) return } requestData, err := unmarshaller(body) if err != nil { w.writeResponse(writer, contentType, gototo.CreateErrorResponse(fmt.Errorf("Failed to unmarshal request: %s", err)), 500) return } workerFunction := w.registeredWorkerFunctions[requestData.Method] if workerFunction == nil { w.writeResponse(writer, contentType, gototo.CreateErrorResponse(fmt.Errorf("No method found: %s", requestData.Method)), 404) return } startTime := time.Now() result := workerFunction(requestData.Parameters) if w.logMetrics { log.Println("Request", requestData.Method, "finished in", time.Now().Sub(startTime)) } w.writeResponse(writer, contentType, result, 200) }
func TestCall(t *testing.T) { tcpAddr, _ := net.ResolveTCPAddr("tcp", ":0") l, err := net.ListenTCP("tcp", tcpAddr) if err != nil { t.Fatal("Failed to create TCP listener:", err) } tcpAddr = l.Addr().(*net.TCPAddr) err = l.Close() if err != nil { t.Fatal("Failed to create TCP listener:", err) } worker := New(fmt.Sprintf("tcp://*:%d", tcpAddr.Port), 10) worker.SetLogMetrics(true) var _ gototo.Worker = worker worker.RegisterWorkerFunction("test_func", worker.MakeWorkerFunction(func(i *SampleValidatedType) *gototo.Response { if i.String != "fail" { return gototo.CreateSuccessResponse(i) } return gototo.CreateErrorResponse(gototo.NewCodedError("Empty string!", 42)) })) worker.RegisterWorkerFunction("slow_test_func", worker.MakeWorkerFunction(func(i *WaitRequest) *gototo.Response { time.Sleep(i.Timeout) return gototo.CreateSuccessResponse(i) })) err = worker.Start() if err != nil { t.Fatal("Failed to start worker:", err) } time.Sleep(100 * time.Millisecond) defer worker.Stop() addr := fmt.Sprintf("tcp://127.0.0.1:%d", tcpAddr.Port) connection := NewConnection(addr) var _ gototo.WorkerConnection = connection connection.RegisterResponseType("test_func", &SampleValidatedType{}, true) connection.RegisterResponseType("slow_test_func", &WaitRequest{}, true) connection.RegisterDefaultOptions("slow_test_func", &gototo.RequestOptions{Timeout: 100 * time.Millisecond, RetryCount: 3}) err = connection.Start() if err != nil { t.Fatal("Failed to start connection:", err) } err = connection.Disconnect(addr) if err != nil { t.Fatal("Failed to disconnect:", err) } if len(connection.GetEndpoints()) > 0 { t.Fatal("Expected no connections") } err = connection.Connect(addr) if err != nil { t.Fatal("Failed to reconnect:", err) } if len(connection.GetEndpoints()) != 1 { t.Fatal("Expected one connections") } err = connection.SetEndpoints() if err != nil { t.Fatal("Failed to disconnect:", err) } if len(connection.GetEndpoints()) > 0 { t.Fatal("Expected no connections") } err = connection.SetEndpoints(addr) if err != nil { t.Fatal("Failed to reconnect:", err) } if len(connection.GetEndpoints()) != 1 { t.Fatal("Expected one connections") } err = connection.Connect(addr) if err != nil { t.Fatal("Failed to reconnect:", err) } if len(connection.GetEndpoints()) != 1 { t.Fatal("Expected one connections") } defer connection.Stop() resp, err := connection.Call("test_func", &SampleValidatedType{String: "test request string"}) if err != nil { t.Fatal("Failed to decode response:", err) } if svt, ok := resp.(*SampleValidatedType); !ok { t.Fatalf("Bad response: %#v\n", resp) } else if svt.String != "test request string" { t.Fatalf("Bad response: %#v\n", resp) } resp, err = connection.Call("test_func", &SampleValidatedType{String: ""}) if err == nil { t.Fatalf("Expected error: %#v %#v\n", resp, err) } else { if responseError, ok := err.(*gototo.ResponseError); !ok { t.Fatalf("Expected *ResponseError: %#v\n", err) } else if responseError.Error() != "Validation failed: Empty String field" { t.Fatalf("Expected 'Validation failed: Empty String field': %#v\n", err) } else if responseError.Code() != gototo.CodeValidationFailed { log.Printf("%#v", responseError) t.Fatalf("Expected validation failed code, found %d", responseError.Code()) } } resp, err = connection.Call("test_func", &SampleValidatedType{String: "fail"}) if err == nil { t.Fatalf("Expected error: %#v %#v\n", resp, err) } else { if responseError, ok := err.(*gototo.ResponseError); !ok { t.Fatalf("Expected *ResponseError: %#v\n", err) } else if responseError.Error() != "Empty string!" { t.Fatalf("Expected 'Empty string!': %#v\n", err) } else if responseError.Code() != 42 { t.Fatalf("Expected error code 42, found %d", responseError.Code()) } } resp, err = connection.Call("slow_test_func", &WaitRequest{Timeout: 200 * time.Millisecond}) if err != nil { t.Error("Unexpected response error:", err) } resp, err = connection.Call("slow_test_func", &WaitRequest{Timeout: 1 * time.Second}) if err != gototo.ErrTimeout { t.Error("Expected timeout, found:", err, resp) } }