v0.1.6 — fix hit tracking: default 302, no-cache headers, 301-warning in UI
This commit is contained in:
parent
8fe9f13c56
commit
d695d4c8c9
6 changed files with 26 additions and 9 deletions
|
|
@ -59,7 +59,10 @@ export default async function DomainDetailPage({ params }: { params: Promise<{ i
|
|||
) : "—"}
|
||||
</Row>
|
||||
{group && <Row k="Gruppe"><Badge variant="blue">{group.name}</Badge></Row>}
|
||||
<Row k="Code">{domain.redirect_code}</Row>
|
||||
<Row k="Code">
|
||||
{domain.redirect_code}
|
||||
{domain.redirect_code === 301 && <span className="ml-1 text-[10px] text-amber-400" title="301 wird vom Browser gecacht">⚠</span>}
|
||||
</Row>
|
||||
<Row k="Pfad übernehmen">{domain.preserve_path ? "ja" : "nein"}</Row>
|
||||
<Row k="www-Subdomain">{domain.include_www ? "ja" : "nein"}</Row>
|
||||
<Row k="Verifiziert">{domain.verified_at ? new Date(domain.verified_at).toLocaleString("de-DE") : "—"}</Row>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default function NewDomainPage() {
|
|||
const [targetMode, setTargetMode] = useState<"url" | "group">("url");
|
||||
const [targetUrl, setTargetUrl] = useState("");
|
||||
const [groupId, setGroupId] = useState<number | "">("");
|
||||
const [redirectCode, setRedirectCode] = useState<301 | 302>(301);
|
||||
const [redirectCode, setRedirectCode] = useState<301 | 302>(302);
|
||||
const [preservePath, setPreservePath] = useState(true);
|
||||
const [includeWww, setIncludeWww] = useState(true);
|
||||
const [groups, setGroups] = useState<Group[]>([]);
|
||||
|
|
@ -152,9 +152,14 @@ export default function NewDomainPage() {
|
|||
onChange={(e) => setRedirectCode(Number(e.target.value) as 301 | 302)}
|
||||
className="flex h-9 w-full rounded-md border border-input bg-zinc-950 px-3 py-1 text-sm text-zinc-100"
|
||||
>
|
||||
<option value={302} className="bg-zinc-900 text-zinc-100">302 Temporär (empfohlen)</option>
|
||||
<option value={301} className="bg-zinc-900 text-zinc-100">301 Permanent</option>
|
||||
<option value={302} className="bg-zinc-900 text-zinc-100">302 Temporär</option>
|
||||
</select>
|
||||
{redirectCode === 301 && (
|
||||
<p className="text-[11px] text-amber-400">
|
||||
⚠ 301 wird vom Browser gecacht — Folge-Aufrufe gehen direkt zum Ziel ohne hier gezählt zu werden.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-end gap-4">
|
||||
<label className="flex items-center gap-2 text-sm">
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default function GroupsPage() {
|
|||
const [open, setOpen] = useState(false);
|
||||
const [name, setName] = useState("");
|
||||
const [targetUrl, setTargetUrl] = useState("");
|
||||
const [code, setCode] = useState<301 | 302>(301);
|
||||
const [code, setCode] = useState<301 | 302>(302);
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
|
|
@ -90,9 +90,12 @@ export default function GroupsPage() {
|
|||
<div className="space-y-2">
|
||||
<Label htmlFor="code">Status-Code</Label>
|
||||
<select id="code" value={code} onChange={(e) => setCode(Number(e.target.value) as 301 | 302)} className="flex h-9 w-full rounded-md border border-input bg-zinc-950 px-3 py-1 text-sm text-zinc-100">
|
||||
<option value={302} className="bg-zinc-900 text-zinc-100">302 Temporär (empfohlen)</option>
|
||||
<option value={301} className="bg-zinc-900 text-zinc-100">301 Permanent</option>
|
||||
<option value={302} className="bg-zinc-900 text-zinc-100">302 Temporär</option>
|
||||
</select>
|
||||
{code === 301 && (
|
||||
<p className="text-[11px] text-amber-400">⚠ 301 wird vom Browser gecacht — Hits gehen verloren.</p>
|
||||
)}
|
||||
</div>
|
||||
{error && <p className="text-sm text-destructive">{error}</p>}
|
||||
<div className="flex justify-end">
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ function ensureSchema(db: Database.Database) {
|
|||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
target_url TEXT NOT NULL,
|
||||
redirect_code INTEGER NOT NULL DEFAULT 301,
|
||||
redirect_code INTEGER NOT NULL DEFAULT 302,
|
||||
created_by INTEGER REFERENCES users(id),
|
||||
created_at INTEGER NOT NULL
|
||||
);
|
||||
|
|
@ -44,7 +44,7 @@ function ensureSchema(db: Database.Database) {
|
|||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
target_url TEXT,
|
||||
group_id INTEGER REFERENCES domain_groups(id) ON DELETE SET NULL,
|
||||
redirect_code INTEGER NOT NULL DEFAULT 301,
|
||||
redirect_code INTEGER NOT NULL DEFAULT 302,
|
||||
preserve_path INTEGER NOT NULL DEFAULT 1,
|
||||
include_www INTEGER NOT NULL DEFAULT 1,
|
||||
created_by INTEGER REFERENCES users(id),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "corex-nexredirect",
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.6",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "tsx watch server.ts",
|
||||
|
|
|
|||
|
|
@ -41,7 +41,13 @@ app.prepare().then(() => {
|
|||
const target = resolved.preserve_path
|
||||
? resolved.target_url + (parsedUrl.path || "")
|
||||
: resolved.target_url;
|
||||
res.writeHead(resolved.redirect_code || 301, { Location: target });
|
||||
res.writeHead(resolved.redirect_code || 302, {
|
||||
Location: target,
|
||||
// Forbid caching so every hit reaches us for analytics.
|
||||
"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
|
||||
Pragma: "no-cache",
|
||||
Expires: "0",
|
||||
});
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue