summaryrefslogtreecommitdiff
path: root/src/couch_inets/http.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch_inets/http.erl')
-rw-r--r--src/couch_inets/http.erl396
1 files changed, 0 insertions, 396 deletions
diff --git a/src/couch_inets/http.erl b/src/couch_inets/http.erl
deleted file mode 100644
index bdc7f73a..00000000
--- a/src/couch_inets/http.erl
+++ /dev/null
@@ -1,396 +0,0 @@
-% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
-%%
-%% 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 Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id$
-%%
-%% This module is very loosely based on code initially developed by
-%% Johan Blom at Mobile Arts AB
-%% Description:
-%%% This version of the HTTP/1.1 client supports:
-%%% - RFC 2616 HTTP 1.1 client part
-%%% - RFC 2818 HTTP Over TLS
-
--module(http).
-
-%% API
--export([request/1, request/4, cancel_request/1, set_options/1,
- verify_cookies/2, cookie_header/1]).
-
--include("http_internal.hrl").
--include("httpc_internal.hrl").
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-
-%%--------------------------------------------------------------------------
-%% request(Method, Request, HTTPOptions, Options) ->
-%% {ok, {StatusLine, Headers, Body}} | {ok, {Status, Body}} |
-%% {ok, RequestId} | {error,Reason} | {ok, {saved_as, FilePath}
-%%
-%% Method - atom() = head | get | put | post | trace | options| delete
-%% Request - {Url, Headers} | {Url, Headers, ContentType, Body}
-%% Url - string()
-%% HTTPOptions - [HttpOption]
-%% HTTPOption - {timeout, Time} | {ssl, SSLOptions} |
-%% {proxy_auth, {User, Password}}
-%% Ssloptions = [SSLOption]
-%% SSLOption = {verify, code()} | {depth, depth()} | {certfile, path()} |
-%% {keyfile, path()} | {password, string()} | {cacertfile, path()} |
-%% {ciphers, string()}
-%% Options - [Option]
-%% Option - {sync, Boolean} | {body_format, BodyFormat} |
-%% {full_result, Boolean} | {stream, To} |
-%% {headers_as_is, Boolean}
-%% StatusLine = {HTTPVersion, StatusCode, ReasonPhrase}</v>
-%% HTTPVersion = string()
-%% StatusCode = integer()
-%% ReasonPhrase = string()
-%% Headers = [Header]
-%% Header = {Field, Value}
-%% Field = string()
-%% Value = string()
-%% Body = string() | binary() - HTLM-code
-%%
-%% Description: Sends a HTTP-request. The function can be both
-%% syncronus and asynchronous in the later case the function will
-%% return {ok, RequestId} and later on a message will be sent to the
-%% calling process on the format {http, {RequestId, {StatusLine,
-%% Headers, Body}}} or {http, {RequestId, {error, Reason}}}
-%% %%--------------------------------------------------------------------------
-request(Url) ->
- request(get, {Url, []}, [], []).
-
-request(Method, {Url, Headers}, HTTPOptions, Options)
- when Method==options;Method==get;Method==head;Method==delete;Method==trace ->
- case http_uri:parse(Url) of
- {error,Reason} ->
- {error,Reason};
- ParsedUrl ->
- handle_request(Method, Url, {ParsedUrl, Headers, [], []},
- HTTPOptions, Options)
- end;
-
-request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options)
- when Method==post;Method==put ->
- case http_uri:parse(Url) of
- {error,Reason} ->
- {error,Reason};
- ParsedUrl ->
- handle_request(Method, Url,
- {ParsedUrl, Headers, ContentType, Body},
- HTTPOptions, Options)
- end.
-
-%%--------------------------------------------------------------------------
-%% request(RequestId) -> ok
-%% RequestId - As returned by request/4
-%%
-%% Description: Cancels a HTTP-request.
-%%-------------------------------------------------------------------------
-cancel_request(RequestId) ->
- ok = httpc_manager:cancel_request(RequestId),
- receive
- %% If the request was allready fullfilled throw away the
- %% answer as the request has been canceled.
- {http, {RequestId, _}} ->
- ok
- after 0 ->
- ok
- end.
-
-%%--------------------------------------------------------------------------
-%% set_options(Options) ->
-%% Options - [Option]
-%% Option - {proxy, {Proxy, NoProxy}} | {max_sessions, MaxSessions} |
-%% {max_pipeline_length, MaxPipeline} |
-%% {pipeline_timeout, PipelineTimeout} | {cookies, CookieMode}
-%% | {ipv6, Ipv6Mode}
-%% Proxy - {Host, Port}
-%% NoProxy - [Domain | HostName | IPAddress]
-%% MaxSessions, MaxPipeline, PipelineTimeout = integer()
-%% CookieMode - enabled | disabled | verify
-%% Ipv6Mode - enabled | disabled
-%% Description: Informs the httpc_manager of the new settings.
-%%-------------------------------------------------------------------------
-set_options(Options) ->
- ensure_started(no_scheme),
- httpc_manager:set_options(Options).
-
-verify_cookies(SetCookieHeaders, Url) ->
- {_, _, Host, Port, Path, _} = http_uri:parse(Url),
- Cookies = http_cookie:cookies(SetCookieHeaders, Path, Host),
- httpc_manager:store_cookies(Cookies, {Host, Port}),
- ok.
-
-cookie_header(Url) ->
- httpc_manager:cookies(Url).
-
-%%%========================================================================
-%%% Internal functions
-%%%========================================================================
-handle_request(Method, Url, {{Scheme, UserInfo, Host, Port, Path, Query},
- Headers, ContentType, Body}, HTTPOptions, Options) ->
- HTTPRecordOptions = http_options(HTTPOptions, #http_options{}),
-
- Sync = http_util:key1search(Options, sync, true),
- NewHeaders = lists:map(fun({Key, Val}) ->
- {http_util:to_lower(Key), Val} end,
- Headers),
- Stream = http_util:key1search(Options, stream, none),
-
- case {Sync, Stream} of
- {true, self} ->
- {error, streaming_error};
- _ ->
- RecordHeaders = header_record(NewHeaders, #http_request_h{}, Host),
- Request = #request{from = self(),
- scheme = Scheme, address = {Host,Port},
- path = Path, pquery = Query, method = Method,
- headers = RecordHeaders,
- content = {ContentType,Body},
- settings = HTTPRecordOptions,
- abs_uri = Url, userinfo = UserInfo,
- stream = Stream,
- headers_as_is =
- headers_as_is(Headers, Options)},
-
- ensure_started(Scheme),
-
- case httpc_manager:request(Request) of
- {ok, RequestId} ->
- handle_answer(RequestId, Sync, Options);
- {error, Reason} ->
- {error, Reason}
- end
- end.
-
-handle_answer(RequestId, false, _) ->
- {ok, RequestId};
-handle_answer(RequestId, true, Options) ->
- receive
- {http, {RequestId, saved_to_file}} ->
- {ok, saved_to_file};
- {http, {RequestId, Result = {_,_,_}}} ->
- return_answer(Options, Result);
- {http, {RequestId, {error, Reason}}} ->
- {error, Reason}
- end.
-
-return_answer(Options, {StatusLine, Headers, BinBody}) ->
- Body =
- case http_util:key1search(Options, body_format, string) of
- string ->
- binary_to_list(BinBody);
- _ ->
- BinBody
- end,
- case http_util:key1search(Options, full_result, true) of
- true ->
- {ok, {StatusLine, Headers, Body}};
- false ->
- {_, Status, _} = StatusLine,
- {ok, {Status, Body}}
- end.
-
-
-%% This options is a workaround for http servers that do not follow the
-%% http standard and have case sensative header parsing. Should only be
-%% used if there is no other way to communicate with the server or for
-%% testing purpose.
-headers_as_is(Headers, Options) ->
- case http_util:key1search(Options, headers_as_is, false) of
- false ->
- [];
- true ->
- Headers
- end.
-
-http_options([], Acc) ->
- Acc;
-http_options([{timeout, Val} | Settings], Acc)
- when is_integer(Val), Val >= 0->
- http_options(Settings, Acc#http_options{timeout = Val});
-http_options([{timeout, infinity} | Settings], Acc) ->
- http_options(Settings, Acc#http_options{timeout = infinity});
-http_options([{autoredirect, Val} | Settings], Acc)
- when Val == true; Val == false ->
- http_options(Settings, Acc#http_options{autoredirect = Val});
-http_options([{ssl, Val} | Settings], Acc) ->
- http_options(Settings, Acc#http_options{ssl = Val});
-http_options([{relaxed, Val} | Settings], Acc)
- when Val == true; Val == false ->
- http_options(Settings, Acc#http_options{relaxed = Val});
-http_options([{proxy_auth, Val = {User, Passwd}} | Settings], Acc)
- when is_list(User),
- is_list(Passwd) ->
- http_options(Settings, Acc#http_options{proxy_auth = Val});
-http_options([Option | Settings], Acc) ->
- error_logger:info_report("Invalid option ignored ~p~n", [Option]),
- http_options(Settings, Acc).
-
-header_record([], RequestHeaders, Host) ->
- validate_headers(RequestHeaders, Host);
-header_record([{"cache-control", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'cache-control' = Val},
- Host);
-header_record([{"connection", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{connection = Val}, Host);
-header_record([{"date", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{date = Val}, Host);
-header_record([{"pragma", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{pragma = Val}, Host);
-header_record([{"trailer", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{trailer = Val}, Host);
-header_record([{"transfer-encoding", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest,
- RequestHeaders#http_request_h{'transfer-encoding' = Val},
- Host);
-header_record([{"upgrade", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{upgrade = Val}, Host);
-header_record([{"via", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{via = Val}, Host);
-header_record([{"warning", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{warning = Val}, Host);
-header_record([{"accept", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{accept = Val}, Host);
-header_record([{"accept-charset", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'accept-charset' = Val},
- Host);
-header_record([{"accept-encoding", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'accept-encoding' = Val},
- Host);
-header_record([{"accept-language", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'accept-language' = Val},
- Host);
-header_record([{"authorization", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{authorization = Val},
- Host);
-header_record([{"expect", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{expect = Val}, Host);
-header_record([{"from", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{from = Val}, Host);
-header_record([{"host", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{host = Val}, Host);
-header_record([{"if-match", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'if-match' = Val},
- Host);
-header_record([{"if-modified-since", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest,
- RequestHeaders#http_request_h{'if-modified-since' = Val},
- Host);
-header_record([{"if-none-match", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'if-none-match' = Val},
- Host);
-header_record([{"if-range", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'if-range' = Val},
- Host);
-
-header_record([{"if-unmodified-since", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'if-unmodified-since'
- = Val}, Host);
-header_record([{"max-forwards", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'max-forwards' = Val},
- Host);
-header_record([{"proxy-authorization", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'proxy-authorization'
- = Val}, Host);
-header_record([{"range", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{range = Val}, Host);
-header_record([{"referer", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{referer = Val}, Host);
-header_record([{"te", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{te = Val}, Host);
-header_record([{"user-agent", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'user-agent' = Val},
- Host);
-header_record([{"allow", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{allow = Val}, Host);
-header_record([{"content-encoding", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest,
- RequestHeaders#http_request_h{'content-encoding' = Val},
- Host);
-header_record([{"content-language", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest,
- RequestHeaders#http_request_h{'content-language' = Val},
- Host);
-header_record([{"content-length", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'content-length' = Val},
- Host);
-header_record([{"content-location", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest,
- RequestHeaders#http_request_h{'content-location' = Val},
- Host);
-header_record([{"content-md5", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'content-md5' = Val},
- Host);
-header_record([{"content-range", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'content-range' = Val},
- Host);
-header_record([{"content-type", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'content-type' = Val},
- Host);
-header_record([{"expires", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{expires = Val}, Host);
-header_record([{"last-modified", Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{'last-modified' = Val},
- Host);
-header_record([{Key, Val} | Rest], RequestHeaders, Host) ->
- header_record(Rest, RequestHeaders#http_request_h{
- other = [{Key, Val} |
- RequestHeaders#http_request_h.other]},
- Host).
-
-validate_headers(RequestHeaders = #http_request_h{te = undefined}, Host) ->
- validate_headers(RequestHeaders#http_request_h{te = ""}, Host);
-validate_headers(RequestHeaders = #http_request_h{host = undefined}, Host) ->
- validate_headers(RequestHeaders#http_request_h{host = Host}, Host);
-validate_headers(RequestHeaders, _) ->
- RequestHeaders.
-
-ensure_started(Scheme) ->
- %% Start of the inets application should really be handled by the
- %% application using inets.
- case application:start(couch_inets) of
- {error,{already_started,couch_inets}} ->
- ok;
- {error, {{already_started,_}, % Started as an included application
- {inets_app, start, _}}} ->
- ok;
- ok ->
- error_logger:info_report("The inets application was not started."
- " Has now been started as a temporary"
- " application.")
- end,
-
- case Scheme of
- https ->
- %% Start of the ssl application should really be handled by the
- %% application using inets.
- case application:start(ssl) of
- {error,{already_started,ssl}} ->
- ok;
- %% Started as an included application
- {error, {{already_started,_},
- {ssl_app, start, _}}} ->
- ok;
- ok ->
- error_logger:info_report("The ssl application was not "
- "started. Has now been started "
- "as a temporary application.")
- end;
- _ ->
- ok
- end.