From 5e76fd508af2799fbefe062fd8bb106ae316cf5d Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Mon, 21 Mar 2011 15:17:07 +0200 Subject: Add opaque/ewgi,ewgi2 --- lib/dialyzer/test/opaque_SUITE_data/results/ewgi | 4 + .../test/opaque_SUITE_data/src/ewgi/ewgi.hrl | 240 ++++++++++++++++++++ .../test/opaque_SUITE_data/src/ewgi/ewgi_api.erl | 65 ++++++ .../opaque_SUITE_data/src/ewgi/ewgi_testapp.erl | 46 ++++ .../test/opaque_SUITE_data/src/ewgi2/ewgi.hrl | 241 +++++++++++++++++++++ .../test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl | 65 ++++++ .../opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl | 46 ++++ 7 files changed, 707 insertions(+) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/results/ewgi create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl (limited to 'lib') diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/ewgi b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi new file mode 100644 index 0000000000..3c8cfb59f8 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi @@ -0,0 +1,4 @@ + +ewgi_api.erl:55: The call gb_trees:to_list({non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument +ewgi_testapp.erl:35: The call ewgi_testapp:htmlise_data("request_data",{non_neg_integer(),'nil' | {_,_,_,_}}) will never return since it differs in the 2nd argument from the success typing arguments: ([95 | 97 | 100 | 101 | 104 | 112 | 113 | 114 | 115 | 116 | 117,...],[{_,_}]) +ewgi_testapp.erl:43: The call gb_trees:to_list(T::{non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl new file mode 100644 index 0000000000..0b98f550f1 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl @@ -0,0 +1,240 @@ +-ifndef(_EWGI_HRL). +-define(_EWGI_HRL, 1). + +% ``The contents of this file are subject to the Mozilla Public License +% Version 1.1 (the "License"); you may not use this file except in +% compliance with the License. You may obtain a copy of the License at +% http://www.mozilla.org/MPL/ +% +% Software distributed under the License is distributed on an "AS IS" +% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +% License for the specific language governing rights and limitations +% under the License. +% +% The Original Code is the EWGI reference implementation. +% +% The Initial Developer of the Original Code is S.G. Consulting +% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C) +% 2007 S.G. Consulting srl. All Rights Reserved. +% +% Contributor(s): Filippo Pacini +% Hunter Morris + +-define(DEFAULT_CHUNKSIZE, 4096). + +-type ewgi_propval() :: atom() | integer() | string() | binary(). +-type ewgi_prop() :: {ewgi_propval(), ewgi_propval()}. +-type ewgi_proplist() :: [ewgi_prop()]. + +%% @type bag() = gb_tree() +-ifdef(HAS_GB_TREE_SPEC). +-type bag() :: gb_tree(). +-else. +-type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}. +-endif. + +%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change: +%%%-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | ewgi_ri_callback()). +%% @type ewgi_ri_callback() = function() +-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | function()) | iolist(). + +%% @type ewgi_read_input() = function() +-type ewgi_read_input() :: fun((ewgi_ri_callback(), integer()) -> ewgi_ri_callback()). + +%% @type ewgi_write_error() = function() +-type ewgi_write_error() :: fun((any()) -> 'ok'). + +%% @type ewgi_version() = {integer(), integer()} +-type ewgi_version() :: {integer(), integer()}. + +%% @type ewgi_spec() = {'ewgi_spec', function(), function(), string(), +%% ewgi_version(), bag()} + +-type ewgi_spec() :: {'ewgi_spec', ewgi_read_input(), + ewgi_write_error(), string(), ewgi_version(), + bag()}. + +-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec') + and (size(R) =:= 6))). +-define(GET_EWGI_READ_INPUT(R), element(2, R)). +-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)). +-define(GET_EWGI_WRITE_ERROR(R), element(3, R)). +-define(SET_EWGI_WRITE_ERROR(A, R), setelement(3, R, A)). +-define(GET_EWGI_URL_SCHEME(R), element(4, R)). +-define(SET_EWGI_URL_SCHEME(A, R), setelement(4, R, A)). +-define(GET_EWGI_VERSION(R), element(5, R)). +-define(SET_EWGI_VERSION(A, R), setelement(5, R, A)). +-define(GET_EWGI_DATA(R), element(6, R)). +-define(SET_EWGI_DATA(A, R), setelement(6, R, A)). + +%% @type ewgi_header_val() = string() | 'undefined' +-type ewgi_header_val() :: string() | 'undefined'. + +%% @type ewgi_header_key() = string() +-type ewgi_header_key() :: string(). + +%% @type ewgi_http_headers() = {'ewgi_http_headers', +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% bag()} + +-type ewgi_http_headers() :: {'ewgi_http_headers', ewgi_header_val(), + ewgi_header_val(), ewgi_header_val(), + ewgi_header_val(), ewgi_header_val(), + ewgi_header_val(), bag()}. + +-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers') + and (size(R) =:= 8))). +-define(GET_HTTP_ACCEPT(R), element(2, R)). +-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)). +-define(GET_HTTP_COOKIE(R), element(3, R)). +-define(SET_HTTP_COOKIE(A, R), setelement(3, R, A)). +-define(GET_HTTP_HOST(R), element(4, R)). +-define(SET_HTTP_HOST(A, R), setelement(4, R, A)). +-define(GET_HTTP_IF_MODIFIED_SINCE(R), element(5, R)). +-define(SET_HTTP_IF_MODIFIED_SINCE(A, R), setelement(5, R, A)). +-define(GET_HTTP_USER_AGENT(R), element(6, R)). +-define(SET_HTTP_USER_AGENT(A, R), setelement(6, R, A)). +-define(GET_HTTP_X_HTTP_METHOD_OVERRIDE(R), element(7, R)). +-define(SET_HTTP_X_HTTP_METHOD_OVERRIDE(A, R), setelement(7, R, A)). +-define(GET_HTTP_OTHER(R), element(8, R)). +-define(SET_HTTP_OTHER(A, R), setelement(8, R, A)). + +%% @type ewgi_request_method() = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | +%% 'DELETE' | 'TRACE' | 'CONNECT' | string() +-type ewgi_request_method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | + 'DELETE' | 'TRACE' | 'CONNECT' | string(). + +%% @type ewgi_val() = string() | 'undefined' +-type ewgi_val() :: string() | 'undefined'. + +%% @type ewgi_request() :: {'ewgi_request', ewgi_val(), integer(), ewgi_val(), +%% ewgi_spec(), ewgi_val(), ewgi_http_headers(), +%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(), +%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(), +%% ewgi_request_method(), ewgi_val(), ewgi_val(), +%% ewgi_val(), ewgi_val(), ewgi_val()} + +-type ewgi_request() :: {'ewgi_request', ewgi_val(), + non_neg_integer(), ewgi_val(), ewgi_spec(), + ewgi_val(), ewgi_http_headers(), ewgi_val(), + ewgi_val(), ewgi_val(), ewgi_val(), + ewgi_val(), ewgi_val(), ewgi_val(), + ewgi_val(), ewgi_request_method(), + ewgi_val(), ewgi_val(), ewgi_val(), + ewgi_val(), ewgi_val()}. + +-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request') + and (size(R) =:= 21))). +-define(GET_AUTH_TYPE(R), element(2, R)). +-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)). +-define(GET_CONTENT_LENGTH(R), element(3, R)). +-define(SET_CONTENT_LENGTH(A, R), setelement(3, R, A)). +-define(GET_CONTENT_TYPE(R), element(4, R)). +-define(SET_CONTENT_TYPE(A, R), setelement(4, R, A)). +-define(GET_EWGI(R), element(5, R)). +-define(SET_EWGI(A, R), setelement(5, R, A)). +-define(GET_GATEWAY_INTERFACE(R), element(6, R)). +-define(SET_GATEWAY_INTERFACE(A, R), setelement(6, R, A)). +-define(GET_HTTP_HEADERS(R), element(7, R)). +-define(SET_HTTP_HEADERS(A, R), setelement(7, R, A)). +-define(GET_PATH_INFO(R), element(8, R)). +-define(SET_PATH_INFO(A, R), setelement(8, R, A)). +-define(GET_PATH_TRANSLATED(R), element(9, R)). +-define(SET_PATH_TRANSLATED(A, R), setelement(9, R, A)). +-define(GET_QUERY_STRING(R), element(10, R)). +-define(SET_QUERY_STRING(A, R), setelement(10, R, A)). +-define(GET_REMOTE_ADDR(R), element(11, R)). +-define(SET_REMOTE_ADDR(A, R), setelement(11, R, A)). +-define(GET_REMOTE_HOST(R), element(12, R)). +-define(SET_REMOTE_HOST(A, R), setelement(12, R, A)). +-define(GET_REMOTE_IDENT(R), element(13, R)). +-define(SET_REMOTE_IDENT(A, R), setelement(13, R, A)). +-define(GET_REMOTE_USER(R), element(14, R)). +-define(SET_REMOTE_USER(A, R), setelement(14, R, A)). +-define(GET_REMOTE_USER_DATA(R), element(15, R)). +-define(SET_REMOTE_USER_DATA(A, R), setelement(15, R, A)). +-define(GET_REQUEST_METHOD(R), element(16, R)). +-define(SET_REQUEST_METHOD(A, R), setelement(16, R, A)). +-define(GET_SCRIPT_NAME(R), element(17, R)). +-define(SET_SCRIPT_NAME(A, R), setelement(17, R, A)). +-define(GET_SERVER_NAME(R), element(18, R)). +-define(SET_SERVER_NAME(A, R), setelement(18, R, A)). +-define(GET_SERVER_PORT(R), element(19, R)). +-define(SET_SERVER_PORT(A, R), setelement(19, R, A)). +-define(GET_SERVER_PROTOCOL(R), element(20, R)). +-define(SET_SERVER_PROTOCOL(A, R), setelement(20, R, A)). +-define(GET_SERVER_SOFTWARE(R), element(21, R)). +-define(SET_SERVER_SOFTWARE(A, R), setelement(21, R, A)). + +%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change: +%%%-type stream() :: fun(() -> {} | {any(), stream()}). +%% @type stream() = function() +-type stream() :: fun(() -> {} | {any(), function()}). + +%% @type ewgi_status() = {integer(), string()} +-type ewgi_status() :: {integer(), string()}. + +%% @type ewgi_message_body() = binary() | iolist() | stream() +-type ewgi_message_body() :: binary() | iolist() | stream(). + +%% @type ewgi_header_list() = [{ewgi_header_key(), ewgi_header_val()}] +-type ewgi_header_list() :: [{ewgi_header_key(), ewgi_header_val()}]. + +%% @type ewgi_response() = {'ewgi_response', ewgi_status(), +%% [{ewgi_header_key(), ewgi_header_val()}], +%% ewgi_message_body(), any()} + +-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}. + +-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response') + and (size(R) =:= 5))). +-define(GET_RESPONSE_STATUS(R), element(2, R)). +-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)). +-define(GET_RESPONSE_HEADERS(R), element(3, R)). +-define(SET_RESPONSE_HEADERS(A, R), setelement(3, R, A)). +-define(GET_RESPONSE_MESSAGE_BODY(R), element(4, R)). +-define(SET_RESPONSE_MESSAGE_BODY(A, R), setelement(4, R, A)). +-define(GET_RESPONSE_ERROR(R), element(5, R)). +-define(SET_RESPONSE_ERROR(A, R), setelement(5, R, A)). + +%% @type ewgi_context() = {'ewgi_context', ewgi_request(), ewgi_response()} + +-type ewgi_context() :: {'ewgi_context', ewgi_request(), ewgi_response()}. + +-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context') + and ?IS_EWGI_REQUEST(element(2, R)) + and ?IS_EWGI_RESPONSE(element(3, R)) + and (size(R) =:= 3))). +-define(GET_EWGI_REQUEST(R), element(2, R)). +-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)). +-define(GET_EWGI_RESPONSE(R), element(3, R)). +-define(SET_EWGI_RESPONSE(A, R), setelement(3, R, A)). + +%% @type ewgi_app() = function() +-type ewgi_app() :: fun((ewgi_context()) -> ewgi_context()). + +-ifndef(debug). +-define(INSPECT_EWGI_RESPONSE(Ctx), Ctx). +-else. +-define(INSPECT_EWGI_RESPONSE(Ctx), + begin + error_logger:info_msg("Inpecting the final ewgi_response()...~n" + "Requested Url: ~p~n" + "Status: ~p~n" + "Headers: ~p~n" + "Body: ~p~n", + [ewgi_api:path_info(Ctx), + ewgi_api:response_status(Ctx), + ewgi_api:response_headers(Ctx), + ewgi_api:response_message_body(Ctx)]), + Ctx + end + ). +-endif. + +-endif. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl new file mode 100644 index 0000000000..60da757d3b --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl @@ -0,0 +1,65 @@ +%%%------------------------------------------------------------------- +%%% File : ewgi_api.erl +%%% Authors : Filippo Pacini +%%% Hunter Morris +%%% License : +%%% The contents of this file are subject to the Mozilla Public +%%% License Version 1.1 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain a copy of +%%% the License at http://www.mozilla.org/MPL/ +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and +%%% limitations under the License. +%%% The Initial Developer of the Original Code is S.G. Consulting +%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C) +%%% 2007 S.G. Consulting srl. All Rights Reserved. +%%% +%%% @doc +%%%

ewgi API. Defines a low level CGI like API.

+%%% +%%% @end +%%% +%%% Created : 10 Oct 2007 by Filippo Pacini +%%%------------------------------------------------------------------- +-module(ewgi_api). + +-include_lib("ewgi.hrl"). + +-export([get_all_headers/1, get_all_data/1]). + +-spec request(ewgi_context()) -> ewgi_request(). +request(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_EWGI_REQUEST(Ctx). + +-spec headers(ewgi_context()) -> ewgi_http_headers(). +headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_HTTP_HEADERS(request(Ctx)). + +get_header_value(Hdr0, Ctx) when is_list(Hdr0), ?IS_EWGI_CONTEXT(Ctx) -> + Hdr = string:to_lower(Hdr0), + get_header1(Hdr, Ctx). + +get_header1("accept", Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_HTTP_ACCEPT(headers(Ctx)). + +unzip_header_value([{_,_}|_]=V) -> + {_, V1} = lists:unzip(V), + string:join(V1, ", "); +unzip_header_value(V) -> + V. + +get_all_headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + H = headers(Ctx), + Other = gb_trees:to_list(?GET_HTTP_OTHER(H)), + Acc = [{K, unzip_header_value(V)} || {K, V} <- Other], + L = [{"accept", get_header_value("accept", Ctx)}|Acc], + lists:filter(fun({_, undefined}) -> false; (_) -> true end, L). + +-spec ewgi_spec(ewgi_context()) -> ewgi_spec(). +ewgi_spec(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_EWGI(request(Ctx)). + +get_all_data(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_EWGI_DATA(ewgi_spec(Ctx)). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl new file mode 100644 index 0000000000..59c1ae9206 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl @@ -0,0 +1,46 @@ +%%%------------------------------------------------------------------- +%%% File : ewgi_testapp.erl +%%% Authors : Hunter Morris +%%% License : +%%% The contents of this file are subject to the Mozilla Public +%%% License Version 1.1 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain a copy of +%%% the License at http://www.mozilla.org/MPL/ +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and +%%% limitations under the License. +%%% The Initial Developer of the Original Code is S.G. Consulting +%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C) +%%% 2007 S.G. Consulting srl. All Rights Reserved. +%%% +%%% @doc +%%%

ewgi test applications

+%%% +%%% @end +%%% +%%% Created : 05 July 2009 by Hunter Morris +%%%------------------------------------------------------------------- +-module(ewgi_testapp). + +-export([htmlise/1]). + +-include_lib("ewgi.hrl"). + +htmlise(C) -> + iolist_to_binary( + ["
", + io_lib:format("
other http headers
~s
", [htmlise_data("http_headers", ewgi_api:get_all_headers(C))]), + io_lib:format("
ewgi extra data
~s
", [htmlise_data("request_data", ewgi_api:get_all_data(C))]), + "
"]). + +htmlise_data(Name, L) when is_list(L) -> + ["
", + [io_lib:format("
~s
~p
", [K, V]) || {K, V} <- L], + "
"]; +htmlise_data(Name, T) -> + case gb_trees:to_list(T) of + [] -> []; + L -> htmlise_data(Name, L) + end. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl new file mode 100644 index 0000000000..5da8ff0ecf --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl @@ -0,0 +1,241 @@ +-ifndef(_EWGI_HRL). +-define(_EWGI_HRL, 1). + +% ``The contents of this file are subject to the Mozilla Public License +% Version 1.1 (the "License"); you may not use this file except in +% compliance with the License. You may obtain a copy of the License at +% http://www.mozilla.org/MPL/ +% +% Software distributed under the License is distributed on an "AS IS" +% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +% License for the specific language governing rights and limitations +% under the License. +% +% The Original Code is the EWGI reference implementation. +% +% The Initial Developer of the Original Code is S.G. Consulting +% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C) +% 2007 S.G. Consulting srl. All Rights Reserved. +% +% Contributor(s): Filippo Pacini +% Hunter Morris + +-define(DEFAULT_CHUNKSIZE, 4096). +-define(HAS_GB_TREE_SPEC, true). + +-type ewgi_propval() :: atom() | integer() | string() | binary(). +-type ewgi_prop() :: {ewgi_propval(), ewgi_propval()}. +-type ewgi_proplist() :: [ewgi_prop()]. + +%% @type bag() = gb_tree() +-ifdef(HAS_GB_TREE_SPEC). +-type bag() :: gb_tree(). +-else. +-type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}. +-endif. + +%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change: +%%%-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | ewgi_ri_callback()). +%% @type ewgi_ri_callback() = function() +-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | function()) | iolist(). + +%% @type ewgi_read_input() = function() +-type ewgi_read_input() :: fun((ewgi_ri_callback(), integer()) -> ewgi_ri_callback()). + +%% @type ewgi_write_error() = function() +-type ewgi_write_error() :: fun((any()) -> 'ok'). + +%% @type ewgi_version() = {integer(), integer()} +-type ewgi_version() :: {integer(), integer()}. + +%% @type ewgi_spec() = {'ewgi_spec', function(), function(), string(), +%% ewgi_version(), bag()} + +-type ewgi_spec() :: {'ewgi_spec', ewgi_read_input(), + ewgi_write_error(), string(), ewgi_version(), + bag()}. + +-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec') + and (size(R) =:= 6))). +-define(GET_EWGI_READ_INPUT(R), element(2, R)). +-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)). +-define(GET_EWGI_WRITE_ERROR(R), element(3, R)). +-define(SET_EWGI_WRITE_ERROR(A, R), setelement(3, R, A)). +-define(GET_EWGI_URL_SCHEME(R), element(4, R)). +-define(SET_EWGI_URL_SCHEME(A, R), setelement(4, R, A)). +-define(GET_EWGI_VERSION(R), element(5, R)). +-define(SET_EWGI_VERSION(A, R), setelement(5, R, A)). +-define(GET_EWGI_DATA(R), element(6, R)). +-define(SET_EWGI_DATA(A, R), setelement(6, R, A)). + +%% @type ewgi_header_val() = string() | 'undefined' +-type ewgi_header_val() :: string() | 'undefined'. + +%% @type ewgi_header_key() = string() +-type ewgi_header_key() :: string(). + +%% @type ewgi_http_headers() = {'ewgi_http_headers', +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% ewgi_header_val(), +%% bag()} + +-type ewgi_http_headers() :: {'ewgi_http_headers', ewgi_header_val(), + ewgi_header_val(), ewgi_header_val(), + ewgi_header_val(), ewgi_header_val(), + ewgi_header_val(), bag()}. + +-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers') + and (size(R) =:= 8))). +-define(GET_HTTP_ACCEPT(R), element(2, R)). +-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)). +-define(GET_HTTP_COOKIE(R), element(3, R)). +-define(SET_HTTP_COOKIE(A, R), setelement(3, R, A)). +-define(GET_HTTP_HOST(R), element(4, R)). +-define(SET_HTTP_HOST(A, R), setelement(4, R, A)). +-define(GET_HTTP_IF_MODIFIED_SINCE(R), element(5, R)). +-define(SET_HTTP_IF_MODIFIED_SINCE(A, R), setelement(5, R, A)). +-define(GET_HTTP_USER_AGENT(R), element(6, R)). +-define(SET_HTTP_USER_AGENT(A, R), setelement(6, R, A)). +-define(GET_HTTP_X_HTTP_METHOD_OVERRIDE(R), element(7, R)). +-define(SET_HTTP_X_HTTP_METHOD_OVERRIDE(A, R), setelement(7, R, A)). +-define(GET_HTTP_OTHER(R), element(8, R)). +-define(SET_HTTP_OTHER(A, R), setelement(8, R, A)). + +%% @type ewgi_request_method() = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | +%% 'DELETE' | 'TRACE' | 'CONNECT' | string() +-type ewgi_request_method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | + 'DELETE' | 'TRACE' | 'CONNECT' | string(). + +%% @type ewgi_val() = string() | 'undefined' +-type ewgi_val() :: string() | 'undefined'. + +%% @type ewgi_request() :: {'ewgi_request', ewgi_val(), integer(), ewgi_val(), +%% ewgi_spec(), ewgi_val(), ewgi_http_headers(), +%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(), +%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(), +%% ewgi_request_method(), ewgi_val(), ewgi_val(), +%% ewgi_val(), ewgi_val(), ewgi_val()} + +-type ewgi_request() :: {'ewgi_request', ewgi_val(), + non_neg_integer(), ewgi_val(), ewgi_spec(), + ewgi_val(), ewgi_http_headers(), ewgi_val(), + ewgi_val(), ewgi_val(), ewgi_val(), + ewgi_val(), ewgi_val(), ewgi_val(), + ewgi_val(), ewgi_request_method(), + ewgi_val(), ewgi_val(), ewgi_val(), + ewgi_val(), ewgi_val()}. + +-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request') + and (size(R) =:= 21))). +-define(GET_AUTH_TYPE(R), element(2, R)). +-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)). +-define(GET_CONTENT_LENGTH(R), element(3, R)). +-define(SET_CONTENT_LENGTH(A, R), setelement(3, R, A)). +-define(GET_CONTENT_TYPE(R), element(4, R)). +-define(SET_CONTENT_TYPE(A, R), setelement(4, R, A)). +-define(GET_EWGI(R), element(5, R)). +-define(SET_EWGI(A, R), setelement(5, R, A)). +-define(GET_GATEWAY_INTERFACE(R), element(6, R)). +-define(SET_GATEWAY_INTERFACE(A, R), setelement(6, R, A)). +-define(GET_HTTP_HEADERS(R), element(7, R)). +-define(SET_HTTP_HEADERS(A, R), setelement(7, R, A)). +-define(GET_PATH_INFO(R), element(8, R)). +-define(SET_PATH_INFO(A, R), setelement(8, R, A)). +-define(GET_PATH_TRANSLATED(R), element(9, R)). +-define(SET_PATH_TRANSLATED(A, R), setelement(9, R, A)). +-define(GET_QUERY_STRING(R), element(10, R)). +-define(SET_QUERY_STRING(A, R), setelement(10, R, A)). +-define(GET_REMOTE_ADDR(R), element(11, R)). +-define(SET_REMOTE_ADDR(A, R), setelement(11, R, A)). +-define(GET_REMOTE_HOST(R), element(12, R)). +-define(SET_REMOTE_HOST(A, R), setelement(12, R, A)). +-define(GET_REMOTE_IDENT(R), element(13, R)). +-define(SET_REMOTE_IDENT(A, R), setelement(13, R, A)). +-define(GET_REMOTE_USER(R), element(14, R)). +-define(SET_REMOTE_USER(A, R), setelement(14, R, A)). +-define(GET_REMOTE_USER_DATA(R), element(15, R)). +-define(SET_REMOTE_USER_DATA(A, R), setelement(15, R, A)). +-define(GET_REQUEST_METHOD(R), element(16, R)). +-define(SET_REQUEST_METHOD(A, R), setelement(16, R, A)). +-define(GET_SCRIPT_NAME(R), element(17, R)). +-define(SET_SCRIPT_NAME(A, R), setelement(17, R, A)). +-define(GET_SERVER_NAME(R), element(18, R)). +-define(SET_SERVER_NAME(A, R), setelement(18, R, A)). +-define(GET_SERVER_PORT(R), element(19, R)). +-define(SET_SERVER_PORT(A, R), setelement(19, R, A)). +-define(GET_SERVER_PROTOCOL(R), element(20, R)). +-define(SET_SERVER_PROTOCOL(A, R), setelement(20, R, A)). +-define(GET_SERVER_SOFTWARE(R), element(21, R)). +-define(SET_SERVER_SOFTWARE(A, R), setelement(21, R, A)). + +%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change: +%%%-type stream() :: fun(() -> {} | {any(), stream()}). +%% @type stream() = function() +-type stream() :: fun(() -> {} | {any(), function()}). + +%% @type ewgi_status() = {integer(), string()} +-type ewgi_status() :: {integer(), string()}. + +%% @type ewgi_message_body() = binary() | iolist() | stream() +-type ewgi_message_body() :: binary() | iolist() | stream(). + +%% @type ewgi_header_list() = [{ewgi_header_key(), ewgi_header_val()}] +-type ewgi_header_list() :: [{ewgi_header_key(), ewgi_header_val()}]. + +%% @type ewgi_response() = {'ewgi_response', ewgi_status(), +%% [{ewgi_header_key(), ewgi_header_val()}], +%% ewgi_message_body(), any()} + +-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}. + +-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response') + and (size(R) =:= 5))). +-define(GET_RESPONSE_STATUS(R), element(2, R)). +-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)). +-define(GET_RESPONSE_HEADERS(R), element(3, R)). +-define(SET_RESPONSE_HEADERS(A, R), setelement(3, R, A)). +-define(GET_RESPONSE_MESSAGE_BODY(R), element(4, R)). +-define(SET_RESPONSE_MESSAGE_BODY(A, R), setelement(4, R, A)). +-define(GET_RESPONSE_ERROR(R), element(5, R)). +-define(SET_RESPONSE_ERROR(A, R), setelement(5, R, A)). + +%% @type ewgi_context() = {'ewgi_context', ewgi_request(), ewgi_response()} + +-type ewgi_context() :: {'ewgi_context', ewgi_request(), ewgi_response()}. + +-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context') + and ?IS_EWGI_REQUEST(element(2, R)) + and ?IS_EWGI_RESPONSE(element(3, R)) + and (size(R) =:= 3))). +-define(GET_EWGI_REQUEST(R), element(2, R)). +-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)). +-define(GET_EWGI_RESPONSE(R), element(3, R)). +-define(SET_EWGI_RESPONSE(A, R), setelement(3, R, A)). + +%% @type ewgi_app() = function() +-type ewgi_app() :: fun((ewgi_context()) -> ewgi_context()). + +-ifndef(debug). +-define(INSPECT_EWGI_RESPONSE(Ctx), Ctx). +-else. +-define(INSPECT_EWGI_RESPONSE(Ctx), + begin + error_logger:info_msg("Inpecting the final ewgi_response()...~n" + "Requested Url: ~p~n" + "Status: ~p~n" + "Headers: ~p~n" + "Body: ~p~n", + [ewgi_api:path_info(Ctx), + ewgi_api:response_status(Ctx), + ewgi_api:response_headers(Ctx), + ewgi_api:response_message_body(Ctx)]), + Ctx + end + ). +-endif. + +-endif. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl new file mode 100644 index 0000000000..60da757d3b --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl @@ -0,0 +1,65 @@ +%%%------------------------------------------------------------------- +%%% File : ewgi_api.erl +%%% Authors : Filippo Pacini +%%% Hunter Morris +%%% License : +%%% The contents of this file are subject to the Mozilla Public +%%% License Version 1.1 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain a copy of +%%% the License at http://www.mozilla.org/MPL/ +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and +%%% limitations under the License. +%%% The Initial Developer of the Original Code is S.G. Consulting +%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C) +%%% 2007 S.G. Consulting srl. All Rights Reserved. +%%% +%%% @doc +%%%

ewgi API. Defines a low level CGI like API.

+%%% +%%% @end +%%% +%%% Created : 10 Oct 2007 by Filippo Pacini +%%%------------------------------------------------------------------- +-module(ewgi_api). + +-include_lib("ewgi.hrl"). + +-export([get_all_headers/1, get_all_data/1]). + +-spec request(ewgi_context()) -> ewgi_request(). +request(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_EWGI_REQUEST(Ctx). + +-spec headers(ewgi_context()) -> ewgi_http_headers(). +headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_HTTP_HEADERS(request(Ctx)). + +get_header_value(Hdr0, Ctx) when is_list(Hdr0), ?IS_EWGI_CONTEXT(Ctx) -> + Hdr = string:to_lower(Hdr0), + get_header1(Hdr, Ctx). + +get_header1("accept", Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_HTTP_ACCEPT(headers(Ctx)). + +unzip_header_value([{_,_}|_]=V) -> + {_, V1} = lists:unzip(V), + string:join(V1, ", "); +unzip_header_value(V) -> + V. + +get_all_headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + H = headers(Ctx), + Other = gb_trees:to_list(?GET_HTTP_OTHER(H)), + Acc = [{K, unzip_header_value(V)} || {K, V} <- Other], + L = [{"accept", get_header_value("accept", Ctx)}|Acc], + lists:filter(fun({_, undefined}) -> false; (_) -> true end, L). + +-spec ewgi_spec(ewgi_context()) -> ewgi_spec(). +ewgi_spec(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_EWGI(request(Ctx)). + +get_all_data(Ctx) when ?IS_EWGI_CONTEXT(Ctx) -> + ?GET_EWGI_DATA(ewgi_spec(Ctx)). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl new file mode 100644 index 0000000000..59c1ae9206 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl @@ -0,0 +1,46 @@ +%%%------------------------------------------------------------------- +%%% File : ewgi_testapp.erl +%%% Authors : Hunter Morris +%%% License : +%%% The contents of this file are subject to the Mozilla Public +%%% License Version 1.1 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain a copy of +%%% the License at http://www.mozilla.org/MPL/ +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and +%%% limitations under the License. +%%% The Initial Developer of the Original Code is S.G. Consulting +%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C) +%%% 2007 S.G. Consulting srl. All Rights Reserved. +%%% +%%% @doc +%%%

ewgi test applications

+%%% +%%% @end +%%% +%%% Created : 05 July 2009 by Hunter Morris +%%%------------------------------------------------------------------- +-module(ewgi_testapp). + +-export([htmlise/1]). + +-include_lib("ewgi.hrl"). + +htmlise(C) -> + iolist_to_binary( + ["
", + io_lib:format("
other http headers
~s
", [htmlise_data("http_headers", ewgi_api:get_all_headers(C))]), + io_lib:format("
ewgi extra data
~s
", [htmlise_data("request_data", ewgi_api:get_all_data(C))]), + "
"]). + +htmlise_data(Name, L) when is_list(L) -> + ["
", + [io_lib:format("
~s
~p
", [K, V]) || {K, V} <- L], + "
"]; +htmlise_data(Name, T) -> + case gb_trees:to_list(T) of + [] -> []; + L -> htmlise_data(Name, L) + end. -- cgit v1.2.3