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. 【PAT Advanced Level】1011. World Cup Betting (20)

    简单模拟题,遍历一遍即可.考察输入输出. #include <iostream> #include <string> #include <stdio.h> #inc ...

  2. 服务 Service 清单文件中可设置的属性

    PS:对于一个Service,在没有在AndroidManifest.xml中声明的情况下使用时,不会像Activity那样直接崩溃并提示找不到Activity. 对于显式Intent启动的Servi ...

  3. 直播【95秀】JNI 基本实现 简洁

    2017-2-8 基本架构 1.使用SurfaceView在UI层面展示视频 2.通过JNI调用C代码控制视频的播放.停止 基本功能 1.从服务器获取正在直播的主播的列表信息 2.进入直播界面 3.可 ...

  4. JavaScript Event Delegation, and event.target vs. event.currentTarget

    原文:https://medium.com/@florenceliang/javascript-event-delegation-and-event-target-vs-event-currentta ...

  5. [React GraphQL] Pass Parameters to urql's useQuery React Hook

    Showing how to use 'uqrl' library to do GraphQL in React. import React, {useState} from 'react' impo ...

  6. Jmeter-Maven-Plugin高级应用:Log Levels

    Log Levels Pages 12 Home Adding additional libraries to the classpath Advanced Configuration Basic C ...

  7. 【C#】利用JMail发送邮件

    有用到需要发送帐号激活邮件,利用Jmail去做蛮简单的,先记录下: 1.首先到Jmail官网下载对应的版本,解压后安装(Jmail 4.4 免费版). 2.到安装目录就可以找到jmail.dll文件, ...

  8. Discuz常见大问题-如何允许用户插入视频-如何自己在页面中插入视频

    从视频的下面分享中获取html代码 然后粘贴到你创建页面的指定位置(注意从优酷复制的视频宽度和高度可能比较小,你可以自己调整,或者占据100%) 最终的实现效果

  9. android开发步步为营之67:使用android开源项目android-async-http异步下载文件

    android-async-http项目地址 https://github.com/loopj/android-async-http.android-async-http顾名思义是异步的http请求, ...

  10. 安装apache+php记录

    安装apache yum install httpd 修改apache配置文件,可以修改apache的默认端口号,根目录等 /etc/httpd/conf/httpd.conf 启动/重启apache ...