http.md 14.6 KB
Newer Older
1
## 使用场景
Q
qiang 已提交
2

3
云函数/云对象URL化 是 uniCloud 为开发者提供的 HTTP 访问服务,让开发者可以通过 HTTP URL 方式访问到云函数或云对象。
Q
qiang 已提交
4 5

- 场景1:比如App端微信支付,需要配服务器回调地址,此时需要一个HTTP URL。
6
- 场景2:非uni-app开发的系统,想要连接uniCloud,读写数据,也需要通过HTTP URL方式访问。
Q
qiang 已提交
7

雪洛's avatar
雪洛 已提交
8 9
url化后需要注意以下几点

Q
qiang 已提交
10 11 12
- 安全:为了保障业务安全性,开发者需在代码中做好权限控制和安全防护,避免未授权访问触发敏感操作。
- 计费:云函数开启了URL化后,如果遇到大量恶意访问,消耗云函数资源,开发者可以将云函数访问地址设置为空即可停止 HTTP 访问支持。

13 14
> 云函数自上线就支持URL化。云对象的URL化需HBuilderX 3.5.2+。下文除非特别提到云对象,否则云函数通指普通云函数和云对象。

Q
qiang 已提交
15 16 17 18 19 20
本文档主要指导您如何在uniCloud web控制台管理和使用云函数URL化。

**使用限制**

- 腾讯云免费服务空间最多只支持配置10个云函数URL化地址

雪洛's avatar
雪洛 已提交
21
## 操作步骤@steps
Q
qiang 已提交
22

雪洛's avatar
雪洛 已提交
23
### 设置云函数 HTTP 访问地址@set-path
Q
qiang 已提交
24

25
1. 登录[uniCloud后台](https://unicloud.dcloud.net.cn/),选择服务空间。
Q
qiang 已提交
26 27 28 29 30
2. 单击左侧菜单栏【云函数】,进入云函数页面。
3. 点击需要配置的云函数的【详情】按钮,配置访问路径。

<img style="max-width:800px;height:auto;" src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/b79d1dc0-5a21-11eb-8a36-ebb87efcf8c0.jpg"></img>

雪洛's avatar
雪洛 已提交
31 32 33
如果配置某云函数路径为`/test`,实际访问`/test``/test/a``/test/b`都会执行此云函数,在云函数内可以使用`event.path`区分访问来源

**注意**
Q
qiang 已提交
34

雪洛's avatar
雪洛 已提交
35 36
- 阿里云使用默认域名时,在浏览器访问url化地址会触发下载。绑定自定义域名则无此问题

雪洛's avatar
雪洛 已提交
37
### 绑定自定义域名@custom-domain
Q
qiang 已提交
38 39 40 41 42 43

**2021年5月25日起腾讯云绑定域名CNAME记录值由默认域名调整为腾讯云给定的`CNAME域名`,已经绑定正常使用的域名无需调整**

1. 单击左侧菜单栏【云函数】,进入云函数页面。
2. 单击【云函数域名绑定】,在弹出的配置窗口中进行配置。

雪洛's avatar
雪洛 已提交
44
<img style="max-width:800px;height:auto;" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/61819e66-9c4d-432f-ab70-5f8f042ce783.jpg"></img>
Q
qiang 已提交
45 46 47 48 49 50 51 52

上一步中填写域名证书且绑定成功后会返回一个`CNAME域名`,将绑定的域名配置CNAME记录值为此`CNAME域名`即可

**注意**

- 每个服务空间最多绑定1个自定义域名
- uniCloud提供默认域名供体验和测试该特性
- 需要注意的是绑定的域名必须已经备案
雪洛's avatar
雪洛 已提交
53
- 腾讯云单个服务空间可支持QPS收服务空间QPS限制,参考:[套餐资源](price.md#tencent-package)
雪洛's avatar
雪洛 已提交
54
- 阿里云单个服务空间可支持被访问的最大 QPS 为1000(具体频次受函数并发限制)
Q
qiang 已提交
55
- 默认域名可支持被访问的最大 QPS 为200,推荐您绑定自定义域名以获取更大的访问频次
雪洛's avatar
雪洛 已提交
56
- 阿里云绑定自定义域名要求此域名在阿里云保留备案信息,参考:[新增备案信息](https://help.aliyun.com/document_detail/36926.html)
Q
qiang 已提交
57 58 59 60 61

如需要更高的QPS支持,请发邮件到service@dcloud.io申请。若您还没有SSL证书,点此[快速获取](https://cloud.tencent.com/act/cps/redirect?redirect=33848&cps_key=c858f748f10419214b870236b5bb94c6)

**关于证书内容与私钥**

雪洛's avatar
雪洛 已提交
62 63 64 65 66 67
申请证书时通常会有下载选项,下载到证书之后找到对应Nginx的证书(包含一个crt文件和一个key文件或者一个pem文件和一个key文件),以文本形式打开crt/pem文件即可看到证书内容,同样的key文件对应着私钥。其他情况请查阅证书颁发者文档。

例:

在腾讯云申请的ssl证书包含一个crt文件和一个key文件,crt的文本内容为证书内容,key文件的内容为私钥

雪洛's avatar
雪洛 已提交
68
在阿里云申请的ssl证书包含一个pem文件和一个key文件,pem的文本内容为证书内容,key文件的内容为私钥
Q
qiang 已提交
69

雪洛's avatar
雪洛 已提交
70 71
## 普通云函数@cf-url

雪洛's avatar
雪洛 已提交
72
### 通过 HTTP URL 方式访问云函数@request-url
Q
qiang 已提交
73

雪洛's avatar
雪洛 已提交
74
通过`https://${云函数Url化域名}/${path}`直接访问函数,其中`${path}`是配置的函数触发路径或其子路径。
Q
qiang 已提交
75

雪洛's avatar
雪洛 已提交
76
### 云函数的入参@input
Q
qiang 已提交
77 78 79

使用 HTTP 访问云函数时,HTTP 请求会被转化为特殊的结构体,称之为**集成请求**,结构如下:

雪洛's avatar
雪洛 已提交
80
```js
Q
qiang 已提交
81 82 83 84 85 86 87 88 89 90 91
{
    path: 'HTTP请求路径,如 /hello',
    httpMethod: 'HTTP请求方法,如 GET',
    headers: {HTTP请求头},
    queryStringParameters: {HTTP请求的Query键值对形式},
    body: 'HTTP请求体',
    isBase64Encoded: 'true or false,表示body是否为Base64编码'
}
```

下面是一个示例:
雪洛's avatar
雪洛 已提交
92
```js
Q
qiang 已提交
93 94 95 96
{
    path: '/',
    httpMethod: 'GET',
    headers: {
雪洛's avatar
雪洛 已提交
97
        'host': 'xxx.example.com',
Q
qiang 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        'connection': 'close',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8'
    },
    isBase64Encoded: false,
    body: ''
}
```


**示例**

使用GET请求`https://${云函数Url化域名}/${functionPath}?a=1&b=2`,云函数接收到的`event`

雪洛's avatar
雪洛 已提交
114
```js
Q
qiang 已提交
115 116 117 118 119 120 121 122 123 124
{
    path: '/',
    httpMethod: 'GET',
    headers: {HTTP请求头},
    queryStringParameters: {a: "1", b: "2"},
    isBase64Encoded: false
}
```


雪洛's avatar
雪洛 已提交
125
使用POST请求`https://${云函数Url化域名}/${functionPath}`,云函数接收到的`event.body`为请求发送的数据,**uni.request默认content-type为application/json**
Q
qiang 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

```js
// 以uni.request为例
uni.request({
  method: 'POST',
  url: 'https://${云函数Url化域名}/${functionPath}',
  data: {
    a: 1,
    b: 2
  },
  success(res) {
    console.log(res);
  }
})

// 云函数收到的event为, 注意如果直接return此格式数据可能会被作为集成响应处理,参考下面的集成响应文档
{
    path: '/',
    httpMethod: 'POST',
    headers: {
    	...
    	"content-type": 'application/json'
    },
    isBase64Encoded: false,
    body: '{"a":1,"b":2}', // 注意此处可能是base64,需要根据isBase64Encoded判断
}
```

雪洛's avatar
雪洛 已提交
154
### 云函数url化返回值
Q
qiang 已提交
155

雪洛's avatar
雪洛 已提交
156
参考:[url化返回值](#output)
Q
qiang 已提交
157 158


雪洛's avatar
雪洛 已提交
159
## 云对象使用url化@cloudobject
Q
qiang 已提交
160

雪洛's avatar
雪洛 已提交
161
云对象使用url化配置仍需按照上文的操作步骤来,参考:[url化操作步骤](#steps)
Q
qiang 已提交
162

雪洛's avatar
雪洛 已提交
163
### 通过 HTTP URL 方式访问云对象@request-co-url
Q
qiang 已提交
164

雪洛's avatar
雪洛 已提交
165
调用url化的云对象时,以`url化路径/云对象方法名`形式的链接访问云对象的方法。例如:云对象配置的触发路径是`/todo`,调用`/todo/addTodo`即会触发云对象的addTodo方法。方法区分大小写且不可含`/`
Q
qiang 已提交
166

雪洛's avatar
雪洛 已提交
167 168
2022年11月11日之前,访问路径只能以方法名结尾,在此时间之后调整为,允许使用多段路径访问云对象方法。仍以上述配置为例,`/todo/addTodo/self``/todo/addTodo/group`都会调用云对象的addTodo方法。

雪洛's avatar
雪洛 已提交
169 170 171
### 云对象入参@input

url内query部分会被转换成云对象方法的入参。以下面的todo云对象为例
Q
qiang 已提交
172 173

```js
雪洛's avatar
雪洛 已提交
174 175 176 177 178 179 180
module.exports = {
	addTodo: function(params) { 
		console.log(params)
        return {
            errCode: 0
        }
	}
Q
qiang 已提交
181 182 183
}
```

雪洛's avatar
雪洛 已提交
184 185 186 187 188 189 190 191
如果通过`https://xxx.com/todo/addTodo?title=todo-title&content=todo-content`调用云对象,todo方法内的console.log会输出以下内容`{title: 'todo-title', content: 'todo-content'}`

需要注意的是自url内解析出的参数均为字符串类型。

**注意**

- url化方式调用云对象时,`_before``_after`均正常执行
- 如果需要获取其他方式传入云对象的参数(如:post一个json内容到云对象),请使用[this.getHttpInfo](cloud-obj.md#get-http-info)获取
雪洛's avatar
雪洛 已提交
192

雪洛's avatar
雪洛 已提交
193
### 云对象url化返回值
雪洛's avatar
雪洛 已提交
194

雪洛's avatar
雪洛 已提交
195
参考:[url化返回值](#output)
Q
qiang 已提交
196

雪洛's avatar
雪洛 已提交
197
## url化返回值@output
Q
qiang 已提交
198

雪洛's avatar
雪洛 已提交
199
云函数、云对象可以返回`string``object``number`等类型的数据,或者返回 [集成响应](#Integrationresponse),uniCloud会将返回值转化为正常的 HTTP 响应。
Q
qiang 已提交
200

雪洛's avatar
雪洛 已提交
201
### 返回字符串或数字
Q
qiang 已提交
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

云函数返回字符串,那么:
```js
exports.main = function() {
    return 'hello gateway'
}
```

最终 HTTP 响应为:
```shell
HTTP/1.1 200 OK
date: Mon, 16 Dec 2019 08:35:31 GMT
content-type: text/plain; charset=utf-8
content-length: 13

hello gateway
```

雪洛's avatar
雪洛 已提交
220
### 返回 Object
Q
qiang 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

返回的`Object`会被转换为 JSON,同时 HTTP 响应的`content-type`会被设置为 `application/json`

```js
exports.main = function() {
    return {
        foo: 'bar'
    }
}
```

最终 HTTP 响应为:
```shell
HTTP/1.1 200 OK
date: Mon, 16 Dec 2019 08:35:31 GMT
content-type: application/json; charset=utf-8
content-length: 13

{"foo":"bar"}
```

雪洛's avatar
雪洛 已提交
242
### 返回集成响应@Integrationresponse
Q
qiang 已提交
243 244 245 246 247 248 249 250 251 252 253 254 255

云函数可以返回如下这样特殊结构的**集成响应**,来自由地控制响应体:

```json
{
    "mpserverlessComposedResponse": true, // 使用阿里云返回集成响应是需要此字段为true
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "body": "..."
}
```

雪洛's avatar
雪洛 已提交
256 257
**headers内可以返回传统服务器的所有响应头,包括Set-Cookie、Content-Type等**

雪洛's avatar
雪洛 已提交
258
#### 使用集成响应返回HTML
Q
qiang 已提交
259 260 261

`content-type`设置为`text/html`,即可在`body`中返回 HTML,会被浏览器自动解析:

雪洛's avatar
雪洛 已提交
262
**阿里云默认域名无法返回html并在浏览器中展示,只可以触发下载(无法修改Content-Disposition)。绑定自定义域名无此限制**
Q
qiang 已提交
263 264

```js
雪洛's avatar
雪洛 已提交
265 266 267 268 269 270 271
{
    mpserverlessComposedResponse: true, // 使用阿里云返回集成响应是需要此字段为true
    statusCode: 200,
    headers: {
        'content-type': 'text/html'
    },
    body: '<h1>Hello</h1>'
Q
qiang 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284
}
```

最终 HTTP 响应为:
```shell
HTTP/1.1 200 OK
date: Mon, 16 Dec 2019 08:35:31 GMT
content-type: text/html; charset=utf-8
content-length: 14

<h1>Hello</h1>
```

雪洛's avatar
雪洛 已提交
285
#### 使用集成响应返回 JS 文件
Q
qiang 已提交
286 287 288 289

`content-type`设置为`application/javascript`,即可在`body`中返回 JavaScript 文件:

```js
雪洛's avatar
雪洛 已提交
290 291 292 293 294 295 296
{
    mpserverlessComposedResponse: true, // 使用阿里云返回集成响应是需要此字段为true
    statusCode: 200,
    headers: {
        'content-type': 'application/javascript'
    },
    body: 'console.log("Hello!")'
Q
qiang 已提交
297 298 299 300 301 302 303 304 305 306 307 308 309
}
```

最终 HTTP 响应为:
```shell
HTTP/1.1 200 OK
date: Mon, 16 Dec 2019 08:35:31 GMT
content-type: application/javascript; charset=utf-8
content-length: 21

console.log("Hello!")
```

雪洛's avatar
雪洛 已提交
310
#### 使用集成响应返回二进制文件
Q
qiang 已提交
311 312 313 314

如果返回体是诸如图片、音视频这样的二进制文件,那么可以将`isBase64Encoded`设置为`true`,并且将二进制文件内容转为 Base64 编码的字符串,例如:

```js
雪洛's avatar
雪洛 已提交
315 316 317 318 319 320 321 322
{
    mpserverlessComposedResponse: true, // 使用阿里云返回集成响应是需要此字段为true
    isBase64Encoded: true,
    statusCode: 200,
    headers: {
        'content-type': 'image/png'
    },
    body: 'iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAY...'
Q
qiang 已提交
323 324 325 326 327 328 329 330 331 332 333 334 335 336
}
```

最终 HTTP 响应为一张 PNG 图片:

```shell
HTTP/1.1 200 OK
date: Mon, 16 Dec 2019 08:35:31 GMT
content-type: image/png
content-length: 9897

<binary payload...>
```

雪洛's avatar
雪洛 已提交
337
#### 返回不同的状态码
Q
qiang 已提交
338 339 340

如需重定向或返回4xx,5xx等自定义状态码等,可以使用如下方式

雪洛's avatar
雪洛 已提交
341
**注意:阿里云默认域名不支持在返回的header里面使用location,绑定自定义域名能正常使用**
Q
qiang 已提交
342 343

```js
雪洛's avatar
雪洛 已提交
344 345 346 347 348 349
{
    mpserverlessComposedResponse: false, // 使用阿里云返回集成响应是需要此字段为true
    isBase64Encoded: false,
    statusCode: 301,
    headers: {
        'location': 'http://www.baidu.com'
Q
qiang 已提交
350 351 352
    }
}
```
雪洛's avatar
雪洛 已提交
353

雪洛's avatar
雪洛 已提交
354
## 处理cookie@cookie
雪洛's avatar
雪洛 已提交
355

雪洛's avatar
雪洛 已提交
356
在某些场景下,cookie依然占有重要地位,例如在云函数URL化的情况下,获取客户端的状态
雪洛's avatar
雪洛 已提交
357

雪洛's avatar
雪洛 已提交
358
在云函数中使用cookie需要依赖cookie库[npm页面地址](http://https://www.npmjs.com/package/cookie),可以通过`npm install cookie` 安装
雪洛's avatar
雪洛 已提交
359

雪洛's avatar
雪洛 已提交
360 361
**普通云函数示例**

雪洛's avatar
雪洛 已提交
362
```js
雪洛's avatar
雪洛 已提交
363 364 365 366 367 368 369 370 371 372
'use strict';
//引入cookie
const cookie = require('cookie')
exports.main = async (event, context) => {
	const cookieData = cookie.parse(event.headers.cookie || '')
	//设置cookie到客户端
	const cookieOptions = {
		//具体参数请查阅 https://www.npmjs.com/package/cookie
		maxAge: 60 * 60 * 24 * 7,//一周
		path:"/"
雪洛's avatar
雪洛 已提交
373
	}
雪洛's avatar
雪洛 已提交
374 375 376 377 378 379 380 381 382 383
	const setCookieData = cookie.serialize('app', 'appName', cookieOptions)
	return {
		statusCode: 200,
		headers: {
				'content-type': '返回数据类型',
				'set-cookie': setCookieData // 在headers内返回set-cookie用于设置客户端cookie
		},
		body: '返回数据'
	}
};
雪洛's avatar
雪洛 已提交
384
```
雪洛's avatar
雪洛 已提交
385

雪洛's avatar
雪洛 已提交
386 387 388
**云对象示例**

```js
雪洛's avatar
雪洛 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
'use strict';
//引入cookie
const cookie = require('cookie')
module.exports = {
  addTodo: function () {
    const httpInfo = this.getHttpInfo()
    const cookieData = cookie.parse(httpInfo.headers.cookie || '')
    //设置cookie到客户端
    const cookieOptions = {
    	//具体参数请查阅 https://www.npmjs.com/package/cookie
    	maxAge: 60 * 60 * 24 * 7,//一周
    	path:"/"
    }
    const setCookieData = cookie.serialize('app', 'appName', cookieOptions)
    return {
    	statusCode: 200,
    	headers: {
    			'content-type': '返回数据类型',
    			'set-cookie': setCookieData // 在headers内返回set-cookie用于设置客户端cookie
    	},
    	body: '返回数据'
    }
  }
};

雪洛's avatar
雪洛 已提交
414 415 416 417
```



雪洛's avatar
雪洛 已提交
418
## 注意事项@tips
雪洛's avatar
雪洛 已提交
419

雪洛's avatar
雪洛 已提交
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
- 阿里云目前请求与响应有如下限制
  + 请求Body大小限制,不能超过1MB。
  + 响应Body大小限制,不能超过1MB。
- 腾讯云目前请求与响应有如下限制
  + 请求Body大小限制,文本不能超过100KB,二进制不能超过20MB。
  + 响应Body大小限制,不能超过6MB。
- url化场景下,path(云函数event.path、云对象httpInfo.path)表示以配置的url化路径为根路径的访问路径。以配置`/test`为云函数url化路径,访问`/test/a/b/c`时path为`/a/b/c`
- 在URL化的场景无法获取客户端平台等信息,但是可以获取客户端IP、客户端userAgent
- 接收到的post请求的请求体可能是被转成base64的,如果是这样需要进行一次转化。
    以接收text/xml格式的post请求为例
    ```js
    // 云函数
    exports.main = function(event) {
        let body = event.body
        if(event.isBase64Encoded){
            body = Buffer.from(body, 'base64').toString('utf8') // 将base64格式的xml内容转为xml字符串
        }
    }

    // 云对象
    module.exports = {
        addTodo: function() {
            let httpInfo = this.getHttpInfo()
            let body = httpInfo.body
            if(httpInfo.isBase64Encoded){
                body = Buffer.from(body, 'base64').toString('utf8') // 将base64格式的xml内容转为xml字符串
            }
        }
    }
    ```