forked from appsmithorg/appsmith
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Include version in all requests (appsmithorg#37551)
We're adding `x-appsmith-version` to every request from the client. If server sees a request with a `x-appsmith-version` that doesn't match its own, it rejects. If the server sees a request _without_ any `x-appsmith-version` header, we don't reject it... for now. On the client, when server responds with the "version mismatch" error, we trigger the "There's a new version, please refresh" toast UI flow. This is a step towards removing our dependency on websockets and client—RTS connection. ## Automation /test sanity ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/12029721517> > Commit: c4321f7 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12029721517&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity` > Spec: > <hr>Tue, 26 Nov 2024 12:28:32 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes - **New Features** - Introduced a custom header for API requests to include application version. - Added specific error handling for 400 Bad Request errors, enhancing user feedback on version mismatches. - **Improvements** - Enhanced error handling for version mismatches, providing clearer error messages. - Simplified version update handling, focusing on logging and user prompts without state management. - Improved default handling for application version configuration to prevent undefined values. - **Chores** - Removed outdated version state management functions to streamline code. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Pawan Kumar <[email protected]>
- Loading branch information
Showing
10 changed files
with
74 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { InternalAxiosRequestConfig } from "axios"; | ||
|
||
export const addVersionHeader = ( | ||
config: InternalAxiosRequestConfig, | ||
options: { version: string }, | ||
) => { | ||
const { version } = options; | ||
|
||
config.headers = config.headers || {}; | ||
config.headers["X-Appsmith-Version"] = version; | ||
|
||
return config; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
src/api/interceptors/response/failureHandlers/handleBadRequestError.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type { AxiosError } from "axios"; | ||
import type { ApiResponse } from "../../../ApiResponses"; | ||
import { handleVersionMismatch } from "sagas/WebsocketSagas/versionUpdatePrompt"; | ||
import { getAppsmithConfigs } from "ee/configs"; | ||
import { SERVER_ERROR_CODES } from "ee/constants/ApiConstants"; | ||
|
||
export const handleBadRequestError = async (error: AxiosError<ApiResponse>) => { | ||
const errorCode = error?.response?.data?.responseMeta.error?.code; | ||
|
||
if ( | ||
error?.response?.status === 400 && | ||
SERVER_ERROR_CODES.VERSION_MISMATCH.includes("" + errorCode) | ||
) { | ||
const responseData = error?.response?.data; | ||
const message = responseData?.responseMeta.error?.message; | ||
const serverVersion = (responseData?.data as { serverVersion: string }) | ||
.serverVersion; | ||
|
||
handleVersionMismatch(getAppsmithConfigs().appVersion.id, serverVersion); | ||
|
||
return Promise.reject({ | ||
...error, | ||
clientDefinedError: true, | ||
statusCode: errorCode, | ||
message, | ||
}); | ||
} | ||
|
||
return null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,37 @@ | ||
// Check if user is updating the app when toast is shown | ||
// Check how many times does the user see a toast before updating | ||
|
||
import { toast } from "@appsmith/ads"; | ||
import { | ||
createMessage, | ||
INFO_VERSION_MISMATCH_FOUND_RELOAD_REQUEST, | ||
} from "ee/constants/messages"; | ||
import type { AppVersionData } from "ee/configs/types"; | ||
import { | ||
getVersionUpdateState, | ||
removeVersionUpdateState, | ||
setVersionUpdateState, | ||
} from "utils/storage"; | ||
import AnalyticsUtil from "ee/utils/AnalyticsUtil"; | ||
|
||
enum UpdateStateEvent { | ||
PROMPT_SHOWN = "PROMPT_SHOWN", | ||
UPDATE_REQUESTED = "UPDATE_REQUESTED", | ||
function handleUpdateRequested(fromVersion: string, toVersion: string) { | ||
AnalyticsUtil.logEvent("VERSION_UPDATE_REQUESTED", { | ||
fromVersion, | ||
toVersion, | ||
}); | ||
// Reload to fetch the latest app version | ||
location.reload(); | ||
} | ||
|
||
export interface VersionUpdateState { | ||
currentVersion: string; | ||
upgradeVersion: string; | ||
timesShown: number; | ||
event: UpdateStateEvent; | ||
} | ||
export async function handleVersionMismatch( | ||
currentVersion: string, | ||
serverVersion: string, | ||
) { | ||
// If no version is set, ignore | ||
if (!currentVersion) return; | ||
|
||
let timesShown = 0; | ||
AnalyticsUtil.logEvent("VERSION_UPDATE_SHOWN", { | ||
fromVersion: currentVersion, | ||
toVersion: serverVersion, | ||
}); | ||
|
||
function showPrompt(newUpdateState: VersionUpdateState) { | ||
toast.show(createMessage(INFO_VERSION_MISMATCH_FOUND_RELOAD_REQUEST), { | ||
kind: "info", | ||
autoClose: false, | ||
action: { | ||
text: "refresh", | ||
effect: () => handleUpdateRequested(newUpdateState), | ||
effect: () => handleUpdateRequested(currentVersion, serverVersion), | ||
}, | ||
}); | ||
} | ||
|
||
function handleUpdateRequested(newUpdateState: VersionUpdateState) { | ||
// store version update with timesShown counter | ||
setVersionUpdateState({ | ||
...newUpdateState, | ||
event: UpdateStateEvent.UPDATE_REQUESTED, | ||
}).then(() => { | ||
AnalyticsUtil.logEvent("VERSION_UPDATE_REQUESTED", { | ||
fromVersion: newUpdateState.currentVersion, | ||
toVersion: newUpdateState.upgradeVersion, | ||
timesShown, | ||
}); | ||
// Reload to fetch the latest app version | ||
location.reload(); | ||
}); | ||
} | ||
|
||
export async function handleVersionUpdate( | ||
currentVersionData: AppVersionData, | ||
serverVersion: string, | ||
) { | ||
const { edition, id: currentVersion } = currentVersionData; | ||
|
||
// If no version is set, ignore | ||
if (!currentVersion) return; | ||
|
||
const versionState: VersionUpdateState | null = await getVersionUpdateState(); | ||
|
||
if (currentVersion === serverVersion) { | ||
if (versionState) { | ||
AnalyticsUtil.logEvent("VERSION_UPDATE_SUCCESS", { | ||
fromVersion: versionState.currentVersion, | ||
toVersion: versionState.upgradeVersion, | ||
edition, | ||
}); | ||
await removeVersionUpdateState(); | ||
} | ||
} | ||
|
||
if (currentVersion !== serverVersion) { | ||
if (versionState) { | ||
timesShown = versionState.timesShown; | ||
|
||
if ( | ||
currentVersion === versionState.currentVersion && | ||
versionState.event === UpdateStateEvent.UPDATE_REQUESTED | ||
) { | ||
AnalyticsUtil.logEvent("VERSION_UPDATED_FAILED", { | ||
fromVersion: versionState.currentVersion, | ||
toVersion: versionState.upgradeVersion, | ||
edition, | ||
}); | ||
} | ||
} | ||
|
||
const newUpdateState: VersionUpdateState = { | ||
currentVersion, | ||
upgradeVersion: serverVersion, | ||
// Increment the timesShown counter | ||
timesShown: timesShown + 1, | ||
event: UpdateStateEvent.PROMPT_SHOWN, | ||
}; | ||
|
||
AnalyticsUtil.logEvent("VERSION_UPDATE_SHOWN", { | ||
fromVersion: currentVersion, | ||
toVersion: serverVersion, | ||
timesShown, | ||
}); | ||
showPrompt(newUpdateState); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters