@@ -36,16 +36,37 @@ class MetadataHandler {
3636
3737 if ( mode === 'terminology' ) {
3838 this . logInfo = 'termcaps' ;
39- const tc = new TerminologyCapabilities ( await this . buildTerminologyCapabilities ( endpoint , provider ) ) ;
39+ const tc = new TerminologyCapabilities ( await this . buildTerminologyCapabilities ( endpoint , provider , req ) ) ;
4040 return res . json ( tc . jsonObj ) ;
4141 }
4242 this . logInfo = 'metadata' ;
4343
4444 // Default: return CapabilityStatement
45- const cs = new CapabilityStatement ( this . buildCapabilityStatement ( endpoint , provider ) ) ;
45+ const cs = new CapabilityStatement ( this . buildCapabilityStatement ( endpoint , provider , req ) ) ;
4646 return res . json ( cs . jsonObj ) ;
4747 }
4848
49+ /**
50+ * Resolve the public base URL for this request.
51+ * Derived from what the client actually asked for (scheme + host) plus the
52+ * endpoint path, so the server echoes the host the client used rather than a
53+ * fixed, hardcoded value. Falls back to config/host only when no request is
54+ * available (e.g. unit tests calling the build methods directly).
55+ * @param {express.Request } [req] - Express request
56+ * @param {Object } endpoint - Endpoint info {path, ...}
57+ * @returns {string } Base URL, e.g. https://tx.fhir.org/r4
58+ */
59+ resolveBaseUrl ( req , endpoint ) {
60+ if ( ! req ) {
61+ return this . config . baseUrl || `https://${ this . host } ${ endpoint . path } ` ;
62+ }
63+ // Requires app.set('trust proxy', ...) and nginx forwarding X-Forwarded-Proto
64+ // for the scheme to be correct behind the reverse proxy.
65+ const proto = req . protocol || 'https' ;
66+ const host = req . get ( 'host' ) || this . host ;
67+ return `${ proto } ://${ host } ${ endpoint . path } ` ;
68+ }
69+
4970 /**
5071 * Handle GET /$versions request
5172 * @param {express.Request } req - Express request (with txEndpoint attached)
@@ -106,11 +127,11 @@ class MetadataHandler {
106127 * @param {Object } provider - Provider for code systems and resources
107128 * @returns {Object } CapabilityStatement resource
108129 */
109- buildCapabilityStatement ( endpoint ) {
130+ buildCapabilityStatement ( endpoint , provider , req ) {
110131
111132 const now = new Date ( ) . toISOString ( ) ;
112133 const fhirVersion = this . mapFhirVersion ( endpoint . fhirVersion ) ;
113- const baseUrl = this . config . baseUrl || `https:// ${ this . host } ${ endpoint . path } ` ;
134+ const baseUrl = this . resolveBaseUrl ( req , endpoint ) ;
114135 const serverVersion = this . config . serverVersion ;
115136
116137 return {
@@ -281,9 +302,9 @@ class MetadataHandler {
281302 * @param {Object } provider - Provider for code systems and resources
282303 * @returns {Object } TerminologyCapabilities resource
283304 */
284- async buildTerminologyCapabilities ( endpoint , provider ) {
305+ async buildTerminologyCapabilities ( endpoint , provider , req ) {
285306 const now = new Date ( ) . toISOString ( ) ;
286- const baseUrl = this . config . baseUrl || `https:// ${ this . host } ${ endpoint . path } ` ;
307+ const baseUrl = this . resolveBaseUrl ( req , endpoint ) ;
287308 const serverVersion = this . config . serverVersion || '1.0.0' ;
288309
289310 const tc = {
0 commit comments