GDScript进行HTTP请求以及session问题

Godot提供了HTTPClient和HTTPRequest两个类来进行HTTP请求,它们的区别在于:

  • HTTPClient更底层,需要自己轮循服务器返回;HTTPRequest只需要发送请求,当服务器数据返回时会触发相应信号
  • HTTPClient并不需要加入场景树的节点中,而HTTPRequest继承自Note类,必须加入到节点中才能正常运行

考虑到自己对底层的东西并不是很熟,而且既然使用HTTP请求,就是因为并不需要很大的请求量,所以就直接使用官方封装好的HTTPRequest类。
我直接参考了官方提供的例子来写了第一个实例。
Ajax.gd

var HttpObject : HTTPRequest

#类初始化
func _init():
	# 创建 HTTP 请求节点并连接完成信号。
	HttpObject = HTTPRequest.new()
	HttpObject.connect("request_completed", self, "_http_request_completed")

#执行get请求
func Get(url):
	var error = HttpObject.request(url)
	if error != OK:
		push_error("HTTP 请求发生了错误。")

#请求成功信号
func _http_request_completed(result, response_code, headers, body):
	if result == 0 and response_code == 200:
		#获得返回的完整数据
		var response = parse_json(body.get_string_from_utf8())
		print(response)

由于我有一个全局单例Global.gd,所以我直接在Global.gd里实例化这个类:

var Ajax
var _ajaxClass = preload("res://script/network/Ajax.gd")

# 首次载入
func _ready():
	Ajax = _ajaxClass.new()
	add_child(Ajax.HttpObject) #必须加入节点才能正常使用,否则会报错
	
	Ajax.Get("http://127.0.0.1:8000/")

经测试可以正常返回服务器数据,但随后发现了问题,即服务器保存的session没有效果,而直接在浏览器测试是好的,说明不是服务器问题。
由于以前js用的ajax类都是别人封装好的,所以对http的底层了解很浅。后来在浏览器中开着F12测试,发现每次服务器返回的标头中都下发了cookie,而每次请求时,在标头中带上上次下发的cookie。
于是改装了一下Ajax.gd

var _cookie : String
func _init():
	_cookie = "0"
	# 创建 HTTP 请求节点并连接完成信号。
	HttpObject = HTTPRequest.new()
	HttpObject.connect("request_completed", self, "_http_request_completed")

#执行get请求
func Get(url):
	var h = [
		"cookie: %s" % _cookie
		]
	var error = HttpObject.request(url, h)
	if error != OK:
		push_error("HTTP 请求发生了错误。")

#请求成功信号
func _http_request_completed(result, response_code, headers, body):
	if result == 0 and response_code == 200:
		#获得返回的完整数据
		var response = parse_json(body.get_string_from_utf8())
		print(response)
		
		#获得下一次请求的cookie
		for s in headers:
			if s.left(11) == "set-cookie:":
				s = s.substr(12)
				s = s.split(";")[0]
				_cookie = s
				break

经测试发现服务器session正常了,登陆账号之类的问题就解决了,但是还有一个问题未解决,就是当上一次发送的请求如果还没有返回,此时发送请求时会被忽略。
不知道这个有什么好的办法,于是自己写了一个请求队列,等上次的请求有结果了,再进行请求。
顺便把Get方法改了一下,传一个请求地址与参数列表,再进行组装。
请求成功的print也改成了信号:

#cookie信息
var _cookie : String

#请求队列
var _queue = []

#是否正在get请求中
var _isGeting = false

var HttpObject : HTTPRequest

#请求成功信号
signal onResponse(model, body)

#类初始化
func _init():
	_cookie = "0"
	# 创建 HTTP 请求节点并连接完成信号。
	HttpObject = HTTPRequest.new()
	HttpObject.connect("request_completed", self, "_http_request_completed")

# 发送请求
func Send(model, body = {}):
	var url = "http://127.0.0.1:8000/"
	#是否包含model
	if model != "":
		url = "%s%s" % [url, model]
	#组成参数
	var qy = ""
	for k in body.keys():
		if qy != "":
			qy = "%s&" % qy
		qy = "%s%s=%s" % [qy, k, body[k].http_escape()]
	if qy != "":
		url = "%s?%s" % [url, qy]
	
	_queue.append({"m" : model, "u" : url})
	_CheckSend()

# 检查是否需要发送请求
func _CheckSend():
	if _queue.size() == 0:
		return
	
	if _isGeting:
		return
	
	_isGeting = true
	var h = [
		"cookie: %s" % _cookie
		]
	
	var url = _queue[0]["u"]
	
	print(url)
	var error = HttpObject.request(url, h)
	if error != OK:
		push_error("HTTP 请求发生了错误。")

# 请求成功
func _http_request_completed(result, response_code, headers, body):
	if result == 0 and response_code == 200:
		#获得返回的完整数据
		var response = parse_json(body.get_string_from_utf8())
		
		#触发事件信号
		emit_signal("onResponse", _queue[0]["m"], response)
		
		#删除已请求成功的元素
		_queue.remove(0)
		
		#获得下一次请求的cookie
		for s in headers:
			if s.left(11) == "set-cookie:":
				s = s.substr(12)
				s = s.split(";")[0]
				_cookie = s
				break
	else:
		push_error("请求网络地址 %s 失败!" % _queue[0]["u"])
	
	_isGeting = false
	_CheckSend()

调用方法:
Ajax.Send("get")
Ajax.Send("register", {"user" : "nazgul", "pswd" : "123456"})

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值