一、安装
Docker
$ docker pull prest/prest:latest
二、运行
Docker
$ docker run --rm -e PREST_HTTP_PORT=3000 \
-e PREST_PG_HOST=xxx.xxx.xxx.xxx\
-e PREST_PG_PORT=5432 \
-e PREST_PG_USER=postgres \
-e PREST_PG_PASS=mysecretpassword \
-e PREST_PG_DATABASE=postgres \
-e PREST_SSL_MODE=disable \
-p 3000:3000 prest/prest:latest
三、Query Statements
使用 curl
进行操作:
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items
增删改查
POST
$ curl -i -X POST http://127.0.0.1:3000/postgres/public/items -H "Content-Type: application/json" -d '{"number": "2", "name": "pencil", "price": "5"}'
-H
:header,接收方自动识别转为 json
-d
:data,post 需要有数据
DELETE
$ curl -i -X DELETE http://127.0.0.1:3000/postgres/public/items?name='notebook'
PATCH/PUT
$ curl -i -X PATCH http://127.0.0.1:3000/postgres/public/items?name='book' -H "Content-Type: application/json" -d '{"price": "30"}'
-d
:可以只写需要更新的数据对应的值。
?
:是定位符,如果没有,则全量更新,删除也是如此。
GET
filter参数
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items?name=$eq'book'
官方文档里写的是:GET /DATABASE/SCHEMA/TABLE?FIELD=$eq.VALUE
。实际上,.
需要删掉,否则获取不到数据。
问题
-
gt
:大于,但是等于也能获取到?(lt
也有一样的问题) -
ne
:不等于,但是等于也能获取到? -
in
:curl -i -X GET http://127.0.0.1:3000/postgres/public/items\?price\=$in\{'20.00','30.00'\}
-
nin
:查询出来的反而是in
的结果。 -
like
:查询出来的是全部。curl -i -X GET http://127.0.0.1:3000/postgres/public/items\?name\=$like'%book'
query string
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items\?_select={name}
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items\?_count={name}
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items\?_distinct\=true
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items\?_order={price} # 默认增序
解决方法
-G
表示 GET。
gt(gte、lt、lte同理)
$ curl -G -d 'price=$gt.15' http://127.0.0.1:3000/postgres/public/items
in、nin
$ curl -G -d 'price=$in.15,30' http://127.0.0.1:3000/postgres/public/items
具体的数组直接写在 $in.
后面,不需要写 []
、{}
。
like、ilike
$ curl -G -d 'name=$like.%25book' http://127.0.0.1:3000/postgres/public/items
如果使用 $like.%book
,则会查询全部,不能正确匹配。经过查阅资料,发现应该是没有转义 %
,因为 %
经过URL编码的结果是 %25
。如果改成 %25
则会成功查询出匹配 name
字段尾部是 book
的所有数据。
遗留问题
为什么 ?price=$gt30
写在链接后面,查询出来的还包括等于的,而把参数写在前面就可以正确查询?
四、报错整理
1. [error] dial tcp 127.0.0.1:5432: connect: connection refused
代码:
$ docker run -e PREST_HTTP_PORT=3000 \
-e PREST_PG_HOST=127.0.0.1 \
-e PREST_PG_USER=postgres \
-e PREST_PG_PASS=mysecretpassword \
-e PREST_PG_DATABASE=prest \
prest/prest:latest
原因:连接被拒绝一般是没有这个 IP 地址或者端口。查看 docker 容器:
$ docker container ls -a
结果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
958000ab2099 postgres:alpine "docker-entrypoint.s…" 6 days ago Up 2 minutes 5432/tcp some-postgres
3470bafff001 nginx:alpine "/docker-entrypoint.…" 6 days ago Exited (255) 6 hours ago 0.0.0.0:8080->80/tcp, :::8080->80/tcp vigorous_cerf
发现 postgres 这个容器没有做 IP 映射,因此 -e PREST_PG_HOST=127.0.0.1
找不到相应 IP 地址。
于是考虑做 IP 映射,使用 -p
在运行 postgres 容器时将端口映射到宿主机的指定端口:
$ docker run --name some-postgres --rm -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres:alpine
再使用 docker ps -a
查看 docker 容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44c4253e9fa2 postgres:alpine "docker-entrypoint.s…" 5 seconds ago Up 3 seconds 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp some-postgres
3470bafff001 nginx:alpine "/docker-entrypoint.…" 6 days ago Exited (255) 6 hours ago 0.0.0.0:8080->80/tcp, :::8080->80/tcp vigorous_cerf
发现这时已经有 iPhone 映射。解释一下这里的 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
分别是什么意思。
0.0.0.0:5432->5432/tcp
:0.0.0.0
代表本机所有 IPV4 地址,因此本机所有 IPV4 地址 + 端口 :5432
都可以指向 postgres。
:::5432->5432/tcp
:::
其实是 0:0:0:0:0:0:0:0
的缩写,代表本机所有 IPV6 地址。
127.0.0.1
:所有网络号为 127 的地址都被称之为回环地址。
再执行以下命令:
$ docker run --rm -e PREST_HTTP_PORT=3000 \
-e PREST_PG_HOST=127.0.0.1 \
-e PREST_PG_USER=postgres \
-e PREST_PG_PASS=mysecretpassword \
-e PREST_PG_DATABASE=prest \
prest/prest:latest
发现还是报错:[error] dial tcp 127.0.0.1:5432: connect: connection refused
。
原因:可以把这个 -e PREST_PG_HOST=127.0.0.1
理解成配置文件,所以肯定是从 prest 这个 docker 里进行寻找 postgres 进行连接,因此找不到。而运行的 postgres 容器则是跑在另一个 docker 里的,两者没有连接桥梁,所以根本跑不通。连接方式有两种,一种是将 postgres 映射到本机上,这样就相当于 postgres 在本机上操作写操作,然后 prest 通过这个端口操作读操作,就可以连接上 postgres 容器了。另一种则是使用两个 docker 容器直连,通过 network
配置 DNS,这样 host 只需要写成需要连接的 docker 容器起的名字就行,可以自动识别端口,如果使用 docker compose,可以直接 host 写成需要连接的 docker 容器起的名字,不需要单独设置 DNS。
参考:docker容器的网络配置,允许docker可以被宿主机以外的其它主机访问以及局域网内可以直接访问docker容器ip
解决方法:
- 使用
--network host
使得 prest 容器可以操作本机(不推荐)。 - 使用 WiFi 网络作为 HOST 地址。此方法有一个缺点,会走一遍路由器,没有方法一快。
执行以下命令查看 WiFi 地址:
$ ifconfig
找到这个:
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=400<CHANNEL_IO>
ether 88:66:5a:3b:56:2a
inet6 fe80::10d9:f421:90f7:60b8%en0 prefixlen 64 secured scopeid 0x6
inet xxx.xxx.xxx.xxx netmask 0xfffffc00 broadcast 10.8.203.255
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: active
xxx.xxx.xxx.xxx
就是 WiFi 的 IP 地址。
然后执行:
$ docker run --rm -e PREST_HTTP_PORT=3000 \
-e PREST_PG_HOST=xxx.xxx.xxx.xxx \
-e PREST_PG_PORT=5432 \
-e PREST_PG_USER=postgres \
-e PREST_PG_PASS=mysecretpassword \
-e PREST_PG_DATABASE=prest \
prest/prest:latest
发现报错:
[error] pq: SSL is not enabled on the server
此时,只需要加一行 -e PREST_SSL_MODE=disable
关闭 SSL 就可以了。
$ docker run --rm -e PREST_HTTP_PORT=3000 \
-e PREST_PG_HOST=xxx.xxx.xxx.xxx \
-e PREST_PG_PORT=5432 \
-e PREST_PG_USER=postgres \
-e PREST_PG_PASS=mysecretpassword \
-e PREST_PG_DATABASE=prest \
-e PREST_SSL_MODE=disable \
prest/prest:latest
发现又报错:
[error] pq: database "prest" does not exist
发现是自己写错了数据库名字,连接进入 postgres 里使用 \l
命令查看数据库名字:
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
然后 exit
退出 postgres 数据库,再执行:
$ docker run --rm -e PREST_HTTP_PORT=3000 \
-e PREST_PG_HOST=xxx.xxx.xxx.xxx \
-e PREST_PG_PORT=5432 \
-e PREST_PG_USER=postgres \
-e PREST_PG_PASS=mysecretpassword \
-e PREST_PG_DATABASE=postgres \
-e PREST_SSL_MODE=disable \
prest/prest:latest
就可以成功运行 prest 连接 postgres 了:
[prestd] Waiting for port xxx.xxx.xxx.xxx:5432 to become available...
[prestd] Ready hosting xxx.xxx.xxx.xxx to port 5432 !
2021/07/20 08:39:38 [warning] adapter is not set. Using the default (postgres)
2021/07/20 08:39:38 [warning] You are running pREST in public mode.
[prest] listening on 0.0.0.0:3000 and serving on /
2. HTTP/1.1 404 Not Found
执行命令:
$ curl -i -X GET http://127.0.0.1:3000/auth --user "username:password"
报错:
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Content-Type-Options: nosniff
Date: Thu, 22 Jul 2021 02:51:30 GMT
Content-Length: 34
{
"error": "404 page not found"
}%
原因:没有 auth
这个路径,端口后面跟着的应该是 /DATABASE/SCHEMA/TABLE
。
解决方法:
$ curl -i -X GET http://127.0.0.1:3000/postgres/public/items