SpringBoot 配置内置Tomcat 解决 RFC 7230 与 RFC 3986 请求字符限制问题

感谢 大专栏 提供教程,本文转自 大专栏

如需要了解更详细信息请移步 大专栏

问题引出:

容器模块引用公司统一要求的父pom以后,springboot版本升级为1.5.14,其内置tomcat变更为8.5.31,启动不报错,发送特殊字符(中括号)Get请求报错:

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

原因:

所有主要版本的Tomcat(7.0.738.0.398.5.7)都加入了对请求头字符的限制。

stackoverflow相关问题

解决方案:

1. 妥协:前端对参数进行uriencode或springboot换容器。

2. 任何初始化代码中配置系统变量(有限制):

System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow", "{}");

原理是在org.apache.tomcat.util.http.parser.HttpParser类,125行静态初始化方法中:

String prop = System.getProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow");
if (prop != null) {
    for (int i = 0; i < prop.length(); i++) {
        char c = prop.charAt(i);
        if (c == '{' || c == '}' || c == '|') {
            REQUEST_TARGET_ALLOW[c] = true;
        } else {
            log.warn(sm.getString("http.invalidRequestTargetCharacter",
                    Character.valueOf(c)));
        }
    }
}

REQUEST_TARGET_ALLOW静态数组保存了请求字符是否被允许的状态,从代码中看出,这种方法只允许{}|三个字符过审。

3. 更优雅的定制化配置:

public class  implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container;
        factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
            @Override
            public void customize(Connector connector) {
                connector.setAttribute("relaxedQueryChars", "[]");
            }
        });
    }
}

原理是在同类的147 行代码构造方法里:

public HttpParser(String relaxedPathChars, String relaxedQueryChars) {
    for (int i = 0; i < ARRAY_SIZE; i++) {
        
        // Combination of multiple rules from RFC7230 and RFC 3986. Must be
        // ASCII, no controls plus a few additional characters excluded
        if (IS_CONTROL[i] || i > 127 ||
                i == ' ' || i == '"' || i == '#' || i == '<' || i == '>' || i == '\' ||
                i == '^' || i == '`'  || i == '{' || i == '|' || i == '}') {
            if (!REQUEST_TARGET_ALLOW[i]) {
                IS_NOT_REQUEST_TARGET[i] = true;
            }
        }

        /*
         * absolute-path  = 1*( "/" segment )
         * segment        = *pchar
         * pchar          = unreserved / pct-encoded / sub-delims / ":" / "@"
         *
         * Note pchar allows everything userinfo allows plus "@"
         */
        if (IS_USERINFO[i] || i == '@' || i == '/' || REQUEST_TARGET_ALLOW[i]) {
            IS_ABSOLUTEPATH_RELAXED[i] = true;
        }

        /*
         * query          = *( pchar / "/" / "?" )
         *
         * Note query allows everything absolute-path allows plus "?"
         */
        if (IS_ABSOLUTEPATH_RELAXED[i] || i == '?' || REQUEST_TARGET_ALLOW[i]) {
            IS_QUERY_RELAXED[i] = true;
        }
    }

    relax(IS_ABSOLUTEPATH_RELAXED, relaxedPathChars);
    relax(IS_QUERY_RELAXED, relaxedQueryChars);
}

connector的配置参数会交给Http11Processor,其创建HttpParser时又传入到构造方法中,最后记录下来。IS_QUERY_RELAXED是判断传参字符是否合法的直接依据,从代码中可以看出REQUEST_TARGET_ALLOW是它的子集。

java多线程——并发测试

感谢:大码侯

cool_wier

关注个人成长和游戏研发,致力于推进国内游戏技术社区的进步。

来源: java多线程——并发测试

编写并发程序时候,可以采取和串行程序相同的编程方式。

唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问题,并且了解其性能瓶颈,本篇针对这些问题来做个简要总结。

linux下日志自动切割-logrotate

logrotate是个十分有用的工具,它可以自动对日志进行截断(或轮循)、压缩以及删除旧的日志文件。例如,你可以设置logrotate,让/var/log/foo日志文件每30天轮循,并删除超过6个月的日志。配置完后,logrotate的运作完全自动化,不必进行任何进一步的人为干预。另外,旧日志也可以通过电子邮件发送,不过该选项超出了本教程的讨论范围。

来至GOLinux:https://linux.cn/article-4126-1.html

主流Linux发行版上都默认安装有logrotate包,如果出于某种原因,logrotate没有出现在里头,你可以使用apt-get或yum命令来安装。

继续阅读

链接

感谢原创Sunny!

看原文件请移步 →_→搭建属于自己的ngrok服务器,实现内网穿透,外网访问内网,可本地开发微信不需要上传服务器-sunny博客|讲述一个程序员的代码史记

ngrok 是一个使用go语言编写的反向代理软件,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放。在官方网站上面可以注册一个账号自己使用,不需要自己搭建也行,但是缺点就是速度慢,还有经常会连不上,所以我们可以通过自己搭建来解决这些问题。对于想本地开发或者想做内网穿透的话ngrok可以帮你这个忙,我们都知道在微信开发的时候,微信服务器只认80端口,这样导致我们哪怕修改一行代码都得把代码上传到服务器上面,就在传文件的时候就已经浪费了特别的时间了,而如果我们把ngrok用上的话就可以节省很多时间,因为外网完全可以访问到内网的web服务器上,哪怕是你自己的电脑。我之前也做过《如何通过SocketLog进行web和微信开发调试》的教程,如果把ngrok和SocketLog搭配起来用的话,我们调试起来就更方便了,除了做微信之外,我们在做支付功能的时候,处理异步回调也很麻烦,也得把文件上传到服务器上面去,可我们同样的使用ngrok和SocketLog结合起来用,我们可以不上传代码,也还可以通过浏览器console来查看处理的过程,快速的帮助我们排查错误。

继续阅读

脚本处理动画的良好方法-requestAnimationFrame

alloyteam发了一篇blog文章《追踪子弹-初中简单的物理和数学》,在文章的最后提到一个动画的计时控制的东东- requestAnimationFrame,它是一个浏览器在通过计时制作动画时,解决显示刷新频率和渲染效率之间的平衡问题。

继续阅读

NanoHTTPD 源码只有一个JAVA文件的轻型Web服务器

今天小弟问我用过NanoHTTPD没有,想在Android上面使用它。百度了下,发现是Apache下面的一个开源项目。于是好奇的看了下,根据介绍说是一个小巧轻型的WEB服务器。它小到什么程度呢,小到源码只有一个JAVA文件,给人一种87V5的感觉。

通过继承这个源码类并实现serve接口,就可以完成web服务器的基本功能。

如果你的项目需要一个简单的静态web服务,相信它是一个不错的选择,当然可以发挥你的聪明才智使用到其它地方,比如移动设备、智能设备等。

如果你想快速搭建起来使用一个简单的DEMO,那么它的源码里 SimpleWebServer 肯定会让你惊喜的。

继续阅读

海量数据相似度计算之simhash和海明距离

 

本文来自:Web开发者-《海量数据相似度计算之simhash和海明距离》

通过 采集系统 我们采集了大量文本数据,但是文本中有很多重复数据影响我们对于结果的分析。分析前我们需要对这些数据去除重复,如何选择和设计文本的去重算法?常见的有余弦夹角算法、欧式距离、Jaccard相似度、最长公共子串、编辑距离等。这些算法对于待比较的文本数据不多时还比较好用,如果我们的爬虫每天采集的数据以千万计算,我们如何对于这些海量千万级的数据进行高效的合并去重。最简单的做法是拿着待比较的文本和数据库中所有的文本比较一遍如果是重复的数据就标示为重复。看起来很简单,我们来做个测试,就拿最简单的两个数据使用Apache提供的 Levenshtein for 循环100w次计算这两个数据的相似度。代码结果如下:

继续阅读