基础不牢,地动山摇

接受配置文件

这段时间又换系统了。一开始想使用 ArchLinux ,但是对于网络那块的问题还是有些不稳定,虽然 ArchLinux 并不难操作,但是真的是太太太太太简洁了!基本上要啥没啥,都得自己去找去安装。尽管教程很多但是除非很喜欢折腾,不然 ArchLinux 并不是适合大部分动手能力强的人。

最后还是选择 Manjaro + i3 的配置方案。Manjaro 配置了一些基本需要用到的软件,比如网络管理、蓝牙管理、电池管理等等一系列刚需软件。如果不喜欢,卸载了换个别的,一样是定制度很高。

在使用新系统的时候,频繁的需要接触配置文件,很多东西都可以通过自己修改配置文件达到自己想要的效果。渐渐的,之前不希望 OneTiny 有任何配置文件的想法逐渐改变。在使用 i3 的时候,很多小而美的软件也有配置文件。独立一个可执行程序虽好,但少了用户自定义的自由,整个软件的可玩性也就不高了。

整改

接受了这个观念,一下子很多问题迎刃而解。例如我想要配置好 9012 端口,下次直接使用 onetiny 命令就运行在 9012 端口,而不用每次运行的时候都得手动指定端口号。

此外有了配置文件和配置目录,更新功能在下载新版本时的临时目录也有地方了,断点续传的临时文件也有地方放了,还有很多配置项都可以在配置文件中写好。

但是未来我还是会开辟一个分支,仅保留核心部分功能,也就是最初的样子,v0.1 那一版的样子,但是会有并发下载、断点续传这些与核心业务相关的功能,而没有什么密码访问、自动更新这些无关核心问题的功能。而 master 分支继续开发新功能。

整改起来也方便。使用 os.UserConfigDir() 就可以获取用户的配置目录路径,在其下创建一个 tiny/ 目录和一个 config.yml 文件即可。

这里采用的是 YAML 格式的配置文件,虽然网上很多说 TOML 是最好的配置文件格式啥的,但…我真没觉得好到想这些布道师说的一样。虽然我也喜欢拥抱新事物,但是项目中配置项很少,YAML 也不复杂。

这里感谢 spf13/viper 这个库,非常好用,功能丰富,使用也不难。配置问题很容易就解决了。

同时为了支持子命令,我换成 urfave/cli 这个库,之前看没看太懂,觉得很繁琐,现在用了之后觉得还不错。

最后是对项目结构小小的重构了一下。根据命令将整个项目分为 core 部分、config 部分、update 部分。

core 部分是核心业务,使用 gin 框架支持,做起来其实和做一个 web 应用相差无几。 config 部分对应子命令 onetiny config,用于设置一些配置。设置生效后会写入文件。 update 部分对应子命令 onetiny update,用于检查更新,自动更新等。

目前的结构就是使用 cli 管理这些命令,每个命令都有不同的职责,所以分成不同的模块,使用不同的库。

新功能

这次还新增了一个访问登录功能。如果开启服务的人指定了访问者需要登录的话,访问者需要输入帐号密码才能看到共享目录,才能下载。

一开始开发这个程序的时候是为了解决自己的场景,就是自己有多台设备,设备之间互传文件的一个问题,是一种单用户的场景。但是慢慢的越做越像一个局域网内的 NSA ,像一台文件服务器,场景中也假设了多用户,而不是一开始的单用户。

不过没关系,反正自己写着玩,自己的程序就是自己喜欢写成啥样就啥样(因为到现在还没人给我提 issue 哈哈哈)。

写这个功能的时候其实就跟写 web 项目时做保持登录一样。 注册方式是通过命令 onetiny sec -u 帐号 -p 密码 来注册,也就是写进配置文件。 访问时会经过中间件 checkLogin() 检查 cookie ,没有 cookie 或者 cookie 对不上就转回去登录。

掉坑

在做登录功能的时候才发现我对 web 其实很不了解,一个完整的登录流程都了解不透彻后来慢慢摸索才明白。

通常的登录流程是这样的:

  • 客户端访问 A 页面,服务端验证是否登录过,也就是有没有 session 或者 cookie 或者 token 之类的;
    • 有就响应,没有就重定向到登录页;
  • 客户端这边收到登录页后需要输入账号密码,通过表单提交到服务端;
  • 这个时候客户端还是停留在登录页的,然后使用 Ajax 监听服务器发来的响应;
    • 根据响应的内容判断是提示密码错误,还是收下 cookie,重新提交访问 A 页面的请求
  • 重新提交访问 A 页面的请求后就就可以等待响应,正常显示了。

在这里踩了两个坑,都是因为基础不牢的原因。

  • 第一个是不了解前端,在后端那研究怎么让浏览器自动重新提交访问请求。其实如果之前不要那么排斥前端,多了解下就会知道 Ajax,且现在大多网站都用 Ajax 来做这一步。Ajax 有原生的,如 XMLHttpRequest,也有 jquery 封装好的等等。

  • 第二个是不了解 HTTP 响应状态码,重定向分很多种情况,瞎用个 301 永久移动 就上去了,结果就是程序都对,但就是登录完还跳回登录页。因为浏览器在访问一个页面时收到 301 的话,它会将这个页面和新的页面做一个绑定,缓存起来。这样下次用户再访问时直接展示那个新的页面。

正确的做法应该是使用 307 临时重定向

最后还是在浏览器调试器里分析出来的,也算是个不大不小的坑。 以前只知道重定向,没关注过不同的重定向的区别。基础不牢,地动山摇。

最后

虽然经验不足的我搞这么一个小功能搞了一天两夜,但也还是收获了一些东西,发现自己一些问题,要抓紧时间补上。而且在写这篇日记的时候发现 gitee 上有人 star 了我的项目,还有三个 watch,一下子觉得这两天掉的头发值了。