yaws调用httpc:request请求Docker容器服务时崩溃如何解决
报错原因解释
你遇到的yaws code at appmod:0 crashed or ret bad val:60报错完全是返回值格式不符合yaws规则导致的,和Docker无关,也不是yaws的bug:
- yaws的appmod回调函数不允许直接返回原始HTML字符串,必须返回约定格式的响应结构
- 报错里的
60就是你返回的HTML内容首字符<的ASCII码,yaws无法识别该值作为合法返回值,因此抛出错误
修复方案
1. 调整返回值结构
你需要把上游请求拿到的结果封装为yaws可识别的结构,修改后的代码示例如下:
out_adm(Url, A) -> % 建议将inets:start()移到服务初始化逻辑中,无需每次请求都调用 inets:start(), Http_result = httpc:request(Url), case Http_result of {ok, {{_Version, 200, _ReasonPhrase}, Headers, Html}} -> ?trace('out_check_adm(A)======PASS_THROUGH HTML====> Url', [Url]), % 过滤掉端到端不允许转发的响应头,避免冲突 FilteredHeaders = lists:filter(fun({K, _}) -> LowerK = string:lowercase(K), not lists:member(LowerK, ["connection", "transfer-encoding", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailer", "upgrade"]) end, Headers), % 构造合法的yaws返回结构 ContentType = proplists:get_value("content-type", FilteredHeaders, "text/html"), [ {status, 200}, {header, {"Content-Type", ContentType}} | lists:map(fun({K, V}) -> {header, {K, V}} end, FilteredHeaders) ] ++ [{html, Html}]; {ok, {{_Version, StatusCode, _ReasonPhrase}, Headers, Content}} -> % 非200响应也按规范返回 [ {status, StatusCode} | lists:map(fun({K, V}) -> {header, {K, V}} end, Headers) ] ++ [{html, Content}]; _ -> {status, 500, "Internal Server Error"} end.
2. 路径映射校准
你之前Nginx的配置是匹配/adm/前缀,/adm/xxx?foo=bar会被转发到http://adm:8080/xxx?foo=bar,你自己做路径转换时要注意不要丢弃/adm/之后的子路径和参数,避免上游服务404。
3. 功能补全(可选)
当前实现仅支持GET请求,如果你需要转发POST/DELETE等其他请求,还需要从yaws传入的A(也就是ARG结构)中提取请求方法、请求头、请求体,一并转发给上游adm服务。
调试方法
如果后续还有返回值相关问题,可以在函数返回前打印完整的返回值,确认格式是否符合要求:
Return = [{status,200}, {html, "<h1>test</h1>"}], io:format("Yaws return value: ~p~n", [Return]), Return.
合法的yaws appmod返回值只能是以下两种形式:
- 单个响应元组,比如
{status, 404}、{html, "<p>test</p>"} - 由多个响应元组组成的列表,比如
[{status,200}, {header, {"Content-Type", "text/plain"}}, {html, "ok"}]
内容的提问来源于stack exchange,提问作者kklepper
相关产品推荐
相关产品推荐

