/* test cases */ func Test_WebPipeEndToEndRequestsShouldSucceed(t *testing.T) { /* server side logic */ itemsMap := make(map[string]string) createItemApi := func(request *webpipe.Request, response *webpipe.Response, _ webpipe.Context) error { id := uuid.NewV4().String() if data, err := request.Payload.Bytes(); err != nil { return err } else { itemsMap[id] = string(data) } response.Payload = webpipe.CreateBytesPayload([]byte(id)) return nil } getItemApi := func(request *webpipe.Request, response *webpipe.Response, _ webpipe.Context) error { id := request.Params.Get("item_id") if item, ok := itemsMap[id]; ok { response.Payload = webpipe.CreateBytesPayload([]byte(item)) } return nil } /* prepare server pipe */ serverHandlers := []webpipe.DelegatingHandler{ func(request *webpipe.Request, response *webpipe.Response, context webpipe.Context) { startTime := time.Now() /* get start timestamp */ context.Next(request, response) /* invoke the remaining part in the stack */ duration := time.Now().Sub(startTime) /* calculate elapsed duration */ response.Header.Set("X-API-DURATION", duration.String()) /* fill the duration header */ }, func(request *webpipe.Request, response *webpipe.Response, context webpipe.Context) { authHeader, found := request.Header["Authorization"] /* check auth header */ if !found || len(authHeader) == 0 { response.StatusCode = http.StatusForbidden /* forbid calling without auth header */ } else { if authHeader[0] != "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" { response.StatusCode = http.StatusUnauthorized /* do authorization */ } else { context.Next(request, response) /* invoke the remaining part in the stack */ } } }, } server := webpipe.CreateServer(serverHandlers) server.Register("POST", "/items", nil, createItemApi) server.Register("GET", "/items/:item_id", nil, getItemApi) go server.Listen(8082) /* prepare client pipe */ invokePerfLog := []string{} clientHandlers := []webpipe.DelegatingHandler{ func(request *webpipe.Request, response *webpipe.Response, context webpipe.Context) { request.Header.Set("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==") /* set auth header */ context.Next(request, response) /* invoke the remaining part in the stack */ }, func(request *webpipe.Request, response *webpipe.Response, context webpipe.Context) { context.Next(request, response) /* invoke the rpc first */ duration := response.Header.Get("X-API-DURATION") invokePerfLog = append(invokePerfLog, duration) }, } /* client side invocations */ client := webpipe.CreateClient("http://localhost:8082", clientHandlers) req := client.NewRequest("POST") req.Payload = webpipe.CreateBytesPayload([]byte("bytes payload for item")) resp, err := client.Invoke("/items", req) /* assertion 1 */ Nil(t, err) Equal(t, http.StatusCreated, resp.StatusCode) Equal(t, 1, len(invokePerfLog)) Equal(t, 1, len(itemsMap)) id, err := resp.Payload.Bytes() Nil(t, err) False(t, len(id) == 0) req = client.NewRequest("GET") req.Params.Set("item_id", string(id)) resp, err = client.Invoke("/items/:item_id", req) /* assertion 2 */ Nil(t, err) Equal(t, http.StatusOK, resp.StatusCode) Equal(t, 2, len(invokePerfLog)) body, err := resp.Payload.Bytes() Nil(t, err) Equal(t, "bytes payload for item", string(body)) }
func Test_InvokeHttpBasicRequestsShouldSucceed(t *testing.T) { /* prepare http router */ router := httprouter.New() var itemsGetReq *http.Request = nil var itemsGetPar httprouter.Params router.GET("/items", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { itemsGetReq = r itemsGetPar = p io.WriteString(w, "ACK") }) router.GET("/items/:item_id", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { itemsGetReq = r itemsGetPar = p io.WriteString(w, "ACK") }) var itemsPatchReq *http.Request = nil var itemsPatchPar httprouter.Params var itemsPatchBody []byte router.PATCH("/items/:item_id", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { itemsPatchReq = r itemsPatchPar = p itemsPatchBody = make([]byte, r.ContentLength) io.ReadAtLeast(r.Body, itemsPatchBody, int(r.ContentLength)) io.WriteString(w, "PATCHED") }) go http.ListenAndServe(":8081", router) /* invoke get items API */ client := webpipe.CreateClient("http://localhost:8081", nil) request := client.NewRequest("GET") request.Queries.Add("id", "123") response, err := client.Invoke("/items", request) Nil(t, err) /* assertions */ Equal(t, "/items?id=123", itemsGetReq.URL.String()) payload, err := response.Payload.Bytes() Nil(t, err) Equal(t, "ACK", string(payload)) Equal(t, 0, len(itemsGetPar)) /* invoke again without queries */ request = client.NewRequest("GET") request.Params.Set("item_id", "100") response, err = client.Invoke("/items/:item_id", request) Nil(t, err) Equal(t, "/items/100", itemsGetReq.URL.String()) payload, err = response.Payload.Bytes() Nil(t, err) Equal(t, "ACK", string(payload)) Equal(t, 1, len(itemsGetPar)) Equal(t, "100", itemsGetPar.ByName("item_id")) /* now patch with some data */ data := make(map[string]interface{}) data["key1"] = "hello" data["key2"] = 100 request = client.NewRequest("PATCH") request.Params.Set("item_id", "500") request.Queries.Set("method", "full_update") request.Payload, err = webpipe.CreateJSONPayload(data) Nil(t, err) response, err = client.Invoke("items/:item_id", request) Nil(t, err) Equal(t, "/items/500?method=full_update", itemsPatchReq.URL.String()) Equal(t, 1, len(itemsPatchPar)) Equal(t, "500", itemsPatchPar.ByName("item_id")) Equal(t, "{\"key1\":\"hello\",\"key2\":100}", string(itemsPatchBody)) }