Skip to content

Commit

Permalink
Merge pull request ChatGPTNextWeb#697 from Yidadaa/bugfix-0410
Browse files Browse the repository at this point in the history
fix: runtime config and proxy fix
  • Loading branch information
Yidadaa authored Apr 10, 2023
2 parents ec985f6 + 6841846 commit 0f739f4
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 111 deletions.
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ RUN apk update && apk add --no-cache git

ENV OPENAI_API_KEY=""
ENV CODE=""
ARG DOCKER=true

WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
Expand Down Expand Up @@ -46,7 +45,7 @@ CMD if [ -n "$PROXY_URL" ]; then \
host=$(echo $PROXY_URL | cut -d/ -f3 | cut -d: -f1); \
port=$(echo $PROXY_URL | cut -d: -f3); \
conf=/etc/proxychains.conf; \
echo "strict_chain" >> $conf; \
echo "strict_chain" > $conf; \
echo "proxy_dns" >> $conf; \
echo "remote_dns_subnet 224" >> $conf; \
echo "tcp_read_time_out 15000" >> $conf; \
Expand Down
17 changes: 0 additions & 17 deletions app/api/access.ts

This file was deleted.

2 changes: 1 addition & 1 deletion app/api/chat-stream/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function createStream(req: NextRequest) {

const parser = createParser(onParse);
for await (const chunk of res.body as any) {
parser.feed(decoder.decode(chunk));
parser.feed(decoder.decode(chunk, { stream: true }));
}
},
});
Expand Down
21 changes: 21 additions & 0 deletions app/api/config/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NextRequest, NextResponse } from "next/server";

import { getServerSideConfig } from "../../config/server";

const serverConfig = getServerSideConfig();

// Danger! Don not write any secret value here!
// 警告!不要在这里写入任何敏感信息!
const DANGER_CONFIG = {
needCode: serverConfig.needCode,
};

declare global {
type DangerConfig = typeof DANGER_CONFIG;
}

export async function POST(req: NextRequest) {
return NextResponse.json({
needCode: serverConfig.needCode,
});
}
9 changes: 1 addition & 8 deletions app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@

require("../polyfill");

import {
useState,
useEffect,
useRef,
useCallback,
MouseEventHandler,
} from "react";
import { useState, useEffect, useRef } from "react";

import { IconButton } from "./button";
import styles from "./home.module.scss";
Expand All @@ -30,7 +24,6 @@ import { Chat } from "./chat";
import dynamic from "next/dynamic";
import { REPO_URL } from "../constant";
import { ErrorBoundary } from "./error";
import { useDebounce } from "use-debounce";

export function Loading(props: { noLogo?: boolean }) {
return (
Expand Down
12 changes: 6 additions & 6 deletions app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { Avatar } from "./chat";

import Locale, { AllLangs, changeLang, getLang } from "../locales";
import { getCurrentVersion, getEmojiUrl } from "../utils";
import { getEmojiUrl } from "../utils";
import Link from "next/link";
import { UPDATE_URL } from "../constant";
import { SearchService, usePromptStore } from "../store/prompt";
Expand Down Expand Up @@ -88,13 +88,13 @@ export function Settings(props: { closeSettings: () => void }) {

const updateStore = useUpdateStore();
const [checkingUpdate, setCheckingUpdate] = useState(false);
const currentId = getCurrentVersion();
const remoteId = updateStore.remoteId;
const hasNewVersion = currentId !== remoteId;
const currentVersion = updateStore.version;
const remoteId = updateStore.remoteVersion;
const hasNewVersion = currentVersion !== remoteId;

function checkUpdate(force = false) {
setCheckingUpdate(true);
updateStore.getLatestCommitId(force).then(() => {
updateStore.getLatestVersion(force).then(() => {
setCheckingUpdate(false);
});
}
Expand Down Expand Up @@ -224,7 +224,7 @@ export function Settings(props: { closeSettings: () => void }) {
</SettingItem>

<SettingItem
title={Locale.Settings.Update.Version(currentId)}
title={Locale.Settings.Update.Version(currentVersion ?? "unknown")}
subTitle={
checkingUpdate
? Locale.Settings.Update.IsChecking
Expand Down
27 changes: 27 additions & 0 deletions app/config/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const COMMIT_ID: string = (() => {
try {
const childProcess = require("child_process");
return (
childProcess
// .execSync("git describe --tags --abbrev=0")
.execSync("git rev-parse --short HEAD")
.toString()
.trim()
);
} catch (e) {
console.error("[Build Config] No git or not from git repo.");
return "unknown";
}
})();

export const getBuildConfig = () => {
if (typeof process === "undefined") {
throw Error(
"[Server Config] you are importing a nodejs-only module outside of nodejs",
);
}

return {
commitId: COMMIT_ID,
};
};
42 changes: 42 additions & 0 deletions app/config/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import md5 from "spark-md5";

declare global {
namespace NodeJS {
interface ProcessEnv {
OPENAI_API_KEY?: string;
CODE?: string;
PROXY_URL?: string;
VERCEL?: string;
}
}
}

const ACCESS_CODES = (function getAccessCodes(): Set<string> {
const code = process.env.CODE;

try {
const codes = (code?.split(",") ?? [])
.filter((v) => !!v)
.map((v) => md5.hash(v.trim()));
return new Set(codes);
} catch (e) {
return new Set();
}
})();

export const getServerSideConfig = () => {
if (typeof process === "undefined") {
throw Error(
"[Server Config] you are importing a nodejs-only module outside of nodejs",
);
}

return {
apiKey: process.env.OPENAI_API_KEY,
code: process.env.CODE,
codes: ACCESS_CODES,
needCode: ACCESS_CODES.size > 0,
proxyUrl: process.env.PROXY_URL,
isVercel: !!process.env.VERCEL,
};
};
1 change: 1 addition & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`;
export const UPDATE_URL = `${REPO_URL}#keep-updated`;
export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
31 changes: 3 additions & 28 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,9 @@
import "./styles/globals.scss";
import "./styles/markdown.scss";
import "./styles/highlight.scss";
import process from "child_process";
import { ACCESS_CODES, IS_IN_DOCKER } from "./api/access";
import { getBuildConfig } from "./config/build";

let COMMIT_ID: string | undefined;
try {
COMMIT_ID = process
// .execSync("git describe --tags --abbrev=0")
.execSync("git rev-parse --short HEAD")
.toString()
.trim();
} catch (e) {
console.error("No git or not from git repo.");
}
const buildConfig = getBuildConfig();

export const metadata = {
title: "ChatGPT Next Web",
Expand All @@ -26,21 +16,6 @@ export const metadata = {
themeColor: "#fafafa",
};

function Meta() {
const metas = {
version: COMMIT_ID ?? "unknown",
access: ACCESS_CODES.size > 0 || IS_IN_DOCKER ? "enabled" : "disabled",
};

return (
<>
{Object.entries(metas).map(([k, v]) => (
<meta name={k} content={v} key={k} />
))}
</>
);
}

export default function RootLayout({
children,
}: {
Expand All @@ -58,7 +33,7 @@ export default function RootLayout({
content="#151515"
media="(prefers-color-scheme: dark)"
/>
<Meta />
<meta name="version" content={buildConfig.commitId} />
<link rel="manifest" href="/site.webmanifest"></link>
<link rel="preconnect" href="https://fonts.googleapis.com"></link>
<link rel="preconnect" href="https://fonts.gstatic.com"></link>
Expand Down
8 changes: 6 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import { Analytics } from "@vercel/analytics/react";

import { Home } from "./components/home";

export default function App() {
import { getServerSideConfig } from "./config/server";

const serverConfig = getServerSideConfig();

export default async function App() {
return (
<>
<Home />
<Analytics />
{serverConfig?.isVercel && <Analytics />}
</>
);
}
2 changes: 1 addition & 1 deletion app/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export async function requestChatStream(
const resTimeoutId = setTimeout(() => finish(), TIME_OUT_MS);
const content = await reader?.read();
clearTimeout(resTimeoutId);
const text = decoder.decode(content?.value);
const text = decoder.decode(content?.value, { stream: true });
responseText += text;

const done = !content || content.done;
Expand Down
34 changes: 31 additions & 3 deletions app/store/access.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
import { queryMeta } from "../utils";

export interface AccessControlStore {
accessCode: string;
token: string;

needCode: boolean;

updateToken: (_: string) => void;
updateCode: (_: string) => void;
enabledAccessControl: () => boolean;
isAuthorized: () => boolean;
fetch: () => void;
}

export const ACCESS_KEY = "access-control";

let fetchState = 0; // 0 not fetch, 1 fetching, 2 done

export const useAccessStore = create<AccessControlStore>()(
persist(
(set, get) => ({
token: "",
accessCode: "",
needCode: true,
enabledAccessControl() {
return queryMeta("access") === "enabled";
get().fetch();

return get().needCode;
},
updateCode(code: string) {
set((state) => ({ accessCode: code }));
Expand All @@ -30,7 +37,28 @@ export const useAccessStore = create<AccessControlStore>()(
},
isAuthorized() {
// has token or has code or disabled access control
return !!get().token || !!get().accessCode || !get().enabledAccessControl();
return (
!!get().token || !!get().accessCode || !get().enabledAccessControl()
);
},
fetch() {
if (fetchState > 0) return;
fetchState = 1;
fetch("/api/config", {
method: "post",
body: null,
})
.then((res) => res.json())
.then((res: DangerConfig) => {
console.log("[Config] got config from server", res);
set(() => ({ ...res }));
})
.catch(() => {
console.error("[Config] failed to fetch config");
})
.finally(() => {
fetchState = 2;
});
},
}),
{
Expand Down
Loading

0 comments on commit 0f739f4

Please sign in to comment.