所以让我们从一些背景开始。我有一个 3 层系统,在 django 中实现了一个 API,在 Apache2 服务器上运行mod_wsgi 。
今天我决定将运行在DigitalOcean的服务器从 Ubuntu 12.04 升级到 Ubuntu 14.04。没什么特别的,只是 Apache2 也更新到了2.4.7版本。在浪费了一天的大部分时间弄清楚他们实际上将默认文件夹从 /var/www 更改为 /var/www/html,破坏了功能之后,我决定测试我的 API。没有接触任何一行代码,我的一些功能就无法正常工作。
我将使用其中一个较小的函数作为示例:
# Returns the location information for the specified animal, within the specified period.
@csrf_exempt # Prevents Cross Site Request Forgery errors.
def get_animal_location_reports_in_time_frame(request):
start_date = request.META.get('HTTP_START_DATE')
end_date = request.META.get('HTTP_END_DATE')
reports = ur_animal_location_reports.objects.select_related('species').filter(date__range=(start_date, end_date), species__localizable=True).order_by('-date')
# Filter by animal if parameter sent.
if request.META.get('HTTP_SPECIES') is not None:
reports = reports.filter(species=request.META.get('HTTP_SPECIES'))
# Add each information to the result object.
response = []
for rep in reports:
response.append(dict(
ID=rep.id,
Species=rep.species.ai_species_species,
Species_slug=rep.species.ai_species_species_slug,
Date=str(rep.date),
Lat=rep.latitude,
Lon=rep.longitude,
Verified=(rep.tracker is not None),
))
# Return the object as a JSON string.
return HttpResponse(json.dumps(response, indent = 4))
经过一些调试,我观察到request.META.get('HTTP_START_DATE')
并request.META.get('HTTP_END_DATE')
返回None
. 我尝试了许多客户端,从 REST 客户端(例如 PyCharm 和RestConsole for Chrome中的客户端)到通常与 API 通信的 Android 应用程序,但结果是相同的,这两个参数没有被发送。
然后我决定测试是否正在发送其他参数,令我恐惧的是,它们确实如此。在上面的函数中,request.META.get('HTTP_SPECIES')
会有正确的值。
在对名称进行了一番摆弄之后,我观察到所有在标题中有_
字符的参数都不会进入 API。
所以我想,很酷,我只用-
代替_
,应该可以的,对吧?错误的。-
以_
! _
此时我完全迷惑了,所以我决定找出罪魁祸首。我使用 django 开发服务器运行 API,通过运行:
sudo python manage.py runserver 0.0.0.0:8000
当使用相同的客户端发送相同的参数时,它们会被 API 很好地拾取!因此,django 没有导致这个,Ubuntu 14.04 没有导致这个,唯一可能导致它的是 Apache 2.4.7!
现在将默认文件夹从 移动/var/www
到/var/www/html
,从而破坏了功能,所有(在我看来)非常愚蠢的理由已经够糟糕了,但这太过分了。
有谁知道这里实际发生了什么以及为什么?