YAWS,CORS:如何定义OPTIONS应返回的内容?

时间:2015-02-02 17:20:38

标签: ajax erlang yaws

我需要让CORS工作。似乎jquery $ ajax进行OPTIONS调用,并且应该返回必要的CORS头。我所有的GET和POST都已经这样做了,但它似乎还不够。在NGINX中,您可以这样做:

location / {
    if ($request_method = OPTIONS ) {
        add_header Access-Control-Allow-Origin "http://example.com";
        add_header Access-Control-Allow-Methods "GET, OPTIONS";
        add_header Access-Control-Allow-Headers "Authorization";
        add_header Access-Control-Allow-Credentials "true";
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }
}

我如何在YAWS中做同样的事情?

1 个答案:

答案 0 :(得分:1)

处理OPTIONS请求的一种方法是使用 Yaws dispatchmod ,类似于Yaws appmod,但Yaws在执行任何其他请求处理之前调用它。以下是基于您问题中信息的示例调度模块:

-module(options_dispatcher).
-export([dispatch/1]).

-include_lib("yaws_api.hrl").

dispatch(Arg) ->
    Req = yaws_api:arg_req(Arg),
    case yaws_api:http_request_method(Req) of
        'OPTIONS' ->
            Vsn = yaws_api:http_request_version(Req),
            Resp = #http_response{
                      version=Vsn,
                      status=200,
                      phrase=yaws_api:code_to_phrase(200)},
            HdrVals = [{"Access-Control-Allow-Origin", "http://example.com"},
                       {"Access-Control-Allow-Methods", "GET, OPTIONS"},
                       {"Access-Control-Allow-Headers", "Authorization"},
                       {"Access-Control-Allow-Credentials", "true"},
                       {"Content-Length", "0"},
                       {"Content-Type", "text/plain"}],
            Headers = lists:foldl(fun({H,V}, Hdrs) ->
                                          yaws_api:set_header(Hdrs, H, V)
                                  end, #headers{}, HdrVals),
            HdrStrings = yaws_api:reformat_header(Headers),
            Reply = [yaws_api:reformat_response(Resp), "\r\n",
                     string:join(HdrStrings, "\r\n"), "\r\n\r\n"],
            Sock = yaws_api:arg_clisock(Arg),
            case yaws_api:get_sslsocket(Sock) of
                {ok, SslSock} ->
                    ssl:send(SslSock, Reply);
                undefined ->
                    gen_tcp:send(Sock, Reply)
            end,
            done;
        _ ->
            continue
    end.

此代码接收Yaws #arg{}记录,与appmod相同,除非通知dispatchmod必须导出dispatch/1函数,而appmod必须导出out/1函数。从那里它检索请求信息并检查HTTP请求方法。如果是OPTIONS,则代码会创建响应记录并设置响应标头,将其格式化为字符串,然后创建Replyiolist,其中包含HTTP响应状态行,格式化的HTTP响应头,以及"\r\n\r\n",用于标记HTTP响应的结束。然后,它根据收到请求的套接字类型使用ssl:send/2gen_tcp:send/2来直接发送回复。最后它返回done告诉雅司那里没有更多的工作要做。对于除OPTIONS以外的任何HTTP方法,代码返回continue以告知Yaws执行其正常分派。

要部署调度程序,请编译代码并将生成的梁文件放在Yaws加载路径中。然后修改Yaws配置的服务器部分以包含设置:

dispatchmod = options_dispatcher

这告诉Yaws服务器有一个dispatchmod,应该作为该服务器的请求调度流的一部分进行调用。然后启动/重启Yaws或使用

yaws --hup --id ID

告诉正在运行的Yaws实例重新加载其配置。