1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2010-2016, University of Amsterdam, 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(http_host, 37 [ http_public_url/2, % +Request, -PublicURL 38 http_public_host_url/2, % +Request, -HostURL 39 http_public_host/4, % +Request, -Host, -Port, +Options 40 % deprecated 41 http_current_host/4 % +Request, -Host, -Port, +Options 42 ]). 43:- if(exists_source(library(http/thread_httpd))). 44:- use_module(library(http/thread_httpd)). 45:- endif. 46:- use_module(library(http/http_wrapper)). 47:- use_module(library(socket)). 48:- use_module(library(option)). 49:- use_module(library(settings)). 50 51:- setting(http:public_host, atom, '', 52 'Name the outside world can use to contact me'). 53:- setting(http:public_port, integer, 80, 54 'Port on the public server'). 55:- setting(http:public_scheme, oneof([http,https]), http, 56 'Default URL scheme to use'). 57 58:- predicate_options(http_public_host/4, 4, [global(boolean)]). 59:- predicate_options(http_current_host/4, 4, 60 [pass_to(http_public_host/4, 4)]).
80http_public_url(Request, URL) :-
81 http_public_host_url(Request, HostURL),
82 option(request_uri(RequestURI), Request),
83 atomic_list_concat([HostURL, RequestURI], URL).
93http_public_host_url(Request, URL) :- 94 http_public_host(Request, Host, Port, 95 [ global(true) 96 ]), 97 setting(http:public_scheme, Scheme), 98 ( scheme_port(Scheme, Port) 99 -> format(atom(URL), '~w://~w', [Scheme, Host]) 100 ; format(atom(URL), '~w://~w:~w', [Scheme, Host, Port]) 101 ). 102 103scheme_port(http, 80). 104scheme_port(https, 443).
true
(default false
), try to replace a local hostname
by a world-wide accessible name.This predicate performs the following steps to find the host and port:
http:public_host
and http:public_port
X-Forwarded-Host
header, which applies if this server
runs behind a proxy.Host
header, which applies for HTTP 1.1 if we are
contacted directly.131http_public_host(_Request, Host, Port, _) :- 132 setting(http:public_host, PublicHost), PublicHost \== '', 133 !, 134 Host = PublicHost, 135 setting(http:public_port, Port). 136http_public_host(Request, Host, Port, Options) :- 137 ( var(Request) 138 -> http_current_request(Request) 139 ; true 140 ), 141 ( memberchk(x_forwarded_host(Forwarded), Request) 142 -> Port = 80, 143 primary_forwarded_host(Forwarded, Host) 144 ; memberchk(host(Host0), Request), 145 ( option(global(true), Options, false) 146 -> global_host(Host0, Host) 147 ; Host = Host0 148 ), 149 option(port(Port), Request, 80) 150 ), 151 !. 152:- if(current_predicate(http_current_server/2)). 153http_public_host(_Request, Host, Port, _Options) :- 154 gethostname(Host), 155 http_current_server(_:_Pred, Port). 156:- endif.
162http_current_host(Request, Hostname, Port, Options) :-
163 http_public_host(Request, Hostname, Port, Options).
171primary_forwarded_host(Spec, Host) :- 172 sub_atom(Spec, B, _, _, ','), 173 !, 174 sub_atom(Spec, 0, B, _, Host). 175primary_forwarded_host(Host, Host).
If the heuristics used by this predicate do not suffice, the setting http:public_host can be used to override.
189global_host(_, Host) :- 190 setting(http:public_host, PublicHost), PublicHost \== '', 191 !, 192 Host = PublicHost. 193global_host(localhost, Host) :- 194 !, 195 gethostname(Host). 196global_host(Local, Host) :- 197 sub_atom(Local, _, _, _, '.'), 198 !, 199 Host = Local. 200global_host(Local, Host) :- 201 tcp_host_to_address(Local, IP), 202 tcp_host_to_address(Host, IP)
Obtain public server location
This library finds the public address of the running server. This can be used to construct URLs that are visible from anywhere on the internet. This module was introduced to deal with OpenID, where a request is redirected to the OpenID server, which in turn redirects to our server (see
http_openid.pl
).The address is established from the settings
http:public_host
andhttp:public_port
if provided. Otherwise it is deduced from the request. */