Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(middleware): oops page for php bots #218

Merged
merged 6 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ const nextConfig = {
},
],
},
{
source: '/oops',
headers: [
{
key: 'cache-control',
value: 's-maxage=6000, stale-while-revalidate=30',
},
],
},
]
},
}
Expand Down
7 changes: 7 additions & 0 deletions src/app/404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ErrorPage from 'next/error'

const NotFound = () => {
return <ErrorPage statusCode={404} title="Page Not Found" />
}

export default NotFound
3 changes: 0 additions & 3 deletions src/app/[community]/error.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
'use client'

import ErrorPage from '@/widgets/ErrorPage'

const ErrorCommunity = () => {
return (
<div>
<h2>Community Page Error</h2>
<ErrorPage />
</div>
)
}
Expand Down
35 changes: 35 additions & 0 deletions src/app/oops/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use client'

import { useRouter } from 'next/navigation'

import { ROUTE } from '@/constant/route'

import Button from '@/widgets/Buttons/Button'
import { LinkAble } from '@/widgets/Common'

import { Wrapper, InnerWrapper, Footer } from './styles'
// import ErrorPage from 'next/error'

const OopsPage = () => {
const router = useRouter()

return (
<Wrapper>
<InnerWrapper>
<h1>Oops</h1>
<p>the content you looking for is not exist</p>
<Footer>
<Button type="primary" right={20} onClick={() => router.back()}>
返回
</Button>

<LinkAble href={`/${ROUTE.HOME}`}>
<Button ghost>Groupher 社区</Button>
</LinkAble>
</Footer>
</InnerWrapper>
</Wrapper>
)
}

export default OopsPage
18 changes: 18 additions & 0 deletions src/app/oops/styles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Link from 'next/link'

import styled, { css, theme } from '@/css'

export const Wrapper = styled.div`
${css.column('align-both')};
width: 100%;
height: 68vh;
position: relative;
`
export const InnerWrapper = styled.div`
${css.column('align-start')};
position: relative;
`
export const Footer = styled.div`
${css.row()};
margin-top: 20px;
`
21 changes: 16 additions & 5 deletions src/app/providers/RootStoreProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use client'

import { FC, ReactNode, memo } from 'react'
import { FC, ReactNode, memo, useEffect } from 'react'
import { Provider } from 'mobx-react'
import { enableStaticRendering } from 'mobx-react-lite'

import { useRouter } from 'next/navigation'

import { useStore } from '@/stores/init'

import {
Expand Down Expand Up @@ -31,6 +33,19 @@ type TProps = {

const RootStoreWrapper: FC<TProps> = ({ children }) => {
const userHasLogin = false
// const router = useRouter()

// useEffect(() => {
// const handleRedirect = async () => {
// if (!community) {
// await router.push('/oops')
// }
// }

// handleRedirect()
// }, [])

const theme = useThemeFromURL()

const metric = useMetric()
const activeThread = useThreadParam()
Expand All @@ -47,10 +62,6 @@ const RootStoreWrapper: FC<TProps> = ({ children }) => {
const wallpaper = useWallpaper(community)
const filterSearchParams = useFilterSearchParams()

// NOTE: 目前在没有启动后端的情况下,如果这行代码出现在 useCommunity 之前,会导致 build 后的代码疯狂
// post 到 /GraphiQL, 奇怪的行为。。,很怀疑是 URQL 客户端的 Bug ..
const theme = useThemeFromURL()

const store = useStore({
metric,
articles: {
Expand Down
18 changes: 9 additions & 9 deletions src/app/queries/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { THREAD } from '@/constant/thread'
import URL_PARAM from '@/constant/url_param'
import { nilOrEmpty } from '@/validator'
import {
LANDIN_ROUTES,
STATIC_ROUTES,
DASHBOARD_ROUTE,
DASHBOARD_BASEINFO_ROUTE,
DASHBOARD_SEO_ROUTE,
Expand All @@ -44,23 +44,23 @@ export const commonRes = (result): TGQSSRResult => {
}
}

export const useIsStaticQuery = (): boolean => {
export const useIsFrameworkQuery = (): boolean => {
const pathname = usePathname()

return startsWith('/_next', pathname) || startsWith('/_vercel', pathname)
}

export const useLandingPages = (): boolean => {
export const useIsStaticPages = (): boolean => {
const pathname = usePathname()

return includes(pathname, LANDIN_ROUTES)
return includes(pathname, STATIC_ROUTES)
}

export const useSkipLandingQuery = (): boolean => {
const isStaticQuery = useIsStaticQuery()
const isLandingPages = useLandingPages()
export const useSkipStaticQuery = (): boolean => {
const isFrameworkQuery = useIsFrameworkQuery()
const isStaticPages = useIsStaticPages()

return isStaticQuery || isLandingPages
return isFrameworkQuery || isStaticPages
}

export const useCommunityParam = (): string => {
Expand Down Expand Up @@ -114,7 +114,7 @@ export const useArticleParams = (): TArticleParams => {
}

export const parseCommunity = (communityPath: string): string => {
if (!communityPath) return HCN
if (!communityPath) return null // HCN
if (communityPath === '_next') return null

return communityPath
Expand Down
24 changes: 12 additions & 12 deletions src/app/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ import {
useArticleParams,
useCommunityParam,
useThreadParam,
useIsStaticQuery,
useSkipLandingQuery,
useIsFrameworkQuery,
useSkipStaticQuery,
useIdParam,
//
parseWallpaper,
Expand Down Expand Up @@ -71,7 +71,7 @@ export const useMetric = (): TMetric => {
}

// export const useSession = (): TSessionRes => {
// const isStaticQuery = useIsStaticQuery()
// const isStaticQuery = useIsFrameworkQuery()

// const [result] = useQuery({
// query: P.sessionState,
Expand Down Expand Up @@ -99,7 +99,7 @@ export const useMetric = (): TMetric => {

export const useCommunity = (userHasLogin: boolean): TCommunityRes => {
const slug = useCommunityParam()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()

const [result] = useQuery({
query: P.community,
Expand All @@ -118,7 +118,7 @@ export const useCommunity = (userHasLogin: boolean): TCommunityRes => {

export const useTags = (): TTagsRes => {
const community = useCommunityParam()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()
const thread = useThreadParam()

const [result] = useQuery({
Expand All @@ -138,7 +138,7 @@ export const useTags = (): TTagsRes => {
export const usePagedPosts = (userHasLogin: boolean): TPagedPostsRes => {
const filter = usePagedArticlesParams()
const thread = useThreadParam()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()
const id = useIdParam()

const [result] = useQuery({
Expand All @@ -155,7 +155,7 @@ export const usePagedPosts = (userHasLogin: boolean): TPagedPostsRes => {

export const usePagedChangelogs = (userHasLogin: boolean): TPagedChangelogsRes => {
const filter = usePagedArticlesParams()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()
const thread = useThreadParam()

const [result] = useQuery({
Expand All @@ -172,7 +172,7 @@ export const usePagedChangelogs = (userHasLogin: boolean): TPagedChangelogsRes =

export const usePost = (userHasLogin: boolean): TPostRes => {
const { community, id } = useArticleParams()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()
const thread = useThreadParam()

const [result] = useQuery({
Expand All @@ -189,7 +189,7 @@ export const usePost = (userHasLogin: boolean): TPostRes => {

export const useChangelog = (userHasLogin: boolean): TChangelogRes => {
const { community, id } = useArticleParams()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()
const thread = useThreadParam()

const [result] = useQuery({
Expand All @@ -206,7 +206,7 @@ export const useChangelog = (userHasLogin: boolean): TChangelogRes => {

export const useGroupedKanbanPosts = (userHasLogin: boolean): TGroupedKanbanPostsRes => {
const community = useCommunityParam()
const skipLandingQuery = useSkipLandingQuery()
const skipLandingQuery = useSkipStaticQuery()
const thread = useThreadParam()

const [result] = useQuery({
Expand All @@ -225,7 +225,7 @@ export const useGroupedKanbanPosts = (userHasLogin: boolean): TGroupedKanbanPost
* wallpaper related settings for all page
*/
export const useWallpaper = (community: TCommunity): TParsedWallpaper => {
const isStaticQuery = useIsStaticQuery()
const isStaticQuery = useIsFrameworkQuery()

// @ts-ignore
return !isStaticQuery ? parseWallpaper(community) : {}
Expand All @@ -235,7 +235,7 @@ export const useWallpaper = (community: TCommunity): TParsedWallpaper => {
* general dashboard settings for all page
*/
export const useDashboard = (community: TCommunity): TParseDashboard => {
const isStaticQuery = useIsStaticQuery()
const isStaticQuery = useIsFrameworkQuery()
const pathname = usePathname()

// @ts-ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const CommunityBrief: FC<TProps> = ({ show }) => {

<Space right={15} />
<Label>帖子</Label>
<Count>{meta.postsCount}</Count>
<Count>{meta?.postsCount}</Count>
</InfoBar>
</Brief>
</Wrapper>
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useMetric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { includes } from 'ramda'
import type { TMetric } from '@/spec'
import METRIC from '@/constant/metric'
import { BANNER_LAYOUT } from '@/constant/layout'
import { LANDIN_ROUTES } from '@/constant/route'
import { STATIC_ROUTES } from '@/constant/route'

/**
* NOTE: should use observer to wrap the component who use this hook
Expand All @@ -21,7 +21,7 @@ const useMetric = (): TMetric => {

const pathname = usePathname()

if (includes(pathname, LANDIN_ROUTES)) {
if (includes(pathname, STATIC_ROUTES)) {
return METRIC.HOME
}

Expand Down
21 changes: 11 additions & 10 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

import { applyMiddleware } from './middlewares/helper'
// import { themeMiddleware } from './middlewares/theme'
import { queryWhitelistMiddleware } from './middlewares/query-whitelist'
import { oopsMiddleware } from './middlewares/oops'
import { avoidScanMiddleware } from './middlewares/avoid-scan'

export function middleware(request: NextRequest) {
// const response = themeMiddleware(request)
// if (response instanceof NextResponse) return response
// middleware in this array will be applied in order
const middlewareFunctions = [
avoidScanMiddleware,
oopsMiddleware,
queryWhitelistMiddleware,
// ... more middlewares
]

// whitelist the query parameters to improve CDN caching
const response = queryWhitelistMiddleware(request)
if (response instanceof NextResponse) return response

// return response instanceof NextResponse ? response : NextResponse.next()

return NextResponse.next()
return applyMiddleware(middlewareFunctions, request)
}
17 changes: 17 additions & 0 deletions src/middlewares/avoid-scan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

import { ROUTE } from '@/constant/route'

export function avoidScanMiddleware(req: NextRequest) {
const { pathname } = req.nextUrl

// 检查pathname是否以.php或.php7结束
if (pathname.endsWith('.php') || pathname.endsWith('.php7')) {
// 重定向到/oops页面
return NextResponse.redirect(new URL(ROUTE.OOPS, req.url))
}

// 如果路径不以.php或.php7结束,则继续处理后续中间件
return NextResponse.next()
}
20 changes: 20 additions & 0 deletions src/middlewares/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { NextResponse } from 'next/server'

/**
* chain the middlewares and apply them to the request
*/
export function applyMiddleware(middlewareFns, req) {
for (const middlewareFn of middlewareFns) {
const response = middlewareFn(req)
// 如果中间件执行结果是重定向或重写,那么就返回该响应并且不再执行后续中间件

if (response instanceof NextResponse) {
// 检查状态码是否代表重定向
if (response.status >= 300 && response.status < 400) {
return response
}
}
}

return NextResponse.next()
}
17 changes: 17 additions & 0 deletions src/middlewares/oops.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

import { ROUTE } from '@/constant/route'

export function oopsMiddleware(req: NextRequest) {
const { pathname } = req.nextUrl

// 若路径为 /404,则重定向到自定义404页面
// just demo
if (pathname === '/404') {
// return NextResponse.rewrite(new URL(ROUTE.OOPS, req.url))
return NextResponse.redirect(new URL(ROUTE.OOPS, req.url))
}

return NextResponse.next()
}
Loading
Loading