feat: www <-> non-www redirection

This commit is contained in:
Andras Bacsai 2022-02-13 22:56:37 +01:00
parent 69d3cb5dd8
commit aec1d184c8
11 changed files with 90 additions and 45 deletions

View File

@ -1,5 +1,5 @@
import { decrypt, encrypt } from '$lib/crypto';
import { removeProxyConfiguration } from '$lib/haproxy';
import { removeProxyConfiguration, removeWwwRedirection } from '$lib/haproxy';
import { asyncExecShell, getEngine } from '$lib/common';
import { getDomain, removeDestinationDocker } from '$lib/common';

View File

@ -50,12 +50,12 @@ export async function completeTransaction(transactionId) {
}
export async function removeProxyConfiguration({ domain }) {
const transactionId = await getNextTransactionId();
const haproxy = await haproxyInstance();
const backendFound = await haproxy
.get(`v2/services/haproxy/configuration/backends/${domain}`)
.json();
if (backendFound) {
const transactionId = await getNextTransactionId();
await haproxy
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
searchParams: {
@ -63,32 +63,9 @@ export async function removeProxyConfiguration({ domain }) {
}
})
.json();
await completeTransaction(transactionId);
}
const rules: any = await haproxy
.get(`v2/services/haproxy/configuration/http_request_rules`, {
searchParams: {
parent_name: 'http',
parent_type: 'frontend'
}
})
.json();
if (rules.data.length > 0) {
const rule = rules.data.find((rule) =>
rule.redir_value.includes(`${domain}%[capture.req.uri]`)
);
if (rule) {
await haproxy
.delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, {
searchParams: {
transaction_id: transactionId,
parent_name: 'http',
parent_type: 'frontend'
}
})
.json();
}
}
await completeTransaction(transactionId);
await removeWwwRedirection(domain);
}
export async function forceSSLOffApplication({ domain }) {
if (!dev) {
@ -303,7 +280,8 @@ export async function configureProxyForApplication({ domain, imageId, applicatio
}
}
export async function configureCoolifyProxyOff({ domain }) {
export async function configureCoolifyProxyOff(fqdn) {
const domain = getDomain(fqdn);
const haproxy = await haproxyInstance();
try {
await checkHAProxy(haproxy);
@ -325,6 +303,7 @@ export async function configureCoolifyProxyOff({ domain }) {
if (!dev) {
await forceSSLOffApplication({ domain });
}
await setWwwRedirection(fqdn);
} catch (error) {
throw error?.response?.body || error;
}
@ -337,7 +316,8 @@ export async function checkHAProxy(haproxy) {
throw 'HAProxy is not running, but it should be!';
}
}
export async function configureCoolifyProxyOn({ domain }) {
export async function configureCoolifyProxyOn(fqdn) {
const domain = getDomain(fqdn);
const haproxy = await haproxyInstance();
try {
await checkHAProxy(haproxy);
@ -544,7 +524,15 @@ export async function configureSimpleServiceProxyOn({ id, domain, port }) {
await checkHAProxy(haproxy);
try {
await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json();
return;
const transactionId = await getNextTransactionId();
await haproxy
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
searchParams: {
transaction_id: transactionId
}
})
.json();
await completeTransaction(transactionId);
} catch (error) {}
try {
const transactionId = await getNextTransactionId();
@ -570,6 +558,12 @@ export async function configureSimpleServiceProxyOn({ id, domain, port }) {
port: port
}
});
console.log({
address: id,
check: 'enabled',
name: id,
port: port
});
await completeTransaction(transactionId);
} catch (error) {
console.log(error);
@ -596,9 +590,45 @@ export async function configureSimpleServiceProxyOff({ domain }) {
.json();
await completeTransaction(transactionId);
} catch (error) {}
await removeWwwRedirection(domain);
return;
}
export async function removeWwwRedirection(domain) {
const haproxy = await haproxyInstance();
try {
await checkHAProxy(haproxy);
} catch (error) {
return;
}
const rules: any = await haproxy
.get(`v2/services/haproxy/configuration/http_request_rules`, {
searchParams: {
parent_name: 'http',
parent_type: 'frontend'
}
})
.json();
if (rules.data.length > 0) {
const rule = rules.data.find((rule) =>
rule.redir_value.includes(`${domain}%[capture.req.uri]`)
);
if (rule) {
const transactionId = await getNextTransactionId();
await haproxy
.delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, {
searchParams: {
transaction_id: transactionId,
parent_name: 'http',
parent_type: 'frontend'
}
})
.json();
await completeTransaction(transactionId);
}
}
}
export async function setWwwRedirection(fqdn) {
const haproxy = await haproxyInstance();
try {
@ -612,6 +642,7 @@ export async function setWwwRedirection(fqdn) {
const domain = getDomain(fqdn);
const isHttps = fqdn.startsWith('https://');
const isWWW = fqdn.includes('www.');
const contTest = `{ req.hdr(host) -i ${isWWW ? domain.replace('www.', '') : `www.${domain}`} }`;
const rules: any = await haproxy
.get(`v2/services/haproxy/configuration/http_request_rules`, {
searchParams: {
@ -638,12 +669,12 @@ export async function setWwwRedirection(fqdn) {
},
json: {
index: nextRule,
cond: `${isWWW ? 'unless' : 'if'}`,
cond_test: `{ hdr_beg(host) -i www }`,
cond: 'if',
cond_test: contTest,
type: 'redirect',
redir_type: 'location',
redir_value: redirectValue,
redir_code: 301
redir_code: dev ? 302 : 301
}
})
.json();

View File

@ -7,6 +7,7 @@ import {
configureProxyForApplication,
forceSSLOnApplication,
reloadHaproxy,
setWwwRedirection,
startCoolifyProxy
} from '$lib/haproxy';
import * as db from '$lib/database';
@ -40,6 +41,7 @@ export default async function () {
});
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
await setWwwRedirection(fqdn);
}
}
}
@ -52,6 +54,7 @@ export default async function () {
const found = await checkContainer('/var/run/docker.sock', 'coolify-haproxy');
if (!found) await startCoolifyProxy('/var/run/docker.sock');
await configureCoolifyProxyOn({ domain });
await setWwwRedirection(fqdn);
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
}

View File

@ -7,6 +7,7 @@ import { letsEncrypt } from '$lib/letsencrypt';
import {
configureSimpleServiceProxyOn,
reloadHaproxy,
setWwwRedirection,
startHttpProxy,
startTcpProxy
} from '$lib/haproxy';
@ -86,13 +87,13 @@ export const post: RequestHandler = async (event) => {
try {
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
await configureSimpleServiceProxyOn({ id, domain, port: consolePort });
await db.updateMinioService({ id, publicPort });
await startHttpProxy(destinationDocker, id, publicPort, apiPort);
if (isHttps) {
await letsEncrypt({ domain, id });
}
await setWwwRedirection(fqdn);
await reloadHaproxy(destinationDocker.engine);
return {
status: 200

View File

@ -4,7 +4,7 @@ import { promises as fs } from 'fs';
import yaml from 'js-yaml';
import type { RequestHandler } from '@sveltejs/kit';
import { letsEncrypt } from '$lib/letsencrypt';
import { configureSimpleServiceProxyOn, reloadHaproxy } from '$lib/haproxy';
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { PrismaErrorHandler } from '$lib/database';
@ -52,6 +52,7 @@ export const post: RequestHandler = async (event) => {
if (isHttps) {
await letsEncrypt({ domain, id });
}
await setWwwRedirection(fqdn);
await reloadHaproxy(destinationDocker.engine);
return {
status: 200

View File

@ -4,7 +4,7 @@ import { promises as fs } from 'fs';
import yaml from 'js-yaml';
import type { RequestHandler } from '@sveltejs/kit';
import { letsEncrypt } from '$lib/letsencrypt';
import { configureSimpleServiceProxyOn, reloadHaproxy } from '$lib/haproxy';
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { PrismaErrorHandler } from '$lib/database';
@ -185,6 +185,7 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
if (isHttps) {
await letsEncrypt({ domain, id });
}
await setWwwRedirection(fqdn);
await reloadHaproxy(destinationDocker.engine);
return {
status: 200

View File

@ -4,7 +4,7 @@ import { promises as fs } from 'fs';
import yaml from 'js-yaml';
import type { RequestHandler } from '@sveltejs/kit';
import { letsEncrypt } from '$lib/letsencrypt';
import { configureSimpleServiceProxyOn, reloadHaproxy } from '$lib/haproxy';
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { getServiceImage, PrismaErrorHandler } from '$lib/database';
@ -70,6 +70,7 @@ export const post: RequestHandler = async (event) => {
if (isHttps) {
await letsEncrypt({ domain, id });
}
await setWwwRedirection(fqdn);
await reloadHaproxy(destinationDocker.engine);
return {
status: 200

View File

@ -4,7 +4,7 @@ import { promises as fs } from 'fs';
import yaml from 'js-yaml';
import type { RequestHandler } from '@sveltejs/kit';
import { letsEncrypt } from '$lib/letsencrypt';
import { configureSimpleServiceProxyOn, reloadHaproxy } from '$lib/haproxy';
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { PrismaErrorHandler } from '$lib/database';
@ -80,6 +80,7 @@ export const post: RequestHandler = async (event) => {
if (isHttps) {
await letsEncrypt({ domain, id });
}
await setWwwRedirection(fqdn);
await reloadHaproxy(destinationDocker.engine);
return {
status: 200

View File

@ -4,7 +4,7 @@ import { promises as fs } from 'fs';
import yaml from 'js-yaml';
import type { RequestHandler } from '@sveltejs/kit';
import { letsEncrypt } from '$lib/letsencrypt';
import { configureSimpleServiceProxyOn, reloadHaproxy } from '$lib/haproxy';
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
import { getDomain } from '$lib/components/common';
import { PrismaErrorHandler } from '$lib/database';
@ -117,6 +117,7 @@ export const post: RequestHandler = async (event) => {
if (isHttps) {
await letsEncrypt({ domain, id });
}
await setWwwRedirection(fqdn);
await reloadHaproxy(destinationDocker.engine);
return {
status: 200

View File

@ -9,6 +9,8 @@ import {
forceSSLOffApplication,
forceSSLOnApplication,
reloadHaproxy,
removeWwwRedirection,
setWwwRedirection,
startCoolifyProxy
} from '$lib/haproxy';
import { letsEncrypt } from '$lib/letsencrypt';
@ -45,9 +47,10 @@ export const del: RequestHandler = async (event) => {
const { fqdn } = await event.request.json();
try {
await db.prisma.setting.update({ where: { fqdn }, data: { fqdn: null } });
const domain = getDomain(fqdn);
await configureCoolifyProxyOff({ domain });
await db.prisma.setting.update({ where: { fqdn }, data: { fqdn: null } });
await configureCoolifyProxyOff(fqdn);
await removeWwwRedirection(domain);
return {
status: 201
};
@ -77,9 +80,10 @@ export const post: RequestHandler = async (event) => {
await db.prisma.setting.update({ where: { id }, data: { isRegistrationEnabled } });
}
if (oldFqdn && oldFqdn !== fqdn) {
const oldDomain = getDomain(oldFqdn);
if (oldFqdn) {
await configureCoolifyProxyOff({ domain: oldDomain });
const oldDomain = getDomain(oldFqdn);
await configureCoolifyProxyOff(oldFqdn);
await removeWwwRedirection(oldDomain);
}
}
if (fqdn) {
@ -88,7 +92,8 @@ export const post: RequestHandler = async (event) => {
const domain = getDomain(fqdn);
const isHttps = fqdn.startsWith('https://');
if (domain) {
await configureCoolifyProxyOn({ domain });
await configureCoolifyProxyOn(fqdn);
await setWwwRedirection(fqdn);
if (isHttps && !dev) {
await letsEncrypt({ domain, isCoolify: true });
await forceSSLOnApplication({ domain });

View File

@ -106,7 +106,7 @@
<div class="px-4 sm:px-6">
<div class="flex space-x-4 py-4 px-4">
<p class="pt-2 text-base font-bold text-stone-100">Domain (FQDN)</p>
<div class="justify-center text-center">
<div class="justify-center">
<input
bind:value={fqdn}
readonly={!$session.isAdmin || isFqdnSet}