From f5a2c7fc5acf496621aeb5ed167bd71eaa991c2e Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 26 Mar 2024 11:41:12 -0700 Subject: [PATCH] Revert "feat(fetch): multiple fields with the same name in post data (#30104)" This reverts commit a849ea97411714d50cda0a0d5c156decbdc2d814. --- docs/src/api/class-apirequestcontext.md | 2 +- docs/src/api/params.md | 5 +- packages/playwright-core/src/client/fetch.ts | 27 ++-- packages/playwright-core/types/types.d.ts | 140 ++----------------- tests/library/browsercontext-fetch.spec.ts | 34 ----- 5 files changed, 26 insertions(+), 182 deletions(-) diff --git a/docs/src/api/class-apirequestcontext.md b/docs/src/api/class-apirequestcontext.md index addf5baacb..dacd5dd343 100644 --- a/docs/src/api/class-apirequestcontext.md +++ b/docs/src/api/class-apirequestcontext.md @@ -566,7 +566,7 @@ api_request_context.post("https://example.com/api/createBook", data=data) ```csharp var data = new Dictionary() { - { "firstName", "John" }, + { "firstNam", "John" }, { "lastName", "Doe" } }; await request.PostAsync("https://example.com/api/createBook", new() { DataObject = data }); diff --git a/docs/src/api/params.md b/docs/src/api/params.md index e64c77f1dc..e3b2894c3c 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -405,7 +405,7 @@ An instance of [FormData] can be created via [`method: APIRequestContext.createF ## js-python-fetch-option-multipart * langs: js, python -- `multipart` <[Object]<[string], [string]|[float]|[boolean]|[ReadStream]|[Object]|Array<[string]|[float]|[boolean]|[ReadStream]|[Object]>>> +- `multipart` <[Object]<[string], [string]|[float]|[boolean]|[ReadStream]|[Object]>> - `name` <[string]> File name - `mimeType` <[string]> File type - `buffer` <[Buffer]> File content @@ -413,8 +413,7 @@ An instance of [FormData] can be created via [`method: APIRequestContext.createF Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless explicitly provided. File values can be passed either as [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) -or as file-like object containing file name, mime-type and its content. If the value is an array, each element -will be sent as a separate field with the same name. +or as file-like object containing file name, mime-type and its content. ## csharp-fetch-option-multipart * langs: csharp diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts index f959b47fb0..8dc3caa570 100644 --- a/packages/playwright-core/src/client/fetch.ts +++ b/packages/playwright-core/src/client/fetch.ts @@ -36,7 +36,7 @@ export type FetchOptions = { headers?: Headers, data?: string | Buffer | Serializable, form?: { [key: string]: string|number|boolean; }; - multipart?: { [key: string]: string|number|boolean|fs.ReadStream|FilePayload|Array; }; + multipart?: { [key: string]: string|number|boolean|fs.ReadStream|FilePayload; }; timeout?: number, failOnStatusCode?: boolean, ignoreHTTPSErrors?: boolean, @@ -188,11 +188,15 @@ export class APIRequestContext extends ChannelOwner { - if (isFilePayload(value)) { - const payload = value as FilePayload; - if (!Buffer.isBuffer(payload.buffer)) - throw new Error(`Unexpected buffer type of 'data.${name}'`); - return { name, file: filePayloadToJson(payload) }; - } else if (value instanceof fs.ReadStream) { - return { name, file: await readStreamToJson(value as fs.ReadStream) }; - } else { - return { name, value: String(value) }; - } -} - function isJsonParsable(value: any) { if (typeof value !== 'string') return false; diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index fecf250801..b0071ffd02 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -15683,8 +15683,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -15701,22 +15700,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. @@ -15833,8 +15817,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -15851,22 +15834,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. @@ -15943,8 +15911,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -15961,22 +15928,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. @@ -16039,8 +15991,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -16057,22 +16008,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. @@ -16135,8 +16071,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -16153,22 +16088,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. @@ -16282,8 +16202,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -16300,22 +16219,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. @@ -16378,8 +16282,7 @@ export interface APIRequestContext { * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless * explicitly provided. File values can be passed either as * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file - * name, mime-type and its content. If the value is an array, each element will be sent as a separate field with the - * same name. + * name, mime-type and its content. */ multipart?: { [key: string]: string|number|boolean|ReadStream|{ /** @@ -16396,22 +16299,7 @@ export interface APIRequestContext { * File content */ buffer: Buffer; - }|Array; }; + }; }; /** * Query parameters to be sent with the URL. diff --git a/tests/library/browsercontext-fetch.spec.ts b/tests/library/browsercontext-fetch.spec.ts index 7129803b2e..bb0bb15362 100644 --- a/tests/library/browsercontext-fetch.spec.ts +++ b/tests/library/browsercontext-fetch.spec.ts @@ -983,40 +983,6 @@ it('should support multipart/form-data and keep the order', async function({ con expect(response.status()).toBe(200); }); -it('should support repeating names in multipart/form-data', async function({ context, server }) { - it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/28070' }); - const postBodyPromise = new Promise(resolve => { - server.setRoute('/empty.html', async (req, res) => { - resolve((await req.postBody).toString('utf-8')); - res.writeHead(200, { - 'content-type': 'text/plain', - }); - res.end('OK.'); - }); - }); - const [postBody, response] = await Promise.all([ - postBodyPromise, - context.request.post(server.EMPTY_PAGE, { - multipart: { - firstName: 'John', - lastName: 'Doe', - file: [{ - name: 'f1.js', - mimeType: 'text/javascript', - buffer: Buffer.from('var x = 10;\r\n;console.log(x);') - }, { - name: 'f2.txt', - mimeType: 'text/plain', - buffer: Buffer.from('hello') - }] - } - }) - ]); - expect(postBody).toContain(`content-disposition: form-data; name="file"; filename="f1.js"\r\ncontent-type: text/javascript\r\n\r\nvar x = 10;\r\n;console.log(x);`); - expect(postBody).toContain(`content-disposition: form-data; name="file"; filename="f2.txt"\r\ncontent-type: text/plain\r\n\r\nhello`); - expect(response.status()).toBe(200); -}); - it('should serialize data to json regardless of content-type', async function({ context, server }) { const data = { firstName: 'John',