微信小程序中开发环境下的POST请求

写在前面

不得不说,开发环境下,微信小程序要是在发起网络请求的话,遇到的坑也是有的。尽管,微信提供了十分便捷的API 供开发者调用。今天在小程序中写了一个表单,需要提交到服务器上,于是发起了一个 POST 请求,结果报错了。

关于网络请求

微信小程序提供了许多使用网络相关的 API,同时文档中也列出了一些(一大堆)注意事项常见问题什么的。比如:


  • 每个微信小程序需要事先设置通讯域名,小程序只可以跟指定的域名与进行网络通信
  • 域名只支持 https (wx.request、wx.uploadFile、wx.downloadFile) 和 wss (wx.connectSocket) 协议
  • 域名不能使用 IP 地址(小程序的局域网 IP 除外)或 localhost
  • 网络请求的 referer header 不可设置
  • wx.request、wx.uploadFile、wx.downloadFile 的最大并发限制是 10 个
  • 小程序进入后台运行后,如果 5s 内网络请求没有结束,会回调错误信息 fail interrupted;在回到前台之前,网络请求接口调用都会无法调用

更多可以查看 相关说明


这些条条框框实在不友好,尤其是开发环境中,向本地服务器发起网络请求时一般都是 localhost。好在文档的末尾,有提到怎样跳过域名校验。

在微信开发者工具中,可以临时开启 开发环境不校验请求域名、TLS版本及HTTPS证书 选项,跳过服务器域名的校验。此时,在微信开发者工具中及手机开启调试模式时,不会进行服务器域名的校验。

所以事情就变得很简单了,关闭域名校验后,直接在程序中调用 API 就行了。

关于 wx.request

相关参数


属性类型默认值说明
urlstring开发者服务器接口地址
datastring/object/ArrayBuffer请求的参数
headerObject设置请求的 header
timeoutnumber超时时间,单位为毫秒
methodstringGETHTTP 请求方法
dataTypestringJSON返回的数据格式
responseTypestringtext响应的数据类型
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

更多关于可以参考文档


代码示例

这里的 url 是我自己的 Django 本地服务器地址,已经启动。于是我们可以仿照文档给出的示例,发起一个 POST 请求可以这样写:

wx.request({
  url: 'http://127.0.0.1:8000/blog/wxapi/',
  data: {
    x: 'haha',
    y: 'ahah'
  },
  method:'POST',     // 默认 GET
  header: {
    'content-type': 'application/x-www-form-urlencoded'    // 默认值 application/json
  },
  success:res=> {
    console.log('---request success---')
    console.log(res.data)
  },
  fail:res=> {
    console.log(res.data)
    console.log('---request fail---')
  },
  complete: res => {
    console.log(res.data)
	console.log('---request complete---')
  }
})

403 Forbidden

然而,这样请求得到的响应码会是 403,显然这是客户端的错误。仔细看提示会发现,这是由于该 POST 请求没有带cookie或者说 cookie 为 null。而 Django 对 POST 请求都会进行 CSRF cookie 验证,防止CSRF(跨站请求伪造)恶意攻击。这个 CSRF cookie 就是 Django 模板里的 form 表单下的 {% csrf_token %}。这也是微信小程序开发与 web开发的一个区别所在。小程序的运行环境是在微信而不是浏览器,尽管我们可以在 header 中设置一个 Set-Cookie,也是无济于事,因为我们拿到的并不是 {% csrf_token %} 这样的令牌。所以 Django 服务器会认为这是一个恶意请求,从而返回 403。

解决办法

要想解决说简单也简单,说难也有些复杂。我们已经明确知道这是一个关于跨域请求的问题。仔细观察 Django 项目中的 setting.py 文件,不难发现其中有这样一段配置:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

这是项目中最基本的中间件,其中 django.middleware.csrf.CsrfViewMiddleware 就和 csrf 验证有关。所以我们不妨将其注释,然后在小程序中重新发起请求。观察控制台输出的 res 部分如下:

data:
	data: "ok"
	x: "haha new"
	y: "ahah new"

errMsg: "request:ok"

header:
	Content-Length: "48"
	Content-Type: "application/json"
	Date: "Sun, 09 Feb 2020 14:44:18 GMT"
	Server: "WSGIServer/0.2 CPython/3.5.3"
	X-Frame-Options: "SAMEORIGIN"

statusCode: 200

备注:服务器端代码views.py

# 微信小程序测试api
def wxapi(request):
    if request.method=='GET':
        context= {
            "data": "ok"
        }
        return JsonResponse(context)
    if request.method=='POST':
        x = request.POST['x']
        y = request.POST['y']
        print(x + "---" + y)
        context = {
            "data": "ok",
            "x":x+" new",
            "y":y+" new"
        }
        return JsonResponse(context)
    return HttpResponse("--ok--")

但是注释该配置是十分危险的下下之策,这里只是开发环境中,为了学习微信小程序,无伤大雅。当然,不这样做的话,我们就需要去实现如何跨域请求拿到 csrf_token 。好在已经有大佬们为我们造好了轮子jango-cors-headers,我们只需要安装配置它就可以了。这里就不详细讲解了。

欢迎参观

学Django时,顺便写了简单的个人博客。前端用的bootstrap框架。笔记都会同步的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值