六一的部落格


关关难过关关过,前路漫漫亦灿灿。




说明

  1. 获取用户Token和网站ID
  2. Hugo使用Node.js包
  3. 使用用户Token和API获取网站数据
  4. 跨域请求资源
  5. 浏览器关闭跨域检查
  6. Hugo挂载文件夹

使用Postman获取用户Token

网页使用过程中, 用户往往在页面操作, 触发后端接口调用. 而在开发过程中, 后端测试接口是否能正常工作, 在和前端对接前, 常常会使用Postman发送请求, 接由后端处理.

Postman使用起来并不复杂, 需要在官网注册帐号. 每次使用前登录帐号, 可以使用之前创建的方法


Postman - UI



填写POST


拷贝用户token



获取网站ID

访问 https://umami.enjoy61.com

入口


网站ID



安装Node.js包axios

不安也可以

  1. 去到Hugo项目执行: 目录中出现 package.jsonpackage-lock.json 文件; 每次在当前目录安装包, 包相关信息会被写入
    1npm init -y
  2. 安装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请求

Umami - Website statistics

1const url = 'https://umami.enjoy61.com';
2const axios = require('axios');
3const token = "<用户token>";
4const website_id = "<网站ID>";

获取访问量和访客数

  1. 添加两个html元素, 用来存放访问量和访客数
    1<span>本站总访问量<a id="pageview"></a>次 · 总访客数<a id="visitor"></a></span>
  2. 获取访问量和访客数
     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}
  3. 设置到元素
     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}
  4. 调用
    1get_website_stat(token);

获取页面阅读数

  1. 添加html元素, 存放阅读量
    1<a id="single-pageview"></a>
  2. 获取页面阅读数
     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}
  3. 设置到元素
    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}
  4. 调用
    1get_single_pageview(token);

跨域请求

向指定页面发送请求, 如果满足以下条件之一, 则为跨域请求:

  1. 域名不同(包括子域不同)
  2. 协议不同
  3. 端口不同

同源策略

Same-origin policy

同源策略

浏览器允许某个网页访问另一个网页的数据, 前提是这两个网页必须有相同的URI, 主机名和端口号, 即两个网页同源.

该策略仅用于脚本.


跨域资源共享

跨域资源共享 Cross-origin resource sharing

页面能够自由地使用其他源的数据.

但一些跨域请求常常会被同源策略禁止.


使用跨域请求获取Token

会被浏览器禁止, 也即是为什么使用Postman而不是在代码中发送请求

如果非要在代码中完成, 需要对浏览器设置


为Nginx配置跨域

  1. 目前是没有在Nginx配置CORS的

  2. 获取token失败, 但获取网站数据成功: 服务端的CORS配置在Umami不在Nginx

  3. 其他情形可以在Nginx配置CORS, 当前仅作示例

    /etc/nginx/sites-avaliable/umami

    请求资源的目的地为 https://umami.enjoy61.com , 则修改配置文件umami

    1location / {
    2    add_header Access-Control-Allow-Origin *;
    3}
    1. Access-Control-Allow-Origin即允许提出跨域资源共享的源; 这里配置 * 属于充分不必要

    2. 如此配置后, 浏览器仍旧会报错, 告知Access-Control-Allow-Origin的值为 *,*

      一则我们的配置生效了, 其次, 发现Umami服务端已对CORS作出了处理


浏览器关闭同源策略

macOS

仅作了解, 会降低浏览器安全性

Chrome关闭同源策略,启动非安全模式

  1. 在桌面创建文件夹 disable, 执行命令

    1open -n /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir=/Users/<用户名>/Desktop/disabled
  2. 出现如下提示即关闭成功


  3. 此时可在代码中发送请求获取用户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();
  4. 也可使用hoppscotch获取token

    Hoppscotch

不在代码中获取token也是有好处的. 网页上可以看到JavaScript代码, 如果使用用户名和密码获取token, 即意味着要将二者写到代码里. JavaScript是很难支持读写文件的.


Hugo挂载文件夹

Hugo - Module configurations: mounts

  1. 只有Hugo项目中的 node_modules 可以被直接识别, themes/tess/node_modules 则不行
  2. 偶尔, 会用到Node.js包的其他文件
  3. 将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
预检请求

使用Umami API获取访问数据



说明

  1. 获取用户Token和网站ID
  2. Hugo使用Node.js包
  3. 使用用户Token和API获取网站数据
  4. 跨域请求资源
  5. 浏览器关闭跨域检查
  6. Hugo挂载文件夹

使用Postman获取用户Token

网页使用过程中, 用户往往在页面操作, 触发后端接口调用. 而在开发过程中, 后端测试接口是否能正常工作, 在和前端对接前, 常常会使用Postman发送请求, 接由后端处理.

Postman使用起来并不复杂, 需要在官网注册帐号. 每次使用前登录帐号, 可以使用之前创建的方法


Postman - UI



填写POST


拷贝用户token



获取网站ID

访问 https://umami.enjoy61.com

入口


网站ID



安装Node.js包axios

不安也可以

  1. 去到Hugo项目执行: 目录中出现 package.jsonpackage-lock.json 文件; 每次在当前目录安装包, 包相关信息会被写入
    1npm init -y
  2. 安装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请求

Umami - Website statistics

1const url = 'https://umami.enjoy61.com';
2const axios = require('axios');
3const token = "<用户token>";
4const website_id = "<网站ID>";

获取访问量和访客数

  1. 添加两个html元素, 用来存放访问量和访客数
    1<span>本站总访问量<a id="pageview"></a>次 · 总访客数<a id="visitor"></a></span>
  2. 获取访问量和访客数
     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}
  3. 设置到元素
     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}
  4. 调用
    1get_website_stat(token);

获取页面阅读数

  1. 添加html元素, 存放阅读量
    1<a id="single-pageview"></a>
  2. 获取页面阅读数
     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}
  3. 设置到元素
    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}
  4. 调用
    1get_single_pageview(token);

跨域请求

向指定页面发送请求, 如果满足以下条件之一, 则为跨域请求:

  1. 域名不同(包括子域不同)
  2. 协议不同
  3. 端口不同

同源策略

Same-origin policy

同源策略

浏览器允许某个网页访问另一个网页的数据, 前提是这两个网页必须有相同的URI, 主机名和端口号, 即两个网页同源.

该策略仅用于脚本.


跨域资源共享

跨域资源共享 Cross-origin resource sharing

页面能够自由地使用其他源的数据.

但一些跨域请求常常会被同源策略禁止.


使用跨域请求获取Token

会被浏览器禁止, 也即是为什么使用Postman而不是在代码中发送请求

如果非要在代码中完成, 需要对浏览器设置


为Nginx配置跨域

  1. 目前是没有在Nginx配置CORS的

  2. 获取token失败, 但获取网站数据成功: 服务端的CORS配置在Umami不在Nginx

  3. 其他情形可以在Nginx配置CORS, 当前仅作示例

    /etc/nginx/sites-avaliable/umami

    请求资源的目的地为 https://umami.enjoy61.com , 则修改配置文件umami

    1location / {
    2    add_header Access-Control-Allow-Origin *;
    3}
    1. Access-Control-Allow-Origin即允许提出跨域资源共享的源; 这里配置 * 属于充分不必要

    2. 如此配置后, 浏览器仍旧会报错, 告知Access-Control-Allow-Origin的值为 *,*

      一则我们的配置生效了, 其次, 发现Umami服务端已对CORS作出了处理


浏览器关闭同源策略

macOS

仅作了解, 会降低浏览器安全性

Chrome关闭同源策略,启动非安全模式

  1. 在桌面创建文件夹 disable, 执行命令

    1open -n /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir=/Users/<用户名>/Desktop/disabled
  2. 出现如下提示即关闭成功


  3. 此时可在代码中发送请求获取用户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();
  4. 也可使用hoppscotch获取token

    Hoppscotch

不在代码中获取token也是有好处的. 网页上可以看到JavaScript代码, 如果使用用户名和密码获取token, 即意味着要将二者写到代码里. JavaScript是很难支持读写文件的.


Hugo挂载文件夹

Hugo - Module configurations: mounts

  1. 只有Hugo项目中的 node_modules 可以被直接识别, themes/tess/node_modules 则不行
  2. 偶尔, 会用到Node.js包的其他文件
  3. 将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
预检请求