From 4f58ddee03509a4c46af160e5824cba80d4c950a Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Thu, 13 Apr 2023 12:39:13 +0200 Subject: [PATCH] feat(medusa,utils): add server level configurable http compression (#3785) * feat(medusa,utils): add server level configurable http compression * chore: remove unwanted middleware * chore: add a log for running compression * chore: change package position * chore: reposition options * chore: change equality --- .changeset/loud-wombats-smoke.md | 6 +++ integration-tests/api/medusa-config.js | 4 ++ packages/medusa/package.json | 1 + packages/medusa/src/api/index.js | 12 ++++++ .../medusa/src/utils/api/http-compression.ts | 39 +++++++++++++++++ packages/medusa/src/utils/api/index.ts | 1 + packages/types/src/common/config-module.ts | 43 ++++++++++++------- yarn.lock | 1 + 8 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 .changeset/loud-wombats-smoke.md create mode 100644 packages/medusa/src/utils/api/http-compression.ts create mode 100644 packages/medusa/src/utils/api/index.ts diff --git a/.changeset/loud-wombats-smoke.md b/.changeset/loud-wombats-smoke.md new file mode 100644 index 0000000000..a6b9a7a231 --- /dev/null +++ b/.changeset/loud-wombats-smoke.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +"@medusajs/types": patch +--- + +feat(medusa,utils): add server level configurable http compression diff --git a/integration-tests/api/medusa-config.js b/integration-tests/api/medusa-config.js index ef65d04db4..744822ab9a 100644 --- a/integration-tests/api/medusa-config.js +++ b/integration-tests/api/medusa-config.js @@ -5,6 +5,7 @@ const DB_NAME = process.env.DB_TEMP_NAME const redisUrl = process.env.REDIS_URL || "redis://localhost:6379" const cacheTTL = process.env.CACHE_TTL || 15 +const enableResponseCompression = process.env.ENABLE_RESPONSE_COMPRESSION || true module.exports = { plugins: [], @@ -14,6 +15,9 @@ module.exports = { database_type: "postgres", jwt_secret: "test", cookie_secret: "test", + http_compression: { + enabled: enableResponseCompression + } }, modules: { cacheService: { diff --git a/packages/medusa/package.json b/packages/medusa/package.json index a2d9d33249..01b44598c5 100644 --- a/packages/medusa/package.json +++ b/packages/medusa/package.json @@ -55,6 +55,7 @@ "chokidar": "^3.4.2", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", + "compression": "^1.7.4", "connect-redis": "^5.0.0", "cookie-parser": "^1.4.6", "core-js": "^3.6.5", diff --git a/packages/medusa/src/api/index.js b/packages/medusa/src/api/index.js index 35268d3ff2..d9b60fbb71 100644 --- a/packages/medusa/src/api/index.js +++ b/packages/medusa/src/api/index.js @@ -1,11 +1,23 @@ import { Router } from "express" import errorHandler from "./middlewares/error-handler" +import compression from "compression" import admin from "./routes/admin" import store from "./routes/store" +import { shouldCompressResponse, compressionOptions } from "../utils/api" // guaranteed to get dependencies export default (container, config) => { const app = Router() + const httpCompressionOptions = compressionOptions(config) + + if (httpCompressionOptions.enabled) { + app.use( + compression({ + filter: shouldCompressResponse, + ...httpCompressionOptions, + }) + ) + } admin(app, container, config) store(app, container, config) diff --git a/packages/medusa/src/utils/api/http-compression.ts b/packages/medusa/src/utils/api/http-compression.ts new file mode 100644 index 0000000000..abd5d501ff --- /dev/null +++ b/packages/medusa/src/utils/api/http-compression.ts @@ -0,0 +1,39 @@ +import { Request, Response, NextFunction } from "express" +import compression from "compression" +import { Logger } from "@medusajs/types" +import { + ProjectConfigOptions, + HttpCompressionOptions, +} from "@medusajs/types" + +export function shouldCompressResponse(req: Request, res: Response) { + const logger: Logger = req.scope.resolve("logger") + const { projectConfig } = req.scope.resolve("configModule") + const { enabled } = compressionOptions(projectConfig) + + if (!enabled) { + return false + } + + if (req.headers["x-no-compression"]) { + // don't compress responses with this request header + return false + } + + // fallback to standard filter function + return compression.filter(req, res) +} + +export function compressionOptions( + config: ProjectConfigOptions +): HttpCompressionOptions { + const responseCompressionOptions = config.http_compression ?? {} + + responseCompressionOptions.enabled = responseCompressionOptions.enabled ?? false + responseCompressionOptions.level = responseCompressionOptions.level ?? 6 + responseCompressionOptions.memLevel = responseCompressionOptions.memLevel ?? 8 + responseCompressionOptions.threshold = + responseCompressionOptions.threshold ?? 1024 + + return responseCompressionOptions +} diff --git a/packages/medusa/src/utils/api/index.ts b/packages/medusa/src/utils/api/index.ts new file mode 100644 index 0000000000..6cb9b8e8e3 --- /dev/null +++ b/packages/medusa/src/utils/api/index.ts @@ -0,0 +1 @@ +export * from "./http-compression" diff --git a/packages/types/src/common/config-module.ts b/packages/types/src/common/config-module.ts index c155d83794..b95af147ef 100644 --- a/packages/types/src/common/config-module.ts +++ b/packages/types/src/common/config-module.ts @@ -13,27 +13,38 @@ type SessionOptions = { ttl?: number } -export type ConfigModule = { - projectConfig: { - redis_url?: string +export type HttpCompressionOptions = { + enabled?: boolean + level?: number + memLevel?: number + threshold?: number | string +} - session_options?: SessionOptions +export type ProjectConfigOptions = { + redis_url?: string - jwt_secret?: string - cookie_secret?: string + session_options?: SessionOptions - database_url?: string - database_type: string - database_database?: string - database_schema?: string - database_logging: LoggerOptions + jwt_secret?: string + cookie_secret?: string - database_extra?: Record & { - ssl: { rejectUnauthorized: false } - } - store_cors?: string - admin_cors?: string + database_url?: string + database_type: string + database_database?: string + database_schema?: string + database_logging: LoggerOptions + + http_compression?: HttpCompressionOptions + + database_extra?: Record & { + ssl: { rejectUnauthorized: false } } + store_cors?: string + admin_cors?: string +} + +export type ConfigModule = { + projectConfig: ProjectConfigOptions featureFlags: Record modules?: Record< string, diff --git a/yarn.lock b/yarn.lock index efdef0c284..b9c46c1d8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6124,6 +6124,7 @@ __metadata: chokidar: ^3.4.2 class-transformer: ^0.5.1 class-validator: ^0.13.2 + compression: ^1.7.4 connect-redis: ^5.0.0 cookie-parser: ^1.4.6 core-js: ^3.6.5