首页
📷在线壁纸
🎬娱乐天地
🔖友情链接
更多
📝留言板
Search
1
【javascript】JS-向当前url追加参数
2,345 阅读
2
【PHP】生成随机昵称
2,202 阅读
3
【PHP】判断一个字符串是否属于序列化后的数据
2,024 阅读
4
【css】html+css给文章页,做阅读全文
1,975 阅读
5
【PHP】 设计模式(23种)
1,909 阅读
📂默认分类
💓typecho
🏳️🌈代码改变世界
🍇 mysql
🍈 Winform
🍓 golang
🍉 设计模式
🥝 PHP
🍎 python
🍊 nginx
🍋 网络安全
🍍 javascript
🫑 database
🍡 AI
🍭文艺范
🍏mac
登录
Search
标签搜索
php
typecho
代码注释
redis
mysql
go
golang
nginx
thinkphp
docker
gin
linux
curl
html
mamp
算法
短网址
构造函数
webhook
代码片段
依然范儿特西
累计撰写
145
篇文章
累计收到
1
条评论
首页
栏目
📂默认分类
💓typecho
🏳️🌈代码改变世界
🍇 mysql
🍈 Winform
🍓 golang
🍉 设计模式
🥝 PHP
🍎 python
🍊 nginx
🍋 网络安全
🍍 javascript
🫑 database
🍡 AI
🍭文艺范
🍏mac
页面
📷在线壁纸
🎬娱乐天地
🔖友情链接
📝留言板
搜索到
124
篇与
的结果
2023-10-10
Gin 框架在中间件中获取 response body 的方法
在写一个Gin框架日志中间件的时候,需要记录请求和响应相关的一些数据,例如请求参数、请求方法、请求时间、请求头、耗时、响应状态码、响应数据等,gin为获取这些数据基本都提供了现成的方法,但是获取响应数据还是有一定难度和复杂度的。那么,该如何获取响应数据也就是 response body 呢?先上代码。代码示例1、先写一个 middleware ,简单打印一下 response bodypackage middleware import ( "bytes" "fmt" "github.com/gin-gonic/gin" ) //自定义一个结构体,实现 gin.ResponseWriter interface type responseWriter struct { gin.ResponseWriter b *bytes.Buffer } //重写 Write([]byte) (int, error) 方法 func (w responseWriter) Write(b []byte) (int, error) { //向一个bytes.buffer中写一份数据来为获取body使用 w.b.Write(b) //完成gin.Context.Writer.Write()原有功能 return w.ResponseWriter.Write(b) } func PrintResponse(c *gin.Context) { writer := responseWriter{ c.Writer, bytes.NewBuffer([]byte{}), } c.Writer = writer c.Next() fmt.Println("response body:" + writer.b.String()) } 2、引用 middleware ,看看效果package main import ( "github.com/gin-gonic/gin" "hello/middleware" "net/http" ) func main() { r := gin.New() //添加获取响应内容 middleware r.Use(middleware.PrintResponse) r.GET("/test", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"name": "laofan"}) }) // Listen and Server in 0.0.0.0:8080 r.Run(":8080") } 打开浏览器访问http://127.0.0.1:8080/test ,即可在控制台中看到 response body 的输出内容response body:{"name":"laofan"}原理通过上面的代码可以看出,gin 通过调用如下方法写入了 response bodyc.JSON(http.StatusOK, gin.H{"name": "laofan"})追进 JSON 方法,源码如下,调用了 Render 方法package gin func (c *Context) JSON(code int, obj interface{}) { c.Render(code, render.JSON{Data: obj}) }追进 Render 方法, 可以看出 gin.Context.Writer 作为参数传给了 r.Render() 方法,这里形参 r 的实参为 render.JSON{Data: obj} ,所以实际调用的是 func (r JSON) Render(w http.ResponseWriter) 方法。package gin // Render writes the response headers and calls render.Render to render data. func (c *Context) Render(code int, r render.Render) { c.Status(code) if !bodyAllowedForStatus(code) { r.WriteContentType(c.Writer) c.Writer.WriteHeaderNow() return } if err := r.Render(c.Writer); err != nil { panic(err) } } func (r JSON) Render(w http.ResponseWriter) 源码如下package render // Render (JSON) writes data with custom ContentType. func (r JSON) Render(w http.ResponseWriter) (err error) { if err = WriteJSON(w, r.Data); err != nil { panic(err) } return } // WriteJSON marshals the given interface object and writes it with custom ContentType. func WriteJSON(w http.ResponseWriter, obj interface{}) error { writeContentType(w, jsonContentType) jsonBytes, err := json.Marshal(obj) if err != nil { return err } _, err = w.Write(jsonBytes) return err } 在 func (r JSON) Render() 方法中,gin.Context.Writer 被传到了 WriteJSON() 方法中,最终写入数据调用的是 gin.Context.Writer.Write() 方法。gin.ResponseWriter 源码如下package gin type Context struct { //... writermem responseWriter Writer ResponseWriter //... } // ResponseWriter ... type ResponseWriter interface { //... http.ResponseWriter //... } 可以看出 gin.Context.Writer 类型为 interface gin.ResponseWriter。package http type ResponseWriter interface { //... Write([]byte) (int, error) //... } 要实现 gin.ResponseWriter 接口,必须实现Write([]byte) (int, error) 方法。所以写入 response body 调用的是 gin.Context.Writer.Write() 方法,gin.Context.Writer 需要是type gin.ResponseWriter interface 的一个具体实现。到此,可以看出上面代码示例的思路:实现 type gin.ResponseWriter interface 并重写 Write([]byte) (int, error) 方法,该方法在实现 gin.Context.Writer.Write() 原有功能的同时,再向一个 bytes.buffer 中写一份数据来用于获取 response body 使用。
2023年10月10日
5 阅读
0 评论
0 点赞
2023-06-28
pnpm add -g pnpm报错解决方案
pnpm add -g pnpm报错解决方案
2023年06月28日
2 阅读
0 评论
1 点赞
2023-06-07
微信支付&支付宝支付回调出口IP段查询
微信支付&支付宝支付回调出口IP段查询
2023年06月07日
6 阅读
0 评论
0 点赞
2023-05-12
基于thinkorm分页所用的分页样式
基于thinkorm分页所用的分页样式
2023年05月12日
1 阅读
0 评论
1 点赞
2023-04-25
可用于Clickhouse的五个开源图形客户端
一款趁手的客户端查询工具非常重要,这里我就给大家推荐几款好用的支持Clickhouse的图形客户端。1、TabixUIhttps://github.com/tabixio/tabixTabix是一个纯前端,可以运行在浏览器中的Clickhouse的客户端,它为Clickhouse量身定制,又比较轻量。它用到了以下的开源库:http://Ajax.org 的Ace.JS百度 eCharteHandsontableLodashpivottableTabix支持以下的功能:直接从浏览器连接ClickHouse一起使用,而无需安装其他软件;查询编辑器,支持突出高亮SQL语法,对所有对象自动完成,包括字典和内置函数的上下文相关帮助。用于映射查询结果的图形,图表和地理参考,包含map / bar / heatmap / river / sankeys / treemap用于查询结果的交互式设计器数据透视表(pivot);用于分析ClickHouse的图形工具;两种颜色的主题:浅色和深色。支持Clickhouse的Metrics支持Clickhouse的Schema2、SQLPadhttps://github.com/sqlpad/sqlpadSQLPad一个Web应用程序,用于编写和运行SQL查询并可视化结果。 通过ODBC支持Postgres,MySQL,SQL Server,ClickHouse,Crate,Vertica,Presto,SAP HANA,Cassandra,Snowflake,Google BigQuery,SQLite等。SQLPad支持几种基本的图表类型,包含Line,Bar,Scatter Plot,Stacked Bar。SQLPad采用了Client/Server架构,Server使用了Nodejs,客户端是React,图表库使用了D3.js如果你的工作需要用到除了Clickhouse之外的这几种支持ODBC的数据库,SQLPad可以一用。3、Supersethttps://link.zhihu.com/?target=https%3A//superset.apache.org/Superset是Airbnb开源的BI和数据可视化工具箱。 Superset快速,轻巧,直观,并带有各种选项,使各种技能的用户都可以轻松浏览和可视化其数据,从简单的折线图到高度详细的地理空间图。目前,Superset已在许多公司大规模运行。 例如,Superset在Kubernetes内的Airbnb生产环境中运行,每天为600多个活跃用户提供服务,每天查看超过10万张图表。Superset提供以下的功能:直观的界面,用于可视化数据集和制作交互式仪表板多种精美的可视化展示数据无代码可视化构建器,用于提取和呈现数据集世界一流的SQL IDE,用于准备数据以进行可视化,其中包括丰富的元数据浏览器轻量级的语义层,使数据分析人员能够快速定义自定义维度和指标对大多数说SQL的数据库提供开箱即用的支持无缝的内存中异步缓存和查询一种可扩展的安全模型,允许配置关于谁可以访问哪些产品功能和数据集的非常复杂的规则。与主要的身份验证后端(数据库,OpenID,LDAP,OAuth,REMOTE_USER等)集成添加自定义可视化插件的功能用于程序化定制的API云原生架构,专为大规模应用而设计4、Redashhttps://github.com/getredash/redashRedash旨在使任何人,无论技术水平如何,都可以利用数据的力量。 SQL用户可以利用Redash来探索,查询,可视化和共享来自任何数据源的数据。他们的工作反过来使组织中的任何人都可以使用数据。每天,全球成千上万个组织中的数百万用户使用Redash来开发见解并制定数据驱动的决策。Redash背后的公司创建于2015年,并于2020年被Spark的所有公司Databrick收购。Redash功能:基于浏览器:浏览器支持所有内容,均带有可共享的URL。易于使用:无需掌握复杂软件即可立即获得数据生产力。查询编辑器:使用浏览器快速编辑SQL和NoSQL查询并自动完成。可视化和仪表板:通过拖放创建漂亮的可视化文件,并将它们组合到单个仪表板中。共享:通过共享可视化文件及其关联的查询轻松进行协作,从而实现对报告和查询的同行审阅。计划刷新:自定义的定期自动更新图表和仪表板。告警:定义条件并在数据更改时立即收到警报。REST API:UI中可以完成的所有操作也可以通过REST API获得。对数据源的广泛支持:可扩展的数据源API,具有对一长串常见数据库和平台的本机支持。Redash有非常丰富的数据源支持(超过35种)。包括SQL和NoSQL的支持。Redash原生支持Clickhouse,不需要额外再安装驱动。5、Metabasehttps://www.metabase.com/https://github.com/metabase/metabaseMetabase 2014年创建于美国硅谷,它的产品理念是公司中每个人都可以提出问题并从数据中学习的一种简单,开源的方式。Metabase需要通过plugin的方式来增加对Clickhouse的支持。ADD https://github.com/enqueue/metabase-clickhouse-driver/releases/download/0.7.3/clickhouse.metabase-driver.jar /plugins/Metabase支持中文,支持三种不同的方式来解决查询问题。Metabase的后端使用了Clojure,纵使是我见多识广,也是被惊到了。Clojure我不熟悉,这里我不做评价。前端框架使用了react,图表使用了d3js。Metabase有自己的企业版本,开源许可证采用了AGPL。这一点不是特别友好。总结好了看了这么多的开源的支持Clickhouse可视化客户端,应该有一款适合你吧。Tabix专门为Clickhouse定制,轻巧,支持Clickhouse的监控,如果你只需要连接Clickhouse做基本的查询,它很适合。SQLPad基于ODBC,本身也很简单,适合使用多种结构化支持ODBC数据源的场景Superset的可视化种类非常丰富,适合需要可视化展现的场景Redash的优势是支持的数据源的种类很多,包含很多NoSQL的数据源。而且它原生内置了Clickhouse的支持。它的SQL编辑,用户管理和安全特性也做得很友好。Metabase对于不懂SQL的非技术人员非常友好,适合非专业人士的数据分析工具。
2023年04月25日
150 阅读
0 评论
1 点赞
2023-03-24
国内外接收短信验证码平台网站
注意:无法打开的话,可能是你的姿势不对,调整你的姿势,再试一次网站地址描述SMS-Activatehttps://sms-activate.org注册ChatGPT推荐免费接收短信http://www.shejiinn.com中国、缅甸Z-SMShttp://z-sms.com中国、美国、缅甸、爱沙尼亚免费接收短信http://www.smszk.com中国在线接收短信https://www.becmd.com美国、中国在线短信接收https://www.pdflibr.com美国、中国、菲律宾MyTrashmobilehttps://zh.mytrashmobile.com美国、英国、加拿大FreePhonenumhttps://ch.freephonenum.com美国、加拿大(支持免费发短信)ReceiveSMShttps://www.receivesms.co/奥地利、比利时、加拿大、瑞士、丹麦、西班牙、英国、意大利、拉脱维亚、波兰、葡萄牙、瑞典、美国Receive SMShttp://receivesmsverification.com比利时、英国、美国Receive Online SMShttp://receiveonlinesms.biz美国、瑞典、挪威、西班牙、英国Receive Free SMShttp://www.freesmsverifications.com美国、英国、法国、波兰、比利时、加拿大SMS-Receivehttps://sms-receive.net俄罗斯、法国、罗马尼亚、西班牙、荷兰、英国Receive-SMS-Nowhttp://www.receive-sms-now.com美国、加拿大、荷兰Receive SMS Onlinehttp://receivesmsonline.in美国、加拿大、西班牙Receive-SMS-Nowhttp://receivefreesms.net美国、加拿大、西班牙SMSReceiveFreehttps://smsreceivefree.com美国、英国、加拿大Receive SMS Online for FREEhttps://www.receive-sms-online.info英国、罗马尼亚、美国、西班牙、法国、德国、俄罗斯Receive a SMS Onlinehttps://receive-a-sms.com美国、澳大利亚、挪威、奥地利、巴西、香港、南非、波兰、英国、加拿大Free SMS Numbers Onlinehttps://smsnumbersonline.com美国、英国、加拿大、波兰Receive SMS online for Freehttps://sms-online.co/receive-free-sms美国、英国、加拿大、瑞典、法国、马来西亚、印度尼西亚Receive-SMShttps://receive-sms.com美国Receive FREE SMS onlinehttp://receivefreesms.com美国、英国、挪威、瑞典、荷兰、澳大利亚、匈牙利、立陶宛、香港等RECEIVE SMS ONLINEhttps://www.receivesmsonline.net美国、加拿大、英国Free Online Phonehttps://www.freeonlinephone.org美国、加拿大、英国、瑞典Receive SMS Onlinehttp://receive-sms-online.com俄国、英国、乌克兰TextNowhttps://www.textnow.com美国Textfreehttps://www.pinger.com/text-free/ SELLAITEhttp://sms.sellaite.com爱沙尼亚Twilihttps://www.twilio.com支持API调用,看上去很不错
2023年03月24日
134 阅读
0 评论
1 点赞
2023-02-15
大文件上传解决方案
大文件上传解决方案
2023年02月15日
25 阅读
0 评论
0 点赞
2023-02-15
redis如何提高缓存命中率
redis如何提高缓存命中率
2023年02月15日
49 阅读
0 评论
0 点赞
2022-12-15
PHP解析小程序返回的buffer信息,并解析成图片
需要引入 GuzzleHttp 包composer require guzzlehttp/guzzle核心代码如下:<?php require __DIR__ . './vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; /** * get client * @return Client */ function httpGetClient() { static $client ; if (!$client) { $client = new Client(); } return $client; } //GET function httpGet($url) { $client = httpGetClient(); $options = [ 'verify' => false, ]; $response = $client->get($url,$options); return $response->getBody()->getContents(); } // POSTBODY function httpPostBody($url, $requestData=[], $header=[]) { $client = httpGetClient(); $options = [ 'headers' => $header, 'body' => json_encode($requestData,JSON_UNESCAPED_UNICODE ), 'verify' => false, ]; $response = $client->post($url, $options); if ($response->getStatusCode()==200) { return $response->getBody()->getContents(); }else{ return null; } } //postForm function httpPostForm($url, $requestData, $header) { $client = new Client(['verify' => false]); try { $response = $client->request('post', $url, ['form_params' => $requestData, 'headers' => $header]); $response->getStatusCode(); // 200 $response->getHeaderLine('content-type'); if ($response->getStatusCode()==200) { return [true,$response->getBody()->getContents()]; }else{ return [false,[]]; } } catch (GuzzleException $e) { } return [false,[]]; } function getAccessToken(){ $appid = ''; $secret = ''; //获取access_token $access_token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$secret; $access_token_data = httpGet($access_token_url); $access_token_data = json_decode($access_token_data,true); return $access_token_data['access_token']; } function getQrcode($access_token){ $url = 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token='.$access_token; $requestData = [ 'path'=>'pages/order-status/index?loose_id=1', 'width'=>430, ]; $header = []; return httpPostBody($url,$requestData,$header); } $access_token = getAccessToken(); //$access_token = ""; $data = getQrcode($access_token); if(is_null(json_decode($data))){ //不是json数据, 有数据流,返回值为null $jpg = $data; //创建文件写入 $file = fopen("img/test.jpg",'w'); fwrite($file,$jpg); fclose($file); }else{ //不是数据流,则代表有错误发生 $data_array = json_decode($data,true); print_r($data_array); } ?> 如果提示你无法写入, 记得新建一个文件夹: img ,并给可写权限
2022年12月15日
29 阅读
0 评论
1 点赞
2022-12-06
window下 phpstudy+nginx报错502的处理办法
1 开启日志修改nginx 日志级别, 开启错误日志和访问日志2 端口检测查看 80 端口和 9000 端口占用情况, 大部分是因为 9000端口被占用导致# 查看所有的端口 netstat -ano # 查询指定的端口占用,在命令行输入: netstat -aon | findstr 端口号 # 查询PID对应的进行进程: tasklist | findstr PID #关闭程序: taskkill /f /t /im 程序名
2022年12月06日
60 阅读
0 评论
1 点赞
1
2
3
...
13