-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
329 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
# 3实现搜索结果 | ||
|
||
## 问ChatGPT的问题 | ||
|
||
现在要用 Next.js 与 chakra.ui 建`whois`站,根据如下描述与已有代码,加上缓存处理,每次查询之后的24小时内都不需要查询外部接口,可以使用外部依赖包。 | ||
|
||
### 用户案例 | ||
|
||
假设用户想要一个带 gantrol 的域名,比较想要 gantrol.com,用户主要想得到什么情报呢? | ||
|
||
- 这个域名的信息,最主要的是,有没有被注册、是否能买到 | ||
- 有没有相关域名可以注册 | ||
|
||
### 外部api | ||
|
||
数据的结构决定代码的结构,必须了解数据,才能写出符合要求的代码。 | ||
|
||
```markdown | ||
https://whois.freeaiapi.xyz/?name=${name}&suffix=${suffix} | ||
``` | ||
|
||
示例:查询 gantrol.com,被拆分为 whois.freeaiapi.xyz/?name=gantrol&suffix=com | ||
|
||
请求的返回分为两种,不清楚怎么调用接口的同学也先别急,可以用<https://whois.gantrol.com> 确认一下。 | ||
|
||
- available = true | ||
|
||
```json | ||
{ | ||
"status": "ok", | ||
"name": "gantrol", | ||
"suffix": "com", | ||
"domain": "gantrol.com", | ||
"creation_datetime": "2020-10-29T04:08:52Z", | ||
"expiry_datetime": "2024-10-29T04:08:52Z", | ||
"available": false, | ||
"info": " Domain Name: GANTROL.COM\r\n Registry Domain ID: 2568931463_DOMAIN_COM-VRSN\r\n Registrar WHOIS Server: whois.paycenter.com.cn\r\n 《省略几百词》 .\r\n" | ||
} | ||
``` | ||
|
||
- available = false | ||
|
||
```json | ||
{ | ||
"status": "ok", | ||
"name": "gantrol", | ||
"suffix": "org", | ||
"domain": "gantrol.org", | ||
"creation_datetime": "", | ||
"expiry_datetime": "", | ||
"available": true, | ||
"info": "Domain not found.\r\n>>> Last update of WHOIS database: 2023-12-05T08:58:08Z <<<\r\n\r\nTerms of Use:..《省略几百词》.\r\n" | ||
} | ||
``` | ||
|
||
### 基本界面设计 | ||
|
||
- 主页主体是Google极简风格的搜索框,商标位置先用文字“域名搜索”替代 | ||
|
||
- 用户搜索`gantrol.com` 后,网站跳转到`/whois/gantrol.com`,然后页面顶端是搜索框,其下是具体的域名信息 | ||
|
||
- "available": true, | ||
|
||
### 已有代码 | ||
|
||
#### index.js | ||
|
||
```jsx | ||
import {Flex, Heading, IconButton, Input} from "@chakra-ui/react"; | ||
import {SearchIcon} from "@chakra-ui/icons"; | ||
import {useState} from "react"; | ||
import {useRouter} from "next/router"; | ||
|
||
export default function Home() { | ||
const [domain, setDomain] = useState(''); | ||
const router = useRouter(); | ||
|
||
const handleSearch = () => { | ||
if (domain) { | ||
router.push(`/whois/${domain}`); | ||
} | ||
}; | ||
|
||
return ( | ||
<Flex | ||
direction="column" | ||
justify="center" | ||
align="center" | ||
height="100vh" | ||
> | ||
<Heading mb={4}>域名搜索</Heading> | ||
<Flex | ||
justify="center" | ||
align="center" | ||
// 添加间距 | ||
gap="2" | ||
> | ||
<Input | ||
placeholder="输入域名" | ||
value={domain} | ||
// 当输入框的值改变时,更改 domain 的值 | ||
onChange={(e) => setDomain(e.target.value)} | ||
// 基础屏幕尺寸下宽度为 90%(适用于较小屏幕的移动设备),以及中等屏幕尺寸(如平板或小型桌面显示器)下的宽度为 400px | ||
width={{base: "90%", md: "400px"}} | ||
/> | ||
<IconButton | ||
icon={<SearchIcon/>} | ||
// 为按钮添加点击事件 | ||
onClick={handleSearch} | ||
/> | ||
</Flex> | ||
</Flex> | ||
); | ||
} | ||
|
||
|
||
``` | ||
|
||
### `src/pages/api/whois.js` | ||
|
||
```javascript | ||
// 导入 Next.js 的 API 路由支持 | ||
import { NextApiRequest, NextApiResponse } from "next"; | ||
|
||
// 处理 API 请求的函数 | ||
export default async function handler(req, res) { | ||
// 从查询字符串中获取域名和后缀 | ||
const { domain } = req.query; | ||
|
||
// 检查是否提供了域名和后缀 | ||
if (!domain) { | ||
return res.status(400).json({ error: "缺少必要的参数:domain" }); | ||
} | ||
|
||
// 解析域名和后缀 | ||
const [name, suffix] = domain.split("."); | ||
|
||
// 构建外部 API 请求的 URL | ||
const apiUrl = `https://whois.freeaiapi.xyz/?name=${name}&suffix=${suffix}`; | ||
|
||
try { | ||
// 使用 fetch 发送请求到外部 API | ||
const response = await fetch(apiUrl); | ||
const data = await response.json(); | ||
|
||
// 将获取到的信息返回给客户端 | ||
res.status(200).json(data); | ||
} catch (error) { | ||
// 处理可能发生的错误 | ||
res.status(500).json({ error: "服务器错误,无法获取域名信息" }); | ||
} | ||
} | ||
``` | ||
|
||
### `src/pages/whois/[domain].js` | ||
|
||
```js | ||
import { Box, Flex, Text, Spinner, Alert, AlertIcon } from "@chakra-ui/react"; | ||
import { useRouter } from "next/router"; | ||
import { useEffect, useState } from "react"; | ||
|
||
export default function Whois() { | ||
const router = useRouter(); | ||
const { domain } = router.query; | ||
const [loading, setLoading] = useState(false); | ||
const [error, setError] = useState(null); | ||
const [domainInfo, setDomainInfo] = useState(null); | ||
|
||
useEffect(() => { | ||
if (domain) { | ||
setLoading(true); | ||
fetch(`/api/whois?domain=${domain}`) | ||
.then(res => res.json()) | ||
.then(data => { | ||
setDomainInfo(data); | ||
setLoading(false); | ||
}) | ||
.catch(error => { | ||
console.error("Error fetching domain info:", error); | ||
setError("无法获取域名信息,请稍后重试。"); | ||
setLoading(false); | ||
}); | ||
} | ||
}, [domain]); | ||
|
||
if (loading) { | ||
return <Spinner />; | ||
} | ||
|
||
if (error) { | ||
return ( | ||
<Alert status="error"> | ||
<AlertIcon /> | ||
{error} | ||
</Alert> | ||
); | ||
} | ||
|
||
return ( | ||
<Flex direction="column" align="center" p={5}> | ||
<Text fontSize="xl" mb={2}>域名信息查询结果</Text> | ||
{domainInfo && ( | ||
<Box p={4} borderWidth="1px" borderRadius="lg"> | ||
<Text><b>域名:</b> {domainInfo.domain}</Text> | ||
<Text><b>是否可注册:</b> {domainInfo.available ? "是" : "否"}</Text> | ||
{domainInfo.creation_datetime && ( | ||
<Text><b>创建时间:</b> {domainInfo.creation_datetime}</Text> | ||
)} | ||
{domainInfo.expiry_datetime && ( | ||
<Text><b>过期时间:</b> {domainInfo.expiry_datetime}</Text> | ||
)} | ||
<Text><b>详细信息:</b></Text> | ||
<Text whiteSpace="pre-wrap">{domainInfo.info}</Text> | ||
</Box> | ||
)} | ||
</Flex> | ||
); | ||
} | ||
|
||
``` | ||
|
||
## GPT 回答示例 | ||
|
||
> 注:回答不唯一 | ||
针对您的项目需求,我们可以通过添加简单的缓存逻辑来优化`whois`查询的性能。这样,每次用户进行域名查询时,我们首先检查缓存中是否存在该域名的信息,如果存在且未超过24小时,我们直接从缓存中返回数据,而不是重新查询外部API。这不仅提高了效率,也减少了对外部API的依赖和调用次数。 | ||
|
||
下面,我将为您展示如何实现这一功能: | ||
|
||
### 1. 安装外部依赖 | ||
|
||
首先,我们需要一个用于缓存的库。`node-cache`是一个简单的缓存库,非常适合我们的需求。您可以通过运行以下命令来安装它: | ||
|
||
```bash | ||
npm install node-cache | ||
``` | ||
|
||
### 2. 修改 `src/pages/api/whois.js` | ||
|
||
在此文件中,我们将添加缓存逻辑。首先,在文件顶部导入`node-cache`,并实例化一个新的缓存对象: | ||
|
||
```javascript | ||
import NodeCache from "node-cache"; | ||
const myCache = new NodeCache({ stdTTL: 86400 }); // 缓存24小时 | ||
``` | ||
|
||
接下来,修改`handler`函数以使用缓存: | ||
|
||
```javascript | ||
export default async function handler(req, res) { | ||
const { domain } = req.query; | ||
if (!domain) { | ||
return res.status(400).json({ error: "缺少必要的参数:domain" }); | ||
} | ||
|
||
// 尝试从缓存中获取数据 | ||
const cachedData = myCache.get(domain); | ||
if (cachedData) { | ||
return res.status(200).json(cachedData); | ||
} | ||
|
||
// 缓存中没有数据,继续查询外部API | ||
const [name, suffix] = domain.split("."); | ||
const apiUrl = `https://whois.freeaiapi.xyz/?name=${name}&suffix=${suffix}`; | ||
|
||
try { | ||
const response = await fetch(apiUrl); | ||
const data = await response.json(); | ||
|
||
// 将数据存储到缓存中 | ||
myCache.set(domain, data); | ||
|
||
res.status(200).json(data); | ||
} catch (error) { | ||
res.status(500).json({ error: "服务器错误,无法获取域名信息" }); | ||
} | ||
} | ||
``` | ||
|
||
### 3. 测试 | ||
|
||
现在,当用户查询一个域名时,系统会首先检查缓存中是否有该域名的信息。如果缓存中有数据,并且数据未过期(24小时内),则直接返回缓存中的数据。否则,会向外部API发送请求,并将返回的数据存储在缓存中供未来使用。 | ||
|
||
### 4. 用户案例 | ||
|
||
针对用户想要的域名信息(比如`gantrol.com`),用户现在可以得到以下信息: | ||
|
||
- 该域名是否已被注册、是否可购买 | ||
- 相关域名的可注册情况 | ||
|
||
由于我们已经添加了缓存机制,所以在24小时内对同一域名的查询不会再次调用外部API,从而加快了响应速度并减少了不必要的API调用。 | ||
|
||
以上就是对您项目中缓存功能的实现建议。希望这些信息对您有所帮助! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,31 @@ | ||
import NodeCache from "node-cache"; | ||
const myCache = new NodeCache({ stdTTL: 86400 }); // 缓存24小时 | ||
|
||
export default async function handler(req, res) { | ||
// 从查询字符串中获取域名和后缀 | ||
const { domain } = req.query; | ||
|
||
// 检查是否提供了域名和后缀 | ||
if (!domain) { | ||
return res.status(400).json({ error: "缺少必要的参数:domain" }); | ||
} | ||
|
||
// 解析域名和后缀 | ||
const [name, suffix] = domain.split("."); | ||
// 尝试从缓存中获取数据 | ||
const cachedData = myCache.get(domain); | ||
if (cachedData) { | ||
return res.status(200).json(cachedData); | ||
} | ||
|
||
// 构建外部 API 请求的 URL | ||
// 缓存中没有数据,继续查询外部API | ||
const [name, suffix] = domain.split("."); | ||
const apiUrl = `https://whois.freeaiapi.xyz/?name=${name}&suffix=${suffix}`; | ||
|
||
try { | ||
// 使用 fetch 发送请求到外部 API | ||
const response = await fetch(apiUrl); | ||
const data = await response.json(); | ||
|
||
// 将获取到的信息返回给客户端 | ||
// 将数据存储到缓存中 | ||
myCache.set(domain, data); | ||
|
||
res.status(200).json(data); | ||
} catch (error) { | ||
// 处理可能发生的错误 | ||
res.status(500).json({ error: "服务器错误,无法获取域名信息" }); | ||
} | ||
} |