mcp: improve error messages from Wait for streamable clients
Previously, the error message received from ClientSession.Wait would only report the closeErr, which would often be nil even if the client transport was broken. Wait should return the reason the session terminated, if abnormal. I'm not sure of the exact semantics of this, but surely returning nil is less useful than returning a meaningful non-nil error. We can refine our handling of errors once we have more feedback. Also add a test for client termination on HTTP server shutdown, described in #265. This should work as long as (1) the session is stateful (with a hanging GET), or (2) the session is stateless but the client has a keepalive ping. Also: don't send DELETE if the session was terminated with 404; +test. Fixes #265
This commit is contained in:
parent
b1c75f04d8
commit
728e0e3ac9
1 changed files with 202 additions and 21 deletions
|
|
@ -29,7 +29,7 @@ type streamableRequestKey struct {
|
|||
type header map[string]string
|
||||
|
||||
type streamableResponse struct {
|
||||
header header
|
||||
header header // response headers
|
||||
status int // or http.StatusOK
|
||||
body string // or ""
|
||||
optional bool // if set, request need not be sent
|
||||
|
|
@ -187,6 +187,56 @@ func TestStreamableClientTransportLifecycle(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestStreamableClientRedundantDelete(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// The lifecycle test verifies various behavior of the streamable client
|
||||
// initialization:
|
||||
// - check that it can handle application/json responses
|
||||
// - check that it sends the negotiated protocol version
|
||||
fake := &fakeStreamableServer{
|
||||
t: t,
|
||||
responses: fakeResponses{
|
||||
{"POST", "", methodInitialize}: {
|
||||
header: header{
|
||||
"Content-Type": "application/json",
|
||||
sessionIDHeader: "123",
|
||||
},
|
||||
body: jsonBody(t, initResp),
|
||||
},
|
||||
{"POST", "123", notificationInitialized}: {
|
||||
status: http.StatusAccepted,
|
||||
wantProtocolVersion: latestProtocolVersion,
|
||||
},
|
||||
{"GET", "123", ""}: {
|
||||
status: http.StatusMethodNotAllowed,
|
||||
optional: true,
|
||||
},
|
||||
{"POST", "123", methodListTools}: {
|
||||
status: http.StatusNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
httpServer := httptest.NewServer(fake)
|
||||
defer httpServer.Close()
|
||||
|
||||
transport := &StreamableClientTransport{Endpoint: httpServer.URL}
|
||||
client := NewClient(testImpl, nil)
|
||||
session, err := client.Connect(ctx, transport, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("client.Connect() failed: %v", err)
|
||||
}
|
||||
_, err = session.ListTools(ctx, nil)
|
||||
if err == nil {
|
||||
t.Errorf("Listing tools: got nil error, want non-nil")
|
||||
}
|
||||
_ = session.Wait() // must not hang
|
||||
if missing := fake.missingRequests(); len(missing) > 0 {
|
||||
t.Errorf("did not receive expected requests: %v", missing)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStreamableClientGETHandling(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue