fix(server): validate Content-Type by parsed media type instead of substring match (#2441)
This commit is contained in:
parent
7015d2129b
commit
561c6d8345
2 changed files with 452 additions and 20 deletions
|
|
@ -10,6 +10,7 @@ import {
|
|||
isJSONRPCResultResponse,
|
||||
isModernProtocolVersion,
|
||||
JSONRPCMessageSchema,
|
||||
mediaTypeEssence,
|
||||
normalizeHeaders,
|
||||
PROTOCOL_VERSION_META_KEY,
|
||||
SdkError,
|
||||
|
|
@ -1080,11 +1081,12 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
|
||||
const hasRequests = messages.some(msg => 'method' in msg && 'id' in msg && msg.id !== undefined);
|
||||
|
||||
// Check the response type
|
||||
// Check the response type (parsed media type — see mediaTypeEssence)
|
||||
const contentType = response.headers.get('content-type');
|
||||
const responseMediaType = mediaTypeEssence(contentType);
|
||||
|
||||
if (hasRequests) {
|
||||
if (contentType?.includes('text/event-stream')) {
|
||||
if (responseMediaType === 'text/event-stream') {
|
||||
// Handle SSE stream responses for requests
|
||||
// We use the same handler as standalone streams, which now supports
|
||||
// reconnection with the last event ID
|
||||
|
|
@ -1097,7 +1099,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
},
|
||||
false
|
||||
);
|
||||
} else if (contentType?.includes('application/json')) {
|
||||
} else if (responseMediaType === 'application/json') {
|
||||
// For non-streaming servers, we might get direct JSON responses
|
||||
const data = await response.json();
|
||||
const responseMessages = Array.isArray(data)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { FetchLike } from '@modelcontextprotocol/core-internal';
|
||||
import { isJsonContentType } from '@modelcontextprotocol/core-internal';
|
||||
import type { Mocked, MockedFunction, MockInstance } from 'vitest';
|
||||
|
||||
import type { OAuthClientProvider } from '../../src/client/auth';
|
||||
|
|
@ -1016,7 +1017,7 @@ describe('createMiddleware', () => {
|
|||
const transformMiddleware = createMiddleware(async (next, input, init) => {
|
||||
const response = await next(input, init);
|
||||
|
||||
if (response.headers.get('content-type')?.includes('application/json')) {
|
||||
if (isJsonContentType(response.headers.get('content-type'))) {
|
||||
const data = (await response.json()) as Record<string, unknown>;
|
||||
const transformed = { ...data, timestamp: 123_456_789 };
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue