mirror of
https://github.com/umami-software/umami.git
synced 2025-12-06 01:18:00 +01:00
Merge pull request #3363 from Maxime-J/docker-rewrites
Replace Docker middleware
This commit is contained in:
commit
5cfaffa3ff
4 changed files with 86 additions and 73 deletions
22
Dockerfile
22
Dockerfile
|
|
@ -13,15 +13,14 @@ FROM node:22-alpine AS builder
|
|||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
COPY docker/middleware.js ./src
|
||||
|
||||
ARG DATABASE_TYPE
|
||||
ARG BASE_PATH
|
||||
|
||||
ENV DATABASE_TYPE $DATABASE_TYPE
|
||||
ENV BASE_PATH $BASE_PATH
|
||||
ENV DATABASE_TYPE=$DATABASE_TYPE
|
||||
ENV BASE_PATH=$BASE_PATH
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
RUN yarn build-docker
|
||||
|
||||
|
|
@ -31,9 +30,9 @@ WORKDIR /app
|
|||
|
||||
ARG NODE_OPTIONS
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
ENV NODE_OPTIONS $NODE_OPTIONS
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV NODE_OPTIONS=$NODE_OPTIONS
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
|
@ -42,10 +41,7 @@ RUN set -x \
|
|||
&& apk add --no-cache curl \
|
||||
&& yarn add npm-run-all dotenv semver prisma@6.1.0
|
||||
|
||||
# You only need to copy next.config.js if you are NOT using the default configuration
|
||||
COPY --from=builder /app/next.config.js .
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||
COPY --from=builder /app/package.json ./package.json
|
||||
COPY --from=builder /app/prisma ./prisma
|
||||
COPY --from=builder /app/scripts ./scripts
|
||||
|
||||
|
|
@ -54,11 +50,13 @@ COPY --from=builder /app/scripts ./scripts
|
|||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
RUN mv ./.next/routes-manifest.json ./.next/routes-manifest-orig.json
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV HOSTNAME 0.0.0.0
|
||||
ENV PORT 3000
|
||||
ENV HOSTNAME=0.0.0.0
|
||||
ENV PORT=3000
|
||||
|
||||
CMD ["yarn", "start-docker"]
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const config = {
|
||||
matcher: '/:path*',
|
||||
};
|
||||
|
||||
const apiHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, DELETE, POST, PUT',
|
||||
'Access-Control-Max-Age': process.env.CORS_MAX_AGE || '86400',
|
||||
'Cache-Control': 'no-cache',
|
||||
};
|
||||
|
||||
const trackerHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Cache-Control': 'public, max-age=86400, must-revalidate',
|
||||
};
|
||||
|
||||
function customCollectEndpoint(req) {
|
||||
const collectEndpoint = process.env.COLLECT_API_ENDPOINT;
|
||||
|
||||
if (collectEndpoint) {
|
||||
const url = req.nextUrl.clone();
|
||||
const { pathname } = url;
|
||||
|
||||
if (pathname.endsWith(collectEndpoint)) {
|
||||
url.pathname = '/api/send';
|
||||
return NextResponse.rewrite(url, { headers: apiHeaders });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function customScriptName(req) {
|
||||
const scriptName = process.env.TRACKER_SCRIPT_NAME;
|
||||
|
||||
if (scriptName) {
|
||||
const url = req.nextUrl.clone();
|
||||
const { pathname } = url;
|
||||
const names = scriptName.split(',').map(name => name.trim().replace(/^\/+/, ''));
|
||||
|
||||
if (names.find(name => pathname.endsWith(name))) {
|
||||
url.pathname = '/script.js';
|
||||
return NextResponse.rewrite(url, { headers: trackerHeaders });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default function middleware(req) {
|
||||
const fns = [customCollectEndpoint, customScriptName];
|
||||
|
||||
for (const fn of fns) {
|
||||
const res = fn(req);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
"build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app",
|
||||
"start": "next start",
|
||||
"build-docker": "npm-run-all build-db build-tracker build-geo build-app",
|
||||
"start-docker": "npm-run-all check-db update-tracker start-server",
|
||||
"start-docker": "npm-run-all check-db update-tracker set-routes-manifest start-server",
|
||||
"start-env": "node scripts/start-env.js",
|
||||
"start-server": "node server.js",
|
||||
"build-app": "next build",
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
"build-geo": "node scripts/build-geo.js",
|
||||
"build-db-schema": "prisma db pull",
|
||||
"build-db-client": "prisma generate",
|
||||
"set-routes-manifest": "node scripts/set-routes-manifest.js",
|
||||
"update-tracker": "node scripts/update-tracker.js",
|
||||
"update-db": "prisma migrate deploy",
|
||||
"check-db": "node scripts/check-db.js",
|
||||
|
|
|
|||
74
scripts/set-routes-manifest.js
Normal file
74
scripts/set-routes-manifest.js
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/* eslint-disable no-console */
|
||||
require('dotenv').config();
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const routesManifestPath = path.resolve(__dirname, '../.next/routes-manifest.json');
|
||||
const originalPath = path.resolve(__dirname, '../.next/routes-manifest-orig.json');
|
||||
const originalManifest = require(originalPath);
|
||||
|
||||
const API_PATH = '/api/:path*';
|
||||
const TRACKER_SCRIPT = '/script.js';
|
||||
|
||||
const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT;
|
||||
const trackerScriptName = process.env.TRACKER_SCRIPT_NAME;
|
||||
|
||||
const headers = [];
|
||||
const rewrites = [];
|
||||
|
||||
if (collectApiEndpoint) {
|
||||
const apiRoute = originalManifest.headers.find((route) => route.source === API_PATH);
|
||||
const routeRegex = new RegExp(apiRoute.regex);
|
||||
|
||||
rewrites.push({
|
||||
source: collectApiEndpoint,
|
||||
destination: '/api/send',
|
||||
});
|
||||
|
||||
if (!routeRegex.test(collectApiEndpoint)) {
|
||||
headers.push({
|
||||
source: collectApiEndpoint,
|
||||
headers: apiRoute.headers,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (trackerScriptName) {
|
||||
const trackerRoute = originalManifest.headers.find((route) => route.source === TRACKER_SCRIPT);
|
||||
|
||||
const names = trackerScriptName?.split(',').map(name => name.trim());
|
||||
|
||||
if (names) {
|
||||
names.forEach(name => {
|
||||
const normalizedSource = `/${name.replace(/^\/+/, '')}`;
|
||||
|
||||
rewrites.push({
|
||||
source: normalizedSource,
|
||||
destination: TRACKER_SCRIPT,
|
||||
});
|
||||
|
||||
headers.push({
|
||||
source: normalizedSource,
|
||||
headers: trackerRoute.headers,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const routesManifest = { ...originalManifest };
|
||||
|
||||
if (rewrites.length != 0) {
|
||||
const { buildCustomRoute } = require('next/dist/lib/build-custom-route');
|
||||
|
||||
const builtHeaders = headers.map((header) => buildCustomRoute('header', header));
|
||||
const builtRewrites = rewrites.map((rewrite) => buildCustomRoute('rewrite', rewrite));
|
||||
|
||||
routesManifest.headers = [...originalManifest.headers, ...builtHeaders];
|
||||
routesManifest.rewrites = [...builtRewrites, ...originalManifest.rewrites];
|
||||
|
||||
console.log('Using updated Next.js routes manifest');
|
||||
} else {
|
||||
console.log('Using original Next.js routes manifest');
|
||||
}
|
||||
|
||||
fs.writeFileSync(routesManifestPath, JSON.stringify(routesManifest, null, 2));
|
||||
Loading…
Add table
Add a link
Reference in a new issue