Foxx微服务 #
一、Foxx概述 #
Foxx是ArangoDB内置的微服务框架,允许在数据库内部运行JavaScript应用。
1.1 Foxx优势 #
| 优势 | 说明 |
|---|---|
| 高性能 | 直接访问数据库,无网络开销 |
| 安全 | 数据不离开数据库 |
| 简单 | 使用JavaScript开发 |
| 集成 | 与AQL无缝集成 |
1.2 Foxx服务结构 #
text
my-service/
├── manifest.json # 服务配置
├── index.js # 主入口文件
├── routes/ # 路由文件
│ └── api.js
├── lib/ # 库文件
│ └── utils.js
└── tests/ # 测试文件
└── test.js
二、服务配置 #
2.1 manifest.json #
json
{
"name": "my-service",
"version": "1.0.0",
"description": "我的Foxx服务",
"author": "Your Name",
"license": "MIT",
"main": "index.js",
"configuration": {
"jwtSecret": {
"description": "JWT密钥",
"type": "string",
"default": "secret"
}
},
"dependencies": {},
"provides": {},
"tests": ["tests/*.js"]
}
2.2 配置选项 #
| 字段 | 说明 |
|---|---|
| name | 服务名称 |
| version | 版本号 |
| main | 入口文件 |
| configuration | 配置参数 |
| dependencies | 依赖服务 |
三、路由定义 #
3.1 基本路由 #
javascript
'use strict';
const createRouter = require('@arangodb/foxx/router');
const router = createRouter();
module.context.use(router);
router.get('/hello', function (req, res) {
res.send('Hello, World!');
});
3.2 带参数的路由 #
javascript
router.get('/users/:id', function (req, res) {
const db = require('@arangodb').db;
const user = db.users.document(req.pathParams.id);
res.send(user);
});
3.3 POST请求 #
javascript
router.post('/users', function (req, res) {
const db = require('@arangodb').db;
const user = db.users.insert(req.body);
res.send(user);
});
3.4 多种HTTP方法 #
javascript
router.get('/users', listUsers)
.post('/users', createUser);
router.get('/users/:id', getUser)
.put('/users/:id', updateUser)
.delete('/users/:id', deleteUser);
四、请求处理 #
4.1 请求参数 #
javascript
router.get('/search', function (req, res) {
const keyword = req.queryParams.keyword;
const page = req.queryParams.page || 1;
const size = req.queryParams.size || 10;
res.send({
keyword: keyword,
page: page,
size: size
});
});
4.2 请求体 #
javascript
router.post('/users', function (req, res) {
const body = req.body;
res.send(body);
});
4.3 路径参数 #
javascript
router.get('/users/:userId/posts/:postId', function (req, res) {
const userId = req.pathParams.userId;
const postId = req.pathParams.postId;
res.send({
userId: userId,
postId: postId
});
});
4.4 请求头 #
javascript
router.get('/info', function (req, res) {
const auth = req.headers['authorization'];
const contentType = req.headers['content-type'];
res.send({
authorization: auth,
contentType: contentType
});
});
五、响应处理 #
5.1 发送JSON #
javascript
router.get('/user', function (req, res) {
res.send({
name: '张三',
email: 'zhangsan@example.com'
});
});
5.2 设置状态码 #
javascript
router.post('/users', function (req, res) {
res.status(201);
res.send({
message: '用户创建成功'
});
});
5.3 错误响应 #
javascript
router.get('/users/:id', function (req, res) {
const db = require('@arangodb').db;
try {
const user = db.users.document(req.pathParams.id);
res.send(user);
} catch (e) {
res.status(404);
res.send({
error: '用户不存在'
});
}
});
5.4 设置响应头 #
javascript
router.get('/download', function (req, res) {
res.set('Content-Type', 'application/octet-stream');
res.set('Content-Disposition', 'attachment; filename="data.json"');
res.send({ data: 'file content' });
});
六、数据库操作 #
6.1 查询数据 #
javascript
router.get('/users', function (req, res) {
const db = require('@arangodb').db;
const users = db._query(`
FOR user IN users
RETURN user
`).toArray();
res.send(users);
});
6.2 带参数查询 #
javascript
router.get('/users/search', function (req, res) {
const db = require('@arangodb').db;
const keyword = req.queryParams.keyword;
const users = db._query(`
FOR user IN users
FILTER CONTAINS(LOWER(user.name), LOWER(@keyword))
RETURN user
`, { keyword: keyword }).toArray();
res.send(users);
});
6.3 插入数据 #
javascript
router.post('/users', function (req, res) {
const db = require('@arangodb').db;
const user = db.users.insert({
name: req.body.name,
email: req.body.email,
createdAt: new Date().toISOString()
});
res.status(201);
res.send(user);
});
6.4 更新数据 #
javascript
router.put('/users/:id', function (req, res) {
const db = require('@arangodb').db;
const user = db.users.update(req.pathParams.id, req.body);
res.send(user);
});
6.5 删除数据 #
javascript
router.delete('/users/:id', function (req, res) {
const db = require('@arangodb').db;
db.users.remove(req.pathParams.id);
res.status(204);
res.send();
});
七、认证授权 #
7.1 JWT认证 #
javascript
const jwt = require('@arangodb/foxx/jwt');
const createRouter = require('@arangodb/foxx/router');
const router = createRouter();
router.post('/login', function (req, res) {
const db = require('@arangodb').db;
const { username, password } = req.body;
const user = db._query(`
FOR user IN users
FILTER user.username == @username
AND user.password == @password
RETURN user
`, { username, password }).toArray()[0];
if (!user) {
res.status(401);
res.send({ error: '用户名或密码错误' });
return;
}
const token = jwt.sign(
{ userId: user._key },
module.context.configuration.jwtSecret,
{ expiresIn: '24h' }
);
res.send({ token: token });
});
module.context.use(router);
7.2 认证中间件 #
javascript
function authMiddleware(req, res, next) {
const authHeader = req.headers['authorization'];
if (!authHeader) {
res.status(401);
res.send({ error: '未提供认证信息' });
return;
}
const token = authHeader.replace('Bearer ', '');
try {
const decoded = jwt.verify(
token,
module.context.configuration.jwtSecret
);
req.user = decoded;
next();
} catch (e) {
res.status(401);
res.send({ error: '无效的令牌' });
}
}
router.get('/profile', authMiddleware, function (req, res) {
const db = require('@arangodb').db;
const user = db.users.document(req.user.userId);
res.send(user);
});
八、服务部署 #
8.1 安装服务 #
Web界面安装:
- 打开ArangoDB Web UI
- 进入 “Services” 页面
- 点击 “Add Service”
- 上传服务包或输入Git URL
命令行安装:
bash
foxx install /my-service /path/to/service
8.2 更新服务 #
bash
foxx upgrade /my-service /path/to/service
8.3 卸载服务 #
bash
foxx uninstall /my-service
8.4 查看服务 #
bash
foxx list
九、完整示例 #
9.1 用户API服务 #
manifest.json:
json
{
"name": "user-api",
"version": "1.0.0",
"main": "index.js",
"configuration": {
"jwtSecret": {
"type": "string",
"default": "my-secret-key"
}
}
}
index.js:
javascript
'use strict';
const createRouter = require('@arangodb/foxx/router');
const router = createRouter();
const db = require('@arangodb').db;
const joi = require('joi');
module.context.use(router);
router.get('/users', function (req, res) {
const page = parseInt(req.queryParams.page) || 1;
const size = parseInt(req.queryParams.size) || 10;
const users = db._query(`
FOR user IN users
SORT user.createdAt DESC
LIMIT @offset, @limit
RETURN {
id: user._key,
name: user.name,
email: user.email,
createdAt: user.createdAt
}
`, {
offset: (page - 1) * size,
limit: size
}).toArray();
const total = db._query(`
FOR user IN users
COLLECT WITH COUNT INTO count
RETURN count
`).toArray()[0];
res.send({
data: users,
pagination: {
page: page,
size: size,
total: total
}
});
})
.queryParam('page', joi.number().optional())
.queryParam('size', joi.number().optional());
router.post('/users', function (req, res) {
const user = db.users.insert({
name: req.body.name,
email: req.body.email,
createdAt: new Date().toISOString()
});
res.status(201);
res.send({
id: user._key,
name: req.body.name,
email: req.body.email
});
})
.body(joi.object({
name: joi.string().required(),
email: joi.string().email().required()
}).required());
router.get('/users/:id', function (req, res) {
try {
const user = db.users.document(req.pathParams.id);
res.send({
id: user._key,
name: user.name,
email: user.email
});
} catch (e) {
res.status(404);
res.send({ error: '用户不存在' });
}
});
router.put('/users/:id', function (req, res) {
try {
db.users.update(req.pathParams.id, req.body);
const user = db.users.document(req.pathParams.id);
res.send({
id: user._key,
name: user.name,
email: user.email
});
} catch (e) {
res.status(404);
res.send({ error: '用户不存在' });
}
});
router.delete('/users/:id', function (req, res) {
try {
db.users.remove(req.pathParams.id);
res.status(204);
res.send();
} catch (e) {
res.status(404);
res.send({ error: '用户不存在' });
}
});
十、总结 #
Foxx微服务要点:
- 服务结构:manifest.json + index.js
- 路由定义:router.get/post/put/delete
- 请求处理:req.queryParams、req.body、req.pathParams
- 响应处理:res.send()、res.status()
- 数据库操作:db._query()、db.collection.method()
下一步,让我们学习集群架构!
最后更新:2026-03-27