From 91b353422b6d26d3ffd893cc57174cc4267372b1 Mon Sep 17 00:00:00 2001 From: Jamie MacLeod Date: Wed, 28 Feb 2024 12:09:52 +0000 Subject: [PATCH] Don't set application/json content-type on formData bodies --- CONTRIBUTING.md | 13 +++++++++---- e2e-tests/testdata/echo_client/js/client.js | 13 +++++++++---- e2e-tests/testdata/echo_client/ts/client.ts | 10 +++++++--- internal/clientgen/javascript.go | 13 +++++++++---- .../testdata/expected_baseauth_javascript.js | 13 +++++++++---- .../testdata/expected_baseauth_typescript.ts | 10 +++++++--- internal/clientgen/testdata/expected_javascript.js | 13 +++++++++---- .../testdata/expected_noauth_javascript.js | 13 +++++++++---- .../testdata/expected_noauth_typescript.ts | 10 +++++++--- internal/clientgen/testdata/expected_typescript.ts | 10 +++++++--- internal/clientgen/typescript.go | 10 +++++++--- 11 files changed, 89 insertions(+), 39 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1304d55a1c..f6d61b01a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,11 +59,16 @@ Note that when you run commands like `encore run` must use the same `encore` bin ### Testing the Daemon run logic The codegen tests in the `internal/clientgen/client_test.go` file uses many auto generated files from the -`e2e-tests/testdata` directory. To generate the client files and other test files, run `go test -golden-update` from -the `e2e-tests` directory. This will generate client files for all the supported client generation languages. +`e2e-tests/testdata` directory. To generate the client files and other test files, run: -Running `go test ./internal/clientgen` will now work and use the most recent client generated files. If -you change the client or content of the `testdata` folder, you may need to regenerate the client files again. +```bash +go test ./internal/clientgen -golden-update +go test ./e2e-tests -golden-update +``` + +This will generate client files for all the supported client generation languages. + +Running `go test ./internal/clientgen` will now work and use the most recent client generated files. If you change the client or content of the `testdata` folder, you may need to regenerate the client files again. ## Architecture diff --git a/e2e-tests/testdata/echo_client/js/client.js b/e2e-tests/testdata/echo_client/js/client.js index ced77695b7..5c8423f6b3 100644 --- a/e2e-tests/testdata/echo_client/js/client.js +++ b/e2e-tests/testdata/echo_client/js/client.js @@ -557,10 +557,8 @@ const boundFetch = fetch.bind(this) class BaseClient { constructor(baseURL, options) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } - + this.headers = {} + // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests if (typeof window === "undefined") { @@ -601,6 +599,13 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // Otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + + // If authorization data generator is present, call it and add the returned data to the request let authData if (this.authGenerator) { diff --git a/e2e-tests/testdata/echo_client/ts/client.ts b/e2e-tests/testdata/echo_client/ts/client.ts index 4bd92a2da5..db5548b7ef 100644 --- a/e2e-tests/testdata/echo_client/ts/client.ts +++ b/e2e-tests/testdata/echo_client/ts/client.ts @@ -799,9 +799,7 @@ class BaseClient { constructor(baseURL: string, options: ClientOptions) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } + this.headers = {} // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests @@ -843,6 +841,12 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + // If authorization data generator is present, call it and add the returned data to the request let authData: echo.AuthParams | undefined if (this.authGenerator) { diff --git a/internal/clientgen/javascript.go b/internal/clientgen/javascript.go index e994f0494e..1c1b20fc98 100644 --- a/internal/clientgen/javascript.go +++ b/internal/clientgen/javascript.go @@ -475,10 +475,8 @@ class BaseClient {`) js.WriteString(` constructor(baseURL, options) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } - + this.headers = {} + // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests if (typeof window === "undefined") { @@ -524,6 +522,13 @@ class BaseClient {`) // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + + // If the body is not FormData, set the Content-Type to application/json + // Otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + `) w := js.newIdentWriter(2) diff --git a/internal/clientgen/testdata/expected_baseauth_javascript.js b/internal/clientgen/testdata/expected_baseauth_javascript.js index cdae6b555b..dfb447e1d3 100644 --- a/internal/clientgen/testdata/expected_baseauth_javascript.js +++ b/internal/clientgen/testdata/expected_baseauth_javascript.js @@ -102,10 +102,8 @@ const boundFetch = fetch.bind(this) class BaseClient { constructor(baseURL, options) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } - + this.headers = {} + // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests if (typeof window === "undefined") { @@ -146,6 +144,13 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // Otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + + // If authorization data generator is present, call it and add the returned data to the request let authData if (this.authGenerator) { diff --git a/internal/clientgen/testdata/expected_baseauth_typescript.ts b/internal/clientgen/testdata/expected_baseauth_typescript.ts index 5b88a9d8bc..f3c5298970 100644 --- a/internal/clientgen/testdata/expected_baseauth_typescript.ts +++ b/internal/clientgen/testdata/expected_baseauth_typescript.ts @@ -167,9 +167,7 @@ class BaseClient { constructor(baseURL: string, options: ClientOptions) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } + this.headers = {} // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests @@ -211,6 +209,12 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + // If authorization data generator is present, call it and add the returned data to the request let authData: string | undefined if (this.authGenerator) { diff --git a/internal/clientgen/testdata/expected_javascript.js b/internal/clientgen/testdata/expected_javascript.js index ecbd7a467e..a63d28843e 100644 --- a/internal/clientgen/testdata/expected_javascript.js +++ b/internal/clientgen/testdata/expected_javascript.js @@ -270,10 +270,8 @@ const boundFetch = fetch.bind(this) class BaseClient { constructor(baseURL, options) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } - + this.headers = {} + // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests if (typeof window === "undefined") { @@ -314,6 +312,13 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // Otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + + // If authorization data generator is present, call it and add the returned data to the request let authData if (this.authGenerator) { diff --git a/internal/clientgen/testdata/expected_noauth_javascript.js b/internal/clientgen/testdata/expected_noauth_javascript.js index a86f239b58..59c365ab13 100644 --- a/internal/clientgen/testdata/expected_noauth_javascript.js +++ b/internal/clientgen/testdata/expected_noauth_javascript.js @@ -86,10 +86,8 @@ const boundFetch = fetch.bind(this) class BaseClient { constructor(baseURL, options) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } - + this.headers = {} + // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests if (typeof window === "undefined") { @@ -119,6 +117,13 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // Otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + + // Make the actual request const queryString = query ? '?' + encodeQuery(query) : '' const response = await this.fetcher(this.baseURL+path+queryString, init) diff --git a/internal/clientgen/testdata/expected_noauth_typescript.ts b/internal/clientgen/testdata/expected_noauth_typescript.ts index 979e0cbe0b..86704bf8f1 100644 --- a/internal/clientgen/testdata/expected_noauth_typescript.ts +++ b/internal/clientgen/testdata/expected_noauth_typescript.ts @@ -129,9 +129,7 @@ class BaseClient { constructor(baseURL: string, options: ClientOptions) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } + this.headers = {} // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests @@ -162,6 +160,12 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + // Make the actual request const queryString = query ? '?' + encodeQuery(query) : '' const response = await this.fetcher(this.baseURL+path+queryString, init) diff --git a/internal/clientgen/testdata/expected_typescript.ts b/internal/clientgen/testdata/expected_typescript.ts index 093d0c1af2..5730586122 100644 --- a/internal/clientgen/testdata/expected_typescript.ts +++ b/internal/clientgen/testdata/expected_typescript.ts @@ -459,9 +459,7 @@ class BaseClient { constructor(baseURL: string, options: ClientOptions) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } + this.headers = {} // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests @@ -503,6 +501,12 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + // If the body is not FormData, set the Content-Type to application/json + // otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } + // If authorization data generator is present, call it and add the returned data to the request let authData: authentication.AuthData | undefined if (this.authGenerator) { diff --git a/internal/clientgen/typescript.go b/internal/clientgen/typescript.go index 1aee49904e..9da1e454e8 100644 --- a/internal/clientgen/typescript.go +++ b/internal/clientgen/typescript.go @@ -702,9 +702,7 @@ class BaseClient { constructor(baseURL: string, options: ClientOptions) { this.baseURL = baseURL - this.headers = { - "Content-Type": "application/json", - } + this.headers = {} // Add User-Agent header if the script is running in the server // because browsers do not allow setting User-Agent headers to requests @@ -751,6 +749,12 @@ class BaseClient { // Merge our headers with any predefined headers init.headers = {...this.headers, ...init.headers, ...headers} + + // If the body is not FormData, set the Content-Type to application/json + // otherwise allow fetch to set the Content-Type including the boundary + if (!(body instanceof FormData)) { + init.headers['Content-Type'] = 'application/json'; + } `) w := ts.newIdentWriter(2)