using afIoc::Injectusing afIoc::RegistryMetausing afIocConfig::ConfigSourceusing web::WebRequsing web::WebUtilusing concurrent** (Service) -** Information about the BedSheet server. constmixin BedSheetServer {** The pod that contains the initial 'AppModule'.abstract Pod? appPod()** The 'AppModule'.abstract Type? appModule()** Returns 'pod.dis' (or 'proj.name'if not found) from the application's pod meta, or the pod name if neither are defined.abstract Str appName()** The port BedSheet is listening to.abstract Int port()** The public facing domain (including scheme & port) used to create absolute URLs.** ** If set, this is taken from the `BedSheetConfigIds.host` config value.** ** If not, then an attempt is made to get this from the HTTP request via the following (in order):** ** 1. The 'Forwarded' HTTP header - see [RFC 7239]`https://tools.ietf.org/html/rfc7239` ** 2. The 'X-Forwarded-XXXX' HTTP headers** 3. The 'host' HTTP header **** See `HttpRequest.host` for details. ** ** If all fails then 'http://localhost:${port}/' is returned.** ** Example:** ** syntax: fantom** bedSheetServer.host() // --> http://www.fantomfactory.org/ abstract Uri host()** The Registry options BedSheet was started with.abstract[Str:Obj] options()** Returns a list of modules loaded by this BedSheet's IoCabstract Type[] moduleTypes()** Returns a unique list of pods that contain modules loaded by this BedSheet's IoC.** ** Useful for gaining a list of pods used in an application, should you wish to *scan* for** classes. abstract Pod[] modulePods()** The request path to this BedSheet 'WebMod'. ** Only really relevant should BedSheet be started in a [RouteMod]`webmod::RouteMod`.** ** Starts and ends with a '/'. Example, '`/pub/`'** ** Returns '`/`' should BedSheet be the root 'WebMod' (the usual case).** ** @see `web::WebReq.modBase`abstract Uri path()** Prepends any extra 'WebMod' path info to the given URL so it may be used by clients and browsers.** The given 'WebMod' local URL should be relative to the BedSheet 'WebMod' and may, or may not, start with a '/'.abstract Uri toClientUrl(Uri localUrl)** Creates an absolute URL for public use; including scheme and authority (host).** The given 'clientUrl' should be relative to the host and start with a '/'.**** The scheme and authority in the generated URL are taken from the 'host()' method. abstract Uri toAbsoluteUrl(Uri clientUrl)}internalconstclass BedSheetServerImpl : BedSheetServer {// nullable for testing @Inject privateconst RegistryMeta? regMeta @Inject privateconst ConfigSource? configSrc new make(|This|in){ in(this)}override Pod? appPod(){ regMeta[BsConstants.meta_appPod]}override Type? appModule(){ regMeta[BsConstants.meta_appModule]}override Str appName(){ regMeta[BsConstants.meta_appName]}override Int port(){ regMeta[BsConstants.meta_proxyPort] ?: regMeta[BsConstants.meta_appPort]}override[Str:Obj] options(){ regMeta.options}override Type[] moduleTypes(){ regMeta.moduleTypes}override Pod[] modulePods(){ regMeta.modulePods}override Uri path(){// default to root for testing webReq?.modBase ?: `/`}override Uri host(){// we get host this way 'cos BedSheetServer is used (in a round about way by Pillow) in a // DependencyProvider, so @Config is not available for injection// host is validated on startup, so we know it's okay bedSheetHost := (Uri) configSrc.get(BedSheetConfigIds.host, Uri#)// if someone has gone to the trouble of setting a config value - then let's use it// as it's probably the normalised host of multiple sitesif(bedSheetHost.host != "localhost")return bedSheetHost// otherwise, lets parse the web req webReq := webReqif(webReq != null){ host := HttpRequestImpl.hostViaHeaders(webReq.headers)if(host != null){// hostViaHeaders is not guarenteed to return a schemeif(host.scheme == null) host = `http:${host}`if(regMeta != null){// generate absolute URLs that point back to the proxy, not the app appPort := regMeta[BsConstants.meta_appPort] ?: 80if(host == `http://localhost:${appPort}/`){ proxyPort := regMeta[BsConstants.meta_proxyPort] ?: 80return`http://localhost:${proxyPort}/`}}return host}}return bedSheetHost}override Uri toClientUrl(Uri localUrl){// if we stop throwing an Err here, then we need to update ColdFeetif(localUrl.host != null || !localUrl.isRel)// can't use Uri.isPathOnly because we allow QueryStrs and Fragments...?throw ArgErr(BsErrMsgs.urlMustBePathOnly(localUrl, `/css/myStyles.css`))return path + localUrl.relTo(`/`)}override Uri toAbsoluteUrl(Uri clientUrl){ Utils.validateLocalUrl(clientUrl, `/css/myStyles.css`)return host + clientUrl.relTo(`/`)}private WebReq? webReq(){// use Actor.locals (and not reg.serviceById) to avoid Errs being thrown during testing Actor.locals["web.req"]}}