Thomas Bonfort
Thomas Bonfort

Reputation: 341

Request Cancellation is not propagated to cloud run container

When an HTTP request sent to a cloud run service is cancelled by the initiating service, the cancelled/closed connection is not propagated to the request that is being serviced inside the cloud run container.

Example code:

package main

import (
    "log"
    "net/http"
    "os"
    "time"
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        select {
        case <-ctx.Done():
            log.Printf("context cancelled")
        case <-time.After(time.Minute):
            w.Write([]byte("OK"))
            log.Printf("request completed. path=%s", r.URL.Path)
        }
    })
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

Running this code locally, a curl request sent to http://localhost:8080 and then cancelled with ctrl-c will show up in the logs as "context cancelled". The same request with the service deployed in cloud run and cancelled will show up as a successful request after 1 minute in the logs.

Upvotes: 5

Views: 705

Answers (2)

Pylinux
Pylinux

Reputation: 11816

If you use HTTP2 when you deploy the cloud run container ctx.Done() works:

    gcloud run deploy <SERVICE_NAME>\
        --project <GPC_PROJECT_ID>\
        --allow-unauthenticated\
        --use-http2 \
        -q\
        --region europe-west1\
        --platform managed\
        --image <CONTAINER_NAME>

Full example: https://github.com/karl-gustav/minimal-sse/blob/main/main.go

Upvotes: 0

ahmet alp balkan
ahmet alp balkan

Reputation: 45224

I don't think Cloud Run offers such a guarantee today.

I am guessing this is because of an implementation detail. The external traffic to a Run service does not directly go to the container, but rather passes through one or more load balancers and proxies. These LBs/proxies may not be properly propagating the client disconnects (or simply buffering requests/responses). This would result in the behavior you’re seeing.

I will go ahead and file an internal feature request about it. Thanks for bringing it up.

Upvotes: 5

Related Questions