Skip to content

Commit

Permalink
api proxy, refresh token SSR fix
Browse files Browse the repository at this point in the history
  • Loading branch information
NookieGrey committed Feb 5, 2025
1 parent 5626fd7 commit dd84fb8
Show file tree
Hide file tree
Showing 35 changed files with 764 additions and 19 deletions.
2 changes: 1 addition & 1 deletion i18n.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function createI18nInstance() {
.init({
fallbackLng: "en",
preload: ["en", "ru"],
ns: ["common", "auth"],
ns: ["common", "auth", "chat"],
defaultNS: "common",
backend: {
loadPath: __dirname + "/locales/{{lng}}/{{ns}}.json",
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
</head>
<body>
<div id="sharebook"><!--home-body--></div>
<script src="./src/entry-client.tsx" type="module"></script>
<script src="/src/entry-client.tsx" type="module"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions locales/ru/chat.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "Чаты"
}
31 changes: 31 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
"dependencies": {
"@reduxjs/toolkit": "^2.5.1",
"antd": "^5.23.0",
"classnames": "^2.5.1",
"compression": "^1.7.5",
"cookie-parser": "^1.4.7",
"cross-env": "^7.0.3",
"express": "^4.21.2",
"express-http-proxy": "^2.1.1",
"i18next": "^24.2.2",
"i18next-browser-languagedetector": "^8.0.2",
"i18next-fs-backend": "^2.6.0",
Expand Down
25 changes: 22 additions & 3 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import express from "express";
import { createI18nInstance } from "./i18n.server.js";
import i18nextMiddleware from "i18next-http-middleware";
import cookieParser from "cookie-parser";
import proxy from "express-http-proxy";

// Constants
const isProduction = process.env.NODE_ENV === "production";
Expand All @@ -18,6 +19,22 @@ const templateHtml = isProduction
const app = express();
app.use(cookieParser());

app.use(
"/api",
proxy("https://194.67.125.199:8443/", {
userResHeaderDecorator(headers, userReq, userRes, proxyReq, proxyRes) {
if (
(userReq.url === "/auth" || userReq.url === "/refresh") &&
userRes.statusCode === 200
) {
headers["set-cookie"][0] += "; path=/";
}
// recieves an Object of headers, returns an Object of headers.
return headers;
},
}),
);

// Add Vite or respective production middlewares
/** @type {import('vite').ViteDevServer | undefined} */
let vite;
Expand Down Expand Up @@ -46,8 +63,6 @@ app.use((req, res, next) => {

// Serve HTML
app.use("*", async (req, res) => {
console.log(req.cookies);

try {
const url = req.originalUrl.replace(base, "/");

Expand All @@ -70,7 +85,11 @@ app.use("*", async (req, res) => {
render = (await import("./dist/server/entry-server.js")).render;
}

const rendered = await render(url, req.i18n);
const rendered = await render(url, req.i18n, req.cookies);

if (rendered.returnCookie) {
res.set("Set-Cookie", `${rendered.returnCookie};path=/`);
}

const html = template
.replace(
Expand Down
2 changes: 2 additions & 0 deletions src/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { HeaderComponent } from "./components/Header";
import { Auth } from "./pages/auth";
import { Favourites } from "./pages/favourites/Favourites.tsx";
import { CreateBook } from "./pages/createBook";
import { Chat } from "./pages/chat/Chat.tsx";

const Router = import.meta.env.SSR ? StaticRouter : BrowserRouter;

Expand All @@ -17,6 +18,7 @@ export function AppRouter({ location }: { location: string }) {
<Route path="/auth" element={<Auth />} />
<Route path="/favourites" element={<Favourites />} />
<Route path="/createBook" element={<CreateBook />} />
<Route path="/chats" element={<Chat />} />
<Route path={"*"} element={<div>404 page not found</div>} />
</Routes>
</Router>
Expand Down
3 changes: 3 additions & 0 deletions src/antdConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const antdThemeConfig: ThemeConfig = {
controlHeight: 40,
paddingContentHorizontal: 25,
},
List: {
itemPadding: "12px",
},
Input: {
colorText: "#000000",
activeBorderColor: "rgba(42, 127, 255, 80)",
Expand Down
27 changes: 24 additions & 3 deletions src/entry-server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,27 @@ import type Entity from "@ant-design/cssinjs/es/Cache";
import type { i18n } from "i18next";
import { setupStore } from "./store.ts";
import { sharebookApi } from "./services/api/sharebookApi.ts";

export async function render(location: string, i18n: i18n) {
import {
setAccessToken,
setRefreshCookie,
setReturnCookie,
} from "./services/auth/authSlice.tsx";

export async function render(
location: string,
i18n: i18n,
cookie: Record<string, string>,
) {
const cache: Entity = createCache();

const store = setupStore();

const cookieString = Object.entries(cookie)
.map(([key, value]) => `${key}=${value}`)
.join(";");

store.dispatch(setRefreshCookie(cookieString));

const element = (
<App cache={cache} location={location} i18n={i18n} store={store} />
);
Expand All @@ -19,11 +34,17 @@ export async function render(location: string, i18n: i18n) {

await Promise.all(store.dispatch(sharebookApi.util.getRunningQueriesThunk()));

const returnCookie = store.getState().auth?.returnCookie;

store.dispatch(setRefreshCookie(null));
store.dispatch(setReturnCookie(null));
store.dispatch(setAccessToken(null));

const body = renderToString(element);

const head = extractStyle(cache);

const state = store.getState();

return { body, head, state };
return { body, head, state, returnCookie };
}
18 changes: 18 additions & 0 deletions src/pages/chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import styles from "./chat.module.scss";
import { ChatUserList } from "./userList";
import { ChatCurrentUser } from "./currentUser";
import { ChatInput } from "./input";
import { ChatBody } from "./body";

export function Chat() {
return (
<div className={styles.container}>
<ChatUserList />
<div className={styles.chatBodyWrapper}>
<ChatCurrentUser />
<ChatBody />
<ChatInput />
</div>
</div>
);
}
24 changes: 24 additions & 0 deletions src/pages/chat/body/ChatBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import styles from "./chatBody.module.scss";
import { useAppSelector } from "../../../store.ts";
import { useGetCorrespondenceQuery } from "../../../services/api/sharebookApi.ts";
import { ChatMessage } from "../chatMessage";

export function ChatBody() {
const activeChatId = useAppSelector((state) => state.chat.activeId);

const response = useGetCorrespondenceQuery({
firstUserId: "6",
secondUserId: "4",
zone: 4,
});

if (!activeChatId) return <div className={styles.centered}>Кому писать?</div>;

return (
<div className={styles.scroll}>
{response.currentData?.map((item) => (
<ChatMessage key={item.messageId} message={item} profileId={6} />
))}
</div>
);
}
23 changes: 23 additions & 0 deletions src/pages/chat/body/chatBody.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.wrapper {
flex: 1;
display: flex;
flex-direction: column;
}

.blank {
flex: 1;
}

.centered {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}

.scroll {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
1 change: 1 addition & 0 deletions src/pages/chat/body/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ChatBody } from "./ChatBody.tsx";
22 changes: 22 additions & 0 deletions src/pages/chat/chat.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.container {
max-width: 1400px;
margin: 0 auto;
height: calc(100vh - 66px);
display: flex;
}

.chatBodyWrapper {
flex: 1;
display: flex;
flex-direction: column;
align-items: stretch;
position: relative;
}

.dropdownOverlay {
backdrop-filter: blur(50px);

ul {
margin-top: 2px !important;
}
}
19 changes: 19 additions & 0 deletions src/pages/chat/chatMessage/ChatMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import styles from "./chatMessage.module.scss";
import { MessageDto } from "../../../services/api/sharebookApi.ts";
import cn from "classnames";

interface ChatMessageProps {
message: MessageDto;
profileId: string | number;
}

export function ChatMessage(props: ChatMessageProps) {
return (
<div className={cn(styles.wrapper, props.profileId === 6 && styles.own)}>
{props.message.text}
<span className={styles.time}>
{props.message.departureDate?.split("T")[1].slice(0, 5)}
</span>
</div>
);
}
23 changes: 23 additions & 0 deletions src/pages/chat/chatMessage/chatMessage.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.wrapper {
border-radius: 12px;
background: #F1F4F6;
padding: 10px 40px 10px 15px;
margin-bottom: 16px;
max-width: 530px;
width: fit-content;
position: relative;

.time {
position: absolute;
right: 6px;
bottom: 6px;
font-size: 12px;
line-height: 15px;
}

&.own {
margin-left: auto;
background: var(--ant-color-primary);
color: #fff;
}
}
1 change: 1 addition & 0 deletions src/pages/chat/chatMessage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ChatMessage } from "./ChatMessage.tsx";
23 changes: 23 additions & 0 deletions src/pages/chat/chatSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

interface ChatState {
activeId: string | null;
}

const initialState: ChatState = {
activeId: null,
};

const chatSlice = createSlice({
name: "chat",
initialState,
reducers: {
setActiveId(state, action: PayloadAction<string>) {
state.activeId = action.payload;
},
},
});

export const { setActiveId } = chatSlice.actions;

export const chatReducer = chatSlice.reducer;
Loading

0 comments on commit dd84fb8

Please sign in to comment.