Haskell 如何在仆人身上接收职务

Haskell 如何在仆人身上接收职务,haskell,servant,Haskell,Servant,下面的代码应该能够发送json正文。 但我总是在以下请求中出错: curl -X POST -i http://localhost:8080/comtrade --data 'name=nut&age=12' 错误消息是: 数据用户=用户{ 年龄:Int, 名称::字符串 }派生泛型 实例FromJSON用户,其中 parseJSON=withObject“User”parseUser 解析器用户::对象->解析器用户 parseUser o=do n获取'[JSON]用户 :生的 m

下面的代码应该能够发送json正文。 但我总是在以下请求中出错:

curl -X POST -i http://localhost:8080/comtrade --data 'name=nut&age=12'
错误消息是:

数据用户=用户{
年龄:Int,
名称::字符串
}派生泛型
实例FromJSON用户,其中
parseJSON=withObject“User”parseUser
解析器用户::对象->解析器用户
parseUser o=do
n获取'[JSON]用户
:生的
myServer::服务器ComTradeAPI
myServer=getUser
:测试
:serveDirectoryWebApp“站点”
哪里
测试::处理程序用户
测试=返回(用户12“螺母”)
getUser::User->Handler Int
getUser usr=return 12
main::IO()
main=openBrowser“http://localhost:8080/index.html"
>>运行8080(serve(代理::Proxy ComTradeAPI)myServer)

有谁能告诉我如何让服务服务器接收POST消息吗?

正如Fyodor Soikin在评论中指出的,OP中的cURL示例不发布JSON,而是发布URL编码的数据。如果使用cURL的
-v
(verbose)选项而不是
-i
,则可以看到这一点:

$ curl -v http://localhost:8080/comtrade -d "{ \"name\": \"nut\", \"age\": 12 }"
*   Trying ::1:8080...
* TCP_NODELAY set
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /comtrade HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.67.0
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 28 out of 28 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 405 Method Not Allowed
< Transfer-Encoding: chunked
< Date: Sat, 13 Mar 2021 12:52:59 GMT
< Server: Warp/3.2.28
< Content-Type: text/plain
<
Only GET or HEAD is supported
请注意,cURL仍然将
内容类型默认为
application/x-www-form-urlencoded
。由于API声明为接收JSON,因此必须明确告诉它JSON来了:

$ curl -i http://localhost:8080/comtrade -H "Content-Type: application/json" -d "{ \"name\": \"nut\", \"age\": 12 }"
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Sat, 13 Mar 2021 12:58:09 GMT
Server: Warp/3.2.28
Content-Type: application/json;charset=utf-8

12

据我所知,Haskell代码没有任何问题。这是一个正确使用HTTP协议的问题。

您的服务API将请求内容类型指定为
'[JSON]
,但您的
curl
命令将其指定为URL编码。
$ curl -v http://localhost:8080/comtrade -d "{ \"name\": \"nut\", \"age\": 12 }"
*   Trying ::1:8080...
* TCP_NODELAY set
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /comtrade HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.67.0
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 28 out of 28 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 405 Method Not Allowed
< Transfer-Encoding: chunked
< Date: Sat, 13 Mar 2021 12:52:59 GMT
< Server: Warp/3.2.28
< Content-Type: text/plain
<
Only GET or HEAD is supported
$ curl -v http://localhost:8080/comtrade -d "{ \"name\": \"nut\", \"age\": 12 }"
*   Trying ::1:8080...
* TCP_NODELAY set
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /comtrade HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.67.0
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 28 out of 28 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 405 Method Not Allowed
< Transfer-Encoding: chunked
< Date: Sat, 13 Mar 2021 12:56:42 GMT
< Server: Warp/3.2.28
< Content-Type: text/plain
<
Only GET or HEAD is supported
$ curl -i http://localhost:8080/comtrade -H "Content-Type: application/json" -d "{ \"name\": \"nut\", \"age\": 12 }"
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Sat, 13 Mar 2021 12:58:09 GMT
Server: Warp/3.2.28
Content-Type: application/json;charset=utf-8

12