Skip to content

Commit

Permalink
update tests and simplify interface for outgoing requests
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyalaribe committed Dec 7, 2023
1 parent 2916318 commit 8800ec8
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 180 deletions.
164 changes: 18 additions & 146 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,7 @@ func main() {
### Golang Chi HTTP router integration
```go
import (
// Import the apitoolkit golang sdk
apitoolkit "github.com/apitoolkit/apitoolkit-go"
"github.com/go-chi/chi/v5"
)

func main() {
Expand Down Expand Up @@ -170,7 +168,6 @@ func main() {
panic(err)
}


// Register with the corresponding middleware of your choice. For Gin router, we use the GinMiddleware method.
router.Use(apitoolkitClient.Middleware)

Expand Down Expand Up @@ -219,19 +216,22 @@ To learn more about jsonpath to help form your queries, please take a look at th

## Outgoing Requests

Access an instrumented http client which will
automatically monitor requests made to third parties. These outgoing requests can be monitored from the apitoolkit dashboard

```go
ctx := context.Background()
HTTPClient := http.DefaultClient
HTTPClient.Transport = apitoolkitClient.WrapRoundTripper(
ctx, HTTPClient.Transport,
WithRedactHeaders([]string{}),
)
httpClient := apitoolkit.HTTPClient(ctx)
httpClient.Post(..) // Use the client like any regular golang http client.

```

The code above shows how to use the custom roundtripper to replace the transport in the default http client.
The resulting HTTP client can be used for any purpose, but will send a copy of all incoming and outgoing requests
to the apitoolkit servers. So to allow monitoring outgoing request from your servers use the `HTTPClient` to make http requests.
You can redact fields using functional options to specify what fields to redact.
eg.

```go
httpClient := apitoolkit.HTTPClient(ctx, apitoolkit.WithRedactHeaders("ABC", "$abc.xyz"))
httpClient.Post(..) // Use the client like any regular golang http client.
```

## Report Errors

Expand All @@ -242,139 +242,11 @@ Examples:
**Native Go**

```go
package main

import (
"fmt"
"net/http"
apitoolkit "github.com/apitoolkit/apitoolkit-go"
)

func main() {
ctx := context.Background()
apitoolkitClient, err := apitoolkit.NewClient(ctx, apitoolkit.Config{APIKey: "<API_KEY>"})
if err != nil {
panic(err)
}

helloHandler := func(w http.ResponseWriter, r *http.Request) {
file, err := os.Open("non-existing-file.txt")
if err != nil {
// Report the error to apitoolkit
apitoolkit.ReportError(r.Context(), err)
}
fmt.Fprintln(w, "{\"Hello\": \"World!\"}")
}

http.Handle("/", apitoolkitClient.Middleware(http.HandlerFunc(helloHandler)))

if err := http.ListenAndServe(":8089", nil); err != nil {
fmt.Println("Server error:", err)
}
}

```

**Gin**

```go
package main

import (
"github.com/gin-gonic/gin"
apitoolkit "github.com/apitoolkit/apitoolkit-go"
)

func main() {
r := gin.Default()
apitoolkitClient, err := apitoolkit.NewClient(context.Background(), apitoolkit.Config{APIKey: "<APIKEY>"})
if err != nil {
panic(err)
}

r.Use(apitoolkitClient.GinMiddleware)

r.GET("/", func(c *gin.Context) {
file, err := os.Open("non-existing-file.txt")
if err != nil {
// Report an error to apitoolkit
apitoolkit.ReportError(c.Request.Context(), err)
}
c.String(http.StatusOK, "Hello, World!")
})

r.Run(":8080")
}
```

**Echo**

```go
package main

import (
//... other imports
apitoolkit "github.com/apitoolkit/apitoolkit-go"
)

func main() {
e := echo.New()
ctx := context.Background()

apitoolkitClient, err := apitoolkit.NewClient(ctx, apitoolkit.Config{APIKey: "<API_KEY>"})
if err != nil {
panic(err)
}

e.Use(apitoolkitClient.EchoMiddleware)

e.GET("/", hello)

e.Logger.Fatal(e.Start(":1323"))
}

func hello(c echo.Context) error {
file, err := os.Open("non-existing-file.txt")
if err != nil {
apitoolkit.ReportError(c.Request().Context(), err)
}
log.Println(file)
return c.String(http.StatusOK, "Hello, World!")
}

```

**Gorilla mux**

```go
import (
//... other imports
apitoolkit "github.com/apitoolkit/apitoolkit-go"
)

func main() {
r := mux.NewRouter()
ctx := context.Background()

apitoolkitClient, err := apitoolkit.NewClient(ctx, apitoolkit.Config{APIKey: "<API_KEY>"})
if err != nil {
panic(err)
}
r.Use(apitoolkitClient.GorillaMuxMiddleware)
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, err := os.Open("mux.json")
if err != nil {
// Report the error to apitoolkit
apitoolkit.ReportError(r.Context(), err)
}
fmt.Fprintln(w, "Hello, World!")
})

server := &http.Server{Addr: ":8080", Handler: r}
err = server.ListenAndServe()
if err != nil {
fmt.Println(err)
}
}
file, err := os.Open("non-existing-file.txt")
if err != nil {
// Report the error to apitoolkit
// Ensure that the ctx is the context which is passed down from the handlers.
apitoolkit.ReportError(ctx, err)
}

```
5 changes: 5 additions & 0 deletions echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,18 @@ func (w *echoBodyLogWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
// EchoMiddleware middleware for echo framework, collects requests, response and publishes the payload
func (c *Client) EchoMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) (err error) {
// Register the client in the context,
// so it can be used for outgoing requests with little ceremony
ctx.Set(string(CurrentClient), c)

msgID := uuid.Must(uuid.NewRandom())
ctx.Set(string(CurrentRequestMessageID), msgID)

errorList := []ATError{}
ctx.Set(string(ErrorListCtxKey), &errorList)
newCtx := context.WithValue(ctx.Request().Context(), ErrorListCtxKey, &errorList)
newCtx = context.WithValue(newCtx, CurrentRequestMessageID, msgID)
newCtx = context.WithValue(newCtx, CurrentClient, c)
ctx.SetRequest(ctx.Request().WithContext(newCtx))

var reqBuf []byte
Expand Down
1 change: 0 additions & 1 deletion echo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ func TestOutgoingRequestEcho(t *testing.T) {
HTTPClient := http.DefaultClient
HTTPClient.Transport = client.WrapRoundTripper(
c.Request().Context(), HTTPClient.Transport,
WithRedactHeaders([]string{}),
)
_, _ = HTTPClient.Get("http://localhost:3000/from-gorilla")

Expand Down
1 change: 1 addition & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type ctxKey string
var (
ErrorListCtxKey = ctxKey("error-list")
CurrentRequestMessageID = ctxKey("current-req-msg-id")
CurrentClient = ctxKey("current=apitoolkit-client")
)

// ATError is the Apitoolkit error type/object
Expand Down
5 changes: 5 additions & 0 deletions fiber.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import (
)

func (c *Client) FiberMiddleware(ctx *fiber.Ctx) error {
// Register the client in the context,
// so it can be used for outgoing requests with little ceremony
ctx.Locals(string(CurrentClient), c)

msgID := uuid.Must(uuid.NewRandom())
ctx.Locals(string(CurrentRequestMessageID), msgID)
errorList := []ATError{}
ctx.Locals(string(ErrorListCtxKey), &errorList)
newCtx := context.WithValue(ctx.Context(), ErrorListCtxKey, &errorList)
newCtx = context.WithValue(newCtx, CurrentClient, c)
newCtx = context.WithValue(newCtx, CurrentRequestMessageID, msgID)
ctx.SetUserContext(newCtx)

Expand Down
1 change: 0 additions & 1 deletion fiber_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ func TestOutgoingRequestFiber(t *testing.T) {
HTTPClient := http.DefaultClient
HTTPClient.Transport = client.WrapRoundTripper(
c.UserContext(), HTTPClient.Transport,
WithRedactHeaders([]string{}),
)
_, _ = HTTPClient.Get("http://localhost:3000/from-gorilla")

Expand Down
5 changes: 5 additions & 0 deletions gin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ func (w *ginBodyLogWriter) WriteString(s string) (int, error) {
}

func (c *Client) GinMiddleware(ctx *gin.Context) {
// Register the client in the context,
// so it can be used for outgoing requests with little ceremony
ctx.Set(string(CurrentClient), c)

msgID := uuid.Must(uuid.NewRandom())
ctx.Set(string(CurrentRequestMessageID), msgID)
errorList := []ATError{}
ctx.Set(string(ErrorListCtxKey), &errorList)
newCtx := context.WithValue(ctx.Request.Context(), ErrorListCtxKey, &errorList)
newCtx = context.WithValue(newCtx, CurrentClient, c)
newCtx = context.WithValue(newCtx, CurrentRequestMessageID, msgID)
ctx.Request = ctx.Request.WithContext(newCtx)

Expand Down
10 changes: 4 additions & 6 deletions gin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,10 @@ func TestOutgoingRequestGin(t *testing.T) {
return nil
}
router.GET("/:slug/test", func(c *gin.Context) {
HTTPClient := http.DefaultClient
HTTPClient.Transport = client.WrapRoundTripper(
c.Request.Context(), HTTPClient.Transport,
WithRedactHeaders([]string{}),
)
_, _ = HTTPClient.Get("http://localhost:3000/from-gorilla")


hClient := HTTPClient(c.Request.Context())
_, _ = hClient.Get("http://localhost:3000/from-gorilla")

c.JSON(http.StatusAccepted, gin.H{"hello": "world"})
})
Expand Down
6 changes: 1 addition & 5 deletions integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ func TestReportingInteg(t *testing.T) {
ts := httptest.NewServer(client.Middleware(http.HandlerFunc(handlerFn)))
defer ts.Close()

atHTTPClient := http.DefaultClient
atHTTPClient.Transport = client.WrapRoundTripper(
ctx, atHTTPClient.Transport,
WithRedactHeaders([]string{}),
)
atHTTPClient := HTTPClient(ctx)
req.SetClient(atHTTPClient)
_, err = req.Post(ts.URL+"/test",
req.Param{"param1": "abc", "param2": 123},
Expand Down
1 change: 1 addition & 0 deletions native.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (c *Client) Middleware(next http.Handler) http.Handler {

errorList := []ATError{}
newCtx = context.WithValue(newCtx, ErrorListCtxKey, &errorList)
newCtx = context.WithValue(newCtx, CurrentClient, c)
req = req.WithContext(newCtx)

reqBuf, _ := io.ReadAll(req.Body)
Expand Down
16 changes: 4 additions & 12 deletions native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,8 @@ func TestOutgoingRequestGorilla(t *testing.T) {
assert.NoError(t, err)
assert.NotEmpty(t, body)

HTTPClient := http.DefaultClient
HTTPClient.Transport = client.WrapRoundTripper(
r.Context(), HTTPClient.Transport,
WithRedactHeaders([]string{}),
)
_, _ = HTTPClient.Get("http://localhost:3000/from-gorilla")
hClient := HTTPClient(r.Context())
_, _ = hClient.Get("http://localhost:3000/from-gorilla")

w.WriteHeader(http.StatusAccepted)
w.Write([]byte("Hello world"))
Expand Down Expand Up @@ -318,12 +314,8 @@ func TestOutgoingRequestChi(t *testing.T) {
return nil
}
router.Get("/:slug/test", func(w http.ResponseWriter, r *http.Request) {
HTTPClient := http.DefaultClient
HTTPClient.Transport = client.WrapRoundTripper(
r.Context(), HTTPClient.Transport,
WithRedactHeaders([]string{}),
)
_, _ = HTTPClient.Get("http://localhost:3000/from-gorilla")
hClient := HTTPClient(r.Context())
_, _ = hClient.Get("http://localhost:3000/from-gorilla")

fmt.Fprint(w, "Hello world")
})
Expand Down
Loading

0 comments on commit 8800ec8

Please sign in to comment.