aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets/src')
-rw-r--r--lib/inets/src/ftp/Makefile28
-rw-r--r--lib/inets/src/ftp/ftp.erl319
-rw-r--r--lib/inets/src/ftp/ftp_internal.hrl13
-rw-r--r--lib/inets/src/http_client/Makefile30
-rw-r--r--lib/inets/src/http_client/http.erl35
-rw-r--r--lib/inets/src/http_client/httpc.erl182
-rw-r--r--lib/inets/src/http_client/httpc_cookie.erl218
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl543
-rw-r--r--lib/inets/src/http_client/httpc_handler_sup.erl8
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl18
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl530
-rw-r--r--lib/inets/src/http_client/httpc_request.erl119
-rw-r--r--lib/inets/src/http_client/httpc_response.erl4
-rw-r--r--lib/inets/src/http_lib/Makefile29
-rw-r--r--lib/inets/src/http_lib/http_chunk.erl10
-rw-r--r--lib/inets/src/http_lib/http_internal.hrl27
-rw-r--r--lib/inets/src/http_lib/http_transport.erl502
-rw-r--r--lib/inets/src/http_lib/http_uri.erl29
-rw-r--r--lib/inets/src/http_lib/http_util.erl33
-rw-r--r--lib/inets/src/http_server/Makefile29
-rw-r--r--lib/inets/src/http_server/httpd.erl286
-rw-r--r--lib/inets/src/http_server/httpd.hrl77
-rw-r--r--lib/inets/src/http_server/httpd_acceptor.erl16
-rw-r--r--lib/inets/src/http_server/httpd_cgi.erl13
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl99
-rw-r--r--lib/inets/src/http_server/httpd_esi.erl15
-rw-r--r--lib/inets/src/http_server/httpd_file.erl10
-rw-r--r--lib/inets/src/http_server/httpd_internal.hrl56
-rw-r--r--lib/inets/src/http_server/httpd_log.erl4
-rw-r--r--lib/inets/src/http_server/httpd_manager.erl38
-rw-r--r--lib/inets/src/http_server/httpd_request.erl66
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl108
-rw-r--r--lib/inets/src/http_server/httpd_script_env.erl3
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl48
-rw-r--r--lib/inets/src/http_server/httpd_util.erl29
-rw-r--r--lib/inets/src/http_server/mod_actions.erl3
-rw-r--r--lib/inets/src/http_server/mod_alias.erl75
-rw-r--r--lib/inets/src/http_server/mod_auth.erl2
-rw-r--r--lib/inets/src/http_server/mod_auth.hrl26
-rw-r--r--lib/inets/src/http_server/mod_auth_dets.erl4
-rw-r--r--lib/inets/src/http_server/mod_auth_mnesia.erl4
-rw-r--r--lib/inets/src/http_server/mod_auth_plain.erl3
-rw-r--r--lib/inets/src/http_server/mod_auth_server.erl2
-rw-r--r--lib/inets/src/http_server/mod_cgi.erl1
-rw-r--r--lib/inets/src/http_server/mod_dir.erl6
-rw-r--r--lib/inets/src/http_server/mod_disk_log.erl4
-rw-r--r--lib/inets/src/http_server/mod_esi.erl49
-rw-r--r--lib/inets/src/http_server/mod_get.erl4
-rw-r--r--lib/inets/src/http_server/mod_head.erl2
-rw-r--r--lib/inets/src/http_server/mod_htaccess.erl3
-rw-r--r--lib/inets/src/http_server/mod_include.erl3
-rw-r--r--lib/inets/src/http_server/mod_log.erl3
-rw-r--r--lib/inets/src/http_server/mod_range.erl4
-rw-r--r--lib/inets/src/http_server/mod_responsecontrol.erl3
-rw-r--r--lib/inets/src/http_server/mod_security.erl2
-rw-r--r--lib/inets/src/http_server/mod_security_server.erl2
-rw-r--r--lib/inets/src/http_server/mod_trace.erl2
-rw-r--r--lib/inets/src/inets_app/Makefile23
-rw-r--r--lib/inets/src/inets_app/inets.app.src1
-rw-r--r--lib/inets/src/inets_app/inets.appup.src114
-rw-r--r--lib/inets/src/inets_app/inets.mk45
-rw-r--r--lib/inets/src/inets_app/inets_service.erl12
-rw-r--r--lib/inets/src/tftp/Makefile22
63 files changed, 2192 insertions, 1806 deletions
diff --git a/lib/inets/src/ftp/Makefile b/lib/inets/src/ftp/Makefile
index 0c15277a18..19b93870df 100644
--- a/lib/inets/src/ftp/Makefile
+++ b/lib/inets/src/ftp/Makefile
@@ -22,6 +22,7 @@ include $(ERL_TOP)/make/target.mk
EBIN = ../../ebin
include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
# ----------------------------------------------------
# Application version
# ----------------------------------------------------
@@ -29,6 +30,7 @@ include ../../vsn.mk
VSN = $(INETS_VSN)
+
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
@@ -52,24 +54,21 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
-# INETS FLAGS
+# FLAGS
# ----------------------------------------------------
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
+
+include ../inets_app/inets.mk
ifeq ($(FTP_DEBUG),true)
INETS_FLAGS += -Dftp_debug
endif
+ERL_COMPILE_FLAGS += \
+ $(INETS_FLAGS) \
+ $(INETS_ERL_COMPILE_FLAGS) \
+ -I../../include \
+ -I../inets_app
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-INETS_ERL_FLAGS += -I ../inets_app -pa ../../ebin
-
-ERL_COMPILE_FLAGS += $(INETS_ERL_FLAGS) \
- $(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
# ----------------------------------------------------
# Targets
@@ -89,9 +88,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/ftp
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/ftp
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
release_docs_spec:
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index 534fcae675..ac72963347 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -25,14 +25,12 @@
-behaviour(gen_server).
-behaviour(inets_service).
--deprecated({open, 3, next_major_release}).
--deprecated({force_active, 1, next_major_release}).
%% API - Client interface
-export([cd/2, close/1, delete/2, formaterror/1,
lcd/2, lpwd/1, ls/1, ls/2,
mkdir/2, nlist/1, nlist/2,
- open/1, open/2, open/3, force_active/1,
+ open/1, open/2,
pwd/1, quote/2,
recv/2, recv/3, recv_bin/2,
recv_chunk_start/2, recv_chunk/1,
@@ -94,6 +92,12 @@
}).
+-type shortage_reason() :: 'etnospc' | 'epnospc'.
+-type restriction_reason() :: 'epath' | 'efnamena' | 'elogin' | 'enotbinary'.
+-type common_reason() :: 'econn' | 'eclosed' | term().
+-type file_write_error_reason() :: term(). % See file:write for more info
+
+
%%%=========================================================================
%%% API - CLIENT FUNCTIONS
%%%=========================================================================
@@ -108,6 +112,9 @@
%% Description: Start an ftp client and connect to a host.
%%--------------------------------------------------------------------------
+-spec open(Host :: string() | inet:ip_address()) ->
+ {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
+
%% <BACKWARD-COMPATIBILLITY>
open({option_list, Options}) when is_list(Options) ->
try
@@ -128,16 +135,14 @@ open({option_list, Options}) when is_list(Options) ->
open(Host) ->
open(Host, []).
+-spec open(Host :: string() | inet:ip_address(), Opts :: list()) ->
+ {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
+
%% <BACKWARD-COMPATIBILLITY>
open(Host, Port) when is_integer(Port) ->
open(Host, [{port, Port}]);
%% </BACKWARD-COMPATIBILLITY>
-%% <BACKWARD-COMPATIBILLITY>
-open(Host, [H|_] = Flags) when is_atom(H) ->
- open(Host, ?FTP_PORT, Flags);
-%% </BACKWARD-COMPATIBILLITY>
-
open(Host, Opts) when is_list(Opts) ->
?fcrt("open", [{host, Host}, {opts, Opts}]),
try
@@ -160,32 +165,6 @@ open(Host, Opts) when is_list(Opts) ->
end.
-%% <BACKWARD-COMPATIBILLITY>
-open(Host, Port, Flags) when is_integer(Port) andalso is_list(Flags) ->
- ?fcrt("open", [{host, Host}, {port, Port}, {flags, Flags}]),
- try
- {ok, StartOptions} = start_options([{flags, Flags}]),
- ?fcrt("open", [{start_options, StartOptions}]),
- {ok, OpenOptions} = open_options([{host, Host}, {port, Port}|Flags]),
- ?fcrt("open", [{open_options, OpenOptions}]),
- case ftp_sup:start_child([[{client, self()} | StartOptions], []]) of
- {ok, Pid} ->
- ?fcrt("open - ok", [{pid, Pid}]),
- call(Pid, {open, ip_comm, OpenOptions}, plain);
- Error1 ->
- ?fcrt("open - error", [{error1, Error1}]),
- Error1
- end
- catch
- throw:Error2 ->
- Error2
- end.
-%% </BACKWARD-COMPATIBILLITY>
-
-
-
-
-
%%--------------------------------------------------------------------------
%% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn}
%% | {error, eacct}
@@ -194,12 +173,24 @@ open(Host, Port, Flags) when is_integer(Port) andalso is_list(Flags) ->
%%
%% Description: Login with or without a supplied account name.
%%--------------------------------------------------------------------------
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string()) ->
+ 'ok' | {'error', Reason :: 'euser' | common_reason()}.
+
user(Pid, User, Pass) ->
call(Pid, {user, User, Pass}, atom).
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string(),
+ Acc :: string()) ->
+ 'ok' | {'error', Reason :: 'euser' | common_reason()}.
+
user(Pid, User, Pass, Acc) ->
call(Pid, {user, User, Pass, Acc}, atom).
+
%%--------------------------------------------------------------------------
%% account(Pid, Acc) -> ok | {error, eacct}
%% Pid = pid()
@@ -207,9 +198,14 @@ user(Pid, User, Pass, Acc) ->
%%
%% Description: Set a user Account.
%%--------------------------------------------------------------------------
+
+-spec account(Pid :: pid(), Acc :: string()) ->
+ 'ok' | {'error', Reason :: 'eacct' | common_reason()}.
+
account(Pid, Acc) ->
call(Pid, {account, Acc}, atom).
+
%%--------------------------------------------------------------------------
%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn}
%% Pid = pid()
@@ -217,19 +213,30 @@ account(Pid, Acc) ->
%%
%% Description: Get the current working directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec pwd(Pid :: pid()) ->
+ {'ok', Dir :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
pwd(Pid) ->
call(Pid, pwd, ctrl).
+
%%--------------------------------------------------------------------------
-%% lpwd(Pid) -> {ok, Dir} | {error, elogin}
+%% lpwd(Pid) -> {ok, Dir}
%% Pid = pid()
%% Dir = string()
%%
%% Description: Get the current working directory at local server.
%%--------------------------------------------------------------------------
+
+-spec lpwd(Pid :: pid()) ->
+ {'ok', Dir :: string()}.
+
lpwd(Pid) ->
call(Pid, lpwd, string).
+
%%--------------------------------------------------------------------------
%% cd(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
%% Pid = pid()
@@ -237,9 +244,14 @@ lpwd(Pid) ->
%%
%% Description: Change current working directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec cd(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
cd(Pid, Dir) ->
call(Pid, {cd, Dir}, atom).
+
%%--------------------------------------------------------------------------
%% lcd(Pid, Dir) -> ok | {error, epath}
%% Pid = pid()
@@ -247,9 +259,14 @@ cd(Pid, Dir) ->
%%
%% Description: Change current working directory for the local client.
%%--------------------------------------------------------------------------
+
+-spec lcd(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason()}.
+
lcd(Pid, Dir) ->
call(Pid, {lcd, Dir}, string).
+
%%--------------------------------------------------------------------------
%% ls(Pid) -> Result
%% ls(Pid, <Dir>) -> Result
@@ -262,11 +279,22 @@ lcd(Pid, Dir) ->
%%
%% Description: Returns a list of files in long format.
%%--------------------------------------------------------------------------
+
+-spec ls(Pid :: pid()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
ls(Pid) ->
ls(Pid, "").
+
+-spec ls(Pid :: pid(), Dir :: string()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
ls(Pid, Dir) ->
call(Pid, {dir, long, Dir}, string).
+
%%--------------------------------------------------------------------------
%% nlist(Pid) -> Result
%% nlist(Pid, Pathname) -> Result
@@ -279,21 +307,37 @@ ls(Pid, Dir) ->
%%
%% Description: Returns a list of files in short format
%%--------------------------------------------------------------------------
+
+-spec nlist(Pid :: pid()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
nlist(Pid) ->
nlist(Pid, "").
+
+-spec nlist(Pid :: pid(), Pathname :: string()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
nlist(Pid, Dir) ->
call(Pid, {dir, short, Dir}, string).
+
%%--------------------------------------------------------------------------
-%% rename(Pid, CurrFile, NewFile) -> ok | {error, epath} | {error, elogin}
-%% | {error, econn}
+%% rename(Pid, Old, New) -> ok | {error, epath} | {error, elogin}
+%% | {error, econn}
%% Pid = pid()
%% CurrFile = NewFile = string()
%%
%% Description: Rename a file at remote server.
%%--------------------------------------------------------------------------
-rename(Pid, CurrFile, NewFile) ->
- call(Pid, {rename, CurrFile, NewFile}, string).
+
+-spec rename(Pid :: pid(), Old :: string(), New :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+rename(Pid, Old, New) ->
+ call(Pid, {rename, Old, New}, string).
+
%%--------------------------------------------------------------------------
%% delete(Pid, File) -> ok | {error, epath} | {error, elogin} |
@@ -303,9 +347,14 @@ rename(Pid, CurrFile, NewFile) ->
%%
%% Description: Remove file at remote server.
%%--------------------------------------------------------------------------
+
+-spec delete(Pid :: pid(), File :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
delete(Pid, File) ->
call(Pid, {delete, File}, string).
+
%%--------------------------------------------------------------------------
%% mkdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
%% Pid = pid(),
@@ -313,9 +362,14 @@ delete(Pid, File) ->
%%
%% Description: Make directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec mkdir(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
mkdir(Pid, Dir) ->
call(Pid, {mkdir, Dir}, atom).
+
%%--------------------------------------------------------------------------
%% rmdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
%% Pid = pid(),
@@ -323,9 +377,14 @@ mkdir(Pid, Dir) ->
%%
%% Description: Remove directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec rmdir(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
rmdir(Pid, Dir) ->
call(Pid, {rmdir, Dir}, atom).
+
%%--------------------------------------------------------------------------
%% type(Pid, Type) -> ok | {error, etype} | {error, elogin} | {error, econn}
%% Pid = pid()
@@ -333,23 +392,41 @@ rmdir(Pid, Dir) ->
%%
%% Description: Set transfer type.
%%--------------------------------------------------------------------------
+
+-spec type(Pid :: pid(), Type :: ascii | binary) ->
+ 'ok' |
+ {'error', Reason :: 'etype' | restriction_reason() | common_reason()}.
+
type(Pid, Type) ->
call(Pid, {type, Type}, atom).
+
%%--------------------------------------------------------------------------
-%% recv(Pid, RemoteFileName <LocalFileName>) -> ok | {error, epath} |
+%% recv(Pid, RemoteFileName [, LocalFileName]) -> ok | {error, epath} |
%% {error, elogin} | {error, econn}
%% Pid = pid()
%% RemoteFileName = LocalFileName = string()
%%
%% Description: Transfer file from remote server.
%%--------------------------------------------------------------------------
+
+-spec recv(Pid :: pid(), RemoteFileName :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() |
+ common_reason() |
+ file_write_error_reason()}.
+
recv(Pid, RemotFileName) ->
recv(Pid, RemotFileName, RemotFileName).
+-spec recv(Pid :: pid(),
+ RemoteFileName :: string(),
+ LocalFileName :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
recv(Pid, RemotFileName, LocalFileName) ->
call(Pid, {recv, RemotFileName, LocalFileName}, atom).
+
%%--------------------------------------------------------------------------
%% recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, epath} | {error, elogin}
%% | {error, econn}
@@ -359,9 +436,16 @@ recv(Pid, RemotFileName, LocalFileName) ->
%%
%% Description: Transfer file from remote server into binary.
%%--------------------------------------------------------------------------
+
+-spec recv_bin(Pid :: pid(),
+ RemoteFile :: string()) ->
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
recv_bin(Pid, RemoteFile) ->
call(Pid, {recv_bin, RemoteFile}, bin).
+
%%--------------------------------------------------------------------------
%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
%% | {error, econn}
@@ -370,9 +454,15 @@ recv_bin(Pid, RemoteFile) ->
%%
%% Description: Start receive of chunks of remote file.
%%--------------------------------------------------------------------------
+
+-spec recv_chunk_start(Pid :: pid(),
+ RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
recv_chunk_start(Pid, RemoteFile) ->
call(Pid, {recv_chunk_start, RemoteFile}, atom).
+
%%--------------------------------------------------------------------------
%% recv_chunk(Pid, RemoteFile) -> ok | {ok, Bin} | {error, Reason}
%% Pid = pid()
@@ -380,24 +470,47 @@ recv_chunk_start(Pid, RemoteFile) ->
%%
%% Description: Transfer file from remote server into binary in chunks
%%--------------------------------------------------------------------------
+
+-spec recv_chunk(Pid :: pid()) ->
+ 'ok' |
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
recv_chunk(Pid) ->
call(Pid, recv_chunk, atom).
+
%%--------------------------------------------------------------------------
-%% send(Pid, LocalFileName <RemotFileName>) -> ok | {error, epath}
-%% | {error, elogin}
-%% | {error, econn}
+%% send(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
+%% | {error, econn}
%% Pid = pid()
%% LocalFileName = RemotFileName = string()
%%
%% Description: Transfer file to remote server.
%%--------------------------------------------------------------------------
+
+-spec send(Pid :: pid(), LocalFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send(Pid, LocalFileName) ->
send(Pid, LocalFileName, LocalFileName).
+-spec send(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send(Pid, LocalFileName, RemotFileName) ->
call(Pid, {send, LocalFileName, RemotFileName}, atom).
+
%%--------------------------------------------------------------------------
%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
%% | {error, enotbinary} | {error, econn}
@@ -407,11 +520,19 @@ send(Pid, LocalFileName, RemotFileName) ->
%%
%% Description: Transfer a binary to a remote file.
%%--------------------------------------------------------------------------
+
+-spec send_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
call(Pid, {send_bin, Bin, RemoteFile}, atom);
send_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
%% | {error, econn}
@@ -420,9 +541,14 @@ send_bin(_Pid, _Bin, _RemoteFile) ->
%%
%% Description: Start transfer of chunks to remote file.
%%--------------------------------------------------------------------------
+
+-spec send_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
send_chunk_start(Pid, RemoteFile) ->
call(Pid, {send_chunk_start, RemoteFile}, atom).
+
%%--------------------------------------------------------------------------
%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} |
%% {error, epath} | {error, econn}
@@ -431,9 +557,14 @@ send_chunk_start(Pid, RemoteFile) ->
%%
%% Description: Start append chunks of data to remote file.
%%--------------------------------------------------------------------------
+
+-spec append_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
append_chunk_start(Pid, RemoteFile) ->
call(Pid, {append_chunk_start, RemoteFile}, atom).
+
%%--------------------------------------------------------------------------
%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
%% | {error, echunk} | {error, econn}
@@ -442,11 +573,19 @@ append_chunk_start(Pid, RemoteFile) ->
%%
%% Purpose: Send chunk to remote file.
%%--------------------------------------------------------------------------
+
+-spec send_chunk(Pid :: pid(), Bin :: binary()) ->
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
+ common_reason()}.
+
send_chunk(Pid, Bin) when is_binary(Bin) ->
call(Pid, {transfer_chunk, Bin}, atom);
send_chunk(_Pid, _Bin) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
%% | {error, echunk} | {error, econn}
@@ -455,11 +594,19 @@ send_chunk(_Pid, _Bin) ->
%%
%% Description: Append chunk to remote file.
%%--------------------------------------------------------------------------
+
+-spec append_chunk(Pid :: pid(), Bin :: binary()) ->
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
+ common_reason()}.
+
append_chunk(Pid, Bin) when is_binary(Bin) ->
call(Pid, {transfer_chunk, Bin}, atom);
append_chunk(_Pid, _Bin) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
%% | {error, econn}
@@ -467,9 +614,17 @@ append_chunk(_Pid, _Bin) ->
%%
%% Description: End sending of chunks to remote file.
%%--------------------------------------------------------------------------
+
+-spec send_chunk_end(Pid :: pid()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send_chunk_end(Pid) ->
call(Pid, chunk_end, atom).
+
%%--------------------------------------------------------------------------
%% append_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
%% | {error, econn}
@@ -477,23 +632,47 @@ send_chunk_end(Pid) ->
%%
%% Description: End appending of chunks to remote file.
%%--------------------------------------------------------------------------
+
+-spec append_chunk_end(Pid :: pid()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
append_chunk_end(Pid) ->
call(Pid, chunk_end, atom).
+
%%--------------------------------------------------------------------------
-%% append(Pid, LocalFileName, RemotFileName) -> ok | {error, epath}
-%% | {error, elogin} | {error, econn}
+%% append(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
+%% | {error, econn}
%% Pid = pid()
%% LocalFileName = RemotFileName = string()
%%
%% Description: Append the local file to the remote file
%%--------------------------------------------------------------------------
+
+-spec append(Pid :: pid(), LocalFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: 'epath' |
+ 'elogin' |
+ 'etnospc' |
+ 'epnospc' |
+ 'efnamena' | common_reason()}.
+
append(Pid, LocalFileName) ->
append(Pid, LocalFileName, LocalFileName).
+-spec append(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
append(Pid, LocalFileName, RemotFileName) ->
call(Pid, {append, LocalFileName, RemotFileName}, atom).
+
%%--------------------------------------------------------------------------
%% append_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
%% | {error, enotbinary} | {error, econn}
@@ -503,41 +682,48 @@ append(Pid, LocalFileName, RemotFileName) ->
%%
%% Purpose: Append a binary to a remote file.
%%--------------------------------------------------------------------------
+
+-spec append_bin(Pid :: pid(),
+ Bin :: binary(),
+ RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
call(Pid, {append_bin, Bin, RemoteFile}, atom);
append_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
-%% quote(Pid, Cmd) -> ok
+%% quote(Pid, Cmd) -> list()
%% Pid = pid()
%% Cmd = string()
%%
%% Description: Send arbitrary ftp command.
%%--------------------------------------------------------------------------
+
+-spec quote(Pid :: pid(), Cmd :: string()) -> list().
+
quote(Pid, Cmd) when is_list(Cmd) ->
call(Pid, {quote, Cmd}, atom).
+
%%--------------------------------------------------------------------------
%% close(Pid) -> ok
%% Pid = pid()
%%
%% Description: End the ftp session.
%%--------------------------------------------------------------------------
+
+-spec close(Pid :: pid()) -> 'ok'.
+
close(Pid) ->
cast(Pid, close),
ok.
-%%--------------------------------------------------------------------------
-%% force_active(Pid) -> ok
-%% Pid = pid()
-%%
-%% Description: Force connection to use active mode.
-%%--------------------------------------------------------------------------
-force_active(Pid) ->
- error_logger:info_report("This function is deprecated use the mode flag "
- "instead"),
- call(Pid, force_active, atom).
%%--------------------------------------------------------------------------
%% formaterror(Tag) -> string()
@@ -545,9 +731,13 @@ force_active(Pid) ->
%%
%% Description: Return diagnostics.
%%--------------------------------------------------------------------------
+
+-spec formaterror(Tag :: term()) -> string().
+
formaterror(Tag) ->
ftp_response:error_string(Tag).
+
info(Pid) ->
call(Pid, info, list).
@@ -848,10 +1038,12 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
Port = key_search(port, Opts, ?FTP_PORT),
Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
Progress = key_search(progress, Opts, ignore),
+ IpFamily = key_search(ipfamily, Opts, inet),
State2 = State#state{client = From,
mode = Mode,
- progress = progress(Progress)},
+ progress = progress(Progress),
+ ipfamily = IpFamily},
?fcrd("handle_call(open) -> setup ctrl connection with",
[{host, Host}, {port, Port}, {timeout, Timeout}]),
@@ -886,9 +1078,6 @@ handle_call({_, {open, ip_comm, Host, Opts}}, From, State) ->
{stop, normal, State2#state{client = undefined}}
end;
-handle_call({_, force_active}, _, State) ->
- {reply, ok, State#state{mode = active}};
-
handle_call({_, {user, User, Password}}, From,
#state{csock = CSock} = State) when (CSock =/= undefined) ->
handle_user(User, Password, "", State#state{client = From});
diff --git a/lib/inets/src/ftp/ftp_internal.hrl b/lib/inets/src/ftp/ftp_internal.hrl
index c3fa1e611d..148f8217ba 100644
--- a/lib/inets/src/ftp/ftp_internal.hrl
+++ b/lib/inets/src/ftp/ftp_internal.hrl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -21,7 +21,8 @@
-ifndef(ftp_internal_hrl).
-define(ftp_internal_hrl, true).
--include("inets_internal.hrl").
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+
-define(SERVICE, ftpc).
-define(fcri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
-define(fcrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile
index 184f45f589..0397b48ab2 100644
--- a/lib/inets/src/http_client/Makefile
+++ b/lib/inets/src/http_client/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2011. All Rights Reserved.
+# Copyright Ericsson AB 2005-2010. All Rights Reserved.
#
# 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
@@ -50,7 +50,7 @@ MODULES = \
httpc_handler_sup \
httpc_profile_sup \
httpc_response \
- httpc_request
+ httpc_request \
HRL_FILES = httpc_internal.hrl
@@ -60,20 +60,17 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
-# INETS FLAGS
-# ----------------------------------------------------
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
-
-
-# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-INETS_ERL_FLAGS += -I ../http_lib -I ../inets_app -pa ../../ebin
-ERL_COMPILE_FLAGS += $(INETS_ERL_FLAGS) \
- $(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
+include ../inets_app/inets.mk
+
+ERL_COMPILE_FLAGS += \
+ $(INETS_FLAGS) \
+ $(INETS_ERL_COMPILE_FLAGS) \
+ -I../../include \
+ -I../inets_app \
+ -I../http_lib
# ----------------------------------------------------
@@ -93,9 +90,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/http_client
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/http_client
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
release_docs_spec:
diff --git a/lib/inets/src/http_client/http.erl b/lib/inets/src/http_client/http.erl
index 7e1e90b50e..bbe2fec267 100644
--- a/lib/inets/src/http_client/http.erl
+++ b/lib/inets/src/http_client/http.erl
@@ -18,21 +18,38 @@
%%
%%
-%% Description:
-%%% This version of the HTTP/1.1 client supports:
-%%% - RFC 2616 HTTP 1.1 client part
-%%% - RFC 2818 HTTP Over TLS
+%%% Description: OLD API MODULE - USE httpc INSTEAD
-module(http).
-%% API
--export([request/1, request/2, request/4, request/5,
+-deprecated({request, 1, next_major_release}).
+-deprecated({request, 2, next_major_release}).
+-deprecated({request, 4, next_major_release}).
+-deprecated({request, 5, next_major_release}).
+-deprecated({cancel_request, 1, next_major_release}).
+-deprecated({cancel_request, 2, next_major_release}).
+-deprecated({set_option, 2, next_major_release}).
+-deprecated({set_option, 3, next_major_release}).
+-deprecated({set_options, 1, next_major_release}).
+-deprecated({set_options, 2, next_major_release}).
+-deprecated({verify_cookies, 2, next_major_release}).
+-deprecated({verify_cookies, 3, next_major_release}).
+-deprecated({cookie_header, 1, next_major_release}).
+-deprecated({cookie_header, 2, next_major_release}).
+-deprecated({stream_next, 1, next_major_release}).
+-deprecated({default_profile, 0, next_major_release}).
+
+%% Deprecated
+-export([
+ request/1, request/2, request/4, request/5,
cancel_request/1, cancel_request/2,
set_option/2, set_option/3,
set_options/1, set_options/2,
- verify_cookies/2, verify_cookies/3, cookie_header/1,
- cookie_header/2, stream_next/1,
- default_profile/0]).
+ verify_cookies/2, verify_cookies/3,
+ cookie_header/1, cookie_header/2,
+ stream_next/1,
+ default_profile/0
+ ]).
%%%=========================================================================
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index ca186f46a7..fe8e93af1f 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -48,7 +48,7 @@
stop_service/1,
services/0, service_info/1]).
--include("http_internal.hrl").
+-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
-define(DEFAULT_PROFILE, default).
@@ -64,17 +64,16 @@ default_profile() ->
profile_name(?DEFAULT_PROFILE) ->
httpc_manager;
+profile_name(Profile) when is_pid(Profile) ->
+ Profile;
profile_name(Profile) ->
- profile_name("httpc_manager_", Profile).
+ Prefix = lists:flatten(io_lib:format("~w_", [?MODULE])),
+ profile_name(Prefix, Profile).
profile_name(Prefix, Profile) when is_atom(Profile) ->
list_to_atom(Prefix ++ atom_to_list(Profile));
-profile_name(Prefix, Profile) when is_pid(Profile) ->
- ProfileStr0 =
- string:strip(string:strip(erlang:pid_to_list(Profile), left, $<), right, $>),
- F = fun($.) -> $_; (X) -> X end,
- ProfileStr = [F(C) || C <- ProfileStr0],
- list_to_atom(Prefix ++ "pid_" ++ ProfileStr).
+profile_name(_Prefix, Profile) when is_pid(Profile) ->
+ Profile.
%%--------------------------------------------------------------------------
@@ -104,14 +103,22 @@ request(Url, Profile) ->
%% HTTPOptions - [HttpOption]
%% HTTPOption - {timeout, Time} | {connect_timeout, Time} |
%% {ssl, SSLOptions} | {proxy_auth, {User, Password}}
-%% Ssloptions = [SSLOption]
-%% SSLOption = {verify, code()} | {depth, depth()} | {certfile, path()} |
+%% Ssloptions = ssl_options() |
+%% {ssl, ssl_options()} |
+%% {ossl, ssl_options()} |
+%% {essl, ssl_options()}
+%% ssl_options() = [ssl_option()]
+%% ssl_option() = {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}
+%% Option - {sync, Boolean} |
+%% {body_format, BodyFormat} |
+%% {full_result, Boolean} |
+%% {stream, To} |
+%% {headers_as_is, Boolean}
%% StatusLine = {HTTPVersion, StatusCode, ReasonPhrase}</v>
%% HTTPVersion = string()
%% StatusCode = integer()
@@ -120,7 +127,10 @@ request(Url, Profile) ->
%% Header = {Field, Value}
%% Field = string()
%% Value = string()
-%% Body = string() | binary() - HTLM-code
+%% Body = string() | binary() | {fun(SendAcc) -> SendFunResult, SendAcc} |
+%% {chunkify, fun(SendAcc) -> SendFunResult, SendAcc} - HTLM-code
+%% SendFunResult = eof | {ok, iolist(), NewSendAcc}
+%% SendAcc = NewSendAcc = term()
%%
%% Description: Sends a HTTP-request. The function can be both
%% syncronus and asynchronous in the later case the function will
@@ -246,7 +256,7 @@ set_option(Key, Value, Profile) ->
%% Description: Store the cookies from <SetCookieHeaders>
%% in the cookie database
%% for the profile <Profile>. This function shall be used when the option
-%% cookie is set to verify.
+%% cookies is set to verify.
%%-------------------------------------------------------------------------
store_cookies(SetCookieHeaders, Url) ->
store_cookies(SetCookieHeaders, Url, default_profile()).
@@ -420,14 +430,33 @@ service_info(Pid) ->
handle_request(Method, Url,
{Scheme, UserInfo, Host, Port, Path, Query},
- Headers, ContentType, Body,
+ Headers0, ContentType, Body0,
HTTPOptions0, Options0, Profile) ->
- Started = http_util:timestamp(),
- NewHeaders = [{http_util:to_lower(Key), Val} || {Key, Val} <- Headers],
+ Started = http_util:timestamp(),
+ NewHeaders0 = [{http_util:to_lower(Key), Val} || {Key, Val} <- Headers0],
try
begin
+ ?hcrt("begin processing", [{started, Started},
+ {new_headers, NewHeaders0}]),
+
+ {NewHeaders, Body} =
+ case Body0 of
+ {chunkify, ProcessBody, Acc}
+ when is_function(ProcessBody, 1) ->
+ NewHeaders1 = ensure_chunked_encoding(NewHeaders0),
+ Body1 = {mk_chunkify_fun(ProcessBody), Acc},
+ {NewHeaders1, Body1};
+ {ProcessBody, _}
+ when is_function(ProcessBody, 1) ->
+ {NewHeaders0, Body0};
+ _ when is_list(Body0) orelse is_binary(Body0) ->
+ {NewHeaders0, Body0};
+ _ ->
+ throw({error, {bad_body, Body0}})
+ end,
+
HTTPOptions = http_options(HTTPOptions0),
Options = request_options(Options0),
Sync = proplists:get_value(sync, Options),
@@ -436,52 +465,84 @@ handle_request(Method, Url,
HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
Receiver = proplists:get_value(receiver, Options),
SocketOpts = proplists:get_value(socket_opts, Options),
- MaybeEscPath = maybe_url_encode(HTTPOptions, Path),
- MaybeEscQuery = maybe_url_encode(HTTPOptions, Query),
- AbsUri = maybe_url_encode(HTTPOptions, Url),
+ MaybeEscPath = maybe_encode_uri(HTTPOptions, Path),
+ MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query),
+ AbsUri = maybe_encode_uri(HTTPOptions, Url),
+
Request = #request{from = Receiver,
scheme = Scheme,
address = {Host, Port},
- path = MaybeEscPath,
- pquery = MaybeEscQuery,
+ path = MaybeEscPath,
+ pquery = MaybeEscQuery,
method = Method,
headers = HeadersRecord,
content = {ContentType, Body},
settings = HTTPOptions,
- abs_uri = AbsUri,
+ abs_uri = AbsUri,
userinfo = UserInfo,
stream = Stream,
- headers_as_is = headers_as_is(Headers, Options),
+ headers_as_is = headers_as_is(Headers0, Options),
socket_opts = SocketOpts,
started = Started},
+
case httpc_manager:request(Request, profile_name(Profile)) of
{ok, RequestId} ->
handle_answer(RequestId, Sync, Options);
{error, Reason} ->
+ ?hcrd("request failed", [{reason, Reason}]),
{error, Reason}
end
end
catch
error:{noproc, _} ->
+ ?hcrv("noproc", [{profile, Profile}]),
{error, {not_started, Profile}};
throw:Error ->
+ ?hcrv("throw", [{error, Error}]),
Error
end.
-maybe_url_encode(#http_options{url_encode = true}, URI) ->
+ensure_chunked_encoding(Hdrs) ->
+ Key = "transfer-encoding",
+ lists:keystore(Key, 1, Hdrs, {Key, "chunked"}).
+
+maybe_encode_uri(#http_options{url_encode = true}, URI) ->
http_uri:encode(URI);
-maybe_url_encode(_, URI) ->
+maybe_encode_uri(_, URI) ->
URI.
+mk_chunkify_fun(ProcessBody) ->
+ fun(eof_body) ->
+ eof;
+ (Acc) ->
+ case ProcessBody(Acc) of
+ eof ->
+ {ok, <<"0\r\n\r\n">>, eof_body};
+ {ok, Data, NewAcc} ->
+ Chunk = [
+ integer_to_list(iolist_size(Data), 16),
+ "\r\n",
+ Data,
+ "\r\n"],
+ {ok, Chunk, NewAcc}
+ end
+ end.
+
+
handle_answer(RequestId, false, _) ->
{ok, RequestId};
handle_answer(RequestId, true, Options) ->
receive
{http, {RequestId, saved_to_file}} ->
+ ?hcrt("received saved-to-file", [{request_id, RequestId}]),
{ok, saved_to_file};
{http, {RequestId, {_,_,_} = Result}} ->
+ ?hcrt("received answer", [{request_id, RequestId},
+ {result, Result}]),
return_answer(Options, Result);
{http, {RequestId, {error, Reason}}} ->
+ ?hcrt("received error", [{request_id, RequestId},
+ {reason, Reason}]),
{error, Reason}
end.
@@ -490,9 +551,7 @@ return_answer(Options, {{"HTTP/0.9",_,_}, _, BinBody}) ->
{ok, Body};
return_answer(Options, {StatusLine, Headers, BinBody}) ->
-
Body = maybe_format_body(BinBody, Options),
-
case proplists:get_value(full_result, Options, true) of
true ->
{ok, {StatusLine, Headers, Body}};
@@ -579,14 +638,16 @@ http_options_default() ->
(_) ->
error
end,
- AutoRedirectPost = fun(Value) when (Value =:= true) orelse
- (Value =:= false) ->
- {ok, Value};
- (_) ->
- error
- end,
+ AutoRedirectPost = boolfun(),
+
SslPost = fun(Value) when is_list(Value) ->
- {ok, Value};
+ {ok, {?HTTP_DEFAULT_SSL_KIND, Value}};
+ ({ssl, SslOptions}) when is_list(SslOptions) ->
+ {ok, {?HTTP_DEFAULT_SSL_KIND, SslOptions}};
+ ({ossl, SslOptions}) when is_list(SslOptions) ->
+ {ok, {ossl, SslOptions}};
+ ({essl, SslOptions}) when is_list(SslOptions) ->
+ {ok, {essl, SslOptions}};
(_) ->
error
end,
@@ -596,12 +657,8 @@ http_options_default() ->
(_) ->
error
end,
- RelaxedPost = fun(Value) when (Value =:= true) orelse
- (Value =:= false) ->
- {ok, Value};
- (_) ->
- error
- end,
+ RelaxedPost = boolfun(),
+
ConnTimeoutPost =
fun(Value) when is_integer(Value) andalso (Value >= 0) ->
{ok, Value};
@@ -610,33 +667,30 @@ http_options_default() ->
(_) ->
error
end,
-
- UrlDecodePost = fun(Value) when (Value =:= true) orelse
- (Value =:= false) ->
- {ok, Value};
- (_) ->
- error
- end,
+
+ UrlDecodePost = boolfun(),
[
- {version, {value, "HTTP/1.1"}, #http_options.version, VersionPost},
- {timeout, {value, ?HTTP_REQUEST_TIMEOUT}, #http_options.timeout, TimeoutPost},
- {autoredirect, {value, true}, #http_options.autoredirect, AutoRedirectPost},
- {ssl, {value, []}, #http_options.ssl, SslPost},
- {proxy_auth, {value, undefined}, #http_options.proxy_auth, ProxyAuthPost},
- {relaxed, {value, false}, #http_options.relaxed, RelaxedPost},
- %% this field has to be *after* the timeout field (as that field is used for the default value)
- {connect_timeout, {field, #http_options.timeout}, #http_options.connect_timeout, ConnTimeoutPost},
- {url_encode, {value, false}, #http_options.url_encode, UrlDecodePost}
+ {version, {value, "HTTP/1.1"}, #http_options.version, VersionPost},
+ {timeout, {value, ?HTTP_REQUEST_TIMEOUT}, #http_options.timeout, TimeoutPost},
+ {autoredirect, {value, true}, #http_options.autoredirect, AutoRedirectPost},
+ {ssl, {value, {?HTTP_DEFAULT_SSL_KIND, []}}, #http_options.ssl, SslPost},
+ {proxy_auth, {value, undefined}, #http_options.proxy_auth, ProxyAuthPost},
+ {relaxed, {value, false}, #http_options.relaxed, RelaxedPost},
+ {url_encode, {value, false}, #http_options.url_encode, UrlDecodePost},
+ %% this field has to be *after* the timeout option (as that field is used for the default value)
+ {connect_timeout, {field, #http_options.timeout}, #http_options.connect_timeout, ConnTimeoutPost}
].
+boolfun() ->
+ fun(Value) when (Value =:= true) orelse
+ (Value =:= false) ->
+ {ok, Value};
+ (_) ->
+ error
+ end.
request_options_defaults() ->
- VerifyBoolean =
- fun(Value) when ((Value =:= true) orelse (Value =:= false)) ->
- ok;
- (_) ->
- error
- end,
+ VerifyBoolean = boolfun(),
VerifySync = VerifyBoolean,
diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl
index 4d61f82b5a..69900bae65 100644
--- a/lib/inets/src/http_client/httpc_cookie.erl
+++ b/lib/inets/src/http_client/httpc_cookie.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% 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
@@ -18,12 +18,32 @@
%%
%% Description: Cookie handling according to RFC 2109
+%% The syntax for the Set-Cookie response header is
+%%
+%% set-cookie = "Set-Cookie:" cookies
+%% cookies = 1#cookie
+%% cookie = NAME "=" VALUE *(";" cookie-av)
+%% NAME = attr
+%% VALUE = value
+%% cookie-av = "Comment" "=" value
+%% | "Domain" "=" value
+%% | "Max-Age" "=" value
+%% | "Path" "=" value
+%% | "Secure"
+%% | "Version" "=" 1*DIGIT
+
+
+%% application:start(inets).
+%% httpc:set_options([{cookies, enabled}, {proxy, {{"www-proxy.ericsson.se",8080}, ["*.ericsson.se"]}}]).
+%% (catch httpc:request("http://www.expedia.com")).
+
-module(httpc_cookie).
-include("httpc_internal.hrl").
-export([open_db/3, close_db/1, insert/2, header/4, cookies/3]).
-export([reset_db/1, which_cookies/1]).
+-export([image_of/2, print/2]).
-record(cookie_db, {db, session_db}).
@@ -125,7 +145,7 @@ insert(#cookie_db{db = Db} = CookieDb,
name = Name,
path = Path,
max_age = 0}) ->
- ?hcrt("insert", [{domain, Key}, {name, Name}, {path, Path}]),
+ ?hcrt("insert cookie", [{domain, Key}, {name, Name}, {path, Path}]),
Pattern = #http_cookie{domain = Key, name = Name, path = Path, _ = '_'},
case dets:match_object(Db, Pattern) of
[] ->
@@ -136,7 +156,7 @@ insert(#cookie_db{db = Db} = CookieDb,
ok;
insert(#cookie_db{db = Db} = CookieDb,
#http_cookie{domain = Key, name = Name, path = Path} = Cookie) ->
- ?hcrt("insert", [{cookie, Cookie}]),
+ ?hcrt("insert cookie", [{cookie, Cookie}]),
Pattern = #http_cookie{domain = Key,
name = Name,
path = Path,
@@ -163,6 +183,7 @@ header(CookieDb, Scheme, {Host, _}, Path) ->
[] ->
{"cookie", ""};
Cookies ->
+ %% print_cookies("Header Cookies", Cookies),
{"cookie", cookies_to_string(Scheme, Cookies)}
end.
@@ -173,11 +194,20 @@ header(CookieDb, Scheme, {Host, _}, Path) ->
%%--------------------------------------------------------------------
cookies(Headers, RequestPath, RequestHost) ->
+
?hcrt("cookies", [{headers, Headers},
{request_path, RequestPath},
{request_host, RequestHost}]),
+
Cookies = parse_set_cookies(Headers, {RequestPath, RequestHost}),
- accept_cookies(Cookies, RequestPath, RequestHost).
+
+ %% print_cookies("Parsed Cookies", Cookies),
+
+ AcceptedCookies = accept_cookies(Cookies, RequestPath, RequestHost),
+
+ %% print_cookies("Accepted Cookies", AcceptedCookies),
+
+ AcceptedCookies.
%%--------------------------------------------------------------------
@@ -266,7 +296,8 @@ cookies_to_string(_, [], CookieStrs) ->
lists:flatten(lists:reverse(CookieStrs))
end;
-cookies_to_string(https, [#http_cookie{secure = true} = Cookie| Cookies],
+cookies_to_string(https = Scheme,
+ [#http_cookie{secure = true} = Cookie| Cookies],
CookieStrs) ->
Str = case Cookies of
[] ->
@@ -274,7 +305,7 @@ cookies_to_string(https, [#http_cookie{secure = true} = Cookie| Cookies],
_ ->
cookie_to_string(Cookie) ++ "; "
end,
- cookies_to_string(https, Cookies, [Str | CookieStrs]);
+ cookies_to_string(Scheme, Cookies, [Str | CookieStrs]);
cookies_to_string(Scheme, [#http_cookie{secure = true}| Cookies],
CookieStrs) ->
@@ -303,63 +334,54 @@ add_domain(Str, #http_cookie{domain_default = true}) ->
add_domain(Str, #http_cookie{domain = Domain}) ->
Str ++ "; $Domain=" ++ Domain.
-parse_set_cookies(OtherHeaders, DefaultPathDomain) ->
- SetCookieHeaders =
- lists:foldl(fun({"set-cookie", Value}, Acc) ->
- [string:tokens(Value, ",")| Acc];
- (_, Acc) ->
- Acc
- end, [], OtherHeaders),
-
- lists:flatten(
- lists:map(fun(CookieHeader) ->
- NewHeader = fix_netscape_cookie(CookieHeader, []),
- parse_set_cookie(NewHeader, [], DefaultPathDomain)
- end,
- SetCookieHeaders)).
-
-parse_set_cookie([], AccCookies, _) ->
- AccCookies;
-parse_set_cookie([CookieHeader | CookieHeaders], AccCookies,
- Defaults = {DefaultPath, DefaultDomain}) ->
- [CookieStr | Attributes] = case string:tokens(CookieHeader, ";") of
- [CStr] ->
- [CStr, ""];
- [CStr | Attr] ->
- [CStr, Attr]
- end,
- Pos = string:chr(CookieStr, $=),
- Name = string:substr(CookieStr, 1, Pos - 1),
- Value = string:substr(CookieStr, Pos + 1),
- Cookie = #http_cookie{name = string:strip(Name),
- value = string:strip(Value)},
- NewAttributes = parse_set_cookie_attributes(Attributes),
- TmpCookie = cookie_attributes(NewAttributes, Cookie),
+parse_set_cookies(CookieHeaders, DefaultPathDomain) ->
+ SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders],
+ Cookies = [parse_set_cookie(SetCookieHeader, DefaultPathDomain) ||
+ SetCookieHeader <- SetCookieHeaders],
+ %% print_cookies("Parsed Cookies", Cookies),
+ Cookies.
+
+parse_set_cookie(CookieHeader, {DefaultPath, DefaultDomain}) ->
+ %% io:format("Raw Cookie: ~s~n", [CookieHeader]),
+ Pos = string:chr(CookieHeader, $=),
+ Name = string:substr(CookieHeader, 1, Pos - 1),
+ {Value, Attrs} =
+ case string:substr(CookieHeader, Pos + 1) of
+ [$;|ValueAndAttrs] ->
+ {"", string:tokens(ValueAndAttrs, ";")};
+ ValueAndAttrs ->
+ [V | A] = string:tokens(ValueAndAttrs, ";"),
+ {V, A}
+ end,
+ Cookie = #http_cookie{name = string:strip(Name),
+ value = string:strip(Value)},
+ Attributes = parse_set_cookie_attributes(Attrs),
+ TmpCookie = cookie_attributes(Attributes, Cookie),
%% Add runtime defult values if necessary
- NewCookie = domain_default(path_default(TmpCookie, DefaultPath),
- DefaultDomain),
- parse_set_cookie(CookieHeaders, [NewCookie | AccCookies], Defaults).
-
-parse_set_cookie_attributes([]) ->
- [];
-parse_set_cookie_attributes([Attributes]) ->
- lists:map(fun(Attr) ->
- [AttrName, AttrValue] =
- case string:tokens(Attr, "=") of
- %% All attributes have the form
- %% Name=Value except "secure"!
- [Name] ->
- [Name, ""];
- [Name, Value] ->
- [Name, Value];
- %% Anything not expected will be
- %% disregarded
- _ ->
- ["Dummy",""]
- end,
- {http_util:to_lower(string:strip(AttrName)),
- string:strip(AttrValue)}
- end, Attributes).
+ NewCookie = domain_default(path_default(TmpCookie, DefaultPath),
+ DefaultDomain),
+ NewCookie.
+
+parse_set_cookie_attributes(Attributes) when is_list(Attributes) ->
+ [parse_set_cookie_attribute(A) || A <- Attributes].
+
+parse_set_cookie_attribute(Attribute) ->
+ {AName, AValue} =
+ case string:tokens(Attribute, "=") of
+ %% All attributes have the form
+ %% Name=Value except "secure"!
+ [Name] ->
+ {Name, ""};
+ [Name, Value] ->
+ {Name, Value};
+ %% Anything not expected will be
+ %% disregarded
+ _ ->
+ {"Dummy", ""}
+ end,
+ StrippedName = http_util:to_lower(string:strip(AName)),
+ StrippedValue = string:strip(AValue),
+ {StrippedName, StrippedValue}.
cookie_attributes([], Cookie) ->
Cookie;
@@ -375,10 +397,15 @@ cookie_attributes([{"max-age", Value}| Attributes], Cookie) ->
Cookie#http_cookie{max_age = ExpireTime});
%% Backwards compatibility with netscape cookies
cookie_attributes([{"expires", Value}| Attributes], Cookie) ->
- Time = http_util:convert_netscapecookie_date(Value),
- ExpireTime = calendar:datetime_to_gregorian_seconds(Time),
- cookie_attributes(Attributes,
- Cookie#http_cookie{max_age = ExpireTime});
+ try http_util:convert_netscapecookie_date(Value) of
+ Time ->
+ ExpireTime = calendar:datetime_to_gregorian_seconds(Time),
+ cookie_attributes(Attributes,
+ Cookie#http_cookie{max_age = ExpireTime})
+ catch
+ _:_ ->
+ cookie_attributes(Attributes, Cookie)
+ end;
cookie_attributes([{"path", Value}| Attributes], Cookie) ->
cookie_attributes(Attributes,
Cookie#http_cookie{path = Value});
@@ -404,7 +431,7 @@ path_default(#http_cookie{path = undefined} = Cookie, DefaultPath) ->
path_default(Cookie, _) ->
Cookie.
-%% Note: if the path is only / that / will be keept
+%% Note: if the path is only / that / will be kept
skip_right_most_slash("/") ->
"/";
skip_right_most_slash(Str) ->
@@ -476,20 +503,43 @@ path_sort(Cookies)->
lists:reverse(lists:keysort(#http_cookie.path, Cookies)).
-%% Informally, the Set-Cookie response header comprises the token
-%% Set-Cookie:, followed by a comma-separated list of one or more
-%% cookies. Netscape cookies expires attribute may also have a,
-%% in this case the header list will have been incorrectly split
-%% in parse_set_cookies/2 this functions fix that problem.
-fix_netscape_cookie([Cookie1, Cookie2 | Rest], Acc) ->
- case inets_regexp:match(string:to_lower(Cookie1), "expires=") of
- {_, _, _} ->
- fix_netscape_cookie(Rest, [Cookie1 ++ Cookie2 | Acc]);
- nomatch ->
- fix_netscape_cookie([Cookie2 |Rest], [Cookie1| Acc])
- end;
-fix_netscape_cookie([Cookie | Rest], Acc) ->
- fix_netscape_cookie(Rest, [Cookie | Acc]);
-
-fix_netscape_cookie([], Acc) ->
- Acc.
+%% print_cookies(Header, Cookies) ->
+%% io:format("~s:~n", [Header]),
+%% Prefix = " ",
+%% lists:foreach(fun(Cookie) -> print(Prefix, Cookie) end, Cookies).
+
+image_of(Prefix,
+ #http_cookie{domain = Domain,
+ domain_default = DomainDef,
+ name = Name,
+ value = Value,
+ comment = Comment,
+ max_age = MaxAge,
+ path = Path,
+ path_default = PathDef,
+ secure = Sec,
+ version = Version}) ->
+ lists:flatten(
+ io_lib:format("~sCookie ~s: "
+ "~n~s Value: ~p"
+ "~n~s Domain: ~p"
+ "~n~s DomainDef: ~p"
+ "~n~s Comment: ~p"
+ "~n~s MaxAge: ~p"
+ "~n~s Path: ~p"
+ "~n~s PathDef: ~p"
+ "~n~s Secure: ~p"
+ "~n~s Version: ~p",
+ [Prefix, Name,
+ Prefix, Value,
+ Prefix, Domain,
+ Prefix, DomainDef,
+ Prefix, Comment,
+ Prefix, MaxAge,
+ Prefix, Path,
+ Prefix, PathDef,
+ Prefix, Sec,
+ Prefix, Version])).
+
+print(Prefix, Cookie) when is_record(Cookie, http_cookie) ->
+ io:format("~s~n", [image_of(Prefix, Cookie)]).
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 5e5a9ce32e..587e24cc8d 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -22,17 +22,17 @@
-behaviour(gen_server).
+-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
--include("http_internal.hrl").
%%--------------------------------------------------------------------
%% Internal Application API
-export([
- start_link/2,
- connect_and_send/2,
+ start_link/4,
+ %% connect_and_send/2,
send/2,
- cancel/2,
+ cancel/3,
stream/3,
stream_next/1,
info/1
@@ -51,7 +51,7 @@
-record(state,
{
request, % #request{}
- session, % #tcp_session{}
+ session, % #session{}
status_line, % {Version, StatusCode, ReasonPharse}
headers, % #http_response_h{}
body, % binary()
@@ -94,13 +94,9 @@
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
-start_link(Options, ProfileName) ->
- Args = [Options, ProfileName],
- gen_server:start_link(?MODULE, Args, []).
-
-connect_and_send(Request, HandlerPid) ->
- call({connect_and_send, Request}, HandlerPid).
-
+start_link(Parent, Request, Options, ProfileName) ->
+ {ok, proc_lib:start_link(?MODULE, init, [[Parent, Request, Options,
+ ProfileName]])}.
%%--------------------------------------------------------------------
%% Function: send(Request, Pid) -> ok
@@ -122,8 +118,8 @@ send(Request, Pid) ->
%% Description: Cancels a request. Intended to be called by the httpc
%% manager process.
%%--------------------------------------------------------------------
-cancel(RequestId, Pid) ->
- cast({cancel, RequestId}, Pid).
+cancel(RequestId, Pid, From) ->
+ cast({cancel, RequestId, From}, Pid).
%%--------------------------------------------------------------------
@@ -177,8 +173,8 @@ stream(BodyPart, Request = #request{stream = Self}, Code)
stream(BodyPart, Request = #request{stream = Self}, 404)
when (Self =:= self) orelse (Self =:= {self, once}) ->
?hcrt("stream - self with 404", [{stream, Self}]),
- httpc_response:send(Request#request.from,
- {Request#request.id, stream, BodyPart}),
+ httpc_response:send(Request#request.from,
+ {Request#request.id, stream, BodyPart}),
{<<>>, Request};
%% Stream to file
@@ -229,16 +225,27 @@ stream(BodyPart, Request,_) -> % only 200 and 206 responses can be streamed
%% but we do not want that so errors will be handled by the process
%% sending an init_error message to itself.
%%--------------------------------------------------------------------
-init([Options, ProfileName]) ->
- ?hcrv("init - starting", [{options, Options}, {profile, ProfileName}]),
+init([Parent, Request, Options, ProfileName]) ->
process_flag(trap_exit, true),
- handle_verbose(Options#options.verbose),
- State = #state{status = undefined,
- options = Options,
- profile_name = ProfileName},
- ?hcrd("init - started", []),
- {ok, State}.
+ %% Do not let initial tcp-connection block the manager-process
+ proc_lib:init_ack(Parent, self()),
+ handle_verbose(Options#options.verbose),
+ Address = handle_proxy(Request#request.address, Options#options.proxy),
+ {ok, State} =
+ case {Address /= Request#request.address, Request#request.scheme} of
+ {true, https} ->
+ Error = https_through_proxy_is_not_currently_supported,
+ self() ! {init_error,
+ Error, httpc_response:error(Request, Error)},
+ {ok, #state{request = Request, options = Options,
+ status = ssl_tunnel}};
+ {_, _} ->
+ connect_and_send_first_request(Address, Request,
+ #state{options = Options,
+ profile_name = ProfileName})
+ end,
+ gen_server:enter_loop(?MODULE, [], State).
%%--------------------------------------------------------------------
%% Function: handle_call(Request, From, State) -> {reply, Reply, State} |
@@ -249,45 +256,9 @@ init([Options, ProfileName]) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling call messages
%%--------------------------------------------------------------------
-
-
-%% This is the first request, the reason the proc was started
-handle_call({connect_and_send, #request{address = Address0,
- scheme = Scheme} = Request},
- _From,
- #state{options = #options{proxy = Proxy},
- status = undefined,
- session = undefined} = State) ->
- ?hcrv("connect and send", [{address0, Address0}, {proxy, Proxy}]),
- Address = handle_proxy(Address0, Proxy),
- if
- ((Address =/= Address0) andalso (Scheme =:= https)) ->
- %% This is what we should do if and when ssl supports
- %% "socket upgrading"
- %%send_ssl_tunnel_request(Address, Request,
- %% #state{options = Options,
- %% status = ssl_tunnel});
- Reason = {failed_connecting,
- https_through_proxy_is_not_currently_supported},
- %% Send a reply to the original caller
- ErrorResponse = httpc_response:error(Request, Reason),
- httpc_response:send(Request#request.from, ErrorResponse),
- %% Reply to the manager
- ErrorReply = {error, Reason},
- {stop, normal, ErrorReply, State};
- true ->
- case connect_and_send_first_request(Address, Request, State) of
- {ok, NewState} ->
- {reply, ok, NewState};
- {stop, Error, NewState} ->
- {stop, normal, Error, NewState}
- end
- end;
-
handle_call(#request{address = Addr} = Request, _,
#state{status = Status,
- session = #tcp_session{socket = Socket,
- type = pipeline} = Session,
+ session = #session{type = pipeline} = Session,
timers = Timers,
options = #options{proxy = Proxy} = _Options,
profile_name = ProfileName} = State)
@@ -301,7 +272,7 @@ handle_call(#request{address = Addr} = Request, _,
Address = handle_proxy(Addr, Proxy),
- case httpc_request:send(Address, Request, Socket) of
+ case httpc_request:send(Address, Session, Request) of
ok ->
?hcrd("request sent", []),
@@ -320,10 +291,10 @@ handle_call(#request{address = Addr} = Request, _,
NewTimers = NewState#state.timers,
NewPipeline = queue:in(Request, State#state.pipeline),
NewSession =
- Session#tcp_session{queue_length =
- %% Queue + current
- queue:len(NewPipeline) + 1,
- client_close = ClientClose},
+ Session#session{queue_length =
+ %% Queue + current
+ queue:len(NewPipeline) + 1,
+ client_close = ClientClose},
httpc_manager:insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{pipeline = NewPipeline,
@@ -336,8 +307,8 @@ handle_call(#request{address = Addr} = Request, _,
cancel_timer(Timers#timers.queue_timer,
timeout_queue),
NewSession =
- Session#tcp_session{queue_length = 1,
- client_close = ClientClose},
+ Session#session{queue_length = 1,
+ client_close = ClientClose},
httpc_manager:insert_session(NewSession, ProfileName),
Relaxed =
(Request#request.settings)#http_options.relaxed,
@@ -357,8 +328,7 @@ handle_call(#request{address = Addr} = Request, _,
handle_call(#request{address = Addr} = Request, _,
#state{status = Status,
- session = #tcp_session{socket = Socket,
- type = keep_alive} = Session,
+ session = #session{type = keep_alive} = Session,
timers = Timers,
options = #options{proxy = Proxy} = _Options,
profile_name = ProfileName} = State)
@@ -370,7 +340,7 @@ handle_call(#request{address = Addr} = Request, _,
{status, Status}]),
Address = handle_proxy(Addr, Proxy),
- case httpc_request:send(Address, Request, Socket) of
+ case httpc_request:send(Address, Session, Request) of
ok ->
?hcrd("request sent", []),
@@ -389,10 +359,10 @@ handle_call(#request{address = Addr} = Request, _,
NewTimers = NewState#state.timers,
NewKeepAlive = queue:in(Request, State#state.keep_alive),
NewSession =
- Session#tcp_session{queue_length =
- %% Queue + current
- queue:len(NewKeepAlive) + 1,
- client_close = ClientClose},
+ Session#session{queue_length =
+ %% Queue + current
+ queue:len(NewKeepAlive) + 1,
+ client_close = ClientClose},
httpc_manager:insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{keep_alive = NewKeepAlive,
@@ -405,8 +375,8 @@ handle_call(#request{address = Addr} = Request, _,
cancel_timer(Timers#timers.queue_timer,
timeout_queue),
NewSession =
- Session#tcp_session{queue_length = 1,
- client_close = ClientClose},
+ Session#session{queue_length = 1,
+ client_close = ClientClose},
httpc_manager:insert_session(NewSession, ProfileName),
Relaxed =
(Request#request.settings)#http_options.relaxed,
@@ -447,25 +417,27 @@ handle_call(info, _, State) ->
%% handle_keep_alive_queue/2 on the other hand will just skip the
%% request as if it was never issued as in this case the request will
%% not have been sent.
-handle_cast({cancel, RequestId},
+handle_cast({cancel, RequestId, From},
#state{request = #request{id = RequestId} = Request,
profile_name = ProfileName,
canceled = Canceled} = State) ->
?hcrv("cancel current request", [{request_id, RequestId},
{profile, ProfileName},
{canceled, Canceled}]),
- httpc_manager:request_canceled(RequestId, ProfileName),
+ httpc_manager:request_canceled(RequestId, ProfileName, From),
?hcrv("canceled", []),
{stop, normal,
State#state{canceled = [RequestId | Canceled],
request = Request#request{from = answer_sent}}};
-handle_cast({cancel, RequestId},
+handle_cast({cancel, RequestId, From},
#state{profile_name = ProfileName,
+ request = #request{id = CurrId},
canceled = Canceled} = State) ->
- ?hcrv("cancel", [{request_id, RequestId},
+ ?hcrv("cancel", [{request_id, RequestId},
+ {curr_req_id, CurrId},
{profile, ProfileName},
{canceled, Canceled}]),
- httpc_manager:request_canceled(RequestId, ProfileName),
+ httpc_manager:request_canceled(RequestId, ProfileName, From),
?hcrv("canceled", []),
{noreply, State#state{canceled = [RequestId | Canceled]}};
@@ -543,7 +515,7 @@ handle_info({Proto, _Socket, Data},
{stop, normal, NewState}
end,
- ?hcri("data processed", []),
+ ?hcri("data processed", [{final_result, FinalResult}]),
FinalResult;
@@ -589,13 +561,13 @@ handle_info({ssl_closed, _}, State = #state{request = undefined}) ->
%%% Error cases
handle_info({tcp_closed, _}, #state{session = Session0} = State) ->
- Socket = Session0#tcp_session.socket,
- Session = Session0#tcp_session{socket = {remote_close, Socket}},
+ Socket = Session0#session.socket,
+ Session = Session0#session{socket = {remote_close, Socket}},
%% {stop, session_remotly_closed, State};
{stop, normal, State#state{session = Session}};
handle_info({ssl_closed, _}, #state{session = Session0} = State) ->
- Socket = Session0#tcp_session.socket,
- Session = Session0#tcp_session{socket = {remote_close, Socket}},
+ Socket = Session0#session.socket,
+ Session = Session0#session{socket = {remote_close, Socket}},
%% {stop, session_remotly_closed, State};
{stop, normal, State#state{session = Session}};
handle_info({tcp_error, _, _} = Reason, State) ->
@@ -657,8 +629,9 @@ handle_info(timeout_queue, #state{timers = Timers} = State) ->
Timers#timers{queue_timer = undefined}}};
%% Setting up the connection to the server somehow failed.
-handle_info({init_error, _, ClientErrMsg},
+handle_info({init_error, Tag, ClientErrMsg},
State = #state{request = Request}) ->
+ ?hcrv("init error", [{tag, Tag}, {client_error, ClientErrMsg}]),
NewState = answer_request(Request, ClientErrMsg, State),
{stop, normal, NewState};
@@ -704,52 +677,56 @@ terminate(normal, #state{session = undefined}) ->
%% Init error sending, no session information has been setup but
%% there is a socket that needs closing.
terminate(normal,
- #state{request = Request,
- session = #tcp_session{id = undefined,
- socket = Socket}}) ->
- http_transport:close(socket_type(Request), Socket);
+ #state{session = #session{id = undefined} = Session}) ->
+ close_socket(Session);
%% Socket closed remotely
terminate(normal,
- #state{session = #tcp_session{socket = {remote_close, Socket},
- id = Id},
+ #state{session = #session{socket = {remote_close, Socket},
+ socket_type = SocketType,
+ id = Id},
profile_name = ProfileName,
- request = Request,
- timers = Timers,
- pipeline = Pipeline}) ->
+ request = Request,
+ timers = Timers,
+ pipeline = Pipeline,
+ keep_alive = KeepAlive} = State) ->
?hcrt("terminate(normal) - remote close",
[{id, Id}, {profile, ProfileName}]),
%% Clobber session
(catch httpc_manager:delete_session(Id, ProfileName)),
+ maybe_retry_queue(Pipeline, State),
+ maybe_retry_queue(KeepAlive, State),
+
%% Cancel timers
- #timers{request_timers = ReqTmrs, queue_timer = QTmr} = Timers,
- cancel_timer(QTmr, timeout_queue),
- lists:foreach(fun({_, Timer}) -> cancel_timer(Timer, timeout) end,
- ReqTmrs),
+ cancel_timers(Timers),
%% Maybe deliver answers to requests
- deliver_answers([Request | queue:to_list(Pipeline)]),
+ deliver_answer(Request),
%% And, just in case, close our side (**really** overkill)
- http_transport:close(socket_type(Request), Socket);
+ http_transport:close(SocketType, Socket);
-terminate(_, #state{session = #tcp_session{id = Id,
- socket = Socket,
- scheme = Scheme},
+terminate(Reason, #state{session = #session{id = Id,
+ socket = Socket,
+ socket_type = SocketType},
request = undefined,
profile_name = ProfileName,
timers = Timers,
pipeline = Pipeline,
keep_alive = KeepAlive} = State) ->
+ ?hcrt("terminate",
+ [{id, Id}, {profile, ProfileName}, {reason, Reason}]),
+
+ %% Clobber session
(catch httpc_manager:delete_session(Id, ProfileName)),
maybe_retry_queue(Pipeline, State),
maybe_retry_queue(KeepAlive, State),
cancel_timer(Timers#timers.queue_timer, timeout_queue),
- http_transport:close(socket_type(Scheme), Socket);
+ http_transport:close(SocketType, Socket);
terminate(Reason, #state{request = undefined}) ->
?hcrt("terminate", [{reason, Reason}]),
@@ -775,65 +752,55 @@ maybe_send_answer(#request{from = answer_sent}, _Reason, State) ->
maybe_send_answer(Request, Answer, State) ->
answer_request(Request, Answer, State).
-deliver_answers([]) ->
- ?hcrd("deliver answer done", []),
- ok;
-deliver_answers([#request{id = Id, from = From} = Request | Requests])
+deliver_answer(#request{id = Id, from = From} = Request)
when is_pid(From) ->
Response = httpc_response:error(Request, socket_closed_remotely),
?hcrd("deliver answer", [{id, Id}, {from, From}, {response, Response}]),
- httpc_response:send(From, Response),
- deliver_answers(Requests);
-deliver_answers([Request|Requests]) ->
+ httpc_response:send(From, Response);
+deliver_answer(Request) ->
?hcrd("skip deliver answer", [{request, Request}]),
- deliver_answers(Requests).
+ ok.
%%--------------------------------------------------------------------
%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
%% Purpose: Convert process state when code is changed
%%--------------------------------------------------------------------
-code_change(_, #state{request = Request, pipeline = Queue} = State,
- from_pre_5_3_5) ->
- Settings = new_http_options(Request#request.settings),
- NewRequest = Request#request{settings = Settings},
- NewQueue = new_queue(Queue, fun new_http_options/1),
- {ok, State#state{request = NewRequest, pipeline = NewQueue}};
-
-code_change(_, #state{request = Request, pipeline = Queue} = State,
- to_pre_5_3_5) ->
- Settings = old_http_options(Request#request.settings),
- NewRequest = Request#request{settings = Settings},
- NewQueue = new_queue(Queue, fun old_http_options/1),
- {ok, State#state{request = NewRequest, pipeline = NewQueue}};
+%% code_change(_, #state{request = Request, pipeline = Queue} = State,
+%% [{from, '5.0.1'}, {to, '5.0.2'}]) ->
+%% Settings = new_http_options(Request#request.settings),
+%% NewRequest = Request#request{settings = Settings},
+%% NewQueue = new_queue(Queue, fun new_http_options/1),
+%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
+
+%% code_change(_, #state{request = Request, pipeline = Queue} = State,
+%% [{from, '5.0.2'}, {to, '5.0.1'}]) ->
+%% Settings = old_http_options(Request#request.settings),
+%% NewRequest = Request#request{settings = Settings},
+%% NewQueue = new_queue(Queue, fun old_http_options/1),
+%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
code_change(_, State, _) ->
{ok, State}.
-new_http_options({http_options,
- Version, Timeout, AutoRedirect, SslOpts,
- ProxyAuth, Relaxed, ConnTimeout}) ->
- UrlEncoding = false,
- {http_options,
- Version, Timeout, AutoRedirect, SslOpts,
- ProxyAuth, Relaxed, ConnTimeout, UrlEncoding}.
-
-old_http_options({http_options,
- Version, TimeOut, AutoRedirect, SslOpts,
- ProxyAuth, Relaxed, ConnTimeout, _UrlEncode}) ->
- {http_options,
- Version, TimeOut, AutoRedirect, SslOpts,
- ProxyAuth, Relaxed, ConnTimeout}.
-
-new_queue(Queue, TransformSettings) ->
- List = queue:to_list(Queue),
- NewList =
- lists:map(fun(Request) ->
- Settings =
- TransformSettings(Request#request.settings),
- Request#request{settings = Settings}
- end, List),
- queue:from_list(NewList).
+%% new_http_options({http_options, TimeOut, AutoRedirect, SslOpts,
+%% Auth, Relaxed}) ->
+%% {http_options, "HTTP/1.1", TimeOut, AutoRedirect, SslOpts,
+%% Auth, Relaxed}.
+
+%% old_http_options({http_options, _, TimeOut, AutoRedirect,
+%% SslOpts, Auth, Relaxed}) ->
+%% {http_options, TimeOut, AutoRedirect, SslOpts, Auth, Relaxed}.
+
+%% new_queue(Queue, Fun) ->
+%% List = queue:to_list(Queue),
+%% NewList =
+%% lists:map(fun(Request) ->
+%% Settings =
+%% Fun(Request#request.settings),
+%% Request#request{settings = Settings}
+%% end, List),
+%% queue:from_list(NewList).
%%%--------------------------------------------------------------------
@@ -863,72 +830,72 @@ connect(SocketType, ToAddress,
inet6fb4 ->
Opts3 = [inet6 | Opts2],
case http_transport:connect(SocketType, ToAddress, Opts3, Timeout) of
- {error, Reason} when ((Reason =:= nxdomain) orelse
- (Reason =:= eafnosupport)) ->
+ {error, _Reason} = Error ->
Opts4 = [inet | Opts2],
- http_transport:connect(SocketType, ToAddress, Opts4, Timeout);
- Other ->
- Other
+ case http_transport:connect(SocketType,
+ ToAddress, Opts4, Timeout) of
+ {error, _} ->
+ %% Reply with the "original" error
+ Error;
+ OK ->
+ OK
+ end;
+ OK ->
+ OK
end;
_ ->
Opts3 = [IpFamily | Opts2],
http_transport:connect(SocketType, ToAddress, Opts3, Timeout)
end.
-
-connect_and_send_first_request(Address,
- #request{settings = Settings,
- headers = Headers,
- address = OrigAddress,
- scheme = Scheme} = Request,
- #state{options = Options} = State) ->
-
- ?hcrd("connect",
- [{address, Address}, {request, Request}, {options, Options}]),
+connect_and_send_first_request(Address, Request, #state{options = Options} = State) ->
SocketType = socket_type(Request),
- ConnTimeout = Settings#http_options.connect_timeout,
+ ConnTimeout = (Request#request.settings)#http_options.connect_timeout,
+ ?hcri("connect",
+ [{address, Address}, {request, Request}, {options, Options}]),
case connect(SocketType, Address, Options, ConnTimeout) of
{ok, Socket} ->
- ?hcrd("connected - now send first request", [{socket, Socket}]),
- case httpc_request:send(Address, Request, Socket) of
+ ClientClose =
+ httpc_request:is_client_closing(
+ Request#request.headers),
+ SessionType = httpc_manager:session_type(Options),
+ SocketType = socket_type(Request),
+ Session = #session{id = {Request#request.address, self()},
+ scheme = Request#request.scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ client_close = ClientClose,
+ type = SessionType},
+ ?hcri("connected - now send first request", [{socket, Socket}]),
+
+ case httpc_request:send(Address, Session, Request) of
ok ->
- ?hcrd("first request sent", []),
- ClientClose =
- httpc_request:is_client_closing(Headers),
- SessionType = httpc_manager:session_type(Options),
- Session =
- #tcp_session{id = {OrigAddress, self()},
- scheme = Scheme,
- socket = Socket,
- client_close = ClientClose,
- type = SessionType},
- TmpState =
- State#state{request = Request,
- session = Session,
- mfa = init_mfa(Request, State),
- status_line = init_status_line(Request),
- headers = undefined,
- body = undefined,
- status = new},
- ?hcrt("activate socket", []),
- activate_once(Session),
+ ?hcri("first request sent", []),
+ TmpState = State#state{request = Request,
+ session = Session,
+ mfa = init_mfa(Request, State),
+ status_line =
+ init_status_line(Request),
+ headers = undefined,
+ body = undefined,
+ status = new},
+ http_transport:setopts(SocketType,
+ Socket, [{active, once}]),
NewState = activate_request_timeout(TmpState),
{ok, NewState};
-
- {error, Reason} = Error ->
- ?hcrv("failed sending request", [{reason, Reason}]),
- {stop, Error,
- State#state{session = {send_failed, Reason},
- request = Request}}
+ {error, Reason} ->
+ self() ! {init_error, error_sending,
+ httpc_response:error(Request, Reason)},
+ {ok, State#state{request = Request,
+ session =
+ #session{socket = Socket}}}
end;
-
- {error, Reason} = Error ->
- ?hcri("connect failed", [{reason, Reason}]),
- {stop, Error, State#state{session = {connect_failed, Reason},
- request = Request}}
+ {error, Reason} ->
+ self() ! {init_error, error_connecting,
+ httpc_response:error(Request, Reason)},
+ {ok, State#state{request = Request}}
end.
-
handler_info(#state{request = Request,
session = Session,
status_line = _StatusLine,
@@ -958,21 +925,20 @@ handler_info(#state{request = Request,
?hcrt("handler info", [{request_info, RequestInfo}]),
%% Info about the current session/socket
- SessionType = Session#tcp_session.type,
- QueueLen = case Session#tcp_session.type of
+ SessionType = Session#session.type,
+ QueueLen = case SessionType of
pipeline ->
queue:len(Pipeline);
keep_alive ->
queue:len(KeepAlive)
end,
- Socket = Session#tcp_session.socket,
- Scheme = Session#tcp_session.scheme,
- SocketType = socket_type(Scheme),
+ Scheme = Session#session.scheme,
+ Socket = Session#session.socket,
+ SocketType = Session#session.socket_type,
?hcrt("handler info", [{session_type, SessionType},
{queue_length, QueueLen},
{scheme, Scheme},
- {socket_type, SocketType},
{socket, Socket}]),
SocketOpts = http_transport:getopts(SocketType, Socket),
@@ -1129,9 +1095,7 @@ handle_response(#state{request = Request,
?hcrd("handle response - continue", []),
%% Send request body
{_, RequestBody} = Request#request.content,
- http_transport:send(socket_type(Session#tcp_session.scheme),
- Session#tcp_session.socket,
- RequestBody),
+ send_raw(Session, RequestBody),
%% Wait for next response
activate_once(Session),
Relaxed = (Request#request.settings)#http_options.relaxed,
@@ -1171,12 +1135,12 @@ handle_response(#state{request = Request,
{ok, Msg, Data} ->
?hcrd("handle response - ok", []),
end_stream(StatusLine, Request),
- NewState = answer_request(Request, Msg, State),
+ NewState = maybe_send_answer(Request, Msg, State),
handle_queue(NewState, Data);
{stop, Msg} ->
?hcrd("handle response - stop", [{msg, Msg}]),
end_stream(StatusLine, Request),
- NewState = answer_request(Request, Msg, State),
+ NewState = maybe_send_answer(Request, Msg, State),
{stop, normal, NewState}
end.
@@ -1193,7 +1157,7 @@ handle_cookies(Headers, Request, #options{cookies = enabled}, ProfileName) ->
httpc_manager:store_cookies(Cookies, Request#request.address,
ProfileName).
-%% This request could not be pipelined or used as sequential keept alive
+%% This request could not be pipelined or used as sequential keep alive
%% queue
handle_queue(#state{status = close} = State, _) ->
{stop, normal, State};
@@ -1228,7 +1192,7 @@ handle_pipeline(#state{status = pipeline,
%% If a pipeline that has been idle for some time is not
%% closed by the server, the client may want to close it.
NewState = activate_queue_timeout(TimeOut, State),
- NewSession = Session#tcp_session{queue_length = 0},
+ NewSession = Session#session{queue_length = 0},
httpc_manager:insert_session(NewSession, ProfileName),
%% Note mfa will be initilized when a new request
%% arrives.
@@ -1246,13 +1210,14 @@ handle_pipeline(#state{status = pipeline,
%% See comment for handle_cast({cancel, RequestId})
{stop, normal,
State#state{request =
- NextRequest#request{from = answer_sent}}};
+ NextRequest#request{from = answer_sent},
+ pipeline = Pipeline}};
false ->
?hcrv("next request", [{request, NextRequest}]),
NewSession =
- Session#tcp_session{queue_length =
- %% Queue + current
- queue:len(Pipeline) + 1},
+ Session#session{queue_length =
+ %% Queue + current
+ queue:len(Pipeline) + 1},
httpc_manager:insert_session(NewSession, ProfileName),
Relaxed =
(NextRequest#request.settings)#http_options.relaxed,
@@ -1301,16 +1266,16 @@ handle_keep_alive_queue(
%% If a keep_alive session has been idle for some time is not
%% closed by the server, the client may want to close it.
NewState = activate_queue_timeout(TimeOut, State),
- NewSession = Session#tcp_session{queue_length = 0},
+ NewSession = Session#session{queue_length = 0},
httpc_manager:insert_session(NewSession, ProfileName),
%% Note mfa will be initilized when a new request
%% arrives.
{noreply,
- NewState#state{request = undefined,
- mfa = undefined,
+ NewState#state{request = undefined,
+ mfa = undefined,
status_line = undefined,
- headers = undefined,
- body = undefined
+ headers = undefined,
+ body = undefined
}
};
{{value, NextRequest}, KeepAlive} ->
@@ -1353,10 +1318,12 @@ case_insensitive_header(Str) when is_list(Str) ->
case_insensitive_header(Str) ->
Str.
-activate_once(#tcp_session{scheme = Scheme, socket = Socket}) ->
- SocketType = socket_type(Scheme),
+activate_once(#session{socket = Socket, socket_type = SocketType}) ->
http_transport:setopts(SocketType, Socket, [{active, once}]).
+close_socket(#session{socket = Socket, socket_type = SocketType}) ->
+ http_transport:close(SocketType, Socket).
+
activate_request_timeout(
#state{request = #request{timer = undefined} = Request} = State) ->
Timeout = (Request#request.settings)#http_options.timeout,
@@ -1389,7 +1356,7 @@ activate_queue_timeout(Time, State) ->
State#state{timers = #timers{queue_timer = Ref}}.
-is_pipeline_enabled_client(#tcp_session{type = pipeline}) ->
+is_pipeline_enabled_client(#session{type = pipeline}) ->
true;
is_pipeline_enabled_client(_) ->
false.
@@ -1402,7 +1369,7 @@ is_keep_alive_enabled_server("HTTP/1.0",
is_keep_alive_enabled_server(_,_) ->
false.
-is_keep_alive_connection(Headers, #tcp_session{client_close = ClientClose}) ->
+is_keep_alive_connection(Headers, #session{client_close = ClientClose}) ->
(not ((ClientClose) orelse httpc_response:is_server_closing(Headers))).
try_to_enable_pipeline_or_keep_alive(
@@ -1427,7 +1394,7 @@ try_to_enable_pipeline_or_keep_alive(
httpc_manager:insert_session(Session, ProfileName),
%% Make sure type is keep_alive in session
%% as it in this case might be pipeline
- NewSession = Session#tcp_session{type = keep_alive},
+ NewSession = Session#session{type = keep_alive},
State#state{status = keep_alive,
session = NewSession}
end;
@@ -1437,7 +1404,7 @@ try_to_enable_pipeline_or_keep_alive(
answer_request(#request{id = RequestId, from = From} = Request, Msg,
#state{timers = Timers, profile_name = ProfileName} = State) ->
- ?hcrt("answer request", [{request, Request}]),
+ ?hcrt("answer request", [{request, Request}, {msg, Msg}]),
httpc_response:send(From, Msg),
RequestTimers = Timers#timers.request_timers,
TimerRef =
@@ -1445,10 +1412,17 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg,
Timer = {RequestId, TimerRef},
cancel_timer(TimerRef, {timeout, Request#request.id}),
httpc_manager:request_done(RequestId, ProfileName),
+
State#state{request = Request#request{from = answer_sent},
timers =
Timers#timers{request_timers =
lists:delete(Timer, RequestTimers)}}.
+
+cancel_timers(#timers{request_timers = ReqTmrs, queue_timer = QTmr}) ->
+ cancel_timer(QTmr, timeout_queue),
+ CancelTimer = fun({_, Timer}) -> cancel_timer(Timer, timeout) end,
+ lists:foreach(CancelTimer, ReqTmrs).
+
cancel_timer(undefined, _) ->
ok;
cancel_timer(Timer, TimeoutMsg) ->
@@ -1562,11 +1536,11 @@ init_status_line(#request{settings = Settings}) ->
socket_type(#request{scheme = http}) ->
ip_comm;
socket_type(#request{scheme = https, settings = Settings}) ->
- {ssl, Settings#http_options.ssl};
-socket_type(http) ->
- ip_comm;
-socket_type(https) ->
- {ssl, []}. %% Dummy value ok for ex setopts that does not use this value
+ Settings#http_options.ssl.
+%% socket_type(http) ->
+%% ip_comm;
+%% socket_type(https) ->
+%% {ssl1, []}. %% Dummy value ok for ex setopts that does not use this value
start_stream({_Version, _Code, _ReasonPhrase}, _Headers,
#request{stream = none} = Request) ->
@@ -1635,18 +1609,15 @@ end_stream(SL, R) ->
next_body_chunk(#state{request = #request{stream = {self, once}},
- once = once, session = Session} = State) ->
- http_transport:setopts(socket_type(Session#tcp_session.scheme),
- Session#tcp_session.socket,
- [{active, once}]),
+ once = once,
+ session = Session} = State) ->
+ activate_once(Session),
State#state{once = inactive};
next_body_chunk(#state{request = #request{stream = {self, once}},
once = inactive} = State) ->
State; %% Wait for user to call stream_next
next_body_chunk(#state{session = Session} = State) ->
- http_transport:setopts(socket_type(Session#tcp_session.scheme),
- Session#tcp_session.socket,
- [{active, once}]),
+ activate_once(Session),
State.
handle_verbose(verbose) ->
@@ -1661,66 +1632,28 @@ handle_verbose(_) ->
ok.
-%%% Normaly I do not comment out code, I throw it away. But this might
-%%% actually be used one day if ssl is improved.
-%% send_ssl_tunnel_request(Address, Request = #request{address = {Host, Port}},
-%% State) ->
-%% %% A ssl tunnel request is a special http request that looks like
-%% %% CONNECT host:port HTTP/1.1
-%% SslTunnelRequest = #request{method = connect, scheme = http,
-%% headers =
-%% #http_request_h{
-%% host = Host,
-%% address = Address,
-%% path = Host ++ ":",
-%% pquery = integer_to_list(Port),
-%% other = [{ "Proxy-Connection", "keep-alive"}]},
-%% Ipv6 = (State#state.options)#options.ipv6,
-%% SocketType = socket_type(SslTunnelRequest),
-%% case http_transport:connect(SocketType,
-%% SslTunnelRequest#request.address, Ipv6) of
-%% {ok, Socket} ->
-%% case httpc_request:send(Address, SslTunnelRequest, Socket) of
-%% ok ->
-%% Session = #tcp_session{id =
-%% {SslTunnelRequest#request.address,
-%% self()},
-%% scheme =
-%% SslTunnelRequest#request.scheme,
-%% socket = Socket},
-%% NewState = State#state{mfa =
-%% {httpc_response, parse,
-%% [State#state.max_header_size]},
-%% request = Request,
-%% session = Session},
-%% http_transport:setopts(socket_type(
-%% SslTunnelRequest#request.scheme),
-%% Socket,
-%% [{active, once}]),
-%% {ok, NewState};
-%% {error, Reason} ->
-%% self() ! {init_error, error_sending,
-%% httpc_response:error(Request, Reason)},
-%% {ok, State#state{request = Request,
-%% session = #tcp_session{socket =
-%% Socket}}}
-%% end;
-%% {error, Reason} ->
-%% self() ! {init_error, error_connecting,
-%% httpc_response:error(Request, Reason)},
-%% {ok, State#state{request = Request}}
-%% end.
-
-%% d(F) ->
-%% d(F, []).
-
-%% d(F, A) ->
-%% d(get(dbg), F, A).
-
-%% d(true, F, A) ->
-%% io:format(user, "~w:~w:" ++ F ++ "~n", [self(), ?MODULE | A]);
-%% d(_, _, _) ->
-%% ok.
+
+send_raw(#session{socket = Socket, socket_type = SocketType},
+ {ProcessBody, Acc}) when is_function(ProcessBody, 1) ->
+ ?hcrt("send raw", [{acc, Acc}]),
+ send_raw(SocketType, Socket, ProcessBody, Acc);
+send_raw(#session{socket = Socket, socket_type = SocketType}, Body) ->
+ http_transport:send(SocketType, Socket, Body).
+
+send_raw(SocketType, Socket, ProcessBody, Acc) ->
+ case ProcessBody(Acc) of
+ eof ->
+ ok;
+ {ok, Data, NewAcc} ->
+ DataBin = iolist_to_binary(Data),
+ ?hcrd("send", [{data, DataBin}]),
+ case http_transport:send(SocketType, Socket, DataBin) of
+ ok ->
+ send_raw(SocketType, Socket, ProcessBody, NewAcc);
+ Error ->
+ Error
+ end
+ end.
call(Msg, Pid) ->
@@ -1732,11 +1665,5 @@ call(Msg, Pid, Timeout) ->
cast(Msg, Pid) ->
gen_server:cast(Pid, Msg).
-
-%% to(To, Start) when is_integer(Start) andalso (Start >= 0) ->
-%% http_util:timeout(To, Start);
-%% to(To, _Start) ->
-%% http_util:timeout(To, t()).
-
t() ->
http_util:timestamp().
diff --git a/lib/inets/src/http_client/httpc_handler_sup.erl b/lib/inets/src/http_client/httpc_handler_sup.erl
index 2a69fd15d0..f7a0b014b3 100644
--- a/lib/inets/src/http_client/httpc_handler_sup.erl
+++ b/lib/inets/src/http_client/httpc_handler_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% 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
@@ -23,7 +23,7 @@
%% API
-export([start_link/0]).
--export([start_child/2]).
+-export([start_child/1]).
%% Supervisor callback
-export([init/1]).
@@ -34,11 +34,9 @@
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-start_child(Options, Profile) ->
- Args = [Options, Profile],
+start_child(Args) ->
supervisor:start_child(?MODULE, Args).
-
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index 7513aa2838..1d8a5b6a92 100644
--- a/lib/inets/src/http_client/httpc_internal.hrl
+++ b/lib/inets/src/http_client/httpc_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% 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
@@ -18,7 +18,11 @@
%%
%%
--include("inets_internal.hrl").
+-ifndef(httpc_internal_hrl).
+-define(httpc_internal_hrl, true).
+
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+
-define(SERVICE, httpc).
-define(hcri(Label, Data), ?report_important(Label, ?SERVICE, Data)).
-define(hcrv(Label, Data), ?report_verbose(Label, ?SERVICE, Data)).
@@ -57,7 +61,7 @@
%% integer() - ms before a connect times out
connect_timeout = ?HTTP_REQUEST_CTIMEOUT,
-
+
%% bool() - Use %-encoding rfc 2396
url_encode
@@ -108,13 +112,14 @@
}
).
--record(tcp_session,
+-record(session,
{
id, % {{Host, Port}, HandlerPid}
client_close, % true | false
scheme, % http (HTTP/TCP) | https (HTTP/SSL/TCP)
socket, % Open socket, used by connection
- queue_length = 1, % Current length of pipeline or keep alive queue
+ socket_type, % socket-type, used by connection
+ queue_length = 1, % Current length of pipeline or keep-alive queue
type % pipeline | keep_alive (wait for response before sending new request)
}).
@@ -142,3 +147,6 @@
%% path, % string()
%% q % query: string()
%% }).
+
+
+-endif. % -ifdef(httpc_internal_hrl).
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 4738517210..9015bf1ce2 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% 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
@@ -21,15 +21,15 @@
-behaviour(gen_server).
+-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
--include("http_internal.hrl").
%% Internal Application API
-export([
start_link/3,
request/2,
cancel_request/2,
- request_canceled/2,
+ request_canceled/3,
request_done/2,
retry_request/2,
redirect_request/2,
@@ -52,7 +52,7 @@
cancel = [], % [{RequestId, HandlerPid, ClientPid}]
handler_db, % ets() - Entry: #handler_info{}
cookie_db, % cookie_db()
- session_db, % ets() - Entry: #tcp_session{}
+ session_db, % ets() - Entry: #session{}
profile_name, % atom()
options = #options{}
}).
@@ -66,6 +66,7 @@
state % State of the handler: initiating | started | operational | canceled
}).
+-define(DELAY, 500).
%%====================================================================
%% Internal Application API
@@ -158,7 +159,8 @@ cancel_request(RequestId, ProfileName) ->
%% be called by the httpc handler process.
%%--------------------------------------------------------------------
-request_canceled(RequestId, ProfileName) ->
+request_canceled(RequestId, ProfileName, From) ->
+ gen_server:reply(From, ok),
cast(ProfileName, {request_canceled, RequestId}).
@@ -176,7 +178,7 @@ request_done(RequestId, ProfileName) ->
%%--------------------------------------------------------------------
%% Function: insert_session(Session, ProfileName) -> _
-%% Session - #tcp_session{}
+%% Session - #session{}
%% ProfileName - atom()
%%
%% Description: Inserts session information into the httpc manager
@@ -324,7 +326,7 @@ do_init(ProfileName, CookiesDir) ->
?hcrt("create session db", []),
SessionDbName = session_db_name(ProfileName),
ets:new(SessionDbName,
- [public, set, named_table, {keypos, #tcp_session.id}]),
+ [public, set, named_table, {keypos, #session.id}]),
%% Create handler db
?hcrt("create handler/request db", []),
@@ -355,44 +357,32 @@ do_init(ProfileName, CookiesDir) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call({request, Request}, _From, State) ->
- ?hcrv("request", [{request, Request}]),
+handle_call({request, Request}, _, State) ->
+ ?hcri("request", [{request, Request}]),
case (catch handle_request(Request, State)) of
- {ok, ReqId, NewState} ->
- {reply, {ok, ReqId}, NewState};
-
+ {reply, Msg, NewState} ->
+ {reply, Msg, NewState};
Error ->
- NewError = {error, {failed_process_request, Error}},
- {reply, NewError, State}
+ {stop, Error, httpc_response:error(Request, Error), State}
end;
-
-handle_call({cancel_request, RequestId}, From,
- #state{handler_db = HandlerDb} = State) ->
- ?hcrv("cancel_request", [{request_id, RequestId}]),
+
+handle_call({cancel_request, RequestId}, From, State) ->
+ ?hcri("cancel_request", [{request_id, RequestId}]),
case ets:lookup(State#state.handler_db, RequestId) of
[] ->
- ?hcrd("nothing to cancel", []),
- Reply = ok, %% Nothing to cancel
- {reply, Reply, State};
-
- [#handler_info{handler = Pid}] when is_pid(Pid) ->
- ?hcrd("found operational handler for this request",
- [{handler, Pid}]),
- httpc_handler:cancel(RequestId, Pid),
- {noreply, State#state{cancel =
- [{RequestId, Pid, From} |
- State#state.cancel]}};
-
- [#handler_info{starter = Pid, state = HandlerState}]
- when is_pid(Pid) ->
- ?hcri("found *initiating* handler for this request",
- [{starter, Pid}, {state, HandlerState}]),
- ets:update_element(HandlerDb, RequestId,
- {#handler_info.state, canceled}),
+ %% The request has allready compleated make sure
+ %% it is deliverd to the client process queue so
+ %% it can be thrown away by httpc:cancel_request
+ %% This delay is hopfully a temporary workaround.
+ %% Note that it will not not delay the manager,
+ %% only the client that called httpc:cancel_request
+ timer:apply_after(?DELAY, gen_server, reply, [From, ok]),
+ {noreply, State};
+ [{_, Pid, _}] ->
+ httpc_handler:cancel(RequestId, Pid, From),
{noreply, State#state{cancel =
- [{RequestId, Pid, From} |
+ [{RequestId, Pid, From} |
State#state.cancel]}}
-
end;
handle_call(reset_cookies, _, #state{cookie_db = CookieDb} = State) ->
@@ -437,43 +427,16 @@ handle_call(Req, From, #state{profile_name = ProfileName} = State) ->
%%--------------------------------------------------------------------
handle_cast({retry_or_redirect_request, {Time, Request}},
#state{profile_name = ProfileName} = State) ->
- ?hcrv("retry or redirect request", [{time, Time}, {request, Request}]),
- case timer:apply_after(Time, ?MODULE, retry_request,
- [Request, ProfileName]) of
- {ok, _} ->
- {noreply, State};
- {error, Reason} ->
- error_report(ProfileName,
- "failed scheduling retry/redirect request"
- "~n Time: ~p"
- "~n Request: ~p"
- "~n Reason: ~p", [Time, Request, Reason]),
- {noreply, State}
- end;
+ {ok, _} = timer:apply_after(Time, ?MODULE, retry_request, [Request, ProfileName]),
+ {noreply, State};
-handle_cast({retry_or_redirect_request, Request},
- #state{profile_name = Profile,
- handler_db = HandlerDb} = State) ->
- ?hcrv("retry or redirect request", [{request, Request}]),
+handle_cast({retry_or_redirect_request, Request}, State) ->
case (catch handle_request(Request, State)) of
- {ok, _, NewState} ->
+ {reply, {ok, _}, NewState} ->
{noreply, NewState};
-
Error ->
- ReqId = Request#request.id,
- error_report(Profile,
- "failed to retry or redirect request ~p"
- "~n Error: ~p", [ReqId, Error]),
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{from = From}] ->
- Error2 = httpc_response:error(Request, Error),
- httpc_response:send(From, Error2),
- ok;
-
- _ ->
- ok
- end,
- {noreply, State}
+ httpc_response:error(Request, Error),
+ {stop, Error, State}
end;
handle_cast({request_canceled, RequestId}, State) ->
@@ -482,7 +445,6 @@ handle_cast({request_canceled, RequestId}, State) ->
case lists:keysearch(RequestId, 1, State#state.cancel) of
{value, Entry = {RequestId, _, From}} ->
?hcrt("found in cancel", [{from, From}]),
- gen_server:reply(From, ok),
{noreply,
State#state{cancel = lists:delete(Entry, State#state.cancel)}};
Else ->
@@ -539,8 +501,6 @@ handle_cast(Msg, #state{profile_name = ProfileName} = State) ->
"recived unknown message"
"~n Msg: ~p", [Msg]),
{noreply, State}.
-
-
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
@@ -548,39 +508,17 @@ handle_cast(Msg, #state{profile_name = ProfileName} = State) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling all non call/cast messages
%%---------------------------------------------------------
-
-handle_info({started, StarterPid, ReqId, HandlerPid}, State) ->
- handle_started(StarterPid, ReqId, HandlerPid, State),
- {noreply, State};
-
-handle_info({connect_and_send, StarterPid, ReqId, HandlerPid, Res}, State) ->
- handle_connect_and_send(StarterPid, ReqId, HandlerPid, Res, State),
- {noreply, State};
-
-handle_info({failed_starting_handler, StarterPid, ReqId, Res}, State) ->
- handle_failed_starting_handler(StarterPid, ReqId, Res, State),
- {noreply, State};
-
-handle_info({'EXIT', Pid, Reason}, #state{handler_db = HandlerDb} = State) ->
- maybe_handle_terminating_starter(Pid, Reason, HandlerDb),
+handle_info({'EXIT', _, _}, State) ->
+ %% Handled in DOWN
{noreply, State};
-
handle_info({'DOWN', _, _, Pid, _}, State) ->
-
- %%
- %% Normally this should have been cleaned up already
- %% (when receiving {request_done, PequestId}), but
- %% just in case there is a glitch, cleanup anyway.
- %%
-
- Pattern = #handler_info{handler = Pid, _ = '_'},
- ets:match_delete(State#state.handler_db, Pattern),
+ ets:match_delete(State#state.handler_db, {'_', Pid, '_'}),
%% If there where any canceled request, handled by the
%% the process that now has terminated, the
%% cancelation can be viewed as sucessfull!
- NewCanceledList =
- lists:foldl(fun({_, HandlerPid, From} = Entry, Acc) ->
+ NewCanceldList =
+ lists:foldl(fun(Entry = {_, HandlerPid, From}, Acc) ->
case HandlerPid of
Pid ->
gen_server:reply(From, ok),
@@ -589,15 +527,13 @@ handle_info({'DOWN', _, _, Pid, _}, State) ->
Acc
end
end, State#state.cancel, State#state.cancel),
- {noreply, State#state{cancel = NewCanceledList}};
-
-handle_info(Info, #state{profile_name = ProfileName} = State) ->
- error_report(ProfileName,
- "received unknown info"
- "~n Info: ~p", [Info]),
+ {noreply, State#state{cancel = NewCanceldList}};
+handle_info(Info, State) ->
+ Report = io_lib:format("Unknown message in "
+ "httpc_manager:handle_info ~p~n", [Info]),
+ error_logger:error_report(Report),
{noreply, State}.
-
%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> _ (ignored by gen_server)
%% Description: Shutdown the httpc_handler
@@ -655,239 +591,95 @@ get_handler_info(Tab) ->
{Pid, State} <- Handlers2],
Handlers3.
-
-%%
-%% The request handler process is started asynchronously by a
-%% "starter process". When the handler has sucessfully been started,
-%% this message (started) is sent.
-%%
-
-handle_started(StarterPid, ReqId, HandlerPid,
- #state{profile_name = Profile,
- handler_db = HandlerDb}) ->
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{state = initiating} = HandlerInfo] ->
- ?hcri("received started ack for initiating handler", []),
- %% As a last resort, make sure we know when it exits,
- %% in case it forgets to notify us.
- %% We dont need to know the ref id?
- erlang:monitor(process, HandlerPid),
- HandlerInfo2 = HandlerInfo#handler_info{handler = HandlerPid,
- state = started},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- [#handler_info{state = State}] ->
- error_report(Profile,
- "unexpected (started) message for handler (~p) in state "
- "~p regarding request ~p - ignoring", [HandlerPid, State, ReqId]),
- ?hcri("received unexpected started message", [{state, State}]),
- ok;
-
- [] ->
- error_report(Profile,
- "unknown handler ~p (~p) started for request ~w - canceling",
- [HandlerPid, StarterPid, ReqId]),
- httpc_handler:cancel(ReqId, HandlerPid)
- end.
-
-
-%%
-%% The request handler process is started asynchronously by a
-%% "starter process". When that process terminates it sends
-%% one of two messages. These ara handled by the two functions
-%% below.
-%%
-
-handle_connect_and_send(_StarterPid, ReqId, HandlerPid, Result,
- #state{profile_name = Profile,
- handler_db = HandlerDb}) ->
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{state = started} = HandlerInfo] when Result =:= ok ->
- ?hcri("received connect-and-send ack for started handler", []),
- HandlerInfo2 = HandlerInfo#handler_info{starter = undefined,
- handler = HandlerPid,
- state = operational},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- [#handler_info{state = canceled} = HandlerInfo] when Result =:= ok ->
- ?hcri("received connect-and-send ack for canceled handler", []),
- httpc_handler:cancel(ReqId, HandlerPid),
- HandlerInfo2 = HandlerInfo#handler_info{starter = undefined,
- handler = HandlerPid},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- [#handler_info{state = State}] when Result =/= ok ->
- error_report(Profile,
- "handler (~p, ~w) failed to connect and/or "
- "send request ~p"
- "~n Result: ~p",
- [HandlerPid, State, ReqId, Result]),
- ?hcri("received connect-and-send error",
- [{result, Result}, {state, State}]),
- %% We don't need to send a response to the original caller
- %% because the handler already sent one in its terminate
- %% function.
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [] ->
- error_report(Profile,
- "handler (~p) successfully started "
- "for unknown request ~p => canceling",
- [HandlerPid, ReqId]),
- httpc_handler:cancel(ReqId, HandlerPid)
- end.
-
-
-handle_failed_starting_handler(_StarterPid, ReqId, Error,
- #state{profile_name = Profile,
- handler_db = HandlerDb}) ->
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{state = canceled}] ->
- error_report(Profile,
- "failed starting handler for request ~p"
- "~n Error: ~p", [ReqId, Error]),
- request_canceled(Profile, ReqId), % Fake signal from handler
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [#handler_info{from = From}] ->
- error_report(Profile,
- "failed starting handler for request ~p"
- "~n Error: ~p", [ReqId, Error]),
- Reason2 =
- case Error of
- {error, Reason} ->
- {failed_connecting, Reason};
- _ ->
- {failed_connecting, Error}
- end,
- DummyReq = #request{id = ReqId},
- httpc_response:send(From, httpc_response:error(DummyReq, Reason2)),
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [] ->
- error_report(Profile,
- "failed starting handler for unknown request ~p"
- "~n Error: ~p", [ReqId, Error]),
- ok
- end.
-
-
-maybe_handle_terminating_starter(MeybeStarterPid, Reason, HandlerDb) ->
- Pattern = #handler_info{starter = MeybeStarterPid, _ = '_'},
- case ets:match_object(HandlerDb, Pattern) of
- [#handler_info{id = ReqId, from = From, state = initiating}] ->
- %% The starter process crashed before it could start the
- %% the handler process, therefor we need to answer the
- %% original caller.
- ?hcri("starter process crashed bfore starting handler",
- [{starter, MeybeStarterPid}, {reason, Reason}]),
- Reason2 =
- case Reason of
- {error, Error} ->
- {failed_connecting, Error};
- _ ->
- {failed_connecting, Reason}
- end,
- DummyReq = #request{id = ReqId},
- httpc_response:send(From, httpc_response:error(DummyReq, Reason2)),
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [#handler_info{state = State} = HandlerInfo] ->
- %% The starter process crashed after the handler was started.
- %% The handler will answer to the original caller.
- ?hcri("starter process crashed after starting handler",
- [{starter, MeybeStarterPid}, {reason, Reason}, {state, State}]),
- HandlerInfo2 = HandlerInfo#handler_info{starter = undefined},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- _ ->
- ok
- end.
-
-
-%% -----
-%% Act as an HTTP/0.9 client that does not know anything
-%% about persistent connections
handle_request(#request{settings =
- #http_options{version = "HTTP/0.9"}} = Request0,
+ #http_options{version = "HTTP/0.9"}} = Request,
State) ->
- Request1 = handle_cookies(generate_request_id(Request0), State),
- Hdrs0 = Request1#request.headers,
- Hdrs1 = Hdrs0#http_request_h{connection = undefined},
- Request2 = Request1#request{headers = Hdrs1},
- create_handler_starter(Request2, State),
- {ok, Request2#request.id, State};
-
-%% -----
-%% Act as an HTTP/1.0 client that does not
-%% use persistent connections
+ %% Act as an HTTP/0.9 client that does not know anything
+ %% about persistent connections
+
+ NewRequest = handle_cookies(generate_request_id(Request), State),
+ NewHeaders =
+ (NewRequest#request.headers)#http_request_h{connection
+ = undefined},
+ start_handler(NewRequest#request{headers = NewHeaders}, State),
+ {reply, {ok, NewRequest#request.id}, State};
+
handle_request(#request{settings =
- #http_options{version = "HTTP/1.0"}} = Request0,
+ #http_options{version = "HTTP/1.0"}} = Request,
State) ->
- Request1 = handle_cookies(generate_request_id(Request0), State),
- Hdrs0 = Request1#request.headers,
- Hdrs1 = Hdrs0#http_request_h{connection = "close"},
- Request2 = Request1#request{headers = Hdrs1},
- create_handler_starter(Request2, State),
- {ok, Request2#request.id, State};
-
-
-%% -----
-handle_request(#request{method = Method,
- address = Address,
- scheme = Scheme} = Request0,
- #state{options = Opts} = State) ->
- Request1 = handle_cookies(generate_request_id(Request0), State),
- SessionType = session_type(Opts),
- case select_session(Method, Address, Scheme, SessionType, State) of
+ %% Act as an HTTP/1.0 client that does not
+ %% use persistent connections
+
+ NewRequest = handle_cookies(generate_request_id(Request), State),
+ NewHeaders =
+ (NewRequest#request.headers)#http_request_h{connection
+ = "close"},
+ start_handler(NewRequest#request{headers = NewHeaders}, State),
+ {reply, {ok, NewRequest#request.id}, State};
+
+handle_request(Request, State = #state{options = Options}) ->
+
+ NewRequest = handle_cookies(generate_request_id(Request), State),
+ SessionType = session_type(Options),
+ case select_session(Request#request.method,
+ Request#request.address,
+ Request#request.scheme, SessionType, State) of
{ok, HandlerPid} ->
- pipeline_or_keep_alive(Request1, HandlerPid, State);
+ pipeline_or_keep_alive(NewRequest, HandlerPid, State);
no_connection ->
- create_handler_starter(Request1, State);
- {no_session, OpenSessions}
- when OpenSessions < Opts#options.max_sessions ->
- create_handler_starter(Request1, State);
+ start_handler(NewRequest, State);
+ {no_session, OpenSessions} when OpenSessions
+ < Options#options.max_sessions ->
+ start_handler(NewRequest, State);
{no_session, _} ->
%% Do not start any more persistent connections
%% towards this server.
- Hdrs0 = Request1#request.headers,
- Hdrs1 = Hdrs0#http_request_h{connection = "close"},
- Request2 = Request1#request{headers = Hdrs1},
- create_handler_starter(Request2, State)
+ NewHeaders =
+ (NewRequest#request.headers)#http_request_h{connection
+ = "close"},
+ start_handler(NewRequest#request{headers = NewHeaders}, State)
end,
- {ok, Request1#request.id, State}.
+ {reply, {ok, NewRequest#request.id}, State}.
+
+
+start_handler(Request, State) ->
+ {ok, Pid} =
+ case is_inets_manager() of
+ true ->
+ httpc_handler_sup:start_child([whereis(httpc_handler_sup),
+ Request, State#state.options,
+ State#state.profile_name]);
+ false ->
+ httpc_handler:start_link(self(), Request, State#state.options,
+ State#state.profile_name)
+ end,
+ ets:insert(State#state.handler_db, {Request#request.id,
+ Pid, Request#request.from}),
+ erlang:monitor(process, Pid).
select_session(Method, HostPort, Scheme, SessionType,
#state{options = #options{max_pipeline_length = MaxPipe,
max_keep_alive_length = MaxKeepAlive},
session_db = SessionDb}) ->
- ?hcrd("select session", [{session_type, SessionType},
- {max_pipeline_length, MaxPipe},
+ ?hcrd("select session", [{session_type, SessionType},
+ {max_pipeline_length, MaxPipe},
{max_keep_alive_length, MaxKeepAlive}]),
case httpc_request:is_idempotent(Method) orelse
(SessionType =:= keep_alive) of
true ->
%% Look for handlers connecting to this host (HostPort)
- %% tcp_session with record name field (tcp_session) and
+ %% session with record name field (session) and
%% socket fields ignored. The fields id (part of: HostPort),
%% client_close, scheme and type specified.
%% The fields id (part of: HandlerPid) and queue_length
%% specified.
- Pattern = #tcp_session{id = {HostPort, '$1'},
- client_close = false,
- scheme = Scheme,
- socket = '_',
- queue_length = '$2',
- type = SessionType},
+ Pattern = #session{id = {HostPort, '$1'},
+ client_close = false,
+ scheme = Scheme,
+ queue_length = '$2',
+ type = SessionType,
+ _ = '_'},
%% {'_', {HostPort, '$1'}, false, Scheme, '_', '$2', SessionTyp},
Candidates = ets:match(SessionDb, Pattern),
?hcrd("select session", [{host_port, HostPort},
@@ -917,92 +709,17 @@ select_session(Candidates, Max) ->
?hcrd("select session - found one", [{handler, HandlerPid}]),
{ok, HandlerPid}
end.
-
-pipeline_or_keep_alive(#request{id = Id} = Request, HandlerPid, State) ->
- ?hcrd("pipeline of keep-alive", [{id, Id}, {handler, HandlerPid}]),
+
+pipeline_or_keep_alive(Request, HandlerPid, State) ->
case (catch httpc_handler:send(Request, HandlerPid)) of
ok ->
- ?hcrd("pipeline or keep-alive - successfully sent", []),
- Entry = #handler_info{id = Id,
- handler = HandlerPid,
- state = operational},
- ets:insert(State#state.handler_db, Entry);
-
- _ -> %% timeout pipelining failed
- ?hcrd("pipeline or keep-alive - failed sending -> "
- "start a new handler", []),
- create_handler_starter(Request, State)
+ ets:insert(State#state.handler_db, {Request#request.id,
+ HandlerPid,
+ Request#request.from});
+ _ -> %timeout pipelining failed
+ start_handler(Request, State)
end.
-
-create_handler_starter(#request{socket_opts = SocketOpts} = Request,
- #state{options = Options} = State)
- when is_list(SocketOpts) ->
- %% The user provided us with (override) socket options
- ?hcrt("create handler starter", [{socket_opts, SocketOpts}, {options, Options}]),
- Options2 = Options#options{socket_opts = SocketOpts},
- create_handler_starter(Request#request{socket_opts = undefined},
- State#state{options = Options2});
-
-create_handler_starter(#request{id = Id,
- from = From} = Request,
- #state{profile_name = ProfileName,
- options = Options,
- handler_db = HandlerDb} = _State) ->
- ?hcrv("create handler starter", [{id, Id}, {profile, ProfileName}]),
- IsInetsManager = is_inets_manager(),
- ManagerPid = self(),
- StarterFun =
- fun() ->
- ?hcrd("handler starter - start",
- [{id, Id},
- {profile, ProfileName},
- {inets_manager, IsInetsManager}]),
- Result1 =
- case IsInetsManager of
- true ->
- httpc_handler_sup:start_child(Options,
- ProfileName);
- false ->
- httpc_handler:start_link(Options,
- ProfileName)
- end,
- ?hcrd("handler starter - maybe connect and send",
- [{id, Id}, {profile, ProfileName}, {result, Result1}]),
- case Result1 of
- {ok, HandlerPid} ->
- StartedMessage =
- {started, self(), Id, HandlerPid},
- ManagerPid ! StartedMessage,
- Result2 = httpc_handler:connect_and_send(Request,
- HandlerPid),
- ?hcrd("handler starter - connected and sent",
- [{id, Id}, {profile, ProfileName},
- {handler, HandlerPid}, {result, Result2}]),
- ConnAndSendMessage =
- {connect_and_send,
- self(), Id, HandlerPid, Result2},
- ManagerPid ! ConnAndSendMessage;
- {error, Reason} ->
- StartFailureMessage =
- {failed_starting_handler, self(), Id, Reason},
- ManagerPid ! StartFailureMessage;
- _ ->
- StartFailureMessage =
- {failed_starting_handler, self(), Id, Result1},
- ManagerPid ! StartFailureMessage
- end
- end,
- Starter = erlang:spawn_link(StarterFun),
- ?hcrd("create handler starter - started", [{id, Id}, {starter, Starter}]),
- Entry = #handler_info{id = Id,
- starter = Starter,
- from = From,
- state = initiating},
- ets:insert(HandlerDb, Entry),
- ok.
-
-
is_inets_manager() ->
case get('$ancestors') of
[httpc_profile_sup | _] ->
@@ -1044,8 +761,6 @@ do_store_cookies([Cookie | Cookies], #state{cookie_db = CookieDb} = State) ->
ok = httpc_cookie:insert(CookieDb, Cookie),
do_store_cookies(Cookies, State).
-
-
session_db_name(ProfileName) ->
make_db_name(ProfileName, "__session_db").
@@ -1073,7 +788,6 @@ cast(ProfileName, Msg) ->
gen_server:cast(ProfileName, Msg).
-
get_proxy(Opts, #options{proxy = Default}) ->
proplists:get_value(proxy, Opts, Default).
@@ -1132,20 +846,6 @@ handle_verbose(trace) ->
handle_verbose(_) ->
ok.
-
error_report(Profile, F, A) ->
Report = io_lib:format("HTTPC-MANAGER<~p> " ++ F ++ "~n", [Profile | A]),
error_logger:error_report(Report).
-
-
-%% d(F) ->
-%% d(F, []).
-
-%% d(F, A) ->
-%% d(get(dbg), F, A).
-
-%% d(true, F, A) ->
-%% io:format(user, "~w:~w:" ++ F ++ "~n", [self(), ?MODULE | A]);
-%% d(_, _, _) ->
-%% ok.
-
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index 55e0af4b42..879053f0f2 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% 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
@@ -19,12 +19,13 @@
-module(httpc_request).
--include("http_internal.hrl").
+-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
%%% Internal API
-export([send/3, is_idempotent/1, is_client_closing/1]).
+
%%%=========================================================================
%%% Internal application API
%%%=========================================================================
@@ -39,10 +40,9 @@
%%
%% Description: Composes and sends a HTTP-request.
%%-------------------------------------------------------------------------
-send(SendAddr, #request{scheme = Scheme, socket_opts = SocketOpts} = Request,
- Socket)
+send(SendAddr, #session{socket = Socket, socket_type = SocketType},
+ #request{socket_opts = SocketOpts} = Request)
when is_list(SocketOpts) ->
- SocketType = socket_type(Scheme),
case http_transport:setopts(SocketType, Socket, SocketOpts) of
ok ->
send(SendAddr, Socket, SocketType,
@@ -50,8 +50,7 @@ send(SendAddr, #request{scheme = Scheme, socket_opts = SocketOpts} = Request,
{error, Reason} ->
{error, {setopts_failed, Reason}}
end;
-send(SendAddr, #request{scheme = Scheme} = Request, Socket) ->
- SocketType = socket_type(Scheme),
+send(SendAddr, #session{socket = Socket, socket_type = SocketType}, Request) ->
send(SendAddr, Socket, SocketType, Request).
send(SendAddr, Socket, SocketType,
@@ -80,36 +79,62 @@ send(SendAddr, Socket, SocketType,
{settings, HttpOptions},
{userinfo, UserInfo}]),
- TmpHeaders = handle_user_info(UserInfo, Headers),
+ TmpHdrs = handle_user_info(UserInfo, Headers),
- {TmpHeaders2, Body} =
- post_data(Method, TmpHeaders, Content, HeadersAsIs),
+ {TmpHdrs2, Body} = post_data(Method, TmpHdrs, Content, HeadersAsIs),
+
+ {NewHeaders, Uri} =
+ case Address of
+ SendAddr ->
+ {TmpHdrs2, Path ++ Query};
+ _Proxy ->
+ TmpHdrs3 = handle_proxy(HttpOptions, TmpHdrs2),
+ {TmpHdrs3, AbsUri}
+ end,
- {NewHeaders, Uri} = case Address of
- SendAddr ->
- {TmpHeaders2, Path ++ Query};
- _Proxy ->
- TmpHeaders3 =
- handle_proxy(HttpOptions, TmpHeaders2),
- {TmpHeaders3, AbsUri}
- end,
-
- FinalHeaders = case NewHeaders of
- HeaderList when is_list(HeaderList) ->
- http_headers(HeaderList, []);
- _ ->
- http_request:http_headers(NewHeaders)
- end,
+ FinalHeaders =
+ case NewHeaders of
+ HeaderList when is_list(HeaderList) ->
+ http_headers(HeaderList, []);
+ _ ->
+ http_request:http_headers(NewHeaders)
+ end,
Version = HttpOptions#http_options.version,
- Message = [method(Method), " ", Uri, " ",
- version(Version), ?CRLF,
- headers(FinalHeaders, Version), ?CRLF, Body],
+ do_send_body(SocketType, Socket, Method, Uri, Version, FinalHeaders, Body).
+
+
+do_send_body(SocketType, Socket, Method, Uri, Version, Headers,
+ {ProcessBody, Acc}) when is_function(ProcessBody, 1) ->
+ ?hcrt("send", [{acc, Acc}]),
+ case do_send_body(SocketType, Socket, Method, Uri, Version, Headers, []) of
+ ok ->
+ do_send_body(SocketType, Socket, ProcessBody, Acc);
+ Error ->
+ Error
+ end;
+do_send_body(SocketType, Socket, Method, Uri, Version, Headers, Body) ->
+ ?hcrt("create message", [{body, Body}]),
+ Message = [method(Method), " ", Uri, " ",
+ version(Version), ?CRLF,
+ headers(Headers, Version), ?CRLF, Body],
?hcrd("send", [{message, Message}]),
-
- http_transport:send(SocketType, Socket, lists:append(Message)).
+ http_transport:send(SocketType, Socket, Message).
+
+do_send_body(SocketType, Socket, ProcessBody, Acc) ->
+ case ProcessBody(Acc) of
+ eof ->
+ ok;
+ {ok, Data, NewAcc} ->
+ case http_transport:send(SocketType, Socket, Data) of
+ ok ->
+ do_send_body(SocketType, Socket, ProcessBody, NewAcc);
+ Error ->
+ Error
+ end
+ end.
%%-------------------------------------------------------------------------
@@ -162,7 +187,6 @@ is_client_closing(Headers) ->
%%%========================================================================
post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
when (Method =:= post) orelse (Method =:= put) ->
- ContentLength = body_length(Body),
NewBody = case Headers#http_request_h.expect of
"100-continue" ->
"";
@@ -171,14 +195,22 @@ post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
end,
NewHeaders = case HeadersAsIs of
- [] ->
- Headers#http_request_h{'content-type' =
- ContentType,
- 'content-length' =
- ContentLength};
- _ ->
- HeadersAsIs
- end,
+ [] ->
+ Headers#http_request_h{
+ 'content-type' = ContentType,
+ 'content-length' = case body_length(Body) of
+ undefined ->
+ % on upload streaming the caller must give a
+ % value to the Content-Length header
+ % (or use chunked Transfer-Encoding)
+ Headers#http_request_h.'content-length';
+ Len when is_list(Len) ->
+ Len
+ end
+ };
+ _ ->
+ HeadersAsIs
+ end,
{NewHeaders, NewBody};
@@ -191,7 +223,10 @@ body_length(Body) when is_binary(Body) ->
integer_to_list(size(Body));
body_length(Body) when is_list(Body) ->
- integer_to_list(length(Body)).
+ integer_to_list(length(Body));
+
+body_length({DataFun, _Acc}) when is_function(DataFun, 1) ->
+ undefined.
method(Method) ->
http_util:to_upper(atom_to_list(Method)).
@@ -209,10 +244,6 @@ headers(_, "HTTP/0.9") ->
headers(Headers, _) ->
Headers.
-socket_type(http) ->
- ip_comm;
-socket_type(https) ->
- {ssl, []}.
http_headers([], Headers) ->
lists:flatten(Headers);
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index df7d40a33e..207b96271c 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -19,10 +19,12 @@
-module(httpc_response).
--include("http_internal.hrl").
+-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
%% API
+%% Avoid warning for local function error/2 clashing with autoimported BIF.
+-compile({no_auto_import,[error/2]}).
-export([parse/1, result/2, send/2, error/2, is_server_closing/1,
stream_start/3]).
diff --git a/lib/inets/src/http_lib/Makefile b/lib/inets/src/http_lib/Makefile
index a715e3c9af..aaf3cfb995 100644
--- a/lib/inets/src/http_lib/Makefile
+++ b/lib/inets/src/http_lib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2011. All Rights Reserved.
+# Copyright Ericsson AB 2005-2010. All Rights Reserved.
#
# 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
@@ -56,24 +56,16 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
-# INETS FLAGS
-# ----------------------------------------------------
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
-
-
-# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-INETS_ERL_FLAGS += -I ../inets_app
-ifeq ($(WARN_UNUSED_WARS),true)
-ERL_COMPILE_FLAGS += +warn_unused_vars
-endif
+include ../inets_app/inets.mk
-ERL_COMPILE_FLAGS += $(INETS_ERL_FLAGS) \
- $(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
+ERL_COMPILE_FLAGS += \
+ $(INETS_FLAGS) \
+ $(INETS_ERL_COMPILE_FLAGS) \
+ -I../../include \
+ -I../inets_app
# ----------------------------------------------------
@@ -95,9 +87,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/http_lib
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/http_lib
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
release_docs_spec:
diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl
index 621bc68eae..57647438e9 100644
--- a/lib/inets/src/http_lib/http_chunk.erl
+++ b/lib/inets/src/http_lib/http_chunk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% 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
@@ -17,7 +17,8 @@
%% %CopyrightEnd%
%%
%% Description: Implements chunked transfer encoding see RFC2616 section
-%% 3.6.1
+%% 3.6.1
+
-module(http_chunk).
-include("http_internal.hrl").
@@ -28,6 +29,7 @@
%% little at a time on a socket.
-export([decode_size/1, ignore_extensions/1, decode_data/1, decode_trailer/1]).
+
%%%=========================================================================
%%% API
%%%=========================================================================
@@ -81,6 +83,9 @@ encode(Chunk) when is_binary(Chunk)->
HEXSize = list_to_binary(http_util:integer_to_hexlist(size(Chunk))),
<<HEXSize/binary, ?CR, ?LF, Chunk/binary, ?CR, ?LF>>;
+encode([<<>>]) ->
+ [];
+
encode(Chunk) when is_list(Chunk)->
HEXSize = http_util:integer_to_hexlist(erlang:iolist_size(Chunk)),
[HEXSize, ?CR, ?LF, Chunk, ?CR, ?LF].
@@ -88,6 +93,7 @@ encode(Chunk) when is_list(Chunk)->
encode_last() ->
<<$0, ?CR, ?LF, ?CR, ?LF >>.
+
%%-------------------------------------------------------------------------
%% handle_headers(HeaderRecord, ChunkedHeaders) -> NewHeaderRecord
%%
diff --git a/lib/inets/src/http_lib/http_internal.hrl b/lib/inets/src/http_lib/http_internal.hrl
index bb2e831727..2e924667c6 100644
--- a/lib/inets/src/http_lib/http_internal.hrl
+++ b/lib/inets/src/http_lib/http_internal.hrl
@@ -1,28 +1,37 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
--include("inets_internal.hrl").
+-ifndef(http_internal_hrl).
+-define(http_internal_hrl, true).
--define(HTTP_MAX_BODY_SIZE, nolimit).
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+
+-define(HTTP_MAX_BODY_SIZE, nolimit).
-define(HTTP_MAX_HEADER_SIZE, 10240).
--define(HTTP_MAX_URI_SIZE, nolimit).
+-define(HTTP_MAX_URI_SIZE, nolimit).
+
+-ifndef(HTTP_DEFAULT_SSL_KIND).
+%% -define(HTTP_DEFAULT_SSL_KIND, ossl).
+-define(HTTP_DEFAULT_SSL_KIND, essl).
+-endif. % -ifdef(HTTP_DEFAULT_SSL_KIND).
+
%%% Response headers
-record(http_response_h,{
@@ -106,3 +115,5 @@
'last-modified',
other=[] % list() - Key/Value list with other headers
}).
+
+-endif. % -ifdef(http_internal_hrl).
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index 587d215051..9b8190ebed 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -23,7 +23,7 @@
-export([
start/1,
connect/3, connect/4,
- listen/2, listen/3,
+ listen/2, listen/3, listen/4,
accept/2, accept/3,
close/2,
send/3,
@@ -33,10 +33,12 @@
peername/2, sockname/2,
resolve/0
]).
-
-export([negotiate/3]).
+-export([ipv4_name/1, ipv6_name/1]).
+
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+-include("http_internal.hrl").
--include("inets_internal.hrl").
-define(SERVICE, httpl).
-define(hlri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
-define(hlrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
@@ -55,6 +57,18 @@
%% Description: Makes sure inet_db or ssl is started.
%%-------------------------------------------------------------------------
start(ip_comm) ->
+ do_start_ip_comm();
+
+%% This is just for backward compatibillity
+start({ssl, _}) ->
+ do_start_ssl();
+start({ossl, _}) ->
+ do_start_ssl();
+start({essl, _}) ->
+ do_start_ssl().
+
+
+do_start_ip_comm() ->
case inet_db:start() of
{ok, _} ->
ok;
@@ -62,8 +76,9 @@ start(ip_comm) ->
ok;
Error ->
Error
- end;
-start({ssl, _}) ->
+ end.
+
+do_start_ssl() ->
case ssl:start() of
ok ->
ok;
@@ -95,28 +110,61 @@ connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout)
Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0],
?hlrt("connect using gen_tcp",
[{host, Host}, {port, Port}, {opts, Opts}, {timeout, Timeout}]),
- gen_tcp:connect(Host, Port, Opts, Timeout);
+ try gen_tcp:connect(Host, Port, Opts, Timeout) of
+ {ok, _} = OK ->
+ OK;
+ {error, _} = ERROR ->
+ ERROR
+ catch
+ exit:{badarg, _} ->
+ {error, {eoptions, Opts}};
+ exit:badarg ->
+ {error, {eoptions, Opts}}
+ end;
-connect({ssl, SslConfig}, {Host, Port}, _, Timeout) ->
- Opts = [binary, {active, false}] ++ SslConfig,
- ?hlrt("connect using ssl",
- [{host, Host}, {port, Port}, {ssl_config, SslConfig},
- {timeout, Timeout}]),
- ssl:connect(Host, Port, Opts, Timeout);
+%% Wrapper for backaward compatibillity
+connect({ssl, SslConfig}, Address, Opts, Timeout) ->
+ connect({?HTTP_DEFAULT_SSL_KIND, SslConfig}, Address, Opts, Timeout);
+
+connect({ossl, SslConfig}, {Host, Port}, _, Timeout) ->
+ Opts = [binary, {active, false}, {ssl_imp, old}] ++ SslConfig,
+ ?hlrt("connect using ossl",
+ [{host, Host},
+ {port, Port},
+ {ssl_config, SslConfig},
+ {timeout, Timeout}]),
+ case (catch ssl:connect(Host, Port, Opts, Timeout)) of
+ {'EXIT', Reason} ->
+ {error, {eoptions, Reason}};
+ {ok, _} = OK ->
+ OK;
+ {error, _} = ERROR ->
+ ERROR
+ end;
-connect({erl_ssl, SslConfig}, {Host, Port}, _, Timeout) ->
- Opts = [binary, {active, false}, {ssl_imp, new}] ++ SslConfig,
- ?hlrt("connect using erl_ssl",
- [{host, Host}, {port, Port}, {ssl_config, SslConfig},
- {timeout, Timeout}]),
- ssl:connect(Host, Port, Opts, Timeout).
+connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) ->
+ Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig,
+ ?hlrt("connect using essl",
+ [{host, Host},
+ {port, Port},
+ {ssl_config, SslConfig},
+ {timeout, Timeout}]),
+ case (catch ssl:connect(Host, Port, Opts, Timeout)) of
+ {'EXIT', Reason} ->
+ {error, {eoptions, Reason}};
+ {ok, _} = OK ->
+ OK;
+ {error, _} = ERROR ->
+ ERROR
+ end.
%%-------------------------------------------------------------------------
-%% listen(SocketType, Port) -> {ok, Socket} | {error, Reason}
+%% listen(SocketType, Addr, Port, Fd) -> {ok, Socket} | {error, Reason}
%% SocketType = ip_comm | {ssl, SSLConfig}
%% Port = integer()
-%% Socket = socket()
+%% Socket = socket()
+%% Fd = undefined | fd()
%%
%% Description: Sets up socket to listen on the port Port on the local
%% host using either gen_tcp or ssl. In the gen_tcp case the port
@@ -128,25 +176,45 @@ connect({erl_ssl, SslConfig}, {Host, Port}, _, Timeout) ->
listen(SocketType, Port) ->
listen(SocketType, undefined, Port).
-listen(ip_comm, Addr, Port) ->
- case (catch listen_ip_comm(Addr, Port)) of
+listen(ip_comm = _SocketType, Addr, Port) ->
+ listen_ip_comm(Addr, Port, undefined);
+
+%% Wrapper for backaward compatibillity
+listen({ssl, SSLConfig}, Addr, Port) ->
+ ?hlrt("listen (wrapper)",
+ [{addr, Addr},
+ {port, Port},
+ {ssl_config, SSLConfig}]),
+ listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port);
+
+listen({ossl, SSLConfig}, Addr, Port) ->
+ ?hlrt("listen (ossl)",
+ [{addr, Addr},
+ {port, Port},
+ {ssl_config, SSLConfig}]),
+ listen_ssl(Addr, Port, [{ssl_imp, old} | SSLConfig]);
+
+listen({essl, SSLConfig}, Addr, Port) ->
+ ?hlrt("listen (essl)",
+ [{addr, Addr},
+ {port, Port},
+ {ssl_config, SSLConfig}]),
+ listen_ssl(Addr, Port, [{ssl_imp, new}, {reuseaddr, true} | SSLConfig]).
+
+
+listen(ip_comm, Addr, Port, Fd) ->
+ listen_ip_comm(Addr, Port, Fd).
+
+listen_ip_comm(Addr, Port, Fd) ->
+ case (catch do_listen_ip_comm(Addr, Port, Fd)) of
{'EXIT', Reason} ->
{error, {exit, Reason}};
Else ->
Else
- end;
-
-listen({ssl, SSLConfig} = Ssl, Addr, Port) ->
- Opt = sock_opt(Ssl, Addr, SSLConfig),
- ssl:listen(Port, Opt);
-
-listen({erl_ssl, SSLConfig} = Ssl, Addr, Port) ->
- Opt = sock_opt(Ssl, Addr, SSLConfig),
- ssl:listen(Port, [{ssl_imp, new} | Opt]).
-
+ end.
-listen_ip_comm(Addr, Port) ->
- {NewPort, Opts, IpFamily} = get_socket_info(Addr, Port),
+do_listen_ip_comm(Addr, Port, Fd) ->
+ {NewPort, Opts, IpFamily} = get_socket_info(Addr, Port, Fd),
case IpFamily of
inet6fb4 ->
Opts2 = [inet6 | Opts],
@@ -156,7 +224,7 @@ listen_ip_comm(Addr, Port) ->
(Reason =:= eafnosupport)) ->
Opts3 = [inet | Opts],
?hlrt("ipv6 listen failed - try ipv4 instead",
- [{reason, Reason}, {port, NewPort}, {opts, Opts3}]),
+ [{reason, Reason}, {port, NewPort}, {opts, Opts3}]),
gen_tcp:listen(NewPort, Opts3);
%% This is when a given hostname has resolved to a
@@ -165,10 +233,11 @@ listen_ip_comm(Addr, Port) ->
{'EXIT', Reason} ->
Opts3 = [inet | Opts],
?hlrt("ipv6 listen exit - try ipv4 instead",
- [{reason, Reason}, {port, NewPort}, {opts, Opts3}]),
+ [{reason, Reason}, {port, NewPort}, {opts, Opts3}]),
gen_tcp:listen(NewPort, Opts3);
Other ->
+ ?hlrt("ipv6 listen done", [{other, Other}]),
Other
end;
_ ->
@@ -177,32 +246,74 @@ listen_ip_comm(Addr, Port) ->
gen_tcp:listen(NewPort, Opts2)
end.
+
+listen_ssl(Addr, Port, Opts0) ->
+ IpFamily = ipfamily_default(Addr, Port),
+ BaseOpts = [{backlog, 128}, {reuseaddr, true} | Opts0],
+ Opts = sock_opts(Addr, BaseOpts),
+ case IpFamily of
+ inet6fb4 ->
+ Opts2 = [inet6 | Opts],
+ ?hlrt("try ipv6 listen", [{opts, Opts2}]),
+ case (catch ssl:listen(Port, Opts2)) of
+ {error, Reason} when ((Reason =:= nxdomain) orelse
+ (Reason =:= eafnosupport)) ->
+ Opts3 = [inet | Opts],
+ ?hlrt("ipv6 listen failed - try ipv4 instead",
+ [{reason, Reason}, {opts, Opts3}]),
+ ssl:listen(Port, Opts3);
+
+ {'EXIT', Reason} ->
+ Opts3 = [inet | Opts],
+ ?hlrt("ipv6 listen exit - try ipv4 instead",
+ [{reason, Reason}, {opts, Opts3}]),
+ ssl:listen(Port, Opts3);
+
+ Other ->
+ ?hlrt("ipv6 listen done", [{other, Other}]),
+ Other
+ end;
+
+ _ ->
+ Opts2 = [IpFamily | Opts],
+ ?hlrt("listen", [{opts, Opts2}]),
+ ssl:listen(Port, Opts2)
+ end.
+
+
ipfamily_default(Addr, Port) ->
httpd_conf:lookup(Addr, Port, ipfamily, inet6fb4).
-get_socket_info(Addr, Port) ->
- Key = list_to_atom("httpd_" ++ integer_to_list(Port)),
- BaseOpts = [{backlog, 128}, {reuseaddr, true}],
+get_socket_info(Addr, Port, Fd0) ->
+ BaseOpts = [{backlog, 128}, {reuseaddr, true}],
IpFamilyDefault = ipfamily_default(Addr, Port),
- case init:get_argument(Key) of
- {ok, [[Value]]} ->
- {Fd, IpFamily} =
- case string:tokens(Value, [$|]) of
- [FdStr, IpFamilyStr] ->
- Fd0 = fd_of(FdStr),
- IpFamily0 = ip_family_of(IpFamilyStr),
- {Fd0, IpFamily0};
- [FdStr] ->
- {fd_of(FdStr), IpFamilyDefault};
- _ ->
- throw({error, {bad_descriptor, Value}})
- end,
- {0, sock_opt(ip_comm, Addr, [{fd, Fd} | BaseOpts]), IpFamily};
- error ->
- {Port, sock_opt(ip_comm, Addr, BaseOpts), IpFamilyDefault}
+ %% The presence of a file descriptor takes precedence
+ case get_fd(Port, Fd0, IpFamilyDefault) of
+ {Fd, IpFamily} ->
+ {0, sock_opts(Addr, [{fd, Fd} | BaseOpts]), IpFamily};
+ undefined ->
+ {Port, sock_opts(Addr, BaseOpts), IpFamilyDefault}
end.
+get_fd(Port, undefined = _Fd, IpFamilyDefault) ->
+ FdKey = list_to_atom("httpd_" ++ integer_to_list(Port)),
+ case init:get_argument(FdKey) of
+ {ok, [[Value]]} ->
+ case string:tokens(Value, [$|]) of
+ [FdStr, IpFamilyStr] ->
+ {fd_of(FdStr), ip_family_of(IpFamilyStr)};
+ [FdStr] ->
+ {fd_of(FdStr), IpFamilyDefault};
+ _ ->
+ throw({error, {bad_descriptor, Value}})
+ end;
+ error ->
+ undefined
+ end;
+get_fd(_Port, Fd, IpFamilyDefault) ->
+ {Fd, IpFamilyDefault}.
+
fd_of(FdStr) ->
case (catch list_to_integer(FdStr)) of
Fd when is_integer(Fd) ->
@@ -234,9 +345,17 @@ ip_family_of(IpFamilyStr) ->
%%-------------------------------------------------------------------------
accept(SocketType, ListenSocket) ->
accept(SocketType, ListenSocket, infinity).
+
accept(ip_comm, ListenSocket, Timeout) ->
gen_tcp:accept(ListenSocket, Timeout);
-accept({ssl,_SSLConfig}, ListenSocket, Timeout) ->
+
+%% Wrapper for backaward compatibillity
+accept({ssl, SSLConfig}, ListenSocket, Timeout) ->
+ accept({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, ListenSocket, Timeout);
+
+accept({ossl, _SSLConfig}, ListenSocket, Timeout) ->
+ ssl:transport_accept(ListenSocket, Timeout);
+accept({essl, _SSLConfig}, ListenSocket, Timeout) ->
ssl:transport_accept(ListenSocket, Timeout).
@@ -250,7 +369,15 @@ accept({ssl,_SSLConfig}, ListenSocket, Timeout) ->
%%-------------------------------------------------------------------------
controlling_process(ip_comm, Socket, NewOwner) ->
gen_tcp:controlling_process(Socket, NewOwner);
-controlling_process({ssl, _}, Socket, NewOwner) ->
+
+%% Wrapper for backaward compatibillity
+controlling_process({ssl, SSLConfig}, Socket, NewOwner) ->
+ controlling_process({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, NewOwner);
+
+controlling_process({ossl, _}, Socket, NewOwner) ->
+ ssl:controlling_process(Socket, NewOwner);
+
+controlling_process({essl, _}, Socket, NewOwner) ->
ssl:controlling_process(Socket, NewOwner).
@@ -265,9 +392,23 @@ controlling_process({ssl, _}, Socket, NewOwner) ->
setopts(ip_comm, Socket, Options) ->
?hlrt("ip_comm setopts", [{socket, Socket}, {options, Options}]),
inet:setopts(Socket, Options);
-setopts({ssl, _}, Socket, Options) ->
- ?hlrt("ssl setopts", [{socket, Socket}, {options, Options}]),
- ssl:setopts(Socket, Options).
+
+%% Wrapper for backaward compatibillity
+setopts({ssl, SSLConfig}, Socket, Options) ->
+ setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
+
+setopts({ossl, _}, Socket, Options) ->
+ ?hlrt("[o]ssl setopts", [{socket, Socket}, {options, Options}]),
+ Reason = (catch ssl:setopts(Socket, Options)),
+ ?hlrt("[o]ssl setopts result", [{reason, Reason}]),
+ Reason;
+
+
+setopts({essl, _}, Socket, Options) ->
+ ?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]),
+ Reason = (catch ssl:setopts(Socket, Options)),
+ ?hlrt("[e]ssl setopts result", [{reason, Reason}]),
+ Reason.
%%-------------------------------------------------------------------------
@@ -289,15 +430,27 @@ getopts(ip_comm, Socket, Options) ->
{error, _} ->
[]
end;
-getopts({ssl, _}, Socket, Options) ->
+
+%% Wrapper for backaward compatibillity
+getopts({ssl, SSLConfig}, Socket, Options) ->
+ getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
+
+getopts({ossl, _}, Socket, Options) ->
?hlrt("ssl getopts", [{socket, Socket}, {options, Options}]),
+ getopts_ssl(Socket, Options);
+
+getopts({essl, _}, Socket, Options) ->
+ ?hlrt("essl getopts", [{socket, Socket}, {options, Options}]),
+ getopts_ssl(Socket, Options).
+
+getopts_ssl(Socket, Options) ->
case ssl:getopts(Socket, Options) of
{ok, SocketOpts} ->
SocketOpts;
{error, _} ->
[]
end.
-
+
%%-------------------------------------------------------------------------
%% getstat(SocketType, Socket) -> socket_stats()
@@ -314,8 +467,15 @@ getstat(ip_comm = _SocketType, Socket) ->
{error, _} ->
[]
end;
-getstat({ssl, _} = _SocketType, _Socket) ->
- %% ?hlrt("ssl getstat", [{socket, Socket}]),
+
+%% Wrapper for backaward compatibillity
+getstat({ssl, SSLConfig}, Socket) ->
+ getstat({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
+
+getstat({ossl, _} = _SocketType, _Socket) ->
+ [];
+
+getstat({essl, _} = _SocketType, _Socket) ->
[].
@@ -328,7 +488,15 @@ getstat({ssl, _} = _SocketType, _Socket) ->
%%-------------------------------------------------------------------------
send(ip_comm, Socket, Message) ->
gen_tcp:send(Socket, Message);
-send({ssl, _}, Socket, Message) ->
+
+%% Wrapper for backaward compatibillity
+send({ssl, SSLConfig}, Socket, Message) ->
+ send({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Message);
+
+send({ossl, _}, Socket, Message) ->
+ ssl:send(Socket, Message);
+
+send({essl, _}, Socket, Message) ->
ssl:send(Socket, Message).
@@ -341,9 +509,18 @@ send({ssl, _}, Socket, Message) ->
%%-------------------------------------------------------------------------
close(ip_comm, Socket) ->
gen_tcp:close(Socket);
-close({ssl, _}, Socket) ->
+
+%% Wrapper for backaward compatibillity
+close({ssl, SSLConfig}, Socket) ->
+ close({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
+
+close({ossl, _}, Socket) ->
+ ssl:close(Socket);
+
+close({essl, _}, Socket) ->
ssl:close(Socket).
+
%%-------------------------------------------------------------------------
%% peername(SocketType, Socket) -> {Port, SockName}
%% SocketType = ip_comm | {ssl, _}
@@ -355,48 +532,28 @@ close({ssl, _}, Socket) ->
%% connection, usning either gen_tcp or ssl.
%%-------------------------------------------------------------------------
peername(ip_comm, Socket) ->
- case inet:peername(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, PeerName};
- {ok,{{A, B, C, D, E, F, G, H}, Port}} ->
- PeerName = http_util:integer_to_hexlist(A) ++ ":"++
- http_util:integer_to_hexlist(B) ++ ":" ++
- http_util:integer_to_hexlist(C) ++ ":" ++
- http_util:integer_to_hexlist(D) ++ ":" ++
- http_util:integer_to_hexlist(E) ++ ":" ++
- http_util:integer_to_hexlist(F) ++ ":" ++
- http_util:integer_to_hexlist(G) ++":"++
- http_util:integer_to_hexlist(H),
- {Port, PeerName};
- {error, Reason} ->
- Report = io_lib:format("~p Failed getting PeerName for socket ~p: "
- "~n Reason: ~p"
- "~n Socket stat: ~p"
- "~n IfList: ~p"
- "~n Fd: ~p"
- "~n",
- [self(),
- Socket,
- Reason,
- (catch inet:getstat(Socket)),
- (catch inet:getiflist(Socket)),
- (catch inet:getfd(Socket))
- ]),
- (catch error_logger:error_report(Report)),
- {-1, "unknown"}
- end;
+ do_peername(inet:peername(Socket));
-peername({ssl, _}, Socket) ->
- case ssl:peername(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, PeerName};
- {error, _} ->
- {-1, "unknown"}
- end.
+%% Wrapper for backaward compatibillity
+peername({ssl, SSLConfig}, Socket) ->
+ peername({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
+
+peername({ossl, _}, Socket) ->
+ do_peername(ssl:peername(Socket));
+
+peername({essl, _}, Socket) ->
+ do_peername(ssl:peername(Socket)).
+
+do_peername({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+ PeerName = ipv4_name(Addr),
+ {Port, PeerName};
+do_peername({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+ PeerName = ipv6_name(Addr),
+ {Port, PeerName};
+do_peername({error, _}) ->
+ {-1, "unknown"}.
%%-------------------------------------------------------------------------
@@ -410,34 +567,28 @@ peername({ssl, _}, Socket) ->
%% other end of connection, using either gen_tcp or ssl.
%%-------------------------------------------------------------------------
sockname(ip_comm, Socket) ->
- case inet:sockname(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- SockName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, SockName};
- {ok,{{A, B, C, D, E, F, G, H}, Port}} ->
- SockName = http_util:integer_to_hexlist(A) ++ ":"++
- http_util:integer_to_hexlist(B) ++ ":" ++
- http_util:integer_to_hexlist(C) ++ ":" ++
- http_util:integer_to_hexlist(D) ++ ":" ++
- http_util:integer_to_hexlist(E) ++ ":" ++
- http_util:integer_to_hexlist(F) ++ ":" ++
- http_util:integer_to_hexlist(G) ++":"++
- http_util:integer_to_hexlist(H),
- {Port, SockName};
- {error, _} ->
- {-1, "unknown"}
- end;
+ do_sockname(inet:sockname(Socket));
-sockname({ssl, _}, Socket) ->
- case ssl:sockname(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- SockName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, SockName};
- {error, _} ->
- {-1, "unknown"}
- end.
+%% Wrapper for backaward compatibillity
+sockname({ssl, SSLConfig}, Socket) ->
+ sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
+
+sockname({ossl, _}, Socket) ->
+ do_sockname(ssl:sockname(Socket));
+
+sockname({essl, _}, Socket) ->
+ do_sockname(ssl:sockname(Socket)).
+
+do_sockname({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+ SockName = ipv4_name(Addr),
+ {Port, SockName};
+do_sockname({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+ SockName = ipv6_name(Addr),
+ {Port, SockName};
+do_sockname({error, _}) ->
+ {-1, "unknown"}.
%%-------------------------------------------------------------------------
@@ -451,46 +602,75 @@ resolve() ->
Name.
+%%-------------------------------------------------------------------------
+%% ipv4_name(Ipv4Addr) -> string()
+%% ipv6_name(Ipv6Addr) -> string()
+%% Ipv4Addr = ip4_address()
+%% Ipv6Addr = ip6_address()
+%%
+%% Description: Returns the local hostname.
+%%-------------------------------------------------------------------------
+ipv4_name({A, B, C, D}) ->
+ integer_to_list(A) ++ "." ++
+ integer_to_list(B) ++ "." ++
+ integer_to_list(C) ++ "." ++
+ integer_to_list(D).
+
+ipv6_name({A, B, C, D, E, F, G, H}) ->
+ http_util:integer_to_hexlist(A) ++ ":"++
+ http_util:integer_to_hexlist(B) ++ ":" ++
+ http_util:integer_to_hexlist(C) ++ ":" ++
+ http_util:integer_to_hexlist(D) ++ ":" ++
+ http_util:integer_to_hexlist(E) ++ ":" ++
+ http_util:integer_to_hexlist(F) ++ ":" ++
+ http_util:integer_to_hexlist(G) ++ ":" ++
+ http_util:integer_to_hexlist(H).
+
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
+%% -- sock_opts --
%% Address any comes from directive: BindAddress "*"
-sock_opt(ip_comm, any = Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]);
-sock_opt(ip_comm, undefined, Opts) ->
- sock_opt2(Opts);
-sock_opt(_, any = _Addr, Opts) ->
- sock_opt2(Opts);
-sock_opt(_, undefined = _Addr, Opts) ->
- sock_opt2(Opts);
-sock_opt(_, {_,_,_,_} = Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]);
-sock_opt(ip_comm, Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]);
-sock_opt(_, Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]).
-
-sock_opt2(Opts) ->
+sock_opts(undefined, Opts) ->
+ sock_opts(Opts);
+sock_opts(any = Addr, Opts) ->
+ sock_opts([{ip, Addr} | Opts]);
+sock_opts(Addr, Opts) ->
+ sock_opts([{ip, Addr} | Opts]).
+
+sock_opts(Opts) ->
[{packet, 0}, {active, false} | Opts].
+
+%% -- negotiate --
negotiate(ip_comm,_,_) ->
+ ?hlrt("negotiate(ip_comm)", []),
ok;
-negotiate({ssl,_},Socket,Timeout) ->
- negotiate(Socket, Timeout);
-negotiate({erl_ssl, _}, Socket, Timeout) ->
- negotiate(Socket, Timeout).
-
-negotiate(Socket, Timeout) ->
+negotiate({ssl, SSLConfig}, Socket, Timeout) ->
+ ?hlrt("negotiate(ssl)", []),
+ negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout);
+negotiate({ossl, _}, Socket, Timeout) ->
+ ?hlrt("negotiate(ossl)", []),
+ negotiate_ssl(Socket, Timeout);
+negotiate({essl, _}, Socket, Timeout) ->
+ ?hlrt("negotiate(essl)", []),
+ negotiate_ssl(Socket, Timeout).
+
+negotiate_ssl(Socket, Timeout) ->
+ ?hlrt("negotiate_ssl", [{socket, Socket}, {timeout, Timeout}]),
case ssl:ssl_accept(Socket, Timeout) of
ok ->
ok;
- {error, Error} ->
- case lists:member(Error,
- [timeout,econnreset,esslaccept,esslerrssl]) of
+ {error, Reason} ->
+ ?hlrd("negotiate_ssl - accept failed", [{reason, Reason}]),
+ %% Look for "valid" error reasons
+ ValidReasons = [timeout, econnreset, esslaccept, esslerrssl],
+ case lists:member(Reason, ValidReasons) of
true ->
- {error,normal};
+ {error, normal};
false ->
- {error, Error}
+ {error, Reason}
end
end.
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index d03acff3a9..607475c359 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
-%%
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -36,7 +36,7 @@ parse(AbsURI) ->
{UserInfo, Host, Port, Path, Query} ->
{Scheme, UserInfo, Host, Port, Path, Query};
_ ->
- {error, {malformed_url, AbsURI}}
+ {error, {malformed_url, AbsURI}}
end
end.
@@ -44,7 +44,8 @@ encode(URI) ->
Reserved = sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?,
$#, $[, $], $<, $>, $\", ${, $}, $|,
$\\, $', $^, $%, $ ]),
- lists:append(lists:map(fun(Char) -> uri_encode(Char, Reserved) end, URI)).
+ %% lists:append(lists:map(fun(Char) -> uri_encode(Char, Reserved) end, URI)).
+ lists:append([uri_encode(Char, Reserved) || Char <- URI]).
decode(String) ->
do_decode(String).
@@ -75,7 +76,8 @@ parse_scheme(AbsURI) ->
end.
parse_uri_rest(Scheme, "//" ++ URIPart) ->
- {Authority, PathQuery} =
+
+ {Authority, PathQuery} =
case split_uri(URIPart, "/", URIPart, 1, 0) of
Split = {_, _} ->
Split;
@@ -87,7 +89,7 @@ parse_uri_rest(Scheme, "//" ++ URIPart) ->
{URIPart,""}
end
end,
-
+
{UserInfo, HostPort} = split_uri(Authority, "@", {"", Authority}, 1, 1),
{Host, Port} = parse_host_port(Scheme, HostPort),
{Path, Query} = parse_path_query(PathQuery),
@@ -97,7 +99,6 @@ parse_uri_rest(Scheme, "//" ++ URIPart) ->
parse_path_query(PathQuery) ->
{Path, Query} = split_uri(PathQuery, "\\?", {PathQuery, ""}, 1, 0),
{path(Path), Query}.
-
parse_host_port(Scheme,"[" ++ HostPort) -> %ipv6
DefaultPort = default_port(Scheme),
@@ -109,12 +110,12 @@ parse_host_port(Scheme, HostPort) ->
DefaultPort = default_port(Scheme),
{Host, Port} = split_uri(HostPort, ":", {HostPort, DefaultPort}, 1, 1),
{Host, int_port(Port)}.
-
+
split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
case inets_regexp:first_match(UriPart, SplitChar) of
{match, Match, _} ->
{string:substr(UriPart, 1, Match - SkipLeft),
- string:substr(UriPart, Match + SkipRight, length(UriPart))};
+ string:substr(UriPart, Match + SkipRight, length(UriPart))};
nomatch ->
NoMatchResult
end.
@@ -138,9 +139,9 @@ uri_encode(Char, Reserved) ->
case sets:is_element(Char, Reserved) of
true ->
[ $% | http_util:integer_to_hexlist(Char)];
- false ->
- [Char]
- end.
+ false ->
+ [Char]
+ end.
hex2dec(X) when (X>=$0) andalso (X=<$9) -> X-$0;
hex2dec(X) when (X>=$A) andalso (X=<$F) -> X-$A+10;
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index 5d8cb9365d..5b21170b78 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -24,9 +24,9 @@
convert_netscapecookie_date/1,
hexlist_to_integer/1, integer_to_hexlist/1,
convert_month/1,
- is_hostname/1,
- html_encode/1,
- timestamp/0, timeout/2
+ is_hostname/1,
+ timestamp/0, timeout/2,
+ html_encode/1
]).
@@ -104,6 +104,22 @@ convert_netscapecookie_date([_D,_A,_Y, $ ,
Sec = list_to_integer([S1,S2]),
{{Year,Month,Day},{Hour,Min,Sec}};
+%% Example: Tue Jan 01 08:00:01 2036 GMT
+convert_netscapecookie_date([_D,_A,_Y, $ ,
+ M,O,N, $ ,
+ D1,D2, $ ,
+ H1,H2, $:,
+ M1,M2, $:,
+ S1,S2, $ ,
+ Y1,Y2,Y3,Y4, $ |_Rest]) ->
+ Year = list_to_integer([Y1,Y2,Y3,Y4]),
+ Day = list_to_integer([D1,D2]),
+ Month = convert_month([M,O,N]),
+ Hour = list_to_integer([H1,H2]),
+ Min = list_to_integer([M1,M2]),
+ Sec = list_to_integer([S1,S2]),
+ {{Year,Month,Day},{Hour,Min,Sec}};
+
%% Sloppy...
convert_netscapecookie_date([_D,_A,_Y, $,, _SP,
D1,D2,_DA,
@@ -186,14 +202,13 @@ timeout(Timeout, Started) ->
_ ->
0
end.
-
+
html_encode(Chars) ->
Reserved = sets:from_list([$&, $<, $>, $\", $', $/]),
lists:append([char_to_html_entity(Char, Reserved) || Char <- Chars]).
-
%%%========================================================================
%%% Internal functions
%%%========================================================================
@@ -245,8 +260,8 @@ convert_to_ascii([Num | Reversed], Number)
char_to_html_entity(Char, Reserved) ->
case sets:is_element(Char, Reserved) of
- true ->
- "&#" ++ integer_to_list(Char) ++ ";";
- false ->
- [Char]
+ true ->
+ "&#" ++ integer_to_list(Char) ++ ";";
+ false ->
+ [Char]
end.
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index 3c36b384b8..55cc68dede 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2011. All Rights Reserved.
+# Copyright Ericsson AB 2005-2010. All Rights Reserved.
#
# 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
@@ -82,7 +82,7 @@ MODULES = \
mod_security \
mod_security_server
-HRL_FILES = httpd.hrl httpd_internal.hrl mod_auth.hrl
+HRL_FILES = httpd.hrl httpd_internal.hrl mod_auth.hrl
ERL_FILES = $(MODULES:%=%.erl)
@@ -90,24 +90,16 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
-# INETS FLAGS
-# ----------------------------------------------------
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
-
-
-# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-INETS_ERL_FLAGS += \
- -I ../http_lib \
- -I ../inets_app \
- -pa $(ERL_TOP)/lib/inets/ebin
+
+include ../inets_app/inets.mk
ERL_COMPILE_FLAGS += \
- $(INETS_ERL_FLAGS) \
$(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
+ $(INETS_ERL_COMPILE_FLAGS) \
+ -I../inets_app \
+ -I../http_lib \
# ----------------------------------------------------
@@ -129,9 +121,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/http_server
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/http_server
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
release_docs_spec:
diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl
index a88d002b03..93608dbf96 100644
--- a/lib/inets/src/http_server/httpd.erl
+++ b/lib/inets/src/http_server/httpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -24,54 +24,24 @@
-include("httpd.hrl").
--deprecated({start, 0, next_major_release}).
--deprecated({start, 1, next_major_release}).
--deprecated({start_link, 1, next_major_release}).
--deprecated({start_child, 0, next_major_release}).
--deprecated({start_child, 1, next_major_release}).
--deprecated({stop, 0, next_major_release}).
--deprecated({stop, 1, next_major_release}).
--deprecated({stop, 2, next_major_release}).
--deprecated({stop_child, 0, next_major_release}).
--deprecated({stop_child, 1, next_major_release}).
--deprecated({stop_child, 2, next_major_release}).
--deprecated({restart, 0, next_major_release}).
--deprecated({restart, 1, next_major_release}).
--deprecated({restart, 2, next_major_release}).
--deprecated({block, 0, next_major_release}).
--deprecated({block, 1, next_major_release}).
--deprecated({block, 2, next_major_release}).
--deprecated({block, 3, next_major_release}).
--deprecated({block, 4, next_major_release}).
--deprecated({unblock, 0, next_major_release}).
--deprecated({unblock, 1, next_major_release}).
--deprecated({unblock, 2, next_major_release}).
-
%% Behavior callbacks
--export([start_standalone/1, start_service/1, stop_service/1, services/0,
- service_info/1]).
+-export([
+ start_standalone/1,
+ start_service/1,
+ stop_service/1,
+ services/0,
+ service_info/1
+ ]).
%% API
-export([parse_query/1, reload_config/2, info/1, info/2, info/3]).
-%% Deprecated
--export([start/0, start/1,
- start_link/0, start_link/1,
- start_child/0,start_child/1,
- stop/0,stop/1,stop/2,
- stop_child/0,stop_child/1,stop_child/2,
- restart/0,restart/1,restart/2]).
-
-%% Management stuff should be internal functions
-%% Will be from r13
--export([block/0,block/1,block/2,block/3,block/4,
- unblock/0,unblock/1,unblock/2]).
-
-%% Internal Debugging and status info stuff...
-%% Keep for now should probably be moved to test catalog
--export([get_status/1,get_status/2,get_status/3,
- get_admin_state/0,get_admin_state/1,get_admin_state/2,
- get_usage_state/0,get_usage_state/1,get_usage_state/2]).
+%% Internal debugging and status info stuff...
+-export([
+ get_status/1, get_status/2, get_status/3,
+ get_admin_state/0, get_admin_state/1, get_admin_state/2,
+ get_usage_state/0, get_usage_state/1, get_usage_state/2
+ ]).
%%%========================================================================
%%% API
@@ -111,6 +81,7 @@ info(Address, Port, Properties) when is_integer(Port) andalso
is_list(Properties) ->
httpd_conf:get_config(Address, Port, Properties).
+
%%%========================================================================
%%% Behavior callbacks
%%%========================================================================
@@ -149,6 +120,8 @@ service_info(Pid) ->
exit:{noproc, _} ->
{error, service_not_available}
end.
+
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -176,6 +149,7 @@ child_name2info({httpd_instance_sup, Address, Port}) ->
{ok, [{bind_address, Address}, {port, Port} | Info]}
end.
+
reload(Config, Address, Port) ->
Name = make_name(Address,Port),
case whereis(Name) of
@@ -185,26 +159,12 @@ reload(Config, Address, Port) ->
{error,not_started}
end.
-reload(Addr, Port) when is_integer(Port) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:reload(Pid, undefined);
- _ ->
- {error,not_started}
- end.
%%% =========================================================
-%%% Function: block/0, block/1, block/2, block/3, block/4
-%%% block()
-%%% block(Port)
-%%% block(ConfigFile)
-%%% block(Addr,Port)
-%%% block(Port,Mode)
-%%% block(ConfigFile,Mode)
-%%% block(Addr,Port,Mode)
-%%% block(ConfigFile,Mode,Timeout)
-%%% block(Addr,Port,Mode,Timeout)
+%%% Function: block/3, block/4
+%%% block(Addr, Port, Mode)
+%%% block(ConfigFile, Mode, Timeout)
+%%% block(Addr, Port, Mode, Timeout)
%%%
%%% Returns: ok | {error,Reason}
%%%
@@ -237,58 +197,32 @@ reload(Addr, Port) when is_integer(Port) ->
%%% Mode -> disturbing | non_disturbing
%%% Timeout -> integer()
%%%
-block() -> block(undefined,8888,disturbing).
-block(Port) when is_integer(Port) ->
- block(undefined,Port,disturbing);
+block(Addr, Port, disturbing) when is_integer(Port) ->
+ do_block(Addr, Port, disturbing);
+block(Addr, Port, non_disturbing) when is_integer(Port) ->
+ do_block(Addr, Port, non_disturbing);
-block(ConfigFile) when is_list(ConfigFile) ->
+block(ConfigFile, Mode, Timeout)
+ when is_list(ConfigFile) andalso
+ is_atom(Mode) andalso
+ is_integer(Timeout) ->
case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- block(Addr,Port,disturbing);
- Error ->
- Error
- end.
-
-block(Addr,Port) when is_integer(Port) ->
- block(Addr,Port,disturbing);
-
-block(Port,Mode) when is_integer(Port) andalso is_atom(Mode) ->
- block(undefined,Port,Mode);
-
-block(ConfigFile,Mode) when is_list(ConfigFile) andalso is_atom(Mode) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- block(Addr,Port,Mode);
- Error ->
- Error
- end.
-
-
-block(Addr,Port,disturbing) when is_integer(Port) ->
- do_block(Addr,Port,disturbing);
-block(Addr,Port,non_disturbing) when is_integer(Port) ->
- do_block(Addr,Port,non_disturbing);
-
-block(ConfigFile,Mode,Timeout) when is_list(ConfigFile) andalso
- is_atom(Mode) andalso
- is_integer(Timeout) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- block(Addr,Port,Mode,Timeout);
+ {ok, Addr, Port} ->
+ block(Addr, Port, Mode, Timeout);
Error ->
Error
end.
-block(Addr,Port,non_disturbing,Timeout)
+block(Addr, Port, non_disturbing, Timeout)
+ when is_integer(Port) andalso is_integer(Timeout) ->
+ do_block(Addr, Port, non_disturbing, Timeout);
+block(Addr,Port,disturbing,Timeout)
when is_integer(Port) andalso is_integer(Timeout) ->
- do_block(Addr,Port,non_disturbing,Timeout);
-block(Addr,Port,disturbing,Timeout) when is_integer(Port) andalso
- is_integer(Timeout) ->
- do_block(Addr,Port,disturbing,Timeout).
+ do_block(Addr, Port, disturbing, Timeout).
-do_block(Addr,Port,Mode) when is_integer(Port) andalso is_atom(Mode) ->
+do_block(Addr, Port, Mode) when is_integer(Port) andalso is_atom(Mode) ->
Name = make_name(Addr,Port),
case whereis(Name) of
Pid when is_pid(Pid) ->
@@ -298,7 +232,7 @@ do_block(Addr,Port,Mode) when is_integer(Port) andalso is_atom(Mode) ->
end.
-do_block(Addr,Port,Mode,Timeout)
+do_block(Addr, Port, Mode, Timeout)
when is_integer(Port) andalso is_atom(Mode) ->
Name = make_name(Addr,Port),
case whereis(Name) of
@@ -310,11 +244,8 @@ do_block(Addr,Port,Mode,Timeout)
%%% =========================================================
-%%% Function: unblock/0, unblock/1, unblock/2
-%%% unblock()
-%%% unblock(Port)
-%%% unblock(ConfigFile)
-%%% unblock(Addr,Port)
+%%% Function: unblock/2
+%%% unblock(Addr, Port)
%%%
%%% Description: This function is used to reverse a previous block
%%% operation on the HTTP server.
@@ -323,16 +254,6 @@ do_block(Addr,Port,Mode,Timeout)
%%% Addr -> {A,B,C,D} | string() | undefined
%%% ConfigFile -> string()
%%%
-unblock() -> unblock(undefined,8888).
-unblock(Port) when is_integer(Port) -> unblock(undefined,Port);
-
-unblock(ConfigFile) when is_list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- unblock(Addr,Port);
- Error ->
- Error
- end.
unblock(Addr, Port) when is_integer(Port) ->
Name = make_name(Addr,Port),
@@ -349,8 +270,8 @@ foreach([KeyValue|Rest]) ->
{ok, Plus2Space, _} = inets_regexp:gsub(KeyValue,"[\+]"," "),
case inets_regexp:split(Plus2Space,"=") of
{ok,[Key|Value]} ->
- [{http_uri:decode(Key), http_uri:decode(lists:flatten(Value))}|
- foreach(Rest)];
+ [{http_uri:decode(Key),
+ http_uri:decode(lists:flatten(Value))}|foreach(Rest)];
{ok,_} ->
foreach(Rest)
end.
@@ -521,80 +442,81 @@ do_reload_config(ConfigList, Mode) ->
%%%--------------------------------------------------------------
%%% Deprecated
%%%--------------------------------------------------------------
-start() ->
- start("/var/tmp/server_root/conf/8888.conf").
-start(ConfigFile) ->
- {ok, Pid} = inets:start(httpd, ConfigFile, stand_alone),
- unlink(Pid),
- {ok, Pid}.
+%% start() ->
+%% start("/var/tmp/server_root/conf/8888.conf").
-start_link() ->
- start("/var/tmp/server_root/conf/8888.conf").
+%% start(ConfigFile) ->
+%% {ok, Pid} = inets:start(httpd, ConfigFile, stand_alone),
+%% unlink(Pid),
+%% {ok, Pid}.
-start_link(ConfigFile) when is_list(ConfigFile) ->
- inets:start(httpd, ConfigFile, stand_alone).
+%% start_link() ->
+%% start("/var/tmp/server_root/conf/8888.conf").
-stop() ->
- stop(8888).
+%% start_link(ConfigFile) when is_list(ConfigFile) ->
+%% inets:start(httpd, ConfigFile, stand_alone).
-stop(Port) when is_integer(Port) ->
- stop(undefined, Port);
-stop(Pid) when is_pid(Pid) ->
- old_stop(Pid);
-stop(ConfigFile) when is_list(ConfigFile) ->
- old_stop(ConfigFile).
+%% stop() ->
+%% stop(8888).
-stop(Addr, Port) when is_integer(Port) ->
- old_stop(Addr, Port).
+%% stop(Port) when is_integer(Port) ->
+%% stop(undefined, Port);
+%% stop(Pid) when is_pid(Pid) ->
+%% old_stop(Pid);
+%% stop(ConfigFile) when is_list(ConfigFile) ->
+%% old_stop(ConfigFile).
-start_child() ->
- start_child("/var/tmp/server_root/conf/8888.conf").
+%% stop(Addr, Port) when is_integer(Port) ->
+%% old_stop(Addr, Port).
-start_child(ConfigFile) ->
- httpd_sup:start_child(ConfigFile).
+%% start_child() ->
+%% start_child("/var/tmp/server_root/conf/8888.conf").
-stop_child() ->
- stop_child(8888).
+%% start_child(ConfigFile) ->
+%% httpd_sup:start_child(ConfigFile).
-stop_child(Port) ->
- stop_child(undefined, Port).
+%% stop_child() ->
+%% stop_child(8888).
-stop_child(Addr, Port) when is_integer(Port) ->
- httpd_sup:stop_child(Addr, Port).
+%% stop_child(Port) ->
+%% stop_child(undefined, Port).
-restart() -> reload(undefined, 8888).
+%% stop_child(Addr, Port) when is_integer(Port) ->
+%% httpd_sup:stop_child(Addr, Port).
-restart(Port) when is_integer(Port) ->
- reload(undefined, Port).
-restart(Addr, Port) ->
- reload(Addr, Port).
+%% restart() -> reload(undefined, 8888).
-old_stop(Pid) when is_pid(Pid) ->
- do_stop(Pid);
-old_stop(ConfigFile) when is_list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok, Addr, Port} ->
- old_stop(Addr, Port);
-
- Error ->
- Error
- end;
-old_stop(_StartArgs) ->
- ok.
+%% restart(Port) when is_integer(Port) ->
+%% reload(undefined, Port).
+%% restart(Addr, Port) ->
+%% reload(Addr, Port).
-old_stop(Addr, Port) when is_integer(Port) ->
- Name = old_make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- do_stop(Pid),
- ok;
- _ ->
- not_started
- end.
+%% old_stop(Pid) when is_pid(Pid) ->
+%% do_stop(Pid);
+%% old_stop(ConfigFile) when is_list(ConfigFile) ->
+%% case get_addr_and_port(ConfigFile) of
+%% {ok, Addr, Port} ->
+%% old_stop(Addr, Port);
+
+%% Error ->
+%% Error
+%% end;
+%% old_stop(_StartArgs) ->
+%% ok.
+
+%% old_stop(Addr, Port) when is_integer(Port) ->
+%% Name = old_make_name(Addr, Port),
+%% case whereis(Name) of
+%% Pid when is_pid(Pid) ->
+%% do_stop(Pid),
+%% ok;
+%% _ ->
+%% not_started
+%% end.
-do_stop(Pid) ->
- exit(Pid, shutdown).
+%% do_stop(Pid) ->
+%% exit(Pid, shutdown).
-old_make_name(Addr,Port) ->
- httpd_util:make_name("httpd_instance_sup",Addr,Port).
+%% old_make_name(Addr,Port) ->
+%% httpd_util:make_name("httpd_instance_sup",Addr,Port).
diff --git a/lib/inets/src/http_server/httpd.hrl b/lib/inets/src/http_server/httpd.hrl
index 0db8a029bb..4eba833e2c 100644
--- a/lib/inets/src/http_server/httpd.hrl
+++ b/lib/inets/src/http_server/httpd.hrl
@@ -1,82 +1,27 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
-%% %CopyrightEnd%
%%
+%% %CopyrightEnd%
%%
+%% This is a simple wrapper for code that has not been updated to
+%% handle the move of this file to the include dir.
--include_lib("kernel/include/file.hrl").
-
--ifndef(SERVER_SOFTWARE).
--define(SERVER_SOFTWARE,"inets/develop"). % Define in Makefile!
--endif.
--define(SERVER_PROTOCOL,"HTTP/1.1").
--define(DEFAULT_MODS, [mod_alias, mod_auth, mod_esi, mod_actions, mod_cgi,
- mod_dir, mod_get, mod_head, mod_log, mod_disk_log]).
--define(SOCKET_CHUNK_SIZE,8192).
--define(SOCKET_MAX_POLL,25).
--define(FILE_CHUNK_SIZE,64*1024).
--define(GATEWAY_INTERFACE,"CGI/1.1").
--define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
--define(DEFAULT_CONTEXT,
- [{errmsg,"[an error occurred while processing this directive]"},
- {timefmt,"%A, %d-%b-%y %T %Z"},
- {sizefmt,"abbrev"}]).
-
-
--ifdef(inets_error).
--define(ERROR(Format, Args), io:format("E(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(ERROR(F,A),[]).
--endif.
-
--ifdef(inets_log).
--define(LOG(Format, Args), io:format("L(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(LOG(F,A),[]).
--endif.
-
--ifdef(inets_debug).
--define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(DEBUG(F,A),[]).
--endif.
-
--ifdef(inets_cdebug).
--define(CDEBUG(Format, Args), io:format("C(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(CDEBUG(F,A),[]).
--endif.
+-ifndef(src_httpd_hrl).
+-define(src_httpd_hrl, true).
+-include_lib("inets/include/httpd.hrl").
--record(init_data,{peername,resolve}).
--record(mod,{init_data,
- data=[],
- socket_type=ip_comm,
- socket,
- config_db,
- method,
- absolute_uri=[],
- request_uri,
- http_version,
- request_line,
- parsed_header=[],
- entity_body,
- connection}).
+-endif. % -ifdef(src_httpd_hrl).
diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl
index fef3fe58c6..bcebb6a9e3 100644
--- a/lib/inets/src/http_server/httpd_acceptor.erl
+++ b/lib/inets/src/http_server/httpd_acceptor.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -139,9 +139,9 @@ acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout) ->
handle_error(Reason, ConfigDb),
?MODULE:acceptor_loop(Manager, SocketType, ListenSocket,
ConfigDb, AcceptTimeout);
- {'EXIT', Reason} ->
- ?hdri("accept exited", [{reason, Reason}]),
- handle_error({'EXIT', Reason}, ConfigDb),
+ {'EXIT', _Reason} = EXIT ->
+ ?hdri("accept exited", [{reason, _Reason}]),
+ handle_error(EXIT, ConfigDb),
?MODULE:acceptor_loop(Manager, SocketType, ListenSocket,
ConfigDb, AcceptTimeout)
end.
diff --git a/lib/inets/src/http_server/httpd_cgi.erl b/lib/inets/src/http_server/httpd_cgi.erl
index 0532d7d100..c06a06aad3 100644
--- a/lib/inets/src/http_server/httpd_cgi.erl
+++ b/lib/inets/src/http_server/httpd_cgi.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -21,7 +21,8 @@
-export([parse_headers/1, handle_headers/1]).
--include("inets_internal.hrl").
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+
%%%=========================================================================
%%% Internal application API
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index 2faf13e9b3..5352eb8bb9 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -25,9 +25,10 @@
%% Application internal API
-export([load/1, load/2, load_mime_types/1, store/1, store/2,
- remove/1, remove_all/1, config/1, get_config/2, get_config/3,
- lookup/2, lookup/3, lookup/4,
- validate_properties/1]).
+ remove/1, remove_all/1, get_config/2, get_config/3,
+ lookup_socket_type/1,
+ lookup/2, lookup/3, lookup/4,
+ validate_properties/1]).
-define(VMODULE,"CONF").
-include("httpd_internal.hrl").
@@ -217,9 +218,12 @@ load("ServerName " ++ ServerName, []) ->
{ok,[],{server_name,clean(ServerName)}};
load("SocketType " ++ SocketType, []) ->
- case check_enum(clean(SocketType),["ssl","ip_comm"]) of
+ %% ssl is the same as HTTP_DEFAULT_SSL_KIND
+ %% ossl is ssl based on OpenSSL (the "old" ssl)
+ %% essl is the pure Erlang-based ssl (the "new" ssl)
+ case check_enum(clean(SocketType), ["ssl", "ossl", "essl", "ip_comm"]) of
{ok, ValidSocketType} ->
- {ok, [], {socket_type,ValidSocketType}};
+ {ok, [], {socket_type, ValidSocketType}};
{error,_} ->
{error, ?NICE(clean(SocketType) ++ " is an invalid SocketType")}
end;
@@ -227,7 +231,7 @@ load("SocketType " ++ SocketType, []) ->
load("Port " ++ Port, []) ->
case make_integer(Port) of
{ok, Integer} ->
- {ok, [], {port,Integer}};
+ {ok, [], {port, Integer}};
{error, _} ->
{error, ?NICE(clean(Port)++" is an invalid Port")}
end;
@@ -301,7 +305,7 @@ load("MaxKeepAliveRequests " ++ MaxRequests, []) ->
" is an invalid MaxKeepAliveRequests")}
end;
-%% This clause is keept for backwards compability
+%% This clause is kept for backwards compatibility
load("MaxKeepAliveRequest " ++ MaxRequests, []) ->
case make_integer(MaxRequests) of
{ok, Integer} ->
@@ -535,7 +539,10 @@ validate_config_params([{server_name, Value} | _]) ->
throw({server_name, Value});
validate_config_params([{socket_type, Value} | Rest])
- when (Value =:= ip_comm) orelse (Value =:= ssl) ->
+ when (Value =:= ip_comm) orelse
+ (Value =:= ssl) orelse
+ (Value =:= ossl) orelse
+ (Value =:= essl) ->
validate_config_params(Rest);
validate_config_params([{socket_type, Value} | _]) ->
throw({socket_type, Value});
@@ -696,6 +703,8 @@ store(ConfigList0) ->
ConfigList)
catch
throw:Error ->
+ ?hdri("store - config parameter validation failed",
+ [{error, Error}]),
{error, {invalid_option, Error}}
end.
@@ -742,27 +751,27 @@ remove(ConfigDB) ->
ets:delete(ConfigDB),
ok.
-config(ConfigDB) ->
- case httpd_util:lookup(ConfigDB, socket_type,ip_comm) of
- ssl ->
- case ssl_certificate_file(ConfigDB) of
- undefined ->
- {error,
- "Directive SSLCertificateFile "
- "not found in the config file"};
- SSLCertificateFile ->
- {ssl,
- SSLCertificateFile++
- ssl_certificate_key_file(ConfigDB)++
- ssl_verify_client(ConfigDB)++
- ssl_ciphers(ConfigDB)++
- ssl_password(ConfigDB)++
- ssl_verify_depth(ConfigDB)++
- ssl_ca_certificate_file(ConfigDB)}
- end;
- ip_comm ->
- ip_comm
- end.
+%% config(ConfigDB) ->
+%% case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
+%% ssl ->
+%% case ssl_certificate_file(ConfigDB) of
+%% undefined ->
+%% {error,
+%% "Directive SSLCertificateFile "
+%% "not found in the config file"};
+%% SSLCertificateFile ->
+%% {ssl,
+%% SSLCertificateFile++
+%% ssl_certificate_key_file(ConfigDB)++
+%% ssl_verify_client(ConfigDB)++
+%% ssl_ciphers(ConfigDB)++
+%% ssl_password(ConfigDB)++
+%% ssl_verify_depth(ConfigDB)++
+%% ssl_ca_certificate_file(ConfigDB)}
+%% end;
+%% ip_comm ->
+%% ip_comm
+%% end.
get_config(Address, Port) ->
@@ -798,6 +807,38 @@ table(Address, Port) ->
httpd_util:make_name("httpd_conf", Address, Port).
+lookup_socket_type(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
+ ip_comm ->
+ ip_comm;
+ SSL when (SSL =:= ssl) orelse (SSL =:= ossl) orelse (SSL =:= essl) ->
+ SSLTag =
+ if
+ (SSL =:= ssl) ->
+ ?HTTP_DEFAULT_SSL_KIND;
+ true ->
+ SSL
+ end,
+ case ssl_certificate_file(ConfigDB) of
+ undefined ->
+ Reason = "Directive SSLCertificateFile "
+ "not found in the config file",
+ throw({error, Reason});
+ SSLCertificateFile ->
+ {SSLTag, SSLCertificateFile ++ ssl_config(ConfigDB)}
+ end
+ end.
+
+ssl_config(ConfigDB) ->
+ ssl_certificate_key_file(ConfigDB) ++
+ ssl_verify_client(ConfigDB) ++
+ ssl_ciphers(ConfigDB) ++
+ ssl_password(ConfigDB) ++
+ ssl_verify_depth(ConfigDB) ++
+ ssl_ca_certificate_file(ConfigDB).
+
+
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
diff --git a/lib/inets/src/http_server/httpd_esi.erl b/lib/inets/src/http_server/httpd_esi.erl
index b1a75fda52..000874d0a3 100644
--- a/lib/inets/src/http_server/httpd_esi.erl
+++ b/lib/inets/src/http_server/httpd_esi.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -21,7 +21,8 @@
-export([parse_headers/1, handle_headers/1]).
--include("inets_internal.hrl").
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+
%%%=========================================================================
%%% Internal application API
@@ -38,7 +39,7 @@
%% body part. Note that it is presumed that <Data> starts with a
%% string including "\r\n\r\n" if there is any header information
%% present. The returned headers will not contain the HTTP header body
-%% delimiter \r\n. (All header, header delimiters are keept.)
+%% delimiter \r\n. (All header, header delimiters are kept.)
%% Ex: ["Content-Type : text/html\r\n Connection : closing \r\n\r\n" |
%% io_list()] --> {"Content-Type : text/html\r\n Connection : closing \r\n",
%% io_list()}
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 4490a6356a..f2ba33099e 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -24,15 +24,16 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
+
handle_error(eacces, Op, ModData, Path) ->
- handle_error(403, Op, ModData, Path,"");
+ handle_error(403, Op, ModData, Path, ": Forbidden");
handle_error(enoent, Op, ModData, Path) ->
- handle_error(404, Op, ModData, Path,"");
+ handle_error(404, Op, ModData, Path, ": File not found");
handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
- ": A component of the file name is not a directory");
+ ": A component of the file name is not a directory");
handle_error(emfile, Op, _ModData, Path) ->
- handle_error(500, Op, none, Path, ": To many open files");
+ handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": File table overflow");
handle_error(_Reason, Op, _ModData, Path) ->
@@ -40,7 +41,6 @@ handle_error(_Reason, Op, _ModData, Path) ->
handle_error(StatusCode, Op, none, Path, Reason) ->
{StatusCode, none, ?NICE("Can't " ++ Op ++ " " ++ Path ++ Reason)};
-
handle_error(StatusCode, Op, ModData, Path, Reason) ->
{StatusCode, ModData#mod.request_uri,
?NICE("Can't " ++ Op ++ " " ++ Path ++ Reason)}.
diff --git a/lib/inets/src/http_server/httpd_internal.hrl b/lib/inets/src/http_server/httpd_internal.hrl
index 7795ab6c18..108469ea0a 100644
--- a/lib/inets/src/http_server/httpd_internal.hrl
+++ b/lib/inets/src/http_server/httpd_internal.hrl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -21,7 +21,51 @@
-ifndef(httpd_internal_hrl).
-define(httpd_internal_hrl, true).
--include("inets_internal.hrl").
+-ifndef(SERVER_SOFTWARE).
+-define(SERVER_SOFTWARE,"inets/develop"). % Define in Makefile!
+-endif.
+-define(SERVER_PROTOCOL,"HTTP/1.1").
+-define(DEFAULT_MODS, [mod_alias, mod_auth, mod_esi, mod_actions, mod_cgi,
+ mod_dir, mod_get, mod_head, mod_log, mod_disk_log]).
+-define(SOCKET_CHUNK_SIZE,8192).
+-define(SOCKET_MAX_POLL,25).
+-define(FILE_CHUNK_SIZE,64*1024).
+-define(GATEWAY_INTERFACE,"CGI/1.1").
+-define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
+-define(DEFAULT_CONTEXT,
+ [{errmsg,"[an error occurred while processing this directive]"},
+ {timefmt,"%A, %d-%b-%y %T %Z"},
+ {sizefmt,"abbrev"}]).
+
+
+-ifdef(inets_error).
+-define(ERROR(Format, Args), io:format("E(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(ERROR(F,A),[]).
+-endif.
+
+-ifdef(inets_log).
+-define(LOG(Format, Args), io:format("L(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(LOG(F,A),[]).
+-endif.
+
+-ifdef(inets_debug).
+-define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(DEBUG(F,A),[]).
+-endif.
+
+-ifdef(inets_cdebug).
+-define(CDEBUG(Format, Args), io:format("C(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(CDEBUG(F,A),[]).
+-endif.
+
-define(SERVICE, httpd).
-define(hdri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
-define(hdrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
diff --git a/lib/inets/src/http_server/httpd_log.erl b/lib/inets/src/http_server/httpd_log.erl
index f3ea3aa0e2..db1e2c627a 100644
--- a/lib/inets/src/http_server/httpd_log.erl
+++ b/lib/inets/src/http_server/httpd_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% 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
@@ -113,7 +113,7 @@ do_error_entry(ConfigDB, RemoteHost, undefined, Date, Reason) ->
do_error_entry(ConfigDB, RemoteHost, URI, Date, Reason) ->
case httpd_util:lookup(ConfigDB, error_log_format, pretty) of
pretty ->
- io_lib:format("[~s] access to ~s failed for ~s reason: ~n~p~n",
+ io_lib:format("[~s] access to ~s failed for ~s, reason: ~n~p~n",
[Date, URI, RemoteHost, Reason]);
compact ->
io_lib:format( "[~s] access to ~s failed for ~s, reason: ~w~n",
diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl
index f2e8763907..b44bc77c41 100644
--- a/lib/inets/src/http_server/httpd_manager.erl
+++ b/lib/inets/src/http_server/httpd_manager.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -238,24 +238,25 @@ init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port]) ->
case (catch do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port)) of
{error, Reason} ->
String = lists:flatten(
- io_lib:format("Failed initiating "
- "web server: ~n~p~n~p~n",
- [ConfigFile,Reason])),
+ io_lib:format("Failed initiating web server: "
+ "~n~p"
+ "~n~p"
+ "~n", [ConfigFile, Reason])),
error_logger:error_report(String),
{stop, {error, Reason}};
{ok, State} ->
{ok, State}
end;
-init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port,
- ListenInfo]) ->
+init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo]) ->
process_flag(trap_exit, true),
case (catch do_init(ConfigFile, ConfigList, AcceptTimeout,
Addr, Port, ListenInfo)) of
{error, Reason} ->
String = lists:flatten(
- io_lib:format("Failed initiating "
- "web server: ~n~p~n~p~n",
- [ConfigFile,Reason])),
+ io_lib:format("Failed initiating web server: "
+ "~n~p"
+ "~n~p"
+ "~n", [ConfigFile, Reason])),
error_logger:error_report(String),
{stop, {error, Reason}};
{ok, State} ->
@@ -264,13 +265,14 @@ init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port,
do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port) ->
NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile),
- ConfigDB = do_initial_store(ConfigList),
- SocketType = httpd_conf:config(ConfigDB),
+ ConfigDB = do_initial_store(ConfigList),
+ SocketType = httpd_conf:lookup_socket_type(ConfigDB),
case httpd_acceptor_sup:start_acceptor(SocketType, Addr,
Port, ConfigDB, AcceptTimeout) of
{ok, _Pid} ->
- Status = [{max_conn,0}, {last_heavy_load,never},
- {last_connection,never}],
+ Status = [{max_conn, 0},
+ {last_heavy_load, never},
+ {last_connection, never}],
State = #state{socket_type = SocketType,
config_file = NewConfigFile,
config_db = ConfigDB,
@@ -284,7 +286,7 @@ do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port) ->
do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo) ->
NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile),
ConfigDB = do_initial_store(ConfigList),
- SocketType = httpd_conf:config(ConfigDB),
+ SocketType = httpd_conf:lookup_socket_type(ConfigDB),
case httpd_acceptor_sup:start_acceptor(SocketType, Addr,
Port, ConfigDB,
AcceptTimeout, ListenInfo) of
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 1c23316ecb..5ba79b2706 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -19,22 +19,35 @@
-module(httpd_request).
--include("http_internal.hrl").
+-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpd.hrl").
+-include("httpd_internal.hrl").
--export([parse/1, whole_body/2, validate/3, update_mod_data/5,
- body_data/2]).
+-export([
+ parse/1,
+ whole_body/2,
+ validate/3,
+ update_mod_data/5,
+ body_data/2
+ ]).
%% Callback API - used for example if the header/body is received a
%% little at a time on a socket.
--export([parse_method/1, parse_uri/1, parse_version/1, parse_headers/1,
- whole_body/1]).
+-export([
+ parse_method/1, parse_uri/1, parse_version/1, parse_headers/1,
+ whole_body/1
+ ]).
+
%%%=========================================================================
%%% Internal application API
%%%=========================================================================
parse([Bin, MaxSizes]) ->
- parse_method(Bin, [], MaxSizes, []).
+ ?hdrt("parse", [{bin, Bin}, {max_sizes, MaxSizes}]),
+ parse_method(Bin, [], MaxSizes, []);
+parse(Unknown) ->
+ ?hdrt("parse", [{unknown, Unknown}]),
+ exit({bad_args, Unknown}).
%% Functions that may be returned during the decoding process
%% if the input data is incompleate.
@@ -119,30 +132,65 @@ update_mod_data(ModData, Method, RequestURI, HTTPVersion, Headers)->
%%% Internal functions
%%%========================================================================
parse_method(<<>>, Method, MaxSizes, Result) ->
+ ?hdrt("parse_method - empty bin",
+ [{method, Method}, {max_sizes, MaxSizes}, {result, Result}]),
{?MODULE, parse_method, [Method, MaxSizes, Result]};
parse_method(<<?SP, Rest/binary>>, Method, MaxSizes, Result) ->
+ ?hdrt("parse_method - SP begin",
+ [{rest, Rest},
+ {method, Method},
+ {max_sizes, MaxSizes},
+ {result, Result}]),
parse_uri(Rest, [], 0, MaxSizes,
[string:strip(lists:reverse(Method)) | Result]);
parse_method(<<Octet, Rest/binary>>, Method, MaxSizes, Result) ->
+ ?hdrt("parse_method",
+ [{octet, Octet},
+ {rest, Rest},
+ {method, Method},
+ {max_sizes, MaxSizes},
+ {result, Result}]),
parse_method(Rest, [Octet | Method], MaxSizes, Result).
-parse_uri(_, _, CurrSize, {MaxURI, _}, _) when CurrSize > MaxURI,
- MaxURI =/= nolimit ->
+parse_uri(_, _, CurrSize, {MaxURI, _}, _)
+ when (CurrSize > MaxURI) andalso (MaxURI =/= nolimit) ->
+ ?hdrt("parse_uri",
+ [{current_size, CurrSize},
+ {max_uri, MaxURI}]),
%% We do not know the version of the client as it comes after the
%% uri send the lowest version in the response so that the client
%% will be able to handle it.
HttpVersion = "HTTP/0.9",
{error, {uri_too_long, MaxURI}, HttpVersion};
parse_uri(<<>>, URI, CurrSize, MaxSizes, Result) ->
+ ?hdrt("parse_uri - empty bin",
+ [{uri, URI},
+ {current_size, CurrSize},
+ {max_sz, MaxSizes},
+ {result, Result}]),
{?MODULE, parse_uri, [URI, CurrSize, MaxSizes, Result]};
parse_uri(<<?SP, Rest/binary>>, URI, _, MaxSizes, Result) ->
+ ?hdrt("parse_uri - SP begin",
+ [{uri, URI},
+ {max_sz, MaxSizes},
+ {result, Result}]),
parse_version(Rest, [], MaxSizes,
[string:strip(lists:reverse(URI)) | Result]);
%% Can happen if it is a simple HTTP/0.9 request e.i "GET /\r\n\r\n"
-parse_uri(<<?CR, _Rest/binary>> = Data, URI, _,MaxSizes, Result) ->
+parse_uri(<<?CR, _Rest/binary>> = Data, URI, _, MaxSizes, Result) ->
+ ?hdrt("parse_uri - CR begin",
+ [{uri, URI},
+ {max_sz, MaxSizes},
+ {result, Result}]),
parse_version(Data, [], MaxSizes,
[string:strip(lists:reverse(URI)) | Result]);
parse_uri(<<Octet, Rest/binary>>, URI, CurrSize, MaxSizes, Result) ->
+ ?hdrt("parse_uri",
+ [{octet, Octet},
+ {uri, URI},
+ {curr_sz, CurrSize},
+ {max_sz, MaxSizes},
+ {result, Result}]),
parse_uri(Rest, [Octet | URI], CurrSize + 1, MaxSizes, Result).
parse_version(<<>>, Version, MaxSizes, Result) ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index 1bf1b20b5b..e07c7b0cd4 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -1,19 +1,25 @@
%%
%% %CopyrightBegin%
+<<<<<<< HEAD
+%%
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%%
+=======
%%
%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
+>>>>>>> bmk/inets/httpd/xss_when_erl_encoded/r13/OTP-9655
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -101,11 +107,13 @@ init([Manager, ConfigDB, AcceptTimeout]) ->
Then = erlang:now(),
+ ?hdrd("negotiate", []),
case http_transport:negotiate(SocketType, Socket, TimeOut) of
{error, Error} ->
+ ?hdrd("negotiation failed", [{error, Error}]),
exit(Error); %% Can be 'normal'.
ok ->
- ?hdrt("negotiated", []),
+ ?hdrt("negotiation successfull", []),
NewTimeout = TimeOut - timer:now_diff(now(),Then) div 1000,
continue_init(Manager, ConfigDB, SocketType, Socket, NewTimeout)
end.
@@ -121,12 +129,9 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
socket = Socket,
init_data = InitData},
- MaxHeaderSize = httpd_util:lookup(ConfigDB, max_header_size,
- ?HTTP_MAX_HEADER_SIZE),
- MaxURISize = httpd_util:lookup(ConfigDB, max_uri_size,
- ?HTTP_MAX_URI_SIZE),
- NrOfRequest = httpd_util:lookup(ConfigDB,
- max_keep_alive_request, infinity),
+ MaxHeaderSize = max_header_size(ConfigDB),
+ MaxURISize = max_uri_size(ConfigDB),
+ NrOfRequest = max_keep_alive_request(ConfigDB),
{_, Status} = httpd_manager:new_connection(Manager),
@@ -142,9 +147,10 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
?hdrt("activate request timeout", []),
NewState = activate_request_timeout(State),
- ?hdrt("update socket options", []),
- http_transport:setopts(SocketType, Socket, [binary,{packet, 0},
- {active, once}]),
+ ?hdrt("set socket options (binary, packet & active)", []),
+ http_transport:setopts(SocketType, Socket,
+ [binary, {packet, 0}, {active, once}]),
+
?hdrt("init done", []),
gen_server:enter_loop(?MODULE, [], NewState).
@@ -180,21 +186,29 @@ handle_cast(Msg, State) ->
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
-handle_info({Proto, Socket, Data}, State =
+handle_info({Proto, Socket, Data},
#state{mfa = {Module, Function, Args} = MFA,
mod = #mod{socket_type = SockType,
socket = Socket} = ModData} = State)
when (((Proto =:= tcp) orelse
(Proto =:= ssl) orelse
(Proto =:= dummy)) andalso is_binary(Data)) ->
+
?hdrd("received data",
[{data, Data}, {proto, Proto},
{socket, Socket}, {socket_type, SockType}, {mfa, MFA}]),
- case Module:Function([Data | Args]) of
+
+%% case (catch Module:Function([Data | Args])) of
+ PROCESSED = (catch Module:Function([Data | Args])),
+
+ ?hdrt("data processed", [{processing_result, PROCESSED}]),
+
+ case PROCESSED of
{ok, Result} ->
?hdrd("data processed", [{result, Result}]),
NewState = cancel_request_timeout(State),
handle_http_msg(Result, NewState);
+
{error, {uri_too_long, MaxSize}, Version} ->
?hdrv("uri too long", [{max_size, MaxSize}, {version, Version}]),
NewModData = ModData#mod{http_version = Version},
@@ -205,7 +219,8 @@ handle_info({Proto, Socket, Data}, State =
{stop, normal, State#state{response_sent = true,
mod = NewModData}};
{error, {header_too_long, MaxSize}, Version} ->
- ?hdrv("header too long", [{max_size, MaxSize}, {version, Version}]),
+ ?hdrv("header too long",
+ [{max_size, MaxSize}, {version, Version}]),
NewModData = ModData#mod{http_version = Version},
httpd_response:send_status(NewModData, 413, "Header too long"),
Reason = io_lib:format("Header too long, max size is ~p~n",
@@ -231,13 +246,13 @@ handle_info({ssl_error, _, _} = Reason, State) ->
%% Timeouts
handle_info(timeout, #state{mod = ModData, mfa = {_, parse, _}} = State) ->
- error_log("No request received on keep-alive connection"
+ error_log("No request received on keep-alive connection "
"before server side timeout", ModData),
%% No response should be sent!
{stop, normal, State#state{response_sent = true}};
handle_info(timeout, #state{mod = ModData} = State) ->
httpd_response:send_status(ModData, 408, "Request timeout"),
- error_log("The client did not send the whole request before the"
+ error_log("The client did not send the whole request before the "
"server side timeout", ModData),
{stop, normal, State#state{response_sent = true}};
@@ -263,14 +278,16 @@ terminate(Reason, #state{response_sent = false, mod = ModData} = State) ->
httpd_response:send_status(ModData, 500, none),
error_log(httpd_util:reason_phrase(500), ModData),
terminate(Reason, State#state{response_sent = true, mod = ModData});
-terminate(_, State) ->
+terminate(_Reason, State) ->
do_terminate(State).
do_terminate(#state{mod = ModData, manager = Manager} = State) ->
catch httpd_manager:done_connection(Manager),
cancel_request_timeout(State),
+ %% receive after 5000 -> ok end,
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket).
+
%%--------------------------------------------------------------------
%% code_change(OldVsn, State, Extra) -> {ok, NewState}
%%
@@ -279,6 +296,7 @@ do_terminate(#state{mod = ModData, manager = Manager} = State) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -383,9 +401,8 @@ is_host_specified_if_required(_, _, _) ->
handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) ->
?hdrt("handle body", []),
- MaxHeaderSize =
- httpd_util:lookup(ConfigDB, max_header_size, ?HTTP_MAX_HEADER_SIZE),
- MaxBodySize = httpd_util:lookup(ConfigDB, max_body_size, nolimit),
+ MaxHeaderSize = max_header_size(ConfigDB),
+ MaxBodySize = max_body_size(ConfigDB),
case handle_expect(State, MaxBodySize) of
ok ->
@@ -538,24 +555,23 @@ handle_response(#state{body = Body,
{stop, normal, State#state{response_sent = true}}.
handle_next_request(#state{mod = #mod{connection = true} = ModData,
- max_keep_alive_request = Max} = State, Data) ->
+ max_keep_alive_request = Max} = State, Data) ->
?hdrt("handle next request", [{max, Max}]),
+
NewModData = #mod{socket_type = ModData#mod.socket_type,
- socket = ModData#mod.socket,
- config_db = ModData#mod.config_db,
- init_data = ModData#mod.init_data},
- MaxHeaderSize =
- httpd_util:lookup(ModData#mod.config_db,
- max_header_size, ?HTTP_MAX_HEADER_SIZE),
- MaxURISize = httpd_util:lookup(ModData#mod.config_db, max_uri_size,
- ?HTTP_MAX_URI_SIZE),
- TmpState = State#state{mod = NewModData,
- mfa = {httpd_request, parse, [{MaxURISize,
- MaxHeaderSize}]},
+ socket = ModData#mod.socket,
+ config_db = ModData#mod.config_db,
+ init_data = ModData#mod.init_data},
+ MaxHeaderSize = max_header_size(ModData#mod.config_db),
+ MaxURISize = max_uri_size(ModData#mod.config_db),
+
+ MFA = {httpd_request, parse, [{MaxURISize, MaxHeaderSize}]},
+ TmpState = State#state{mod = NewModData,
+ mfa = MFA,
max_keep_alive_request = decrease(Max),
- headers = undefined,
- body = undefined,
- response_sent = false},
+ headers = undefined,
+ body = undefined,
+ response_sent = false},
NewState = activate_request_timeout(TmpState),
@@ -596,7 +612,7 @@ decrease(N) ->
error_log(ReasonString, Info) ->
Error = lists:flatten(
- io_lib:format("Error reading request:~s",[ReasonString])),
+ io_lib:format("Error reading request: ~s", [ReasonString])),
error_log(mod_log, Info, Error),
error_log(mod_disk_log, Info, Error).
@@ -609,3 +625,21 @@ error_log(Mod, #mod{config_db = ConfigDB} = Info, String) ->
_ ->
ok
end.
+
+
+%%--------------------------------------------------------------------
+%% Config access wrapper functions
+%%--------------------------------------------------------------------
+
+max_header_size(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, max_header_size, ?HTTP_MAX_HEADER_SIZE).
+
+max_uri_size(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, max_uri_size, ?HTTP_MAX_URI_SIZE).
+
+max_body_size(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, max_body_size, nolimit).
+
+max_keep_alive_request(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, max_keep_alive_request, infinity).
+
diff --git a/lib/inets/src/http_server/httpd_script_env.erl b/lib/inets/src/http_server/httpd_script_env.erl
index a742cbef76..d3115150b0 100644
--- a/lib/inets/src/http_server/httpd_script_env.erl
+++ b/lib/inets/src/http_server/httpd_script_env.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
%%
%% 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
@@ -23,6 +23,7 @@
-export([create_env/3]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
%%%=========================================================================
%%% Internal application API
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index 90d74e3a14..264dc9f006 100644
--- a/lib/inets/src/http_server/httpd_sup.erl
+++ b/lib/inets/src/http_server/httpd_sup.erl
@@ -39,7 +39,6 @@
-include("httpd_internal.hrl").
-include("inets_internal.hrl").
-
%%%=========================================================================
%%% API
%%%=========================================================================
@@ -91,7 +90,7 @@ id(Address, Port) ->
%%% Supervisor callback
%%%=========================================================================
init([HttpdServices]) ->
- ?hdrd("starting", []),
+ ?hdrd("starting", [{httpd_service, HttpdServices}]),
RestartStrategy = one_for_one,
MaxR = 10,
MaxT = 3600,
@@ -183,24 +182,32 @@ httpd_child_spec(ConfigFile, AcceptTimeout, Debug) ->
Error
end.
-httpd_child_spec(Config, AcceptTimeout, Debug, Addr, 0) ->
- case start_listen(Addr, 0, Config) of
- {Pid, {NewPort, NewConfig, ListenSocket}} ->
- Name = {httpd_instance_sup, Addr, NewPort},
- StartFunc = {httpd_instance_sup, start_link,
- [NewConfig, AcceptTimeout,
- {Pid, ListenSocket}, Debug]},
- Restart = permanent,
- Shutdown = infinity,
- Modules = [httpd_instance_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules};
- {Pid, {error, Reason}} ->
- exit(Pid, normal),
- {error, Reason}
- end;
-
httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port) ->
+ case Port == 0 orelse proplists:is_defined(fd, Config) of
+ true ->
+ httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port);
+ false ->
+ httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port)
+ end.
+
+httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port) ->
+ case start_listen(Addr, Port, Config) of
+ {Pid, {NewPort, NewConfig, ListenSocket}} ->
+ Name = {httpd_instance_sup, Addr, NewPort},
+ StartFunc = {httpd_instance_sup, start_link,
+ [NewConfig, AcceptTimeout,
+ {Pid, ListenSocket}, Debug]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [httpd_instance_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules};
+ {Pid, {error, Reason}} ->
+ exit(Pid, normal),
+ {error, Reason}
+ end.
+
+httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port) ->
Name = {httpd_instance_sup, Addr, Port},
StartFunc = {httpd_instance_sup, start_link,
[Config, AcceptTimeout, Debug]},
@@ -225,7 +232,8 @@ listen(Address, Port, Config) ->
SocketType = proplists:get_value(socket_type, Config, ip_comm),
case http_transport:start(SocketType) of
ok ->
- case http_transport:listen(SocketType, Address, Port) of
+ Fd = proplists:get_value(fd, Config),
+ case http_transport:listen(SocketType, Address, Port, Fd) of
{ok, ListenSocket} ->
NewConfig = proplists:delete(port, Config),
{ok, NewPort} = inet:port(ListenSocket),
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 15bfe9c621..b0b18b9c3d 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -21,7 +21,7 @@
-export([ip_address/2, lookup/2, lookup/3, multi_lookup/2,
lookup_mime/2, lookup_mime/3, lookup_mime_default/2,
lookup_mime_default/3, reason_phrase/1, message/3, rfc1123_date/0,
- rfc1123_date/1, day/1, month/1,
+ rfc1123_date/1, day/1, month/1,
flatlength/1, split_path/1, split_script_path/1,
suffix/1, split/3, uniq/1,
make_name/2,make_name/3,make_name/4,strip/1,
@@ -33,7 +33,6 @@
mime_types_validate/1, custom_date/0]).
-export([encode_hex/1, decode_hex/1]).
-
-include_lib("kernel/include/file.hrl").
ip_address({_,_,_,_} = Address, _IpFamily) ->
@@ -176,7 +175,7 @@ reason_phrase(_) -> "Internal Server Error".
%% message
message(301,URL,_) ->
- "The document has moved <A HREF=\"" ++ maybe_encode(URL) ++"\">here</A>.";
+ "The document has moved <A HREF=\""++ maybe_encode(URL) ++"\">here</A>.";
message(304, _URL,_) ->
"The document has not been changed.";
message(400, none, _) ->
@@ -202,7 +201,7 @@ message(404,RequestURI,_) ->
message(408, Timeout, _) ->
Timeout;
message(412,none,_) ->
- "The requested preconditions where false";
+ "The requested preconditions were false";
message(413, Reason,_) ->
"Entity: " ++ html_encode(Reason);
message(414,ReasonPhrase,_) ->
@@ -211,7 +210,7 @@ message(416,ReasonPhrase,_) ->
html_encode(ReasonPhrase);
message(500,_,ConfigDB) ->
- ServerAdmin = lookup(ConfigDB, server_admin, "unknown@unknown"),
+ ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"),
"The server encountered an internal error or "
"misconfiguration and was unable to complete "
"your request.<P>Please contact the server administrator "
@@ -222,12 +221,12 @@ message(500,_,ConfigDB) ->
message(501,{Method, RequestURI, HTTPVersion}, _ConfigDB) ->
if
is_atom(Method) ->
- atom_to_list(Method)++
+ atom_to_list(Method) ++
" to " ++
html_encode(RequestURI) ++
" (" ++ HTTPVersion ++ ") not supported.";
is_list(Method) ->
- Method++
+ Method ++
" to " ++
html_encode(RequestURI) ++
" (" ++ HTTPVersion ++ ") not supported."
@@ -237,12 +236,12 @@ message(503, String, _ConfigDB) ->
"This service in unavailable due to: " ++ html_encode(String).
maybe_encode(URI) ->
- case lists:member($%, URI) of
- true ->
- URI;
- false ->
- http_uri:encode(URI)
- end.
+ Decoded = try http_uri:decode(URI) of
+ N -> N
+ catch
+ error:_ -> URI
+ end,
+ http_uri:encode(Decoded).
html_encode(String) ->
try http_uri:decode(String) of
@@ -444,7 +443,7 @@ split_path(Path) ->
split_path([],SoFar) ->
{http_uri:decode(lists:reverse(SoFar)),[]};
split_path([$/|Rest],SoFar) ->
- Path = http_uri:decode(lists:reverse(SoFar)),
+ Path=http_uri:decode(lists:reverse(SoFar)),
case file:read_file_info(Path) of
{ok,FileInfo} when FileInfo#file_info.type =:= regular ->
{Path,[$/|Rest]};
@@ -631,7 +630,6 @@ hexlist_to_integer(List)->
%%----------------------------------------------------------------------
%%Converts an integer to an hexlist
%%----------------------------------------------------------------------
-
integer_to_hexlist(Num) when is_integer(Num) ->
http_util:integer_to_hexlist(Num).
@@ -756,7 +754,6 @@ valid_accept_timeout(A) ->
valid_config(_) ->
ok.
-
%%----------------------------------------------------------------------
%% Enable debugging,
%%----------------------------------------------------------------------
diff --git a/lib/inets/src/http_server/mod_actions.erl b/lib/inets/src/http_server/mod_actions.erl
index d50ed4b16c..c3946ff9b4 100644
--- a/lib/inets/src/http_server/mod_actions.erl
+++ b/lib/inets/src/http_server/mod_actions.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -21,6 +21,7 @@
-export([do/1,load/2, store/2]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
%% do
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl
index 41fcdb5e3a..0b9fe4cfe0 100644
--- a/lib/inets/src/http_server/mod_alias.erl
+++ b/lib/inets/src/http_server/mod_alias.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -104,6 +104,19 @@ real_name(ConfigDB, RequestURI, []) ->
httpd_util:split_path(default_index(ConfigDB, RealName)),
{ShortPath, Path, AfterPath};
+real_name(ConfigDB, RequestURI, [{MP,Replacement}|Rest])
+ when element(1, MP) =:= re_pattern ->
+ case re:run(RequestURI, MP, [{capture,[]}]) of
+ match ->
+ NewURI = re:replace(RequestURI, MP, Replacement, [{return,list}]),
+ {ShortPath,_} = httpd_util:split_path(NewURI),
+ {Path,AfterPath} =
+ httpd_util:split_path(default_index(ConfigDB, NewURI)),
+ {ShortPath, Path, AfterPath};
+ nomatch ->
+ real_name(ConfigDB, RequestURI, Rest)
+ end;
+
real_name(ConfigDB, RequestURI, [{FakeName,RealName}|Rest]) ->
case inets_regexp:match(RequestURI, "^" ++ FakeName) of
{match, _, _} ->
@@ -121,6 +134,18 @@ real_name(ConfigDB, RequestURI, [{FakeName,RealName}|Rest]) ->
real_script_name(_ConfigDB, _RequestURI, []) ->
not_a_script;
+
+real_script_name(ConfigDB, RequestURI, [{MP,Replacement} | Rest])
+ when element(1, MP) =:= re_pattern ->
+ case re:run(RequestURI, MP, [{capture,[]}]) of
+ match ->
+ ActualName =
+ re:replace(RequestURI, MP, Replacement, [{return,list}]),
+ httpd_util:split_script_path(default_index(ConfigDB, ActualName));
+ nomatch ->
+ real_script_name(ConfigDB, RequestURI, Rest)
+ end;
+
real_script_name(ConfigDB, RequestURI, [{FakeName,RealName} | Rest]) ->
case inets_regexp:match(RequestURI, "^" ++ FakeName) of
{match,_,_} ->
@@ -181,6 +206,8 @@ load("Alias " ++ Alias, []) ->
{ok, _} ->
{error,?NICE(httpd_conf:clean(Alias)++" is an invalid Alias")}
end;
+load("ReWrite " ++ Rule, Acc) ->
+ load_re_write(Rule, Acc, "ReWrite", re_write);
load("ScriptAlias " ++ ScriptAlias, []) ->
case inets_regexp:split(ScriptAlias, " ") of
{ok, [FakeName, RealName]} ->
@@ -190,6 +217,24 @@ load("ScriptAlias " ++ ScriptAlias, []) ->
{ok, _} ->
{error, ?NICE(httpd_conf:clean(ScriptAlias)++
" is an invalid ScriptAlias")}
+ end;
+load("ScriptReWrite " ++ Rule, Acc) ->
+ load_re_write(Rule, Acc, "ScriptReWrite", script_re_write).
+
+load_re_write(Rule0, Acc, Type, Tag) ->
+ case lists:dropwhile(
+ fun ($\s) -> true; ($\t) -> true; (_) -> false end,
+ Rule0) of
+ "" ->
+ {error, ?NICE(httpd_conf:clean(Rule0)++" is an invalid "++Type)};
+ Rule ->
+ case string:chr(Rule, $\s) of
+ 0 ->
+ {ok, Acc, {Tag, {Rule, ""}}};
+ N ->
+ {Re, [_|Replacement]} = lists:split(N-1, Rule),
+ {ok, Acc, {Tag, {Re, Replacement}}}
+ end
end.
store({directory_index, Value} = Conf, _) when is_list(Value) ->
@@ -201,16 +246,36 @@ store({directory_index, Value} = Conf, _) when is_list(Value) ->
end;
store({directory_index, Value}, _) ->
{error, {wrong_type, {directory_index, Value}}};
-store({alias, {Fake, Real}} = Conf, _)
- when is_list(Fake) andalso is_list(Real) ->
+store({alias, {Fake, Real}} = Conf, _)
+ when is_list(Fake), is_list(Real) ->
{ok, Conf};
store({alias, Value}, _) ->
{error, {wrong_type, {alias, Value}}};
+store({re_write, {Re, Replacement}} = Conf, _)
+ when is_list(Re), is_list(Replacement) ->
+ case re:compile(Re) of
+ {ok, MP} ->
+ {ok, {alias, {MP, Replacement}}};
+ {error,_} ->
+ {error, {re_compile, Conf}}
+ end;
+store({re_write, _} = Conf, _) ->
+ {error, {wrong_type, Conf}};
store({script_alias, {Fake, Real}} = Conf, _)
- when is_list(Fake) andalso is_list(Real) ->
+ when is_list(Fake), is_list(Real) ->
{ok, Conf};
store({script_alias, Value}, _) ->
- {error, {wrong_type, {script_alias, Value}}}.
+ {error, {wrong_type, {script_alias, Value}}};
+store({script_re_write, {Re, Replacement}} = Conf, _)
+ when is_list(Re), is_list(Replacement) ->
+ case re:compile(Re) of
+ {ok, MP} ->
+ {ok, {script_alias, {MP, Replacement}}};
+ {error,_} ->
+ {error, {re_compile, Conf}}
+ end;
+store({script_re_write, _} = Conf, _) ->
+ {error, {wrong_type, Conf}}.
is_directory_index_list([]) ->
true;
diff --git a/lib/inets/src/http_server/mod_auth.erl b/lib/inets/src/http_server/mod_auth.erl
index b1d8b03fe4..85a87ab884 100644
--- a/lib/inets/src/http_server/mod_auth.erl
+++ b/lib/inets/src/http_server/mod_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
diff --git a/lib/inets/src/http_server/mod_auth.hrl b/lib/inets/src/http_server/mod_auth.hrl
index 9b316cecc4..674e6d1652 100644
--- a/lib/inets/src/http_server/mod_auth.hrl
+++ b/lib/inets/src/http_server/mod_auth.hrl
@@ -1,29 +1,27 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
-%% %CopyrightEnd%
%%
+%% %CopyrightEnd%
%%
+%% This is a simple wrapper for code that has not been updated to
+%% handle the move of this file to the include dir.
+
+-ifndef(src_mod_auth_hrl).
+-define(src_mod_auth_hrl, true).
--record(httpd_user,
- {username,
- password,
- user_data}).
+-include_lib("inets/include/mod_auth.hrl").
--record(httpd_group,
- {name,
- userlist}).
-
+-endif. % -ifdef(src_mod_auth_hrl).
diff --git a/lib/inets/src/http_server/mod_auth_dets.erl b/lib/inets/src/http_server/mod_auth_dets.erl
index 2abf5c517a..a48725d5d9 100644
--- a/lib/inets/src/http_server/mod_auth_dets.erl
+++ b/lib/inets/src/http_server/mod_auth_dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% 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
@@ -35,7 +35,7 @@
-export([store_directory_data/3]).
-include("httpd.hrl").
--include("inets_internal.hrl").
+-include("httpd_internal.hrl").
-include("mod_auth.hrl").
store_directory_data(_Directory, DirData, Server_root) ->
diff --git a/lib/inets/src/http_server/mod_auth_mnesia.erl b/lib/inets/src/http_server/mod_auth_mnesia.erl
index ffe028617b..91beb0e062 100644
--- a/lib/inets/src/http_server/mod_auth_mnesia.erl
+++ b/lib/inets/src/http_server/mod_auth_mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% 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
@@ -55,7 +55,7 @@ store_directory_data(_Directory, _DirData, _Server_root) ->
%% API
%%
-%% Compability API
+%% Compatibility API
store_user(UserName, Password, Port, Dir, _AccessPassword) ->
%% AccessPassword is ignored - was not used in previous version
diff --git a/lib/inets/src/http_server/mod_auth_plain.erl b/lib/inets/src/http_server/mod_auth_plain.erl
index 12342ba8da..c0a83711ba 100644
--- a/lib/inets/src/http_server/mod_auth_plain.erl
+++ b/lib/inets/src/http_server/mod_auth_plain.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% 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
@@ -24,6 +24,7 @@
-include("httpd_internal.hrl").
-include("inets_internal.hrl").
+
-define(VMODULE,"AUTH_PLAIN").
%% Internal API
diff --git a/lib/inets/src/http_server/mod_auth_server.erl b/lib/inets/src/http_server/mod_auth_server.erl
index fc50356838..947273bd9e 100644
--- a/lib/inets/src/http_server/mod_auth_server.erl
+++ b/lib/inets/src/http_server/mod_auth_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% 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
diff --git a/lib/inets/src/http_server/mod_cgi.erl b/lib/inets/src/http_server/mod_cgi.erl
index 33605b9698..c854166c29 100644
--- a/lib/inets/src/http_server/mod_cgi.erl
+++ b/lib/inets/src/http_server/mod_cgi.erl
@@ -27,6 +27,7 @@
-export([do/1, load/2, store/2]).
-include("http_internal.hrl").
+-include("httpd_internal.hrl").
-include("httpd.hrl").
-define(VMODULE,"CGI").
diff --git a/lib/inets/src/http_server/mod_dir.erl b/lib/inets/src/http_server/mod_dir.erl
index 35e9de24e2..d791ee28e9 100644
--- a/lib/inets/src/http_server/mod_dir.erl
+++ b/lib/inets/src/http_server/mod_dir.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -19,11 +19,11 @@
%%
-module(mod_dir).
--export([do/1]).
-
-include("httpd.hrl").
-include("httpd_internal.hrl").
+-export([do/1]).
+
%% do
do(Info) ->
diff --git a/lib/inets/src/http_server/mod_disk_log.erl b/lib/inets/src/http_server/mod_disk_log.erl
index 95e0d00c70..5a3766de66 100644
--- a/lib/inets/src/http_server/mod_disk_log.erl
+++ b/lib/inets/src/http_server/mod_disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -28,7 +28,7 @@
-define(VMODULE,"DISK_LOG").
-include("httpd.hrl").
-
+-include("httpd_internal.hrl").
%%%=========================================================================
%%% API
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index bbdb67bb0e..e36c33b282 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -29,6 +29,7 @@
-export([do/1, load/2, store/2]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
-include("inets_internal.hrl").
-define(VMODULE,"ESI").
@@ -38,6 +39,7 @@
%%%=========================================================================
%%% API
%%%=========================================================================
+
%%--------------------------------------------------------------------------
%% deliver(SessionID, Data) -> ok | {error, bad_sessionID}
%% SessionID = pid()
@@ -49,7 +51,7 @@
%% request handling process so it can forward it to the client.
%%-------------------------------------------------------------------------
deliver(SessionID, Data) when is_pid(SessionID) ->
- SessionID ! {ok, Data},
+ SessionID ! {esi_data, Data},
ok;
deliver(_SessionID, _Data) ->
{error, bad_sessionID}.
@@ -66,6 +68,7 @@ deliver(_SessionID, _Data) ->
%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
%%-------------------------------------------------------------------------
do(ModData) ->
+ ?hdrt("do", []),
case proplists:get_value(status, ModData#mod.data) of
{_StatusCode, _PhraseArgs, _Reason} ->
{proceed, ModData#mod.data};
@@ -185,6 +188,7 @@ store({erl_script_nocache, Value}, _) ->
%%% Internal functions
%%%========================================================================
generate_response(ModData) ->
+ ?hdrt("generate response", []),
case scheme(ModData#mod.request_uri, ModData#mod.config_db) of
{eval, ESIBody, Modules} ->
eval(ModData, ESIBody, Modules);
@@ -236,6 +240,7 @@ alias_match_str(Alias, eval_script_alias) ->
erl(#mod{method = Method} = ModData, ESIBody, Modules)
when (Method =:= "GET") orelse (Method =:= "HEAD") ->
+ ?hdrt("erl", [{method, Method}]),
case httpd_util:split(ESIBody,":|%3A|/",2) of
{ok, [ModuleName, FuncAndInput]} ->
case httpd_util:split(FuncAndInput,"[\?/]",2) of
@@ -261,6 +266,7 @@ erl(#mod{request_uri = ReqUri,
method = "PUT",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
+ ?hdrt("erl", [{method, put}]),
{proceed, [{status,{501,{"PUT", ReqUri, Version},
?NICE("Erl mechanism doesn't support method PUT")}}|
Data]};
@@ -269,12 +275,14 @@ erl(#mod{request_uri = ReqUri,
method = "DELETE",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
+ ?hdrt("erl", [{method, delete}]),
{proceed,[{status,{501,{"DELETE", ReqUri, Version},
?NICE("Erl mechanism doesn't support method DELETE")}}|
Data]};
erl(#mod{method = "POST",
entity_body = Body} = ModData, ESIBody, Modules) ->
+ ?hdrt("erl", [{method, post}]),
case httpd_util:split(ESIBody,":|%3A|/",2) of
{ok,[ModuleName, Function]} ->
generate_webpage(ModData, ESIBody, Modules,
@@ -290,6 +298,7 @@ generate_webpage(ModData, ESIBody, [all], Module, FunctionName,
FunctionName, Input, ScriptElements);
generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
Input, ScriptElements) ->
+ ?hdrt("generate webpage", []),
Function = list_to_atom(FunctionName),
case lists:member(Module, Modules) of
true ->
@@ -310,8 +319,9 @@ generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
%% Old API that waits for the dymnamic webpage to be totally generated
%% before anythig is sent back to the client.
-erl_scheme_webpage_whole(Module, Function, Env, Input, ModData) ->
- case (catch Module:Function(Env, Input)) of
+erl_scheme_webpage_whole(Mod, Func, Env, Input, ModData) ->
+ ?hdrt("erl_scheme_webpage_whole", [{module, Mod}, {function, Func}]),
+ case (catch Mod:Func(Env, Input)) of
{'EXIT',{undef, _}} ->
{proceed, [{status, {404, ModData#mod.request_uri, "Not found"}}
| ModData#mod.data]};
@@ -348,6 +358,7 @@ erl_scheme_webpage_whole(Module, Function, Env, Input, ModData) ->
%% in small chunks at the time during generation.
erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
process_flag(trap_exit, true),
+ ?hdrt("erl_scheme_webpage_chunk", [{module, Mod}, {function, Func}]),
Self = self(),
%% Spawn worker that generates the webpage.
%% It would be nicer to use erlang:function_exported/3 but if the
@@ -373,9 +384,12 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid) ->
deliver_webpage_chunk(ModData, Pid, Timeout).
deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
+ ?hdrt("deliver_webpage_chunk", [{timeout, Timeout}]),
case receive_headers(Timeout) of
{error, Reason} ->
%% Happens when webpage generator callback/3 is undefined
+ ?hdrv("deliver_webpage_chunk - failed receiving headers",
+ [{reason, Reason}]),
{error, Reason};
{Headers, Body} ->
case httpd_esi:handle_headers(Headers) of
@@ -400,7 +414,8 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
IsDisableChunkedSend)
end;
timeout ->
- send_headers(ModData, {504, "Timeout"},[{"connection", "close"}]),
+ ?hdrv("deliver_webpage_chunk - timeout", []),
+ send_headers(ModData, 504, [{"connection", "close"}]),
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket),
process_flag(trap_exit,false),
{proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]}
@@ -408,11 +423,17 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
receive_headers(Timeout) ->
receive
+ {esi_data, Chunk} ->
+ ?hdrt("receive_headers - received esi data (esi)", []),
+ httpd_esi:parse_headers(lists:flatten(Chunk));
{ok, Chunk} ->
+ ?hdrt("receive_headers - received esi data (ok)", []),
httpd_esi:parse_headers(lists:flatten(Chunk));
{'EXIT', Pid, erl_scheme_webpage_chunk_undefined} when is_pid(Pid) ->
+ ?hdrd("receive_headers - exit:chunk-undef", []),
{error, erl_scheme_webpage_chunk_undefined};
{'EXIT', Pid, Reason} when is_pid(Pid) ->
+ ?hdrv("receive_headers - exit", [{reason, Reason}]),
exit({mod_esi_linked_process_died, Pid, Reason})
after Timeout ->
timeout
@@ -428,19 +449,33 @@ handle_body(_, #mod{method = "HEAD"} = ModData, _, _, Size, _) ->
{proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]};
handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
+ ?hdrt("handle_body - send chunk", [{timeout, Timeout}, {size, Size}]),
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
+ {esi_data, Data} when is_binary(Data) ->
+ ?hdrt("handle_body - received binary data (esi)", []),
+ handle_body(Pid, ModData, Data, Timeout, Size + byte_size(Data),
+ IsDisableChunkedSend);
+ {esi_data, Data} ->
+ ?hdrt("handle_body - received data (esi)", []),
+ handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
+ IsDisableChunkedSend);
{ok, Data} ->
+ ?hdrt("handle_body - received data (ok)", []),
handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
IsDisableChunkedSend);
{'EXIT', Pid, normal} when is_pid(Pid) ->
+ ?hdrt("handle_body - exit:normal", []),
httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
{proceed, [{response, {already_sent, 200, Size}} |
ModData#mod.data]};
{'EXIT', Pid, Reason} when is_pid(Pid) ->
+ ?hdrv("handle_body - exit", [{reason, Reason}]),
httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
exit({mod_esi_linked_process_died, Pid, Reason})
+
after Timeout ->
+ ?hdrv("handle_body - timeout", []),
process_flag(trap_exit,false),
httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
exit({mod_esi_linked_process_timeout, Pid})
@@ -474,6 +509,7 @@ eval(#mod{request_uri = ReqUri,
method = "PUT",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
+ ?hdrt("eval", [{method, put}]),
{proceed,[{status,{501,{"PUT", ReqUri, Version},
?NICE("Eval mechanism doesn't support method PUT")}}|
Data]};
@@ -482,6 +518,7 @@ eval(#mod{request_uri = ReqUri,
method = "DELETE",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
+ ?hdrt("eval", [{method, delete}]),
{proceed,[{status,{501,{"DELETE", ReqUri, Version},
?NICE("Eval mechanism doesn't support method DELETE")}}|
Data]};
@@ -490,12 +527,14 @@ eval(#mod{request_uri = ReqUri,
method = "POST",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
+ ?hdrt("eval", [{method, post}]),
{proceed,[{status,{501,{"POST", ReqUri, Version},
?NICE("Eval mechanism doesn't support method POST")}}|
Data]};
eval(#mod{method = Method} = ModData, ESIBody, Modules)
- when Method == "GET"; Method == "HEAD" ->
+ when (Method =:= "GET") orelse (Method =:= "HEAD") ->
+ ?hdrt("eval", [{method, Method}]),
case is_authorized(ESIBody, Modules) of
true ->
case generate_webpage(ESIBody) of
diff --git a/lib/inets/src/http_server/mod_get.erl b/lib/inets/src/http_server/mod_get.erl
index 9fd1fcec47..5cb30e3d97 100644
--- a/lib/inets/src/http_server/mod_get.erl
+++ b/lib/inets/src/http_server/mod_get.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -20,7 +20,7 @@
-module(mod_get).
-export([do/1]).
-include("httpd.hrl").
-
+-include("httpd_internal.hrl").
%% do
do(Info) ->
diff --git a/lib/inets/src/http_server/mod_head.erl b/lib/inets/src/http_server/mod_head.erl
index 8b08d61651..c346fd4d23 100644
--- a/lib/inets/src/http_server/mod_head.erl
+++ b/lib/inets/src/http_server/mod_head.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
diff --git a/lib/inets/src/http_server/mod_htaccess.erl b/lib/inets/src/http_server/mod_htaccess.erl
index d8835198f5..e1f66d01c8 100644
--- a/lib/inets/src/http_server/mod_htaccess.erl
+++ b/lib/inets/src/http_server/mod_htaccess.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% 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
@@ -23,6 +23,7 @@
-export([do/1, load/2, store/2]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Public methods that interface the eswapi %%
diff --git a/lib/inets/src/http_server/mod_include.erl b/lib/inets/src/http_server/mod_include.erl
index 790bf8f937..35f45bdd33 100644
--- a/lib/inets/src/http_server/mod_include.erl
+++ b/lib/inets/src/http_server/mod_include.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -21,6 +21,7 @@
-export([do/1,parse/2,config/6,include/6,echo/6,fsize/6,flastmod/6,exec/6]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
-define(VMODULE,"INCLUDE").
diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl
index de24d5a569..c8a2ec0dc4 100644
--- a/lib/inets/src/http_server/mod_log.erl
+++ b/lib/inets/src/http_server/mod_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% 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
@@ -26,6 +26,7 @@
-export([do/1, load/2, store/2, remove/1]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
-define(VMODULE,"LOG").
%%%=========================================================================
diff --git a/lib/inets/src/http_server/mod_range.erl b/lib/inets/src/http_server/mod_range.erl
index 0698fb9099..a0408cba79 100644
--- a/lib/inets/src/http_server/mod_range.erl
+++ b/lib/inets/src/http_server/mod_range.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% 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
@@ -20,7 +20,7 @@
-module(mod_range).
-export([do/1]).
-include("httpd.hrl").
-
+-include("httpd_internal.hrl").
%% do
do(Info) ->
diff --git a/lib/inets/src/http_server/mod_responsecontrol.erl b/lib/inets/src/http_server/mod_responsecontrol.erl
index 79e2e1bdba..5d5b60cdbd 100644
--- a/lib/inets/src/http_server/mod_responsecontrol.erl
+++ b/lib/inets/src/http_server/mod_responsecontrol.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% 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
@@ -22,6 +22,7 @@
-export([do/1]).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
do(Info) ->
?DEBUG("do -> response_control",[]),
diff --git a/lib/inets/src/http_server/mod_security.erl b/lib/inets/src/http_server/mod_security.erl
index 5cdbeb9792..41988732ad 100644
--- a/lib/inets/src/http_server/mod_security.erl
+++ b/lib/inets/src/http_server/mod_security.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% 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
diff --git a/lib/inets/src/http_server/mod_security_server.erl b/lib/inets/src/http_server/mod_security_server.erl
index ca8bee0c8e..784b3eba70 100644
--- a/lib/inets/src/http_server/mod_security_server.erl
+++ b/lib/inets/src/http_server/mod_security_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% 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
diff --git a/lib/inets/src/http_server/mod_trace.erl b/lib/inets/src/http_server/mod_trace.erl
index df482228d8..7233925783 100644
--- a/lib/inets/src/http_server/mod_trace.erl
+++ b/lib/inets/src/http_server/mod_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
%%
%% 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
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index 33c9e34a3a..20e22917e2 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -47,7 +47,9 @@ MODULES = \
inets_sup \
inets_regexp
-HRL_FILES = inets_internal.hrl
+INTERNAL_HRL_FILES = inets_internal.hrl
+EXTERNAL_HRL_FILES = ../../include/httpd.hrl \
+ ../../include/mod_auth.hrl
ERL_FILES = $(MODULES:%=%.erl)
@@ -67,18 +69,14 @@ APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
# ----------------------------------------------------
-# INETS FLAGS
-# ----------------------------------------------------
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
-
-
-# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += $(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
+include inets.mk
+
+ERL_COMPILE_FLAGS += \
+ $(INETS_FLAGS) \
+ $(INETS_ERL_COMPILE_FLAGS)
# ----------------------------------------------------
@@ -112,7 +110,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/inets_app
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/inets_app
+ $(INSTALL_DIR) $(RELSYSDIR)/include
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
$(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 04f6365b98..cb036157a5 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -107,5 +107,6 @@
tftp_sup
]},
{registered,[inets_sup, httpc_manager]},
+ %% If the "new" ssl is used then 'crypto' must be started before inets.
{applications,[kernel,stdlib]},
{mod,{inets_app,[]}}]}.
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 5b04c7ed93..ede0c10bef 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -1,117 +1,129 @@
%% This is an -*- erlang -*- file.
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
{"%VSN%",
[
- {"5.3.5",
+ {"5.7.1",
[
+ {load_module, http_uri, soft_purge, soft_purge, []},
{load_module, http_util, soft_purge, soft_purge, []},
{load_module, httpd_util, soft_purge, soft_purge, [http_util]},
- {load_module, httpd_file, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge, []}
+ {load_module, httpd_file, soft_purge, soft_purge, []},
+ {load_module, httpd_request, soft_purge, soft_purge, []}
]
},
- {"5.3.4",
+ {"5.7",
[
- {restart_application, inets}
+ {load_module, http_uri, soft_purge, soft_purge, []},
+ {load_module, httpd_util, soft_purge, soft_purge, [http_util]},
+ {load_module, httpd_file, soft_purge, soft_purge, []}
+ {load_module, httpd_request, soft_purge, soft_purge, []},
+ {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]},
+ {load_module, http_util, soft_purge, soft_purge, []}
]
},
- {"5.3.3",
- [
- {restart_application, inets}
+ {"5.6",
+ [
+ {load_module, http_uri, soft_purge, soft_purge, []},
+ {load_module, httpd_util, soft_purge, soft_purge, [http_util]},
+ {load_module, httpd_file, soft_purge, soft_purge, []}
+ {load_module, httpd_request, soft_purge, soft_purge, []},
+ {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
+ {load_module, http_transport, soft_purge, soft_purge, [http_transport]},
+ {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]},
+ {load_module, http_util, soft_purge, soft_purge, []},
+ {update, httpc_handler, soft, soft_purge, soft_purge, []},
+ {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]},
+ {update, ftp, soft, soft_purge, soft_purge, []}
]
},
- {"5.3.2",
+ {"5.5.2",
[
{restart_application, inets}
]
},
- {"5.3.1",
+ {"5.5.1",
[
{restart_application, inets}
]
},
- {"5.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.2",
- [
- {restart_application, inets}
- ]
- },
- {"5.1.3",
+ {"5.5",
[
{restart_application, inets}
]
},
- {"5.1.2",
+ {"5.4",
[
{restart_application, inets}
]
- }
+ }
],
- [
- {"5.3.5",
+ [
+ {"5.7.1",
[
+ {load_module, http_uri, soft_purge, soft_purge, []},
{load_module, http_util, soft_purge, soft_purge, []},
{load_module, httpd_util, soft_purge, soft_purge, [http_util]},
- {load_module, httpd_file, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge, []}
+ {load_module, httpd_file, soft_purge, soft_purge, []},
+ {load_module, httpd_request, soft_purge, soft_purge, []},
]
},
- {"5.3.4",
+ {"5.7",
[
- {restart_application, inets}
- ]
- },
- {"5.3.3",
- [
- {restart_application, inets}
- ]
- },
- {"5.3.2",
- [
- {restart_application, inets}
+ {load_module, http_uri, soft_purge, soft_purge, []},
+ {load_module, httpd_util, soft_purge, soft_purge, [http_util]},
+ {load_module, httpd_file, soft_purge, soft_purge, []}
+ {load_module, httpd_request, soft_purge, soft_purge, []},
+ {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]},
+ {load_module, http_util, soft_purge, soft_purge, []}
]
},
- {"5.3.1",
- [
- {restart_application, inets}
+ {"5.6",
+ [
+ {load_module, http_uri, soft_purge, soft_purge, []},
+ {load_module, httpd_util, soft_purge, soft_purge, [http_util]},
+ {load_module, httpd_file, soft_purge, soft_purge, []}
+ {load_module, httpd_request, soft_purge, soft_purge, []},
+ {load_module, httpc, soft_purge, soft_purge, [httpc_manager]},
+ {load_module, http_transport, soft_purge, soft_purge, [http_transport]},
+ {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]},
+ {load_module, http_util, soft_purge, soft_purge, []},
+ {update, httpc_handler, soft, soft_purge, soft_purge, []},
+ {update, httpc_manager, soft, soft_purge, soft_purge, [httpc_handler]},
+ {update, ftp, soft, soft_purge, soft_purge, []}
]
},
- {"5.3",
+ {"5.5.2",
[
{restart_application, inets}
]
},
- {"5.2",
+ {"5.5.1",
[
{restart_application, inets}
]
},
- {"5.1.3",
+ {"5.5",
[
{restart_application, inets}
]
- },
- {"5.1.2",
+ },
+ {"5.4",
[
{restart_application, inets}
]
diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk
new file mode 100644
index 0000000000..b6e9fe1d96
--- /dev/null
+++ b/lib/inets/src/inets_app/inets.mk
@@ -0,0 +1,45 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010. All Rights Reserved.
+#
+# 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 online 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.
+#
+# %CopyrightEnd%
+
+ifeq ($(INETS_TRACE), io)
+ERL_COMPILE_FLAGS += -Dinets_trace_io
+endif
+
+ifeq ($(INETS_DEBUG), true)
+ERL_COMPILE_FLAGS += -Dinets_debug
+endif
+
+ifeq ($(USE_INETS_HIPE), true)
+ERL_COMPILE_FLAGS += +native
+endif
+
+ifeq ($(WARN_UNUSED_WARS), true)
+ERL_COMPILE_FLAGS += +warn_unused_vars
+endif
+
+INETS_APP_VSN_COMPILE_FLAGS = \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,app_vsn,$(APP_VSN)}'
+
+INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
+
+INETS_ERL_COMPILE_FLAGS += \
+ -pa $(ERL_TOP)/lib/inets/ebin \
+ $(INETS_APP_VSN_COMPILE_FLAGS)
+
diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl
index 3499314d54..e9eb9892f2 100644
--- a/lib/inets/src/inets_app/inets_service.erl
+++ b/lib/inets/src/inets_app/inets_service.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%%
%% 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 online 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.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -61,5 +61,5 @@ behaviour_info(_) ->
%% service_info() -> [{Property, Value}] | {error, Reason}
-%% ex: http:service_info() -> [{profile, ProfileName}]
+%% ex: httpc:service_info() -> [{profile, ProfileName}]
%% httpd:service_info() -> [{host, Host}, {port, Port}]
diff --git a/lib/inets/src/tftp/Makefile b/lib/inets/src/tftp/Makefile
index b4339da1e2..759b70c8e4 100644
--- a/lib/inets/src/tftp/Makefile
+++ b/lib/inets/src/tftp/Makefile
@@ -56,17 +56,16 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
-# INETS FLAGS
+# FLAGS
# ----------------------------------------------------
-INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
+include ../inets_app/inets.mk
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS += $(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
+ERL_COMPILE_FLAGS += \
+ $(INETS_FLAGS) \
+ $(INETS_ERL_COMPILE_FLAGS) \
+ -I../../include \
+ -I../inets_app
# ----------------------------------------------------
@@ -87,9 +86,10 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/tftp
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src/tftp
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
release_docs_spec: