• 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    由于我有一个全局单例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/")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    经测试可以正常返回服务器数据,但随后发现了问题,即服务器保存的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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    经测试发现服务器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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

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

  • 相关阅读:
    关于专利技术交底书分类的真相
    创意指南丨VR游览沉浸式空间体验
    汇编-MOVSXD64位带符号扩展传送
    测试员可以提高获得面试机会的9个简历投递秘笈
    阿里云国际版忘记会员名或登录密码,怎么办?
    程序员应了解的那些事(111)~进程、线程及堆栈关系
    产品推荐 | 基于Anlogic系列EG4S20 FPGA开发板
    求链表的倒数第m个元素(递归 / 双指针)
    C++——list(2)
    六级高频词汇——Group07
  • 原文地址:https://blog.csdn.net/shalyun/article/details/126684479