当前位置: 首页 > news >正文

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"})

相关文章:

  • Python + Selenium + Chrome Driver 自动化点击+评论+刷弹幕(仅供学习)
  • workmanager导入android studio
  • Fast R-CNN
  • 【Spring系列03】依赖注入(DI)[之set注入]
  • 机器学习笔记之支持向量机(二)引出对偶问题
  • invokeBeanFactoryPostProcessors
  • 使用 pnpm monorepo + ts 制作个功能完善的 CLI 命令行工具
  • leetcode:714. 买卖股票的最佳时机含手续费
  • 基于MATLAB的曼彻斯特调制与解调实现
  • SpringBoot 实现 Oracle 主从数据库的动态切换,并实现读写分离
  • 24.缓存
  • 【AJAX是什么】【AJAX的基本使用】
  • 丈母娘想女婿了,小伟和陈萌刚拍完婚纱照,就被大衣哥安排去看望
  • 猿创征文|Android kotlin实现动态更换应用图标和名称
  • Java高阶数据结构之红黑树
  • python3.6+scrapy+mysql 爬虫实战
  • 5、React组件事件详解
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Android 架构优化~MVP 架构改造
  • Android单元测试 - 几个重要问题
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • download使用浅析
  • es6(二):字符串的扩展
  • JavaScript DOM 10 - 滚动
  • LeetCode18.四数之和 JavaScript
  • Mac转Windows的拯救指南
  • Ruby 2.x 源代码分析:扩展 概述
  • SpiderData 2019年2月23日 DApp数据排行榜
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • Yeoman_Bower_Grunt
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 猴子数据域名防封接口降低小说被封的风险
  • 你真的知道 == 和 equals 的区别吗?
  • 深入浅出Node.js
  • 一道闭包题引发的思考
  • 一文看透浏览器架构
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​业务双活的数据切换思路设计(下)
  • (23)Linux的软硬连接
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (SpringBoot)第二章:Spring创建和使用
  • (笔试题)合法字符串
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (一)基于IDEA的JAVA基础10
  • (译)2019年前端性能优化清单 — 下篇
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • *** 2003
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选