requestid

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 25, 2024 License: MIT Imports: 5 Imported by: 0

README

RequestID

GitHub Releases Build Status codecov Go Report Card GoDevDoc Donate

A library to propagate Request ID across the context.

Prerequisites

  • Go >= 1.21

Install

go get go.nhat.io/requestid

Usage

HTTP Server

You can use requestid.NewHandler() to wrap your HTTP handler or requestid.HandlerMiddleware() if you use chi router.

HTTP Client

You can use requestid.DefaultTransport or requestid.NewRoundTripper() to wrap your HTTP transport. If your client factory supports middleware, you can use requestid.RoundTripperMiddleware().

OpenTelemetry Propagation

You can use requestid.Propagator to propagate Request ID across the context. See the doc for more details.

Examples

Example 1: HTTP server and client middleware.

package integration_test

import (
	"context"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"go.nhat.io/requestid"
)

func TestHTTP(t *testing.T) {
	t.Parallel()

	actual := ""

	// Setup HTTP Client.
	c := &http.Client{
		Transport: requestid.DefaultTransport,
		Timeout:   time.Second,
	}

	// Spin up server 2.
	srv2 := httptest.NewServer(newRouter(func(w http.ResponseWriter, r *http.Request) {
		actual = requestid.FromContext(r.Context())

		w.WriteHeader(http.StatusOK)
	}))

	t.Cleanup(srv2.Close)

	// Spin up server 1.
	srv1 := httptest.NewServer(newRouter(func(w http.ResponseWriter, r *http.Request) {
		nextReq, err := http.NewRequestWithContext(r.Context(), http.MethodGet, srv2.URL, nil)
		require.NoError(t, err)

		resp, err := c.Do(nextReq)
		require.NoError(t, err)

		defer resp.Body.Close()

		w.WriteHeader(http.StatusOK)
	}))

	t.Cleanup(srv1.Close)

	// Make request for testing.
	requestID := uuid.New().String()

	req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, srv1.URL, nil)
	require.NoError(t, err)

	req.Header.Set("x-request-id", requestID)

	resp, err := c.Do(req)
	require.NoError(t, err)

	defer resp.Body.Close()

	// Assertions.
	assert.Equal(t, http.StatusOK, resp.StatusCode)
	assert.Equal(t, requestID, actual)
}

func newRouter(h func(w http.ResponseWriter, r *http.Request)) *chi.Mux {
	r := chi.NewRouter()

	r.Use(requestid.HandlerMiddleware())
	r.Get("/", h)

	return r
}

Example 2: OpenTelemetry propagation.

package integration_test

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

	"go.nhat.io/requestid"
)

func TestPropagator(t *testing.T) {
	t.Parallel()

	requestID := uuid.New().String()
	actual := ""

	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		actual = requestid.FromContext(r.Context())
	})

	srv := httptest.NewServer(otelhttp.NewHandler(h, "test",
		otelhttp.WithPropagators(requestid.Propagator{})),
	)

	defer srv.Close()

	req, err := http.NewRequest(http.MethodGet, srv.URL, nil)
	require.NoError(t, err)

	req.Header.Set("x-request-id", requestID)

	resp, err := srv.Client().Do(req)
	require.NoError(t, err)
	require.NoError(t, resp.Body.Close())

	assert.Equal(t, requestID, actual)
}

Donation

If this project help you reduce time to develop, you can give me a cup of coffee :)

Paypal donation

paypal

       or scan this

Documentation

Overview

Package requestid provides functionalities to inject and extract request IDs from the context.

Index

Constants

This section is empty.

Variables

DefaultTransport is a wrapper around http.DefaultTransport that injects the request ID into the header.

Functions

func ContextWithRequestID

func ContextWithRequestID(ctx context.Context, id string) context.Context

ContextWithRequestID injects the request ID into the context.

func FromContext

func FromContext(ctx context.Context) string

FromContext extracts the request ID from the context.

func HandlerMiddleware

func HandlerMiddleware() func(http.Handler) http.Handler

HandlerMiddleware returns a middleware that extracts the requestID from the header and injects it into the context.

func NewHandler

func NewHandler(h http.Handler) http.Handler

NewHandler wraps a http.Handler to extract the requestID from the header and inject it into the context.

func NewRoundTripper

func NewRoundTripper(rt http.RoundTripper) http.RoundTripper

NewRoundTripper wraps a http.RoundTripper to inject the request ID in the context into the header.

func RoundTripperMiddleware

func RoundTripperMiddleware() func(http.RoundTripper) http.RoundTripper

RoundTripperMiddleware returns a middleware that injects the request ID in the context into the header.

Types

type Propagator

type Propagator struct{}

Propagator is a request ID propagator.

func (Propagator) Extract

Extract extracts the request ID from the header.

func (Propagator) Fields

func (p Propagator) Fields() []string

Fields returns the keys whose values are set with ContextWithRequestID.

func (Propagator) Inject

func (p Propagator) Inject(ctx context.Context, carrier propagation.TextMapCarrier)

Inject injects the request ID into the header.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL