普通页面支持 API 的方式对接外部接口,实现灵活扩展,API 详情请参考 amis 文档

在爱速搭中有两个特殊功能:

API 代理

普通页面中的 api 在最终渲染时会进行 url 替换,比如在页面设计中的配置中可能这样写的:

  1. {
  2. "api": "https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/sample"
  3. }

在实际运行中,爱速搭会将这个地址进行转换,实际在页面中会是类似下面的地址

  1. {
  2. "api": "/api/proxy/34fbe7"
  3. }

这样做有以下几个好处:

  1. 解决前端跨域问题,因为第三方 api 肯定不在爱速搭域名下
  2. 避免接口地址暴露
  3. 传递一些爱速搭特有的信息,比如当前用户名、环境、应用 key 等

前面说到的特有信息可以通过下面这些 header 获取:

  • x-isuda-token,在「应用设置」中的 token
  • x-isuda-appkey,应用短路径
  • x-isuda-env,应用环境,开发环境是 dev,也可能是 qasandbox或者latest
  • x-isuda-userid,用户在爱速搭中的 id
  • x-isuda-username,用户名
  • x-isuda-oauth-id,oauth id,如果启用了 oauth 登录的话
  • x-isuda-oauth-access-token,oauth 的 access token 如果启用了 oauth 登录的话
  • x-isuda-roles,用户所属的角色名列表
  • x-isuda-profile-access-token 获取用户信息的 access token,具体请看下方说明

如果不放心直接根据 header 下发的 x-isuda-username 完成用户认证,还可以通过环境变量关掉这个功能

  1. ISUDA_DISABLE_PROXY_USER_ID: true

这样就只会下发以下 header 了。

  • x-isuda-token
  • x-isuda-appkey
  • x-isuda-env
  • x-isuda-profile-access-token
  • x-isuda-oauth-id,oauth id,如果开启了 oauth 登录认证的话
  • x-isuda-oauth-access-token,oauth 的 access token,如果开启了 oauth 登录认证的话

然后通过请求 /openapi/profile?token={{这里用 x-isuda-profile-access-token 返回的 token 值}} 就会获取以下信息。

  1. {
  2. "username": "xxxx",
  3. "roles": ["xxxx", "xxx"],
  4. "userid": "xxxx",
  5. "email": "xxx@xx.com"
  6. }

如果不想经过内置代理

可以在 url 前加上 raw:,就不会走代理。

需要解决跨域问题,比如返回跨域 header:示例如下

  • Access-Control-Allow-Origin: https://suda.bce.baidu.com,或者爱速搭部署的域名
  • Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
  • Access-Control-Allow-Methods: POST, GET, OPTIONS

示例代码(express):

  1. // 放在所有路由前面
  2. app.use(function (req, res, next) {
  3. res.header('Access-Control-Allow-Origin', 'https://suda.bce.baidu.com');
  4. res.header('Access-Control-Allow-Credentials', 'true');
  5. res.header(
  6. 'Access-Control-Allow-Headers',
  7. 'Origin, X-Requested-With, Content-Type, Accept'
  8. );
  9. res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
  10. next();
  11. });

如果接口需要登录,可以在未登录的时候返回 401,内容是:

  1. {
  2. "location": "http://跳转登录的页面地址"
  3. }

需要注意在新浏览器下默认会限制 cookie 跨域,所以登录后保存状态的 cookie 必须加上 SameSite=None; Secure,类似如下

  1. Set-Cookie: session=123; SameSite=None; Secure

如果想本地开发接口请查看这里

在各种语言下获取参数的方法

Node

以 Express 为例

  1. const express = require('express');
  2. const app = express();
  3. const bodyParser = require('body-parser');
  4. app.use(bodyParser.json());
  5. app.post('/api', function(req, res) {
  6. console.log(req.body); // 参数 json
  7. res.json(...);
  8. })
  9. app.listen(3000)

Java

以 Spring 为例

  1. @RequestMapping(value = "/api", method = POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  2. @ResponseBody
  3. public String api(@RequestBody String body) {
  4. // body 就是字符串形式的 json,需要使用 Jackson 等库解析为对象来使用
  5. }

PHP

  1. <?PHP
  2. $json = file_get_contents('php://input');
  3. $data = json_decode($json);

.NET

  1. using Microsoft.AspNetCore.Mvc;
  2. using System.IO;
  3. using Newtonsoft.Json;
  4. namespace MvcMovie.Controllers
  5. {
  6. public class HelloWorldController : Controller
  7. {
  8. [HttpPost]
  9. public JsonResult Index()
  10. {
  11. using (var reader = new StreamReader(HttpContext.Request.Body))
  12. {
  13. dynamic json = JsonConvert.DeserializeObject(reader.ReadToEnd());
  14. var conditions = json.conditions;
  15. var data = new { status = 0, msg = "" };
  16. return Json(data);
  17. }
  18. }
  19. }
  20. }

go

  1. func api(w http.ResponseWriter, r *http.Request) {
  2. body, _ := ioutil.ReadAll(r.Body)
  3. var result map[string]interface{} // 这里简化了,最好参考对应的参数说明文档创建 struct
  4. json.Unmarshal(body, &result)
  5. }

Python

  1. import json
  2. # falcon 框架
  3. class SugarAPI(object):
  4. def on_post(self, req, resp):
  5. data = json.load(req.bounded_stream)
  6. # flask 框架
  7. from flask import request
  8. @app.route('/api', methods=['POST'])
  9. def sugar_api():
  10. data = json.loads(request.data)

Ruby

  1. require 'sinatra'
  2. require 'json'
  3. post '/api/' do
  4. request.body.rewind
  5. request_payload = JSON.parse request.body.read
  6. end