django+nginx+uwsgi部署的站点访问某个URL时发生了400 bad request的错误,而使用django自带的开发版的web server时没有遇到此问题。初步判断是nginx或uwsgi配置问题。

网上有说是因为request header过大而nginx配置的client_header_buffer_size和large_client_header_buffers过小引起的,但就当前的状态来看感觉不太可能。因为request header并不是特别大。至于是别的什么原因还暂未找到,所以还是先试试看。

在nginx配置文件nginx.conf中的http部分加入如下两行参数:
client_header_buffer_size 16k;
large_client_header_buffers 4 64k;
nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取header值。若该值设置过小而请求头/COOKIE过大则会报400 bad request错误。

调整参数重新载入配置文件重启uwsgi后发现问题并未解决。
经仔细查看才发现原来是请求的URL中参数包含了特殊字符%,导致Web Server没能够正确解析出该URL,才报了这个错误。

在URL中下列字符具有特殊含义:
符号 含义     如何转义
+     URL中+号表示空格                           %2B     
空格 URL中的空格可以用+号或者编码 %20   
/   分隔目录和子目录                                 %2F       
?     分隔实际的URL和参数                     %3F       
%     指定特殊字符                                    %25       
#     表示书签                                             %23       
&     URL中指定的参数间的分隔符        %26       
=     URL中指定参数的值                        %3D

比如sever端从提交的表单的输入框中的值构造包含参数的URL,
若提交的内容为“pkgcr+awldb”,地址栏的URL显示为“xxx/?q=pkgcr%2Bawldb”,也即参数中q的值实际上为“pkgcr+awldb”
若提交的内容为“pkgcr awldb”,地址栏的URL显示为“xxx/?q=pkgcr+awldb”,也即参数中q的值实际上为“pkgcr awldb”
若提交的内容为“pkgcr/awldb”,地址栏的URL显示为“xxx/?q=pkgcr%2Fawldb”,也即参数中q的值实际上为“pkgcr/awldb”
若提交的内容为“pkgcr?awldb”,地址栏的URL显示为“xxx/?q=pkgcr%3Fawldb”,也即参数中q的值实际上为“pkgcr?awldb”
若提交的内容为“pkgcr%awldb”,地址栏的URL显示为“xxx/?q=pkgcr%25awldb”,也即参数中q的值实际上为“pkgcr%awldb”
若提交的内容为“pkgcr#awldb”,地址栏的URL显示为“xxx/?q=pkgcr%23awldb”,也即参数中q的值实际上为“pkgcr#awldb”
若提交的内容为“pkgcr&awldb”,地址栏的URL显示为“xxx/?q=pkgcr%26awldb”,也即参数中q的值实际上为“pkgcr&awldb”
若提交的内容为“pkgcr=awldb”,地址栏的URL显示为“xxx/?q=pkgcr%3Dawldb”,也即参数中q的值实际上为“pkgcr=awldb”

若要是直接在server端构造URL呢?比如server端的文件中有个变量ip,值为“172.142.%”,要在server端构造一个URL供客户端访问,如“href=?ip={ip}&q='mysql'”(此处假定{ip}是对变量的一种引用方式),那么我们点击这个链接会是什么结果呢?

我们会看到,因为变量ip中包含特殊字符“%”,而“%”在URL中具有特殊含义,我们通过上述方式构造的URL相当于是“href=?ip=172.142.%&q=mysql”,web服务器解析该URL时无法解释%&从而导致出错。同样的原因,包含其他一些特殊字符时也会发生一些意想不到的问题,比如有另一个变量addr,值为“china&america”,构造的URL为“href=?addr={addr}&q=‘mysql’”,此时构建的URL相当于是“href=?addr=china&america&q=mysql”,web服务器会把该URL中的第一个“&”后的“america”解析为另外一个参数而不是将“china&america”整体作为“addr”参数的值。

那么如何在需要的时候在URL中包含诸如%、&、+、=等等这样的特殊的字符呢?答案就是用相应的编码代替特殊字符本身来构建URL。比如上例中可以先将ip的值替换为“172.142.%25”,将addr的值替换为“china%26america”,这样构建出的URL分别为“href=?ip=172.142.%25&q=mysql”和“href=?addr=china%26america&q=‘mysql’”,这样最终能够将URL中的参数ip的值成功解析为“172.142.%”而将addr的值成功解析为china&america,而且不会引起其他参数解析混乱。

最终,发现是在访问url的中文未进行转码导致的400错误。

ps: js中文转码(encodeURIComponent)

记一次400错误引发的血案(URL中特殊符号的转义/400 bad request错误)的更多相关文章

  1. Matlab一个错误引发的血案:??? Error using ==> str2num Requires string or character array input.

    Matlab总遇到一些神奇的问题,让人摸不着头脑.昨天编写程序的时候遇到一个让我十分火大的问题,也是自己的matlab基础不好吧. 先描述一下问题,再GUI界面有个listbox,Tag属性是’lis ...

  2. NetCore踩坑记1、 一块网卡引发的血案

    公司的项目架构演进,我们也趁机尝试迁移到netcore,系列随笔讲记录我们的踩坑和填坑记录. HttpClient不行? 这是我们第一次尝试netcore 简要介绍环境 netcore2.2+aspn ...

  3. Feign 400错误引发的一系列问题

    Feign 400错误引发的一系列问题 问题介绍 在使用Feign进行远程调用的时候出现非常奇怪的400错误,错误信息大概如下: feign.FeignException: status 400 re ...

  4. 一次使用自定义 Http Header 引发的血案

    一次使用自定义 Http Header 引发的血案 HttpClient Http Header 自定义 nginx 不转发  起因 最近在整理我们产品的 OpenAPI Demo (Python.C ...

  5. 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器

    1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...

  6. [WCF]缺少一行代码引发的血案

    这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性.具体来说,这是一个关于如何自动为服务接口(契约 ...

  7. Integer.parseInt 引发的血案

    Integer.parseInt 处理一个空字符串, 结果出错了, 程序没有注意到,搞了很久, 引发了血案啊!! 最后,终于 观察到了, 最后的部分: Caused by: java.lang.NoC ...

  8. Replication的犄角旮旯(六)-- 一个DDL引发的血案(上)(如何近似估算DDL操作进度)

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

  9. 一个字母引发的血案 java.io.File中mkdir()和mkdirs()

    一个字母引发的血案 明天开始放年假了,临放假前有个爬虫的任务,其中需要把网络图片保存到本地,很简单,马上写完了代码: //省略部分代码... Long fileId= (Long) data.get( ...

随机推荐

  1. Octave下操作CH341

    #include <octave/oct.h> #include <windows.h> #include <cstdint> #include <fstre ...

  2. 第十二章 springboot + mongodb(复杂查询)

    简单查询:使用自定义的XxxRepository接口即可.(见 第十一章 springboot + mongodb(简单查询)) 复杂查询:使用MongoTemplate以及一些查询条件构建类(Bas ...

  3. C++ vector 删除符合条件的元素

    C++ vector中实际删除元素使用的是容器vecrot中std::vector::erase()方法. C++ 中std::remove()并不删除元素,因为容器的size()没有变化,只是元素的 ...

  4. iOS开发-多线程简介

    多线程从概念上理解是指从软件或者硬件上实现多个线程并发执行的技术,简单点理解就是同一时间可以执行多个事情(比如说一边听歌一边码代码),听歌是一个线程,码代码是一个线程,如果是单核CPU的话,上面两个动 ...

  5. java类过滤器,防止页面SQL注入

    package com.tarena.dingdang.filter; import java.io.IOException; import java.util.Enumeration; import ...

  6. 理解js中的new

    new 操作符 在有上面的基础概念的介绍之后,在加上new操作符,我们就能完成传统面向对象的class + new的方式创建对象,在Javascript中,我们将这类方式成为Pseudoclassic ...

  7. Learning How To Code Neural Networks

    原文:https://medium.com/learning-new-stuff/how-to-learn-neural-networks-758b78f2736e#.ly5wpz44d This i ...

  8. C++的基本类型

  9. Linux-cpu分析-vmstat

    转载:https://blog.csdn.net/ty_hf/article/details/63394960 一. 前言 为了更方便的理解本篇内容含义,所以请最好看看如下繁琐的概念,更容易理解. 没 ...

  10. centos+apache+mod_ssl

    参考网站:配置Apache建立openssl证书实现SSL访问:http://blog.51yip.com/apachenginx/958.html用ca工具生成证书的方法:http://hi.bai ...