fix: modernize nullresolve runtime
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
name: Docker (tags)
|
||||
name: Docker (non-tag pushes)
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -6,44 +6,12 @@ on:
|
||||
- '**'
|
||||
|
||||
env:
|
||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
NPMCI_LOGIN_DOCKER_GITEA: ${{ github.server_url }}|${{ gitea.repository_owner }}|${{ secrets.GITEA_TOKEN }}
|
||||
IMAGE: code.foss.global/host.today/ht-docker-node:szci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||
NPMCI_LOGIN_DOCKER_DOCKERREGISTRY: ${{ secrets.NPMCI_LOGIN_DOCKER_DOCKERREGISTRY }}
|
||||
|
||||
jobs:
|
||||
security:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install pnpm and npmci
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --prod
|
||||
continue-on-error: true
|
||||
|
||||
- name: Audit development dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --dev
|
||||
continue-on-error: true
|
||||
|
||||
test:
|
||||
needs: security
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
@@ -54,18 +22,14 @@ jobs:
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
pnpm install -g @git.zone/tsdocker@latest
|
||||
pnpm install
|
||||
|
||||
- name: Test stable
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci npm test
|
||||
- name: Test
|
||||
run: pnpm test
|
||||
|
||||
- name: Test build
|
||||
run: |
|
||||
npmci npm prepare
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci command npm run build
|
||||
- name: Build image
|
||||
run: tsdocker build
|
||||
|
||||
- name: Test image
|
||||
run: tsdocker test
|
||||
|
||||
@@ -6,75 +6,15 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
NPMCI_LOGIN_DOCKER_GITEA: ${{ github.server_url }}|${{ gitea.repository_owner }}|${{ secrets.GITEA_TOKEN }}
|
||||
IMAGE: code.foss.global/host.today/ht-docker-node:szci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||
NPMCI_LOGIN_DOCKER_DOCKERREGISTRY: ${{ secrets.NPMCI_LOGIN_DOCKER_DOCKERREGISTRY }}
|
||||
|
||||
jobs:
|
||||
security:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --prod
|
||||
continue-on-error: true
|
||||
|
||||
- name: Audit development dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --dev
|
||||
continue-on-error: true
|
||||
|
||||
test:
|
||||
needs: security
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @ship.zone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Test stable
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci npm test
|
||||
|
||||
- name: Test build
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci command npm run build
|
||||
|
||||
release:
|
||||
needs: test
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: code.foss.global/hosttoday/ht-docker-dbase:npmci
|
||||
image: code.foss.global/host.today/ht-docker-dbase:szci
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -82,25 +22,20 @@ jobs:
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @ship.zone/npmci
|
||||
pnpm install -g @git.zone/tsdocker@latest
|
||||
pnpm install
|
||||
|
||||
- name: Release
|
||||
run: |
|
||||
npmci docker login
|
||||
npmci docker build
|
||||
npmci docker test
|
||||
# npmci docker push
|
||||
npmci docker push
|
||||
- name: Login to registries
|
||||
run: tsdocker login
|
||||
|
||||
metadata:
|
||||
needs: test
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
- name: List images
|
||||
run: tsdocker list
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build images
|
||||
run: tsdocker build
|
||||
|
||||
- name: Trigger
|
||||
run: npmci trigger
|
||||
- name: Test images
|
||||
run: tsdocker test
|
||||
|
||||
- name: Push to code.foss.global
|
||||
run: tsdocker push code.foss.global
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
{
|
||||
"npmci": {
|
||||
"npmGlobalTools": [],
|
||||
"dockerRegistryRepoMap": {
|
||||
"registry.gitlab.com": "losslessone/services/servezone/nullresolve"
|
||||
"@git.zone/tsdocker": {
|
||||
"registries": ["code.foss.global"],
|
||||
"registryRepoMap": {
|
||||
"code.foss.global": "serve.zone/nullresolve"
|
||||
},
|
||||
"dockerBuildargEnvMap": {
|
||||
"NPMCI_TOKEN_NPM2": "NPMCI_TOKEN_NPM2"
|
||||
},
|
||||
"npmRegistryUrl": "verdaccio.lossless.one"
|
||||
"platforms": ["linux/amd64", "linux/arm64"]
|
||||
},
|
||||
"gitzone": {
|
||||
"@git.zone/cli": {
|
||||
"projectType": "service",
|
||||
"module": {
|
||||
"githost": "gitlab.com",
|
||||
"gitscope": "losslessone/services/servezone",
|
||||
"githost": "code.foss.global",
|
||||
"gitscope": "serve.zone",
|
||||
"gitrepo": "nullresolve",
|
||||
"description": "The nullresolve project is a private service designed to handle requests that would otherwise remain unserved, providing appropriate feedback mechanisms within the servzone architecture.",
|
||||
"npmPackagename": "@losslessone_private/nullresolve",
|
||||
"license": "MIT",
|
||||
"license": "UNLICENSED",
|
||||
"keywords": [
|
||||
"nullresolve",
|
||||
"service",
|
||||
+20
-33
@@ -1,46 +1,33 @@
|
||||
# gitzone dockerfile_service
|
||||
## STAGE 1 // BUILD
|
||||
FROM code.foss.global/host.today/ht-docker-node:npmci as node1
|
||||
COPY ./ /app
|
||||
FROM code.foss.global/host.today/ht-docker-node:lts AS build
|
||||
|
||||
WORKDIR /app
|
||||
ARG NPMCI_TOKEN_NPM2
|
||||
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
|
||||
RUN npmci npm prepare
|
||||
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm config set store-dir .pnpm-store
|
||||
RUN rm -rf node_modules && pnpm install
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
COPY . ./
|
||||
RUN pnpm run build
|
||||
|
||||
# gitzone dockerfile_service
|
||||
## STAGE 2 // install production
|
||||
FROM code.foss.global/host.today/ht-docker-node:npmci as node2
|
||||
WORKDIR /app
|
||||
COPY --from=node1 /app /app
|
||||
RUN rm -rf .pnpm-store
|
||||
ARG NPMCI_TOKEN_NPM2
|
||||
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
|
||||
RUN npmci npm prepare
|
||||
RUN pnpm config set store-dir .pnpm-store
|
||||
RUN rm -rf node_modules/ && pnpm install --prod
|
||||
RUN pnpm prune --prod
|
||||
|
||||
## STAGE 2 // PRODUCTION
|
||||
FROM code.foss.global/host.today/ht-docker-node:lts AS production
|
||||
|
||||
## STAGE 3 // rebuild dependencies for alpine
|
||||
FROM code.foss.global/host.today/ht-docker-node:alpinenpmci as node3
|
||||
WORKDIR /app
|
||||
COPY --from=node2 /app /app
|
||||
ARG NPMCI_TOKEN_NPM2
|
||||
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
|
||||
RUN npmci npm prepare
|
||||
RUN pnpm config set store-dir .pnpm-store
|
||||
RUN pnpm rebuild -r
|
||||
|
||||
## STAGE 4 // the final production image with all dependencies in place
|
||||
FROM code.foss.global/host.today/ht-docker-node:alpine as node4
|
||||
WORKDIR /app
|
||||
COPY --from=node3 /app /app
|
||||
ENV NODE_ENV=production
|
||||
|
||||
### Healthchecks
|
||||
RUN pnpm install -g @servezone/healthy
|
||||
HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=3 CMD [ "healthy" ]
|
||||
COPY --from=build /app/package.json ./package.json
|
||||
COPY --from=build /app/node_modules ./node_modules
|
||||
COPY --from=build /app/cli.js ./cli.js
|
||||
COPY --from=build /app/dist_ts ./dist_ts
|
||||
|
||||
LABEL org.opencontainers.image.title="nullresolve" \
|
||||
org.opencontainers.image.description="serve.zone fallback response service" \
|
||||
org.opencontainers.image.source="https://code.foss.global/serve.zone/nullresolve"
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["npm", "start"]
|
||||
CMD ["node", "cli.js"]
|
||||
|
||||
+16
-15
@@ -10,21 +10,22 @@
|
||||
"start": "(node cli.js)",
|
||||
"startTs": "(node cli.ts.js)",
|
||||
"build": "(tsbuild --web --allowimplicitany)",
|
||||
"watch": "(tswatch service)"
|
||||
"watch": "(tswatch service)",
|
||||
"build:docker": "tsdocker build --verbose",
|
||||
"release:docker": "tsdocker push --verbose"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.1.63",
|
||||
"@git.zone/tstest": "^1.0.71",
|
||||
"@git.zone/tswatch": "^2.0.37",
|
||||
"@push.rocks/tapbundle": "^5.0.3",
|
||||
"@types/node": "^22.10.2"
|
||||
"@git.zone/tsbuild": "^4.4.0",
|
||||
"@git.zone/tsdocker": "^2.2.4",
|
||||
"@git.zone/tsrun": "^2.0.2",
|
||||
"@git.zone/tstest": "^3.6.3",
|
||||
"@git.zone/tswatch": "^3.3.2",
|
||||
"@types/node": "^25.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@api.global/typedserver": "^3.0.53",
|
||||
"@git.zone/tsrun": "^1.2.37",
|
||||
"@push.rocks/projectinfo": "^5.0.1",
|
||||
"@push.rocks/smartlog": "^3.0.7",
|
||||
"@push.rocks/smartpath": "^5.0.5",
|
||||
"@api.global/typedserver": "^8.4.6",
|
||||
"@push.rocks/projectinfo": "^5.1.0",
|
||||
"@push.rocks/smartpath": "^6.0.0",
|
||||
"@push.rocks/smartstatus": "^1.1.1"
|
||||
},
|
||||
"private": true,
|
||||
@@ -37,7 +38,7 @@
|
||||
"dist_ts_web/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
"npmextra.json",
|
||||
".smartconfig.json",
|
||||
"readme.md"
|
||||
],
|
||||
"browserslist": [
|
||||
@@ -45,12 +46,12 @@
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://gitlab.com/losslessone/services/servezone/nullresolve.git"
|
||||
"url": "git+https://code.foss.global/serve.zone/nullresolve.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/losslessone/services/servezone/nullresolve/issues"
|
||||
"url": "https://code.foss.global/serve.zone/nullresolve/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/losslessone/services/servezone/nullresolve#readme",
|
||||
"homepage": "https://code.foss.global/serve.zone/nullresolve#readme",
|
||||
"keywords": [
|
||||
"nullresolve",
|
||||
"service",
|
||||
|
||||
Generated
+4168
-4209
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
|
||||
import * as nullresolve from '../ts/index.js';
|
||||
|
||||
@@ -11,4 +11,4 @@ tap.test('should create, start and stop an instance of nullresolve', async () =>
|
||||
await nullresolveInstance.stop();
|
||||
});
|
||||
|
||||
tap.start();
|
||||
export default tap.start();
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
node --input-type=module <<'NODE'
|
||||
import fs from 'node:fs';
|
||||
|
||||
const readJson = (path) => JSON.parse(fs.readFileSync(path, 'utf8'));
|
||||
|
||||
const checks = {
|
||||
packageVersion: readJson('/app/package.json').version,
|
||||
typedserverVersion: readJson('/app/node_modules/@api.global/typedserver/package.json').version,
|
||||
hasCli: fs.existsSync('/app/cli.js'),
|
||||
};
|
||||
|
||||
await import('/app/dist_ts/index.js');
|
||||
|
||||
if (checks.packageVersion !== '1.0.31') {
|
||||
throw new Error(`Unexpected nullresolve package version ${checks.packageVersion}`);
|
||||
}
|
||||
if (checks.typedserverVersion !== '8.4.6') {
|
||||
throw new Error(`Unexpected typedserver version ${checks.typedserverVersion}`);
|
||||
}
|
||||
if (!checks.hasCli) {
|
||||
throw new Error('Missing cli.js');
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(checks));
|
||||
NODE
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@losslessone_private/nullresolve',
|
||||
version: '1.0.31',
|
||||
description: 'The nullresolve project is a private service designed to handle requests that would otherwise remain unserved, providing appropriate feedback mechanisms within the servzone architecture.'
|
||||
}
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
import './nullresolve.logging.js';
|
||||
import { NullResolve } from './nullresolve.classes.nullresolve.js';
|
||||
export { NullResolve };
|
||||
|
||||
let mainNullResolve: NullResolve;
|
||||
let mainNullResolve: NullResolve | null;
|
||||
|
||||
export const runCli = async () => {
|
||||
mainNullResolve = new NullResolve();
|
||||
|
||||
@@ -1,147 +1,162 @@
|
||||
import * as plugins from './nullresolve.plugins.js';
|
||||
import { projectinfo } from './nullresolve.projectinfo.js';
|
||||
import * as paths from './nullresolve.paths.js';
|
||||
import { configObject } from './nullresolve.config.js';
|
||||
import type { IHtmlInfoOptions } from '@api.global/typedserver/infohtml';
|
||||
|
||||
export interface INullResolveOptions {
|
||||
port?: number;
|
||||
serviceDomain?: string;
|
||||
}
|
||||
|
||||
type TResolvedNullResolveOptions = INullResolveOptions & {
|
||||
serviceDomain: string;
|
||||
};
|
||||
|
||||
export class NullResolve {
|
||||
public serviceServer: plugins.typedserver.utilityservers.UtilityServiceServer;
|
||||
public serviceServer: plugins.typedserver.utilityservers.UtilityServiceServer | null = null;
|
||||
private options: TResolvedNullResolveOptions;
|
||||
|
||||
constructor() {
|
||||
this.serviceServer = new plugins.typedserver.utilityservers.UtilityServiceServer({
|
||||
constructor(optionsArg: INullResolveOptions = {}) {
|
||||
this.options = {
|
||||
serviceDomain: 'nullresolve.lossless.one',
|
||||
serviceName: 'nullresolve',
|
||||
serviceVersion: projectinfo.npm.version,
|
||||
addCustomRoutes: async (serverArg) => {
|
||||
serverArg.addRoute(
|
||||
'/status/:code',
|
||||
new plugins.typedserver.servertools.Handler('GET', async (req, res) => {
|
||||
let infoHtmlOptions: plugins.typedserverInfoHtml.IHtmlInfoOptions;
|
||||
...optionsArg,
|
||||
};
|
||||
}
|
||||
|
||||
switch (req.params.code) {
|
||||
case 'ipblock':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: Blocked IP',
|
||||
heading: 'Blocked IP',
|
||||
text: 'Your IP (::CLIENT_IP::) is not allowed to access this ressource.',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: 'ipblock',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case 'firewall':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: Firewall',
|
||||
heading: 'Firewall',
|
||||
text: 'Your request has been blocked by our firewall since it showed possibly harmful behaviour.',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: 'firewall',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case '500class':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: 5xx',
|
||||
heading: '5xx',
|
||||
text: '::CLOUDFLARE_ERROR_500S_BOX::',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: '5xx error',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case '1000class':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: DNS Resolution failed',
|
||||
heading: '1xxx',
|
||||
text: '::CLOUDFLARE_ERROR_1000S_BOX::',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: '1000 class error',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case 'alwaysonline':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: No Cache',
|
||||
heading: 'No Cache',
|
||||
text: '::ALWAYS_ONLINE_NO_COPY_BOX::',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: 'alwaysonline triggered. Potentially offline!',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case 'waf':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: Firewall Challenge',
|
||||
heading: 'Firewall Challenge',
|
||||
text: '::CAPTCHA_BOX::',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case 'country':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: Country Challenge',
|
||||
heading: 'Country Challenge',
|
||||
text: '::CAPTCHA_BOX::',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
case 'attack':
|
||||
infoHtmlOptions = {
|
||||
title: 'Lossless Network: Advanced User Challenge',
|
||||
heading: 'Advanced User Challenge',
|
||||
text: '::IM_UNDER_ATTACK_BOX::',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
break;
|
||||
default:
|
||||
const statusInstance = plugins.smartstatus.HttpStatus.getHttpStatusByString(
|
||||
req.params.code,
|
||||
);
|
||||
infoHtmlOptions = {
|
||||
title: `Lossless Network: ${statusInstance.code.toString()}`,
|
||||
heading: statusInstance.code.toString(),
|
||||
text: statusInstance.text,
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
const infoHtmlInstance =
|
||||
await plugins.typedserverInfoHtml.InfoHtml.fromOptions(infoHtmlOptions);
|
||||
res.status(200);
|
||||
res.send(infoHtmlInstance.htmlString);
|
||||
}),
|
||||
);
|
||||
|
||||
serverArg.addRoute(
|
||||
'/custom',
|
||||
new plugins.typedserver.servertools.Handler('GET', async (req, res) => {
|
||||
console.log(req.query);
|
||||
const options: any = {
|
||||
title: 'Lossless Network',
|
||||
heading: 'Error!',
|
||||
text: 'Please wait...',
|
||||
redirectTo: 'https://lossless.com',
|
||||
...req.query,
|
||||
};
|
||||
const infoHtmlInstance = await plugins.typedserverInfoHtml.InfoHtml.fromOptions({
|
||||
title: decodeURI(options.title),
|
||||
heading: decodeURI(options.heading),
|
||||
text: decodeURI(options.text),
|
||||
redirectTo: decodeURI(options.redirectTo),
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: `nullresolve custom: ${decodeURI(options.title)}`,
|
||||
});
|
||||
res.status(200);
|
||||
res.send(infoHtmlInstance.htmlString);
|
||||
}),
|
||||
);
|
||||
private async createInfoHtmlResponse(
|
||||
infoHtmlOptionsArg: IHtmlInfoOptions,
|
||||
) {
|
||||
const { InfoHtml } = await import('@api.global/typedserver/infohtml');
|
||||
const infoHtmlInstance = await InfoHtml.fromOptions(infoHtmlOptionsArg);
|
||||
return new Response(infoHtmlInstance.htmlString, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'text/html; charset=utf-8',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private getStatusInfoOptions(statusCodeArg: string): IHtmlInfoOptions {
|
||||
switch (statusCodeArg) {
|
||||
case 'ipblock':
|
||||
return {
|
||||
title: 'Lossless Network: Blocked IP',
|
||||
heading: 'Blocked IP',
|
||||
text: 'Your IP (::CLIENT_IP::) is not allowed to access this resource.',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: 'ipblock',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case 'firewall':
|
||||
return {
|
||||
title: 'Lossless Network: Firewall',
|
||||
heading: 'Firewall',
|
||||
text: 'Your request has been blocked by our firewall since it showed possibly harmful behaviour.',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: 'firewall',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case '500class':
|
||||
return {
|
||||
title: 'Lossless Network: 5xx',
|
||||
heading: '5xx',
|
||||
text: '::CLOUDFLARE_ERROR_500S_BOX::',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: '5xx error',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case '1000class':
|
||||
return {
|
||||
title: 'Lossless Network: DNS Resolution failed',
|
||||
heading: '1xxx',
|
||||
text: '::CLOUDFLARE_ERROR_1000S_BOX::',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: '1000 class error',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case 'alwaysonline':
|
||||
return {
|
||||
title: 'Lossless Network: No Cache',
|
||||
heading: 'No Cache',
|
||||
text: '::ALWAYS_ONLINE_NO_COPY_BOX::',
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: 'alwaysonline triggered. Potentially offline!',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case 'waf':
|
||||
return {
|
||||
title: 'Lossless Network: Firewall Challenge',
|
||||
heading: 'Firewall Challenge',
|
||||
text: '::CAPTCHA_BOX::',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case 'country':
|
||||
return {
|
||||
title: 'Lossless Network: Country Challenge',
|
||||
heading: 'Country Challenge',
|
||||
text: '::CAPTCHA_BOX::',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
case 'attack':
|
||||
return {
|
||||
title: 'Lossless Network: Advanced User Challenge',
|
||||
heading: 'Advanced User Challenge',
|
||||
text: '::IM_UNDER_ATTACK_BOX::',
|
||||
redirectTo: 'https://lossless.com',
|
||||
};
|
||||
default: {
|
||||
const statusInstance = plugins.smartstatus.HttpStatus.getHttpStatusByString(statusCodeArg);
|
||||
return {
|
||||
title: `Lossless Network: ${statusInstance.code.toString()}`,
|
||||
heading: statusInstance.code.toString(),
|
||||
text: statusInstance.text,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async addCustomRoutes(typedServerArg: plugins.typedserver.TypedServer) {
|
||||
typedServerArg.addRoute('/status/:code', 'GET', async (ctxArg) => {
|
||||
return this.createInfoHtmlResponse(this.getStatusInfoOptions(ctxArg.params.code));
|
||||
});
|
||||
|
||||
typedServerArg.addRoute('/custom', 'GET', async (ctxArg) => {
|
||||
const options = {
|
||||
title: ctxArg.query.title || 'Lossless Network',
|
||||
heading: ctxArg.query.heading || 'Error!',
|
||||
text: ctxArg.query.text || 'Please wait...',
|
||||
redirectTo: ctxArg.query.redirectTo || 'https://lossless.com',
|
||||
};
|
||||
|
||||
return this.createInfoHtmlResponse({
|
||||
...options,
|
||||
sentryDsn: configObject.sentryDsn,
|
||||
sentryMessage: `nullresolve custom: ${options.title}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async start() {
|
||||
if (this.serviceServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const projectinfo = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
|
||||
this.serviceServer = new plugins.typedserver.utilityservers.UtilityServiceServer({
|
||||
serviceDomain: this.options.serviceDomain,
|
||||
serviceName: 'nullresolve',
|
||||
serviceVersion: projectinfo.npm.version,
|
||||
port: this.options.port,
|
||||
addCustomRoutes: async (typedServerArg) => this.addCustomRoutes(typedServerArg),
|
||||
});
|
||||
await this.serviceServer.start();
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
if (!this.serviceServer) {
|
||||
return;
|
||||
}
|
||||
await this.serviceServer.stop();
|
||||
this.serviceServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import * as plugins from './nullresolve.plugins.js';
|
||||
import * as paths from './nullresolve.paths.js';
|
||||
|
||||
const projectInfoNpm = new plugins.projectinfo.ProjectinfoNpm(paths.packageDir);
|
||||
|
||||
import { commitinfo } from './00_commitinfo_data.js';
|
||||
|
||||
export const logger = plugins.smartlog.Smartlog.createForCommitinfo(commitinfo);
|
||||
@@ -5,14 +5,12 @@ export { path };
|
||||
|
||||
// @api.global scope
|
||||
import * as typedserver from '@api.global/typedserver';
|
||||
import * as typedserverInfoHtml from '@api.global/typedserver/infohtml';
|
||||
|
||||
export { typedserver, typedserverInfoHtml };
|
||||
export { typedserver };
|
||||
|
||||
// @push.rocks scope
|
||||
import * as projectinfo from '@push.rocks/projectinfo';
|
||||
import * as smartlog from '@push.rocks/smartlog';
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
import * as smartstatus from '@push.rocks/smartstatus';
|
||||
|
||||
export { projectinfo, smartlog, smartpath, smartstatus };
|
||||
export { projectinfo, smartpath, smartstatus };
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import * as plugins from './nullresolve.plugins.js';
|
||||
import * as paths from './nullresolve.paths.js';
|
||||
|
||||
export const projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
|
||||
Reference in New Issue
Block a user