func RequestIdMiddleware(h cc.ContextHandler) cc.ContextHandler { return cc.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { ctx = NewContextWithRequestID(ctx, req) println("-->Request id serve http") h.ServeHTTPContext(ctx, rw, req) println("<--Request id http served") }) }
func TestQuote(t *testing.T) { soapServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, `<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <m:GetLastTradePriceResponse xmlns:m="Some-URI"> <Price>34.5</Price> </m:GetLastTradePriceResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>`) })) defer soapServer.Close() soapURL, _ := url.Parse(soapServer.URL) wrapped := quote.Middleware(customctx.ContextHandlerFunc(quote.NewQuoteHandler(soapURL.Host))) wrapped = timing.TimerMiddleware(wrapped) h := &customctx.ContextAdapter{ Ctx: context.Background(), Handler: wrapped, } ts := httptest.NewServer(h) defer ts.Close() req, err := http.NewRequest("GET", ts.URL+"/quote/MSFT", nil) if err != nil { log.Fatal(err.Error()) } client := http.Client{} resp, err := client.Do(req) if err != nil { log.Fatal(err.Error()) } body, err := ioutil.ReadAll(resp.Body) defer resp.Body.Close() if err != nil { log.Fatal(err.Error()) } println(string(body)) if !strings.Contains(string(body), "34.5") { t.Fail() } }
//Middleware returns a context aware wrapper that converts a GET on a stock symbol //to a SOAP request to the quote service func Middleware(ctxHandler cc.ContextHandler) cc.ContextHandler { return cc.ContextHandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { const timerName = "message and protocol transformation" timing.StartTimer(ctx, timerName) //Grab the symbol to quote from the uri resourceID, err := extractResource(r.RequestURI) if err != nil { w.WriteHeader(http.StatusNotFound) w.Write([]byte(err.Error())) return } println("quote for", resourceID) //Convert the method to POST for SOAP, and set the soap service //endpoint for the destination server r.Method = "POST" r.URL.Path = "/services/quote/getquote" //Form the SOAP payload payload := getQuoteRequestForSymbol(resourceID) payloadBytes, err := xml.Marshal(&payload) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } //Post the payload, and record the response r.Body = ioutil.NopCloser(bytes.NewReader(payloadBytes)) rec := httptest.NewRecorder() ctxHandler.ServeHTTPContext(ctx, rec, r) //Parse the recorded response to allow the quote price to be extracted var response responseEnvelope err = xml.Unmarshal(rec.Body.Bytes(), &response) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) timing.EndTimer(ctx, timerName, err) return } //Return just the price to the caller w.Write([]byte(response.Body.GetLastTradePriceResponse.Price + "\n")) timing.EndTimer(ctx, timerName, nil) }) }
func main() { var endpoint = "mb:4545" endPointFromEnv := os.Getenv("QUOTE_ENDPOINT") if endPointFromEnv != "" { endpoint = endPointFromEnv fmt.Println("Using endpoint from environment:", endpoint) } fmt.Println("starting wrapped quote at ", endpoint) wrapped := quote.Middleware(customctx.ContextHandlerFunc(quote.NewQuoteHandler(endpoint))) wrapped = timing.TimerMiddleware(wrapped) h := &customctx.ContextAdapter{ Ctx: context.Background(), Handler: wrapped, } http.ListenAndServe(":8080", h) }
func TimerMiddleware(h cc.ContextHandler) cc.ContextHandler { return cc.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { ctx = newContextWithTimings(ctx, req) start := time.Now() println("-->Timer mgmt serve http") h.ServeHTTPContext(ctx, rw, req) println("<--Timer mgmt http served") stop := time.Now() timings := ctx.Value(timeKey).(*timings) timingStr, err := timings.dumpTimings(stop.Sub(start)) if err != nil { log.Println("Unable to dump timings", err.Error()) } else { log.Println(string(timingStr)) } }) }
func TestWithXRequestID(t *testing.T) { h := &customctx.ContextAdapter{ Ctx: context.Background(), Handler: timing.TimerMiddleware(reqid.RequestIdMiddleware(customctx.ContextHandlerFunc(handler))), } ts := httptest.NewServer(h) defer ts.Close() req, err := http.NewRequest("GET", ts.URL, nil) if err != nil { log.Fatal(err.Error()) } req.Header.Set("X-Request-ID", "request-id") client := http.Client{} var resp *http.Response for i := 0; i < 1; i++ { resp, err = client.Do(req) if err != nil { log.Fatal(err.Error()) } } body, err := ioutil.ReadAll(resp.Body) defer resp.Body.Close() if err != nil { log.Fatal(err.Error()) } if !strings.Contains(string(body), "request-id") { t.Fail() } }