前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >URL中一个“+”号引发的投诉

URL中一个“+”号引发的投诉

作者头像
一猿小讲
发布2021-07-23 14:20:21
4550
发布2021-07-23 14:20:21
举报
文章被收录于专栏:一猿小讲一猿小讲

1

猿与故事

程序员苏大强,平时穿着斑点衫、人字拖,若送他一盘串或一条金链子,活生生的古惑仔,所以大家都喊他强哥。不过这两天苏大强却愁眉不展,陷入了一个疑难漩涡而不能自拔。

故事的发展是这个样子的,苏大强负责开发获取银行电子凭证的需求,凭借他多年实战经验,并且拥有程序员核心技能之填坑力,自功能上线后一直平稳运行,通过监控系统来看每天成功率都是 100%,但是 6.24 这天成功率为 0%,成功率走势一下跌入谷底。

电子凭证获取成功率的走势,犹如苏大强的心跳。不过苏大强是大场面先生,啥场面都经历过,生产无小事儿,说时迟那时快,苏大强已经开启了排查问题之旅。

首先,从日志中找到 6.24 那笔获取电子凭证的请求报文,拿到如下请求下载的链接地址。

代码语言:javascript
复制
http://x.x.x.:8888/xbank/download?fileId=120_AXm+g8nbWnJ

然后,苏大强在浏览器里访问好几下,都是提示文件下载失败,开始怀疑银行没有生成电子凭证文件,遂联系行方确认电子凭证是否存在,行方确认文件着实存在。

代码语言:javascript
复制
{"result":"下载失败!","code":"999999"}

问题就是这么个问题,到底是咋回事儿呢?苏大强的心犹如小鹿在乱撞,反反复复验证了好几次,终不得其解。

正当苏大强排查验证之时,一封业务投诉的邮件映入眼帘,没想到剧情会愈演愈激烈 ... ...

当旁边的程序员王多鱼看到投诉邮件后,又看看苏大强青春痘泛滥而又愁眉不展的大宽脸,出于内心的纯真与好奇遂出手相助。

”是不是 URL 中的 + 号导致的?我之前的项目中遇到过类似的问题“王多鱼弱弱的问了一句。

”肯定是,因为其它电子凭证文件获取一切正常。“苏大强拍着大腿坚定的说。

接着,苏大强尝试对传入的文件编号的值进行编码操作。

代码语言:javascript
复制
编码前:120_AXm+g8nbWnJ
编码后:120_AXm%2Bg8nbWnJ

通过 URL 编码后的链接,再次访问银行获取电子凭证文件,果不其然,电子凭证文件正常获取。

监控系统终于恢复了往日的平静,苏大强嘴角上扬,微微一笑很倾城。

2

情景再现

尽可能的模拟复现苏大强的问题,首先模拟电子凭证下载服务端代码。

代码语言:javascript
复制
@Controller
public class DownloadController {
    @RequestMapping("/download")
    private void download(@RequestParam(value = "fileId") String fileId,
                          HttpServletResponse response) throws Exception {

        System.out.println(String.format("服务端接收:要下载的文件ID【%s】", fileId));
    }
}

模拟电子凭证下载客户端(尽力复原苏大强的代码)

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) throws Exception {
        // case 1:文件id含有 + 号的问题
        StringBuilder builder = new StringBuilder();
        builder.append("http://localhost:8888/xbank/download");
        builder.append("?fileId=").append("666_AAA+NNN");
        System.out.println(String.format("客户端发送请求:下载文件的URL【%s】", builder.toString()));

        HttpClientUtil.sendHttpRequestReturnStr(builder.toString());
    }
}

服务端、客户端运行起来。

客户端输出

代码语言:javascript
复制
客户端发送请求:下载文件的URL【http://localhost:8888/xbank/download?fileId=666_AAA+NNN】

服务端输出

代码语言:javascript
复制
服务端接收:要下载的文件ID【666_AAA NNN】

纳尼?+ 号去哪里了?真搞丢了。

原来客户端向服务器传递参数时,URL 默认的将参数中的“+”被转义成空格导致的,尝试通过 URLEncoder 进行编码解决。

代码语言:javascript
复制
builder.append("?fileId=").append(URLEncoder.encode("666_AAA+NNN","UTF-8"));

运行客户端模拟下载凭证文件,此时服务端接收到的文件 ID 正常。

服务端接收:要下载的文件ID【666_AAA NNN】

除了本文提到的"+"会被转义,&、# 等字符也会出现解析的问题,所以能进行编码的地方最好进行编码传输,以免后顾之忧。

常使用的解决方案:

  • 页面端可利用 escape()、encodeURI()、encodeURIComponent() 函数进行 URL 编码,防止服务端特殊字符接收解析出现问题。
  • Java端可利用本文提及的 URLEncoder.encode() 方法,先进行 URL 编码,再进行请求。

3

菜菜的闲话

《礼记·大学》有云:知止而后有定;定而后能静;静而后能安;安而后能虑;虑而后能得。

解决问题要能够让自己静下来,只有静下来方能追究问题的本质。

久经码场,能静下来写 Bug、找 Bug 可谓是一件非常幸福的事情。

一起聊技术、谈业务、喷架构,少走弯路,不踩大坑。会持续输出精彩分享,敬请期待!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一猿小讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档