From 09d76d23914e0d52d0f8125fccc184198119e9d9 Mon Sep 17 00:00:00 2001 From: Andrew Tunnell-Jones Date: Fri, 29 Oct 2010 09:01:55 +0000 Subject: [PATCH] Use ibrowse instead of httpc as HTTP client httpc seems to do something odd that Google doesn't like in associate requests. ibrowse does as well (includes port superflously in the request, kudos Chandru for spotting the bug) but this is fixed in my ibrowse fork and in the upcoming ibrowse release. ibrowse is wrapped by openid_http to hide following redirects and other minutia. --- .gitignore | 3 ++- rebar.config | 1 + src/openid.erl | 4 +--- src/openid_http.erl | 51 +++++++++++++++++++++++++++++++++++++++++++++ src/yadis.erl | 8 +++---- 5 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 rebar.config create mode 100644 src/openid_http.erl diff --git a/.gitignore b/.gitignore index d32088c..ac32c68 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ Mnesia.* sasl_err* erl_crash* -ebin/openid.app \ No newline at end of file +ebin/openid.app +deps/* \ No newline at end of file diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..0fc40b3 --- /dev/null +++ b/rebar.config @@ -0,0 +1 @@ +{deps, [{ibrowse, ".*", {git, "git://github.com/andrewtj/ibrowse.git", "master"}}]}. \ No newline at end of file diff --git a/src/openid.erl b/src/openid.erl index b2bd704..de0fdbe 100644 --- a/src/openid.erl +++ b/src/openid.erl @@ -152,9 +152,7 @@ associate(OpURL) -> ReqBody = openid_pm:url_encode(Params), - Request = {OpURL, [], ?CONTENT_TYPE, ReqBody}, - - {ok, {_,_,Body}} = httpc:request(post, Request, [], []), + {ok, 200, _Headers, Body} = openid_http:post(OpURL, ?CONTENT_TYPE, ReqBody), Response = openid_pm:kvf_decode(Body), diff --git a/src/openid_http.erl b/src/openid_http.erl new file mode 100644 index 0000000..064868c --- /dev/null +++ b/src/openid_http.erl @@ -0,0 +1,51 @@ +-module(openid_http). +-include("deps/ibrowse/src/ibrowse.hrl"). +-export([get/1, post/3]). + +-define(MAX_REDIRECTS, 5). %% too generous? + +get(URL) -> + get(URL, ?MAX_REDIRECTS). + +get(URL, Redirects) -> + ReqHeaders = [{"Accept", "application/xrds+xml;level=1, */*"}, + {"Connection", "close"}, + {"User-Agent", "Erlang/erl_openid"}], + ResponseRaw = ibrowse:send_req(URL, ReqHeaders, get), + Response = normalise_response(ResponseRaw), + case Response of + {ok, Rcode, RespHeaders, _Body} + when Rcode > 300 andalso Rcode < 304 andalso Redirects > 0 -> + case get_redirect_url(URL, RespHeaders) of + undefined -> Response; + URL -> Response; + NewURL -> get(NewURL, Redirects - 1) + end; + Response -> Response + end. + +post(URL, ContentType, Body) -> + Raw = ibrowse:send_req(URL, [{content_type, ContentType}], post, Body), + normalise_response(Raw). + +get_redirect_url(OldURL, Headers) -> + Location = proplists:get_value("location", Headers), + case Location of + "http://" ++ _ -> Location; + "https://" ++ _ -> Location; + [$/|_] = Location -> + #url{protocol=Protocol, host=Host, port=Port} = ibrowse_lib:parse_url(OldURL), + PortFrag = case {Protocol, Port} of + {http, 80} -> ""; + {https, 443} -> ""; + _ -> ":" ++ integer_to_list(Port) + end, + atom_to_list(Protocol) ++ "://" ++ Host ++ PortFrag ++ Location; + _ -> undefined + end. + +normalise_response({ok, RcodeList, Headers, Body}) -> + RcodeInt = list_to_integer(RcodeList), + LowHeaders = [ {string:to_lower(K), V} || {K, V} <- Headers ], + {ok, RcodeInt, LowHeaders, Body}; +normalise_response(X) -> X. diff --git a/src/yadis.erl b/src/yadis.erl index a542e2b..ddb69cf 100644 --- a/src/yadis.erl +++ b/src/yadis.erl @@ -46,8 +46,8 @@ retrieve(Identifier) -> false -> Normalized end, - case httpc:request(get, {URL, ?HTTP_HEADERS}, ?HTTP_OPTIONS, ?REQ_OPTIONS) of - {ok, {_Status, Headers, Body}} -> + case openid_http:get(URL) of + {ok, 200, Headers, Body} -> DescriptorURL = get_descriptor_url(Headers, Body), XRDS = handle_response(DescriptorURL, Headers, Body), case XRDS of @@ -101,8 +101,8 @@ try_descriptor_url(URL) -> retrieve_step_two(URL). retrieve_step_two(YadisURL) -> - case httpc:request(get, {YadisURL, ?HTTP_HEADERS}, ?HTTP_OPTIONS, ?REQ_OPTIONS) of - {ok, {_Status, Headers, Body}} -> + case openid_http:get(YadisURL) of + {ok, 200, Headers, Body} -> get_xrds(?GVD("content-type", Headers, none), Body); Other -> {error, {http_error, {step_two, YadisURL, Other}}}