📄 httpd_conf.erl
字号:
%% load_mime_types/1 -> {ok, MimeTypes} | {error, Reason}%%load_mime_types(MimeTypesFile) -> case file:open(MimeTypesFile, read) of {ok, Stream} -> parse_mime_types(Stream, []); {error, _} -> {error, ?NICE("Can't open " ++ MimeTypesFile)} end.%% Phase 2: Storestore(ConfigList) -> Modules = httpd_util:key1search(ConfigList, modules, []), Port = httpd_util:key1search(ConfigList, port), Addr = httpd_util:key1search(ConfigList,bind_address), Name = httpd_util:make_name("httpd_conf",Addr,Port), ConfigDB = ets:new(Name, [named_table, bag, protected]), store(ConfigDB, ConfigList, lists:append(Modules,[?MODULE]),ConfigList).store({mime_types,MimeTypesList},ConfigList) -> Port = httpd_util:key1search(ConfigList, port), Addr = httpd_util:key1search(ConfigList, bind_address), Name = httpd_util:make_name("httpd_mime",Addr,Port), {ok, MimeTypesDB} = store_mime_types(Name,MimeTypesList), {ok, {mime_types,MimeTypesDB}};store(ConfigListEntry, _ConfigList) -> {ok, ConfigListEntry}.%% Phase 3: Removeremove_all(ConfigDB) -> Modules = httpd_util:lookup(ConfigDB,modules,[]), remove_traverse(ConfigDB, lists:append(Modules,[?MODULE])).remove(ConfigDB) -> ets:delete(ConfigDB), ok.config(ConfigDB) -> case httpd_util:lookup(ConfigDB,com_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.%%%========================================================================%%% Internal functions%%%========================================================================%%% Phase 1 Load:bootstrap([]) -> {error, ?NICE("Modules must be specified in the config file")};bootstrap([Line|Config]) -> case Line of "Modules " ++ Modules -> {ok, ModuleList} = regexp:split(Modules," "), TheMods = [list_to_atom(X) || X <- ModuleList], case verify_modules(TheMods) of ok -> {ok, TheMods}; {error, Reason} -> {error, Reason} end; _ -> bootstrap(Config) end.load_config(Config, Modules) -> %% Create default contexts for all modules Contexts = lists:duplicate(length(Modules), []), load_config(Config, Modules, Contexts, []).load_config([], _Modules, _Contexts, ConfigList) -> case a_must(ConfigList, [server_name,port,server_root,document_root]) of ok -> {ok, ConfigList}; {missing, Directive} -> {error, ?NICE(atom_to_list(Directive)++ " must be specified in the config file")} end;load_config([Line|Config], Modules, Contexts, ConfigList) -> case load_traverse(Line, Contexts, Modules, [], ConfigList, no) of {ok, NewContexts, NewConfigList} -> load_config(Config, Modules, NewContexts, NewConfigList); {error, Reason} -> {error, Reason} end.%% This loads the config file into each module specified by Modules%% Each module has its own context that is passed to and (optionally)%% returned by the modules load function. The module can also return%% a ConfigEntry, which will be added to the global configuration%% list.%% All configuration directives are guaranteed to be passed to all%% modules. Each module only implements the function clauses of%% the load function for the configuration directives it supports,%% it's ok if an apply returns {'EXIT', {function_clause, ..}}.load_traverse(Line, [], [], _NewContexts, _ConfigList, no) -> {error, ?NICE("Configuration directive not recognized: "++Line)};load_traverse(_Line, [], [], NewContexts, ConfigList, yes) -> {ok, lists:reverse(NewContexts), ConfigList};load_traverse(Line, [Context|Contexts], [Module|Modules], NewContexts, ConfigList, State) -> case catch apply(Module, load, [Line, Context]) of {'EXIT', {function_clause, _}} -> load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList, State); {'EXIT',{undef, _}} -> load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList,yes); {'EXIT', Reason} -> error_logger:error_report({'EXIT', Reason}), load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList, State); {ok, NewContext} -> load_traverse(Line, Contexts, Modules, [NewContext|NewContexts], ConfigList,yes); {ok, NewContext, ConfigEntry} when tuple(ConfigEntry) -> load_traverse(Line, Contexts, Modules, [NewContext|NewContexts], [ConfigEntry|ConfigList], yes); {ok, NewContext, ConfigEntry} when list(ConfigEntry) -> load_traverse(Line, Contexts, Modules, [NewContext|NewContexts], lists:append(ConfigEntry, ConfigList), yes); {error, Reason} -> {error, Reason} end. %% Verifies that all specified modules are available.verify_modules([]) -> ok;verify_modules([Mod|Rest]) -> case code:which(Mod) of non_existing -> {error, ?NICE(atom_to_list(Mod)++" does not exist")}; _Path -> verify_modules(Rest) end.%% Reads the entire configuration file and returns list of strings or%% and error.read_config_file(FileName) -> case file:open(FileName, read) of {ok, Stream} -> read_config_file(Stream, []); {error, _Reason} -> {error, ?NICE("Cannot open "++FileName)} end.read_config_file(Stream, SoFar) -> case io:get_line(Stream, []) of eof -> file:close(Stream), {ok, lists:reverse(SoFar)}; {error, Reason} -> file:close(Stream), {error, Reason}; [$#|_Rest] -> %% Ignore commented lines for efficiency later .. read_config_file(Stream, SoFar); Line -> {ok, NewLine, _}=regexp:sub(clean(Line),"[\t\r\f ]"," "), case NewLine of [] -> %% Also ignore empty lines .. read_config_file(Stream, SoFar); _Other -> read_config_file(Stream, [NewLine|SoFar]) end end.parse_mime_types(Stream,MimeTypesList) -> Line= case io:get_line(Stream,'') of eof -> eof; String -> clean(String) end, parse_mime_types(Stream, MimeTypesList, Line).parse_mime_types(Stream, MimeTypesList, eof) -> file:close(Stream), {ok, MimeTypesList};parse_mime_types(Stream, MimeTypesList, "") -> parse_mime_types(Stream, MimeTypesList);parse_mime_types(Stream, MimeTypesList, [$#|_]) -> parse_mime_types(Stream, MimeTypesList);parse_mime_types(Stream, MimeTypesList, Line) -> case regexp:split(Line, " ") of {ok, [NewMimeType|Suffixes]} -> parse_mime_types(Stream, lists:append(suffixes(NewMimeType,Suffixes), MimeTypesList)); {ok, _} -> {error, ?NICE(Line)} end.suffixes(_MimeType,[]) -> [];suffixes(MimeType,[Suffix|Rest]) -> [{Suffix,MimeType}|suffixes(MimeType,Rest)].a_must(_ConfigList,[]) -> ok;a_must(ConfigList,[Directive|Rest]) -> case httpd_util:key1search(ConfigList,Directive) of undefined -> {missing,Directive}; _ -> a_must(ConfigList,Rest) end.%% Pahse 2: storestore(ConfigDB, _ConfigList, _Modules,[]) -> {ok, ConfigDB};store(ConfigDB, ConfigList, Modules, [ConfigListEntry|Rest]) -> case store_traverse(ConfigListEntry,ConfigList,Modules) of {ok, ConfigDBEntry} when tuple(ConfigDBEntry) -> ets:insert(ConfigDB,ConfigDBEntry), store(ConfigDB,ConfigList,Modules,Rest); {ok, ConfigDBEntry} when list(ConfigDBEntry) -> lists:foreach(fun(Entry) -> ets:insert(ConfigDB,Entry) end,ConfigDBEntry), store(ConfigDB,ConfigList,Modules,Rest); {error, Reason} -> {error,Reason} end.store_traverse(_ConfigListEntry, _ConfigList,[]) -> {error,?NICE("Unable to store configuration...")};store_traverse(ConfigListEntry, ConfigList, [Module|Rest]) -> case catch apply(Module,store,[ConfigListEntry, ConfigList]) of {'EXIT',{function_clause,_}} -> store_traverse(ConfigListEntry,ConfigList,Rest); {'EXIT',{undef, _}} -> store_traverse(ConfigListEntry,ConfigList,Rest); {'EXIT', Reason} -> error_logger:error_report({'EXIT',Reason}), store_traverse(ConfigListEntry,ConfigList,Rest); Result -> Result end.store_mime_types(Name,MimeTypesList) -> %% Make sure that the ets table is not duplicated %% when reloading configuration catch ets:delete(Name), MimeTypesDB = ets:new(Name, [named_table, set, protected]), store_mime_types1(MimeTypesDB, MimeTypesList).store_mime_types1(MimeTypesDB,[]) -> {ok, MimeTypesDB};store_mime_types1(MimeTypesDB,[Type|Rest]) -> ets:insert(MimeTypesDB, Type), store_mime_types1(MimeTypesDB, Rest).%% Phase 3: removeremove_traverse(_ConfigDB,[]) -> ok;remove_traverse(ConfigDB,[Module|Rest]) -> case (catch apply(Module,remove,[ConfigDB])) of {'EXIT',{undef,_}} -> remove_traverse(ConfigDB,Rest); {'EXIT',{function_clause,_}} -> remove_traverse(ConfigDB,Rest); {'EXIT',Reason} -> error_logger:error_report({'EXIT',Reason}), remove_traverse(ConfigDB,Rest); {error,Reason} -> error_logger:error_report(Reason), remove_traverse(ConfigDB,Rest); _ -> remove_traverse(ConfigDB,Rest) end.ssl_certificate_file(ConfigDB) -> case httpd_util:lookup(ConfigDB,ssl_certificate_file) of undefined -> undefined; SSLCertificateFile -> [{certfile,SSLCertificateFile}] end.ssl_certificate_key_file(ConfigDB) -> case httpd_util:lookup(ConfigDB,ssl_certificate_key_file) of undefined -> []; SSLCertificateKeyFile -> [{keyfile,SSLCertificateKeyFile}] end.ssl_verify_client(ConfigDB) -> case httpd_util:lookup(ConfigDB,ssl_verify_client) of undefined -> []; SSLVerifyClient -> [{verify,SSLVerifyClient}] end.ssl_ciphers(ConfigDB) -> case httpd_util:lookup(ConfigDB,ssl_ciphers) of undefined -> []; Ciphers -> [{ciphers, Ciphers}] end.ssl_password(ConfigDB) -> case httpd_util:lookup(ConfigDB,ssl_password_callback_module) of undefined -> []; Module -> case httpd_util:lookup(ConfigDB, ssl_password_callback_function) of undefined -> []; Function -> case catch apply(Module, Function, []) of Password when list(Password) -> [{password, Password}]; Error -> error_report(ssl_password,Module,Function,Error), [] end end end.ssl_verify_depth(ConfigDB) -> case httpd_util:lookup(ConfigDB, ssl_verify_client_depth) of undefined -> []; Depth -> [{depth, Depth}] end.ssl_ca_certificate_file(ConfigDB) -> case httpd_util:lookup(ConfigDB, ssl_ca_certificate_file) of undefined -> []; File -> [{cacertfile, File}] end.error_report(Where,M,F,Error) -> error_logger:error_report([{?MODULE, Where}, {apply, {M, F, []}}, Error]).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -