Bu örnekte, HTTP istek bağlamını (context) tüm bağlam anahtar/değer çiftleriyle klonlayacağız. Ancak buradaki önemli olan nokta, iptal veya sonlandırma eklerini atacağız. Bunun nedeni, yanıt döndürüldüğünde veya herhangi bir nedenle bağlam iptal edildiğinde, bağlamımızın sonlandırılmasını ve uygulamamızın zamanından önce kesilmesini istemememizdir.


Burada iki seçenek var. İlki, tüm anahtar/değer çiftlerini yepyeni bir bağlamda manuel olarak ayarladığınız ve HTTP istek bağlamını göz ardı ettiğiniz yerdir. Ancak, anahtarı/değeri bilmiyorsanız, bu işe yaramaz. İkinci seçenek, yukarıda anlattığımız şeydir, bu yüzden mevcut HTTP istek içeriğini ayırıp klonlayacağız.


Dikkat etmeniz gereken bir şey var. HTTP istek bağlamının, bir bağlama gereksinimi olan arka plan görevinizle ilgisi yoksa, sadece yepyeni bir bağlam oluşturun. HTTP istek içeriğini klonlamayın.


Örneğimiz basit. HTTP istek bağlamında birkaç anahtar/değer çifti belirlediğimiz iki ara yazılımımız olacak. Ayrıca üzerine zaman aşımı/sonlandırma tarihi de ekleyeceğiz. Daha sonra orjinal ve ayrılmış/klon bağlamının nasıl göründüğünü terminale yazdıracağız.


Yapı


├── context
│   └── detached.go
├── main.go
└── middleware
├── one.go
└── two.go

Dosyalar


detached.go


package context

import (
"context"
"time"
)

type detached struct {
ctx context.Context
}

func (detached) Deadline() (time.Time, bool) {
return time.Time{}, false
}

func (detached) Done() <-chan struct{} {
return nil
}

func (detached) Err() error {
return nil
}

func (d detached) Value(key interface{}) interface{} {
return d.ctx.Value(key)
}

func Detach(ctx context.Context) context.Context {
return detached{ctx: ctx}
}

one.go


Siz, aşağıda yaptığım gibi bağlam anahtarını/değerini ayarlamayın. Bunları doğru yöntem ile ayarlayın.


package middleware

import (
"context"
"net/http"
"time"
)

func One(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "one-key", "one-value")

// This will set a deadline on the context.
ctx, cancel := context.WithTimeout(ctx, time.Millisecond*1)
_ = cancel

h.ServeHTTP(w, r.WithContext(ctx))
})
}

two.go


Siz, aşağıda yaptığım gibi bağlam anahtarını/değerini ayarlamayın. Bunları doğru yöntem ile ayarlayın.


package middleware

import (
"context"
"net/http"
"time"
)

func Two(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "two-key", "two-value")

// This will set a deadline on the context.
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(time.Millisecond*time.Duration(1)))
_ = cancel

h.ServeHTTP(w, r.WithContext(ctx))
})
}

main.go


package main

import (
"fmt"
"log"
"net/http"

"sport/context"
"sport/middleware"
)

func main() {
log.Println("sport running...")

handler := http.NewServeMux()
handler.HandleFunc("/", home)

log.Fatalln(http.ListenAndServe(":8181", middleware.One(middleware.Two(handler))))
}

func home(w http.ResponseWriter, r *http.Request) {
log.Println("home")

// Detached context.
detachedCtx := context.Detach(r.Context())
detachedDeadline, ok := detachedCtx.Deadline()
fmt.Println("DETACHED ---")
fmt.Println("Deadline():", detachedDeadline, ok)
fmt.Println("Err():", r.Context().Err())
log.Println(detachedCtx.Value("one-key"))
log.Println(detachedCtx.Value("two-key"))

// Original context.
originalCtx := r.Context()
originalDeadline, ok := originalCtx.Deadline()
fmt.Println("ORIGINAL ---")
fmt.Println("Deadline():", originalDeadline, ok)
fmt.Println("Err():", r.Context().Err())
log.Println(originalCtx.Value("one-key"))
log.Println(originalCtx.Value("two-key"))
}

Test


http://localhost:8181 adresini ziyaret ettiğinizde, terminal çıktısı aşağıdaki gibi olacak. Gördüğünüz gibi, ayrılmış/klonlanmış bağlamımız zaman aşımı/sonlandırma tarih bilgisini attı, böylece artık iptal edilmeyecek.


DETACHED ---
Deadline(): 0001-01-01 00:00:00 +0000 UTC false
Err():
2020/09/15 12:42:14 one-value
2020/09/15 12:42:14 two-value
ORIGINAL ---
Deadline(): 2020-09-15 12:42:14.746067 +0100 BST m=+5.217963805 true
Err():
2020/09/15 12:42:14 one-value
2020/09/15 12:42:14 two-value