插件记录Node,如何给img标签里的请求添加自定义header

图片 1

图片 2

介绍

是这样的需求,有一个web页面,里面图片的上传和预览来自于一个独立的文件服务器,对http的请求需要进行访问权限的设置,就是在请求的header里加一个Authorization的字段。上传好说我用的Axios直接添加一个header就行了,但是预览就比较麻烦了,因为img这个标签图片下载展示是浏览器自己实现的,没有办法去修改。所以首先想到就是通过接口添加自定义header转发请求或者其他通过接口的方案了,那怎么通过前端页面去实现这个功能,首先声明的是这里用了一些新的API,所以如果是一些比较老的浏览器那就没法这么做了。

  1. 问题由来

随着程序的增长,日志记录成为跟踪所有内容的关键部分。它对于调试目的尤为重要。

问题分析:img标签的src属性只能设置url,不能设置这次请求的header。既然这样,能不能通过别的方式先把图片下载下来然后再给img标签作展示,相当于把src属性的下载和展示分成了两步,先调用接口获取到了数据,然后再把数据给展示出来,也就是src里的值不是一个url地址而是一个数据流。

在做两款H5的APP项目,前期采用微信官方推荐的weui组件库。后来因呈现的效果不理想,组件不丰富,最终项目完成后全部升级采用了有赞开发的vant组件库。同时将webpack顺利从3升级到4。相信好多做TOB的开发朋友都会选择顺手组件库。组件库内置了很多样式,方便了我们开发者,同时又因高度封装,有时也会给我们带来一点点困扰。比如,在使用vant组件库中的环形进度条时,查看官方文档,有改变进度条颜色,有改变轨道颜色,也有改变填充颜色。就是没有改变显示文字颜色的。凑巧的是,我们的需求就是要改变文字颜色。怎么办呢?写个css不就好了么。

现在已经有了 npm
的日志记录模块。这些模块可以将日志存储在不同格式或级别的文件中。我们将使用流行的ORM
Mongoose 讨论 Node.js Express 程序中的 API 日志记录。

可以这样,首先通过Object.defineProperty定义一个authSrc属性用来替换src属性的值,然后在window.onload里等dom加载完以后去再下载图片。

  1. 编写样式

那么如何创建一个Mongoose 插件,以更清洁的方式为你进行记录并简化 API
日志?

!DOCTYPE htmlhtml lang="en"head meta charset="UTF-8" titleProxy Image/title script Object.defineProperty(Image.prototype, 'authsrc', { writable : true, enumerable : true, configurable : true }) window.onload = () = { let img = document.getElementById('img'); let url = img.getAttribute('authsrc'); let request = new XMLHttpRequest(); request.responseType = 'blob'; request.open('get', url, true); request.setRequestHeader('Authorization', '凭证信息'); request.onreadystatechange = e = { if (request.readyState == XMLHttpRequest.DONE  request.status == 200) { img.src = URL.createObjectURL(request.response); img.onload = () = { URL.revokeObjectURL(img.src); } } }; request.send(null); } /script/headbodyimg width="100" height="100" authsrc="_201909111450326.jpg"/body/html

为了说明情况,我为本文专门配合了一个测试demo。微信关注公众号,回复vuescoped,可获得。假如您现在也已经初始化好了一个Vue项目,并引入了我们需要的vant组件库。接下来,我们在components文件夹中新建一个CssScope.vue的单文件组件。基本代码如下:

Mongoose 中的插件是什么?

这样虽然可以实现功能,但是每次还需要执行额外的脚本,不能在Dom加载完的时候自动去下载展示,不够优雅。能不能自动去下载展示呢

templatedivvan-circle v-model="currentRate" :rate="90" :speed="100" :text="text" //div/templatestyle lang="less" scoped/stylescript.../script

在 Mongoose
中,模式是可插入的。插件就像一个函数,你可以在模式中使用它,并在模式实例上一次次地重用。

通过自定义元素加载

编译运行,我们在浏览器就会看到一个进度为90%的环形进度条。当然显示文字90%显示是黑色,现在我们就来改变它。最初我们想到,文字颜色color是可以从父级继承的,所以我们在Style标签中写下如下css样式:

Mongoose
还提供全局插件,你可以将其用于所有模式。例如我们将会编写一个插件,它将创建两个jsons的diff并写入mongodb

自定义元素不太了解的可以参考这里Using custom
elements,这里还有个w3c的草案autonomous-custom-element。

style lang="less" scoped.van-circle{color:blue;}/style

步骤1:创建基本日志模式模型

!DOCTYPE htmlhtml lang="en"head meta charset="UTF-8" titleProxy Image/title script let requestImage = function (url, element) { let request = new XMLHttpRequest(); request.responseType = 'blob'; request.open('get', url, true); request.setRequestHeader('Authorization', '凭证信息'); request.onreadystatechange = e = { if (request.readyState == XMLHttpRequest.DONE  request.status == 200) { element.src = URL.createObjectURL(request.response); element.onload = () = { URL.revokeObjectURL(element.src); } } }; request.send(null); } class AuthImg extends HTMLImageElement { constructor() { super(); this._lastUrl = ''; } static get observedAttributes() { return ['authSrc']; } connectedCallback() { let url = this.getAttribute('authSrc'); if (url !== this._lastUrl) { this._lastUrl = url; requestImage(url, this); } console.log('connectedCallback() is called.'); } } window.customElements.define('auth-img', AuthImg, {extends: 'img'}); /script/headbodyimg width="100" height="100" is="auth-img" authSrc="_201909111450326.jpg"/body/html

回到浏览器,文字颜色没变。通过Chrome的开者工具,找到我们的圆形进度条。才发现,原来,这个组件内部是一个svg
和 div
标签组成,svg用于显示我们图形,div用于显示文字。并且在这个div上存在一个class

van-circle__text。根据css优先级,我们刚在父级设置的字体颜色无效。找到原因,那就好办了。我们需要在Style标签中定义这个class选择器,并设置它字体颜色为蓝色。于是我们删除刚写的样式,改写为如下:

让我们创建一个具有以下六个属性的基本日志模式:

利用Node作请求转发

style lang="less" scoped.van-circle{ .van-circle__text{olor:blue;}}/style

Action:按照它的名称,这是 API
的一个动作过程,无论是create、update、delete还是别的什么。Category:API
类别。例如医生和患者。它更像是一个阶级。CreatedBy:正在使用或调用
API
的用户。Message:你可以在此处包含你想要显示的任何类型的消息,这些消息在调试过程中有意义或有帮助。Diff:这是主要属性,它是两个JSONdiff

这里我是在Electron客户端用的,是通过进程间通信的方式获取到了用户凭证信息,如果是部署在服务器上的话,应该使用其他方式。

这下应该可以了,可回到浏览器,效果依旧。黑色,还是黑色。此时,回到chrome,在开发者工具找到我们的元素。仔细的你才发现,显示文字的标签和它的父级好像不一样,少个data-v-xxx的属性。也许是style的
scoped搞鬼,那我们就去掉。回到浏览器,文字颜色居然改变了。欢喜之余,总感觉哪里不对?我们得查查这个水鬼scoped

如果你希望对自己的应用程序有意义,可以添加更多字段,也可以根据需要更改和升级架构。这是我们的模型:models/log.js

let app = ((request, response) = { let config = { host: 'xxx.com', method: 'GET', path: request.url, headers: { Authorization: '用户凭证' } }; let proxyRequest = (config, proxyResponse = { proxyResponse.on('data', data = { response.write(data, 'image/jpg'); }); proxyResponse.on('end', () = { response.end(); }); response.writeHead(proxyResponse.statusCode, proxyResponse.headers); }) request.on('data', data = { proxyRequest.write(data, 'image/jpg'); }) request.on('end', () = { proxyRequest.end(); })});app.listen(port, () = { console.log('has start proxy server!');})
  1. Style中的 Scoped神奇效果
const mongoose = require('mongoose')const Schema = mongoose.Schemaconst { ObjectId } = Schemaconst LogSchema = new Schema({ action: { type: String, required: true }, category: { type: String, required: true }, createdBy: { type: ObjectId, ref: 'Account', required: true }, message: { type: String, required: true }, diff: { type: Schema.Types.Mixed },},{ timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' },})LogSchema.index({ action: 1, category: 1 })module.exports = mongoose.model('Log', LogSchema)

利用Nginx

我们的项目采用Less作为CSS
预处理语言。在组件中习惯于使用一个带有scoped属性的Style标签,scoped
属性的效果,就是在编译打包后,在当前组件能一眼看到的标签中统一添加一个随机的属性,编译的css也会对于加上那个随机属性

步骤2:编写一个函数来获得 2 个 JSON 之间的差异

发表评论

电子邮件地址不会被公开。 必填项已用*标注