HTTP

# HTTP http模块提供一些进行http请求的函数。 ## http.get(url[, options, callback]) - url {string} 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。 - options {Object} 请求选项。参见[http.request()][]。 - callback {Function} 回调函数,可选,其参数是一个[Response][]对象。如果不加回调函数,则该请求将阻塞、同步地执行。 对地址url进行一次HTTP GET 请求。 如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。 最简单GET请求如下: ```js console.show(); var r = http.get("www.baidu.com"); log("code = " + r.statusCode); log("html = " + r.body.string()); ``` 采用回调形式的GET请求如下: ```js console.show(); http.get("www.baidu.com", {}, function(res, err){ if(err){ console.error(err); return; } log("code = " + res.statusCode); log("html = " + res.body.string()); }); ``` 如果要增加HTTP头部信息,则在options参数中添加,例如: ```js console.show(); var r = http.get("www.baidu.com", { headers: { 'Accept-Language': 'zh-cn,zh;q=0.5', 'User-Agent': 'Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11' } }); log("code = " + r.statusCode); log("html = " + r.body.string()); ``` 一个请求天气并解析返回的天气JSON结果的例子如下: ```js var city = "广州"; var res = http.get("http://www.sojson.com/open/api/weather/json.shtml?city=" + city); if(res.statusCode != 200){ toast("请求失败: " + res.statusCode + " " + res.statusMessage); }else{ var weather = res.body.json(); log(weather); toast(util.format("温度: %s 湿度: %s 空气质量: %s", weather.data.wendu, weather.data.shidu, weather.quality)); } ``` ```js //等待联网 //此代码由飞云脚本圈原创(www.feiyunjs.com) function waitForNetworking(sleepTime) { while (true) { sleep(sleepTime); //等待缓冲时间 try { if (http.get("www.baidu.com").statusCode == 200) { break; }; } catch (err) { log("报错信息-->> " + err); }; }; }; //判断是否联网 //此代码由飞云脚本圈原创(www.feiyunjs.com) function isNetworking(sleepTime) { if (http.get("www.baidu.com").statusCode == 200) { return true; } else { return false; }; }; ``` ## http.post(url, data[, options, callback]) - url {string} 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。 - data {string} | {Object} POST数据。 - options {Object} 请求选项。 - callback {Function} 回调,其参数是一个[Response][]对象。如果不加回调参数,则该请求将阻塞、同步地执行。 对地址url进行一次HTTP POST 请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。 其中POST数据可以是字符串或键值对。具体含义取决于options.contentType的值。 默认为"application/x-www-form-urlencoded"(表单提交), 这种方式是JQuery的ajax函数的默认方式。 一个模拟表单提交登录淘宝的例子如下: ```js var url = "https://login.taobao.com/member/login.jhtml"; var username = "你的用户名"; var password = "你的密码"; var res = http.post(url, { "TPL_username": username, "TPL_password": password }); //取页面html源码 var html = res.body.string(); if(html.contains("页面跳转中")){ toast("登录成功"); }else{ toast("登录失败"); } ``` > 以下非官方例子 比如服务器上存有一段json数据。 ```json { "ret": 200, "data": { "name": "飞云脚本圈", "url": "http://www.feiyunjs.com" }, "msg": "" } ``` 我们要获取其中的name值 ```js //此代码由飞云脚本圈原创(www.feiyunjs.com) //接口采用PhalApi开发 let url = "http://news.feiyunjs.com/phalapi/public/"; let res = http.post(url, { "service": "App.Zllgcimei.Imei", "imei": device.getIMEI(), "imei_tag": "测试标签", "whos": "feiyun", }); let appName; let html = res.body.string(); //取页面html源码 // log(html) let json = JSON.parse(html); if (json.ret == "200") { appName = json.data.name } else { log("请求失败!") } log(appName) ``` ## http.postJson(url[, data, options, callback]) - url {string} 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。 - data {Object} POST数据。 - options {Object} 请求选项。 - callback {Function} 回调,其参数是一个[Response][]对象。如果不加回调参数,则该请求将阻塞、同步地执行。 以JSON格式向目标Url发起POST请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。 JSON格式指的是,将会调用JSON.stringify()把data对象转换为JSON字符串,并在HTTP头部信息中把"Content-Type"属性置为"application/json"。这种方式是AngularJS的ajax函数的默认方式。 一个调用图灵机器人接口的例子如下: ```js var url = "http://www.tuling123.com/openapi/api"; r = http.postJson(url, { key: "65458a5df537443b89b31f1c03202a80", info: "你好啊", userid: "1", }); toastLog(r.body.string()); ``` ## http.postMultipart(url, files[, options, callback]) - url {string} 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。 - files {Object} POST数据。 - options {Object} 请求选项。 - callback {Function} 回调,其参数是一个Response对象。如果不加回调参数,则该请求将阻塞、同步地执行。 向目标地址发起类型为multipart/form-data的请求(通常用于文件上传等) 其中files参数是{name1: value1, name2: value2, ...}的键值对,value的格式可以是以下几种情况: 1. string 2. 文件类型,即open()返回的类型 3. [fileName, filePath] 4. [fileName, mimeType, filePath] 其中1属于非文件参数,2、3、4为文件参数。举个例子,最简单的文件上传的请求为: ```js var res = http.postMultipart(url, { file: open("/sdcard/1.txt") }); log(res.body.string()); ``` 如果使用格式2,则代码为 ```js var res = http.postMultipart(url, { file: ["1.txt", "/sdcard/1.txt"] }); log(res.body.string()); ``` 如果使用格式3,则代码为 ```js var res = http.postMultipart(url, { file: ["1.txt", "text/plain", "/sdcard/1.txt"] }); log(res.body.string()); ``` 如果使用格式2的同时要附带非文件参数"appId=abcdefghijk",则为: ```js var res = http.postMultipart(url, { appId: "adcdefghijk", file: open("/sdcard/1.txt") }); log(res.body.string()); ``` ## http.request(url[, options, callback]) - url {string} 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。 - options {Object} 请求选项。参见[http.buildRequest()][]。 - callback {Function} 回调,其参数是一个[Response][]对象。如果不加回调参数,则该请求将阻塞、同步地执行。 对目标地址url发起一次HTTP请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。 选项options可以包含以下属性: 1. headers {Object} 键值对形式的HTTP头部信息。有关HTTP头部信息,参见菜鸟教程:HTTP响应头信息。 2. method {string} HTTP请求方法。包括"GET", "POST", "PUT", "DELET", "PATCH"。 3. contentType {string} HTTP头部信息中的"Content-Type", 表示HTTP请求的内容类型。例如"text/plain", "application/json"。更多信息参见菜鸟教程:HTTP contentType。 4. body {string} | {Array} | {Function} HTTP请求的内容。可以是一个字符串,也可以是一个字节数组;或者是一个以BufferedSink为参数的函数。 > 该函数是get, post, postJson等函数的基础函数。因此除非是PUT, DELET等请求,或者需要更高定制的HTTP请求,否则直接使用get, post, postJson等函数会更加方便。 # Response HTTP请求的响应。 ## Response.statusCode {number} 当前响应的HTTP状态码。例如200(OK), 404(Not Found)等。 有关HTTP状态码的信息,参见菜鸟教程:HTTP状态码。 ## Response.statusMessage {string} 当前响应的HTTP状态信息。例如"OK", "Bad Request", "Forbidden"。 有关HTTP状态码的信息,参见菜鸟教程:HTTP状态码。 例子: ```js var res = http.get("www.baidu.com"); if(res.statusCode >= 200 && res.statusCode < 300){ toast("页面获取成功!"); }else if(res.statusCode == 404){ toast("页面没找到哦..."); }else{ toast("错误: " + res.statusCode + " " + res.statusMessage); } ``` ## Response.headers {Object} 当前响应的HTTP头部信息。该对象的键是响应头名称,值是各自的响应头值。 所有响应头名称都是小写的(吗)。 有关HTTP头部信息,参见菜鸟教程:HTTP响应头信息。 例子: ```js console.show(); var res = http.get("www.qq.com"); console.log("HTTP Headers:") for(var headerName in res.headers){ console.log("%s: %s", headerName, res.headers[headerName]); } ``` ## Response.body {Object} 当前响应的内容。他有以下属性和函数: - bytes() {Array} 以字节数组形式返回响应内容 - string() {string} 以字符串形式返回响应内容 - json() {Object} 把响应内容作为JSON格式的数据并调用JSON.parse,返回解析后的对象 - contentType {string} 当前响应的内容类型 ## Response.request {Request} 当前响应所对应的请求。参见[Request][]。 ## Response.url {number} 当前响应所对应的请求URL。 ## Response.method {string} 当前响应所对应的HTTP请求的方法。例如"GET", "POST", "PUT"等。 # 示例 ## 获取网页 ```js var url = "www.baidu.com"; var res = http.get(url); if(res.statusCode == 200){ toast("请求成功"); console.show(); log(res.body.string()); }else{ toast("请求失败:" + res.statusMessage); } ``` ## http超时返回null ```js (function () { let request = http.request; // 覆盖http关键函数request,其他http返回最终会调用这个函数 http.request = function () { try { // 捕捉所有异常 return request.apply(http, arguments); } catch (e) { // 出现异常返回null console.error(e); return null; } } })(); //设置超时为10秒 http.__okhttp__.setTimeout(10000); // 获取一个不存在的网站,应该会Timeout (或者把网络断开) console.log(http.get("https://www.google.com.hk")); toast("程序结束"); ``` ## 文件上传 ```js //如果遇到SocketTimeout的异常,重新多运行几次脚本即可 console.show(); example1(); example2(); example3(); example4(); example5(); function example1(){ var res = http.postMultipart("http://posttestserver.com/post.php", { "file": open("/sdcard/1.txt") }); log("例子1:"); log(res.body.string()); } function example2(){ var res = http.postMultipart("http://posttestserver.com/post.php", { "file": ["1.txt", "/sdcard/1.txt"] }); log("例子2:"); log(res.body.string()); } function example3(){ var res = http.postMultipart("http://posttestserver.com/post.php", { "file": ["1.txt", "text/plain", "/sdcard/1.txt"] }); log("例子3:"); log(res.body.string()); } function example4(){ var res = http.postMultipart("http://posttestserver.com/post.php", { "file": open("/sdcard/1.txt"), "aKey": "aValue" }); log("例子4:"); log(res.body.string()); } ``` ## 图片文件下载 ```js var url = "http://www.autojs.org/assets/uploads/profile/3-profileavatar.png"; var res = http.get(url); if(res.statusCode != 200){ toast("请求失败"); } files.writeBytes("/sdcard/1.png", res.body.bytes()); toast("下载成功"); app.viewFile("/sdcard/1.png"); ``` ## js文件下载 ```js //此代码由飞云脚本圈原创(www.feiyunjs.com) // https://www.bootcdn.cn/jquery/ let url = "https://cdn.bootcss.com/jquery/3.4.1/core.js" let res = http.get(url); let fileName = getEndValue(url) if (res.statusCode != 200) { toast("请求失败"); } else { files.write("/sdcard/" + fileName, res.body.string()); toast("下载成功"); app.viewFile("/sdcard/" + fileName); } // JS 获取最后一个 / 后面的值 function getEndValue(url) { //获取最后一个/的位置 var site = url.lastIndexOf("\/"); //截取最后一个/后的值 return url.substring(site + 1, url.length); } ``` ## 获取cookie 适用于免费版和收费版的cookie管理 ```js function mCookieManager() { var versionName = app.autojs.versionName; if (versionName.toString().startsWith("Pro")) { http.__okhttp__.muteClient(new OkHttpClient.Builder().cookieJar(web.webkitCookieJar)) return cookieManager = web.cookieManager; } else { http.__okhttp__.muteClient(new OkHttpClient.Builder().cookieJar(new org.autojs.autojs.network.util.WebkitCookieManagerProxy())) return cookieManager = android.webkit.CookieManager.getInstance(); } } ```