使用Umami API获取访问数据
2023年12月5日 2024年2月13日
说明
- 获取用户Token和网站ID
- Hugo使用Node.js包
- 使用用户Token和API获取网站数据
- 跨域请求资源
- 浏览器关闭跨域检查
- Hugo挂载文件夹
使用Postman获取用户Token
网页使用过程中, 用户往往在页面操作, 触发后端接口调用. 而在开发过程中, 后端测试接口是否能正常工作, 在和前端对接前, 常常会使用Postman发送请求, 接由后端处理.
Postman使用起来并不复杂, 需要在官网注册帐号. 每次使用前登录帐号, 可以使用之前创建的方法
Postman - UI
填写POST
拷贝用户token
获取网站ID
访问 https://umami.enjoy61.com
入口
网站ID
安装Node.js包axios
不安也可以
- 去到Hugo项目执行: 目录中出现
package.json
和package-lock.json
文件; 每次在当前目录安装包, 包相关信息会被写入
1npm init -y
- 安装axios
1npm install axios --save-dev
创建JavaScript脚本文件, 负责Umami相关逻辑
我放在header中
1{{ $built := resources.Get "js/umami.js" | js.Build "main-umami.js" | minify | fingerprint "sha512" }} 2{{ with $built }} 3 <script src="{{ $built.RelPermalink }}" integrity="{{ $built.Data.Integrity }}" crossorigin="anonymous" defer></script> 4{{ end }}
使用axios发送Get请求
1const url = 'https://umami.enjoy61.com'; 2const axios = require('axios'); 3const token = "<用户token>"; 4const website_id = "<网站ID>";
获取访问量和访客数
- 添加两个html元素, 用来存放访问量和访客数
1<span>本站总访问量<a id="pageview"></a>次 · 总访客数<a id="visitor"></a>人</span>
- 获取访问量和访客数
1function get_website_stat(token) 2{ 3 // console.log("ok2"); 4 var cur_time = Date.parse(new Date()); 5 const url_final = url + "/api/websites/" + website_id + "/pageviews?startAt=0&endAt=" + cur_time + "&unit=year"; 6 7 axios.get(url_final, {headers : {'Authorization' : 'Bearer ' + token, 'mode' : 'cors'}}) 8 .then(response => { 9 // console.log(response.data); 10 update_stat(response.data.pageviews, response.data.sessions); 11 }) 12 .catch(error => { 13 console.log("error2"); 14 // console.log(error); 15 }); 16}
- 设置到元素
1function update_stat(pageviews, sessions) 2{ 3 var pageview_num = 0; 4 for (i = 0; i < pageviews.length; ++i) 5 { 6 pageview_num += pageviews[i].y; 7 } 8 9 var visitor_num = 0; 10 for (i = 0; i < sessions.length; ++i) 11 { 12 visitor_num += sessions[i].y; 13 } 14 // console.log(pageview_num, visitor_num); 15 16 const pageview_elem = document.getElementById("pageview"); 17 pageview_elem.innerText = pageview_num; 18 19 const visitor_elem = document.getElementById("visitor"); 20 visitor_elem.innerText = visitor_num; 21}
- 调用
1get_website_stat(token);
获取页面阅读数
- 添加html元素, 存放阅读量
1<a id="single-pageview"></a>
- 获取页面阅读数
1function get_single_pageview(token) 2{ 3 // console.log("ok2"); 4 var cur_time = Date.parse(new Date()); 5 6 const url_local = encodeURIComponent(window.location.pathname); 7 // console.log(url_local); 8 const url_final = url + "/api/websites/" + website_id + "/stats?startAt=0&endAt=" + cur_time + "&url=" + url_local; 9 10 axios.get(url_final, {headers : {'Authorization' : 'Bearer ' + token, 'mode' : 'cors'}}) 11 .then(response => { 12 // console.log(response.data.pageviews.value); 13 update_single_pageview(response.data.pageviews.value); 14 }) 15 .catch(error => { 16 console.log("error2"); // console.log(error); 17 }); 18}
- 设置到元素
1function update_single_pageview(times) 2{ 3 const pageview_elem = document.getElementById("single-pageview"); 4 if (pageview_elem) 5 { 6 pageview_elem.innerText = times; 7 } 8}
- 调用
1get_single_pageview(token);
跨域请求
向指定页面发送请求, 如果满足以下条件之一, 则为跨域请求:
- 域名不同(包括子域不同)
- 协议不同
- 端口不同
同源策略
Same-origin policy
同源策略
浏览器允许某个网页访问另一个网页的数据, 前提是这两个网页必须有相同的URI, 主机名和端口号, 即两个网页同源.
该策略仅用于脚本.
跨域资源共享
跨域资源共享
Cross-origin resource sharing
页面能够自由地使用其他源的数据.
但一些跨域请求常常会被同源策略禁止.
使用跨域请求获取Token
会被浏览器禁止, 也即是为什么使用Postman而不是在代码中发送请求
如果非要在代码中完成, 需要对浏览器设置
为Nginx配置跨域
-
目前是没有在Nginx配置CORS的
-
获取token失败, 但获取网站数据成功: 服务端的CORS配置在Umami不在Nginx
-
其他情形可以在Nginx配置CORS, 当前仅作示例
/etc/nginx/sites-avaliable/umami
请求资源的目的地为
https://umami.enjoy61.com
, 则修改配置文件umami1location / { 2 add_header Access-Control-Allow-Origin *; 3}
-
Access-Control-Allow-Origin即允许提出跨域资源共享的源; 这里配置
*
属于充分不必要 -
如此配置后, 浏览器仍旧会报错, 告知Access-Control-Allow-Origin的值为
*,*
一则我们的配置生效了, 其次, 发现Umami服务端已对CORS作出了处理
-
浏览器关闭同源策略
macOS
仅作了解, 会降低浏览器安全性
-
在桌面创建文件夹
disable
, 执行命令1open -n /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir=/Users/<用户名>/Desktop/disabled
-
出现如下提示即关闭成功
-
此时可在代码中发送请求获取用户token
1const user_info = { 2 'username' : 'admin', 3 'password' : '<umami密码>' 4}; 5 6function get_user_token() 7{ 8 const url_token = url + "/api/auth/login"; 9 axios.post(url_token, user_info) 10 .then(response => { 11 console.log("ok1", response.data.token); 12 console.log(response.data.user); 13 }) 14 .catch(error => { 15 console.log("error1"); 16 // console.log(error); 17 }); 18} 19get_user_token();
-
也可使用hoppscotch获取token
Hoppscotch
不在代码中获取token也是有好处的. 网页上可以看到JavaScript代码, 如果使用用户名和密码获取token, 即意味着要将二者写到代码里. JavaScript是很难支持读写文件的.
Hugo挂载文件夹
Hugo - Module configurations: mounts
- 只有Hugo项目中的
node_modules
可以被直接识别,themes/tess/node_modules
则不行 - 偶尔, 会用到Node.js包的其他文件
- 将mermaid挂载到
assets/js/vendor/mermaid
1[module] 2[[module.mounts]] 3source = "node_modules/mermaid" 4target = "assets/js/vendor/mermaid"
便签
- | |
---|---|
Hugo - Minify | 减小资源体积 |
在Hugo中使用highlight.js | |
Hugo - mount | |
JS中文乱码 | |
Umami - 事件 | |
阅读量图标 | |
axios的get和post | |
axios | |
Node.js发送请求 | |
JS - fetch | |
使用fetch | |
HTML空格 | |
Nginx配置CORS | |
预检请求 |