ssl enforce
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
PORT=3030
|
||||
API_HOST_PORT=8030
|
||||
PUBLIC_API_URL=https://dune.api.coppnic.cc
|
||||
PUBLIC_UI_URL=https://ui.dune.api.coppnic.cc
|
||||
FORCE_HTTPS=true
|
||||
MONGODB_URI=mongodb://root:change-me@37.60.245.70:27017
|
||||
MONGODB_DB=duneawa
|
||||
MAX_PAGES=
|
||||
|
||||
23
README.md
23
README.md
@@ -10,7 +10,7 @@ npm run import:smoke
|
||||
npm start
|
||||
```
|
||||
|
||||
Open Swagger UI at `http://localhost:3030/docs`.
|
||||
Open Swagger UI locally at `http://localhost:3030/docs`.
|
||||
|
||||
## Docker
|
||||
|
||||
@@ -18,7 +18,26 @@ Open Swagger UI at `http://localhost:3030/docs`.
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
The API listens on `http://localhost:8030` by default when run through Docker Compose. Set `API_HOST_PORT=3031` if your machine needs the alternate host port.
|
||||
The container listens on `3030` and Docker Compose exposes it on `8030` by default. Set `API_HOST_PORT=3031` if your machine needs the alternate host port.
|
||||
|
||||
## Public HTTPS Domains
|
||||
|
||||
This app is configured for Dokploy/Traefik HTTPS by default. Traefik should terminate TLS and route both public HTTPS domains to the app container:
|
||||
|
||||
```text
|
||||
https://dune.api.coppnic.cc -> container port 3030
|
||||
https://ui.dune.api.coppnic.cc -> container port 3030
|
||||
```
|
||||
|
||||
The public API URL is `https://dune.api.coppnic.cc`. Swagger UI is available at `https://ui.dune.api.coppnic.cc/docs`.
|
||||
|
||||
The OpenAPI document advertises the HTTPS API domain by default, so Swagger requests go to the right public API host. These values can be adjusted through environment variables:
|
||||
|
||||
```env
|
||||
PUBLIC_API_URL=https://dune.api.coppnic.cc
|
||||
PUBLIC_UI_URL=https://ui.dune.api.coppnic.cc
|
||||
FORCE_HTTPS=true
|
||||
```
|
||||
|
||||
## Import All Data
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ services:
|
||||
- "${API_HOST_PORT:-8030}:${PORT:-3030}"
|
||||
environment:
|
||||
PORT: ${PORT:-3030}
|
||||
PUBLIC_API_URL: ${PUBLIC_API_URL:-https://dune.api.coppnic.cc}
|
||||
PUBLIC_UI_URL: ${PUBLIC_UI_URL:-https://ui.dune.api.coppnic.cc}
|
||||
FORCE_HTTPS: ${FORCE_HTTPS:-true}
|
||||
MONGODB_URI: ${MONGODB_URI}
|
||||
MONGODB_DB: ${MONGODB_DB:-duneawa}
|
||||
MAX_PAGES: ${MAX_PAGES:-}
|
||||
|
||||
22
src/app.js
22
src/app.js
@@ -1,6 +1,7 @@
|
||||
const cors = require("cors");
|
||||
const express = require("express");
|
||||
const swaggerUi = require("swagger-ui-express");
|
||||
const { config } = require("./config");
|
||||
const { pingMongo } = require("./db/client");
|
||||
const { router: apiRouter } = require("./routes/api");
|
||||
const { openApiDocument } = require("./swagger/openapi");
|
||||
@@ -8,11 +9,30 @@ const { openApiDocument } = require("./swagger/openapi");
|
||||
function createApp() {
|
||||
const app = express();
|
||||
|
||||
app.set("trust proxy", true);
|
||||
app.use(cors());
|
||||
app.use(express.json({ limit: "2mb" }));
|
||||
app.use((request, response, next) => {
|
||||
const forwardedProto = request.get("x-forwarded-proto");
|
||||
const isSecure = request.secure || forwardedProto === "https";
|
||||
const isLocalhost = ["localhost", "127.0.0.1", "::1"].includes(
|
||||
request.hostname,
|
||||
);
|
||||
|
||||
if (config.public.forceHttps && !isSecure && !isLocalhost) {
|
||||
const baseUrl =
|
||||
request.hostname === "ui.dune.api.coppnic.cc"
|
||||
? config.public.uiUrl
|
||||
: config.public.apiUrl;
|
||||
response.redirect(308, new URL(request.originalUrl, baseUrl).toString());
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
app.get("/", (request, response) => {
|
||||
response.redirect("/docs");
|
||||
response.redirect(308, `${config.public.uiUrl}/docs`);
|
||||
});
|
||||
|
||||
app.get("/health", async (request, response) => {
|
||||
|
||||
@@ -15,8 +15,21 @@ function parseOptionalPositiveInteger(value, name) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function parseBoolean(value, fallback = false) {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return ["1", "true", "yes", "on"].includes(String(value).toLowerCase());
|
||||
}
|
||||
|
||||
const config = {
|
||||
port: parseOptionalPositiveInteger(process.env.PORT, "PORT") || 3030,
|
||||
public: {
|
||||
apiUrl: process.env.PUBLIC_API_URL || "https://dune.api.coppnic.cc",
|
||||
uiUrl: process.env.PUBLIC_UI_URL || "https://ui.dune.api.coppnic.cc",
|
||||
forceHttps: parseBoolean(process.env.FORCE_HTTPS, true),
|
||||
},
|
||||
mongodb: {
|
||||
uri:
|
||||
process.env.MONGODB_URI || "mongodb://root:63eba009@37.60.245.70:27017",
|
||||
@@ -32,4 +45,4 @@ const config = {
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = { config, parseOptionalPositiveInteger };
|
||||
module.exports = { config, parseBoolean, parseOptionalPositiveInteger };
|
||||
|
||||
@@ -10,7 +10,8 @@ async function start() {
|
||||
const app = createApp();
|
||||
const server = app.listen(config.port, () => {
|
||||
console.log(`Dune API listening on http://localhost:${config.port}`);
|
||||
console.log(`Swagger UI available at http://localhost:${config.port}/docs`);
|
||||
console.log(`Public API URL: ${config.public.apiUrl}`);
|
||||
console.log(`Public Swagger UI URL: ${config.public.uiUrl}/docs`);
|
||||
});
|
||||
|
||||
async function shutdown(signal) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { DATASETS, LANGUAGES } = require("../datasets");
|
||||
const { config } = require("../config");
|
||||
|
||||
const datasetKeys = Object.keys(DATASETS);
|
||||
|
||||
@@ -9,7 +10,7 @@ const openApiDocument = {
|
||||
version: "1.0.0",
|
||||
description: "API for Dune: Awakening Questlog data stored in MongoDB.",
|
||||
},
|
||||
servers: [{ url: "/" }],
|
||||
servers: [{ url: config.public.apiUrl }],
|
||||
tags: [{ name: "Health" }, { name: "Data" }, { name: "Import" }],
|
||||
paths: {
|
||||
"/health": {
|
||||
|
||||
Reference in New Issue
Block a user