client-js icon indicating copy to clipboard operation
client-js copied to clipboard

Doesn't work with NextJs

Open buttercoding opened this issue 1 year ago • 2 comments

This very basic use of fhirclient from a NextJs app throws the following error...

  code: "ERR_INVALID_URL",
  base: "http://localhost:3000:3000",

Clearly the 3000:3000 is the issue. I've tried resolving it by modifying x-forwarded-host and x-forwarded-port headers, which does get me to the EHR login screen, but causes the same error downstream. Perhaps there are default NextJs settings that need to be tweaked?

import type { NextApiRequest, NextApiResponse } from "next";
import smart from "fhirclient";
import { fhirclient } from "fhirclient/lib/types";

export class StorageWrapper {
	session: any;

	constructor(session: any) {
		this.session = session;
	}

	async get(key: string): Promise<any> {
		return this.session[key];
	}

	async set(key: string, value: any): Promise<any> {
		this.session[key] = value;
		return value;
	}

	async unset(key: string): Promise<boolean> {
		if (Object.prototype.hasOwnProperty.call(this.session, key)) {
			delete this.session[key];
			return true;
		}
		return false;
	}
}

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
	try {
		const redirectUri = `http://localhost/api/integration/fhir/callback?otherstuff`;

		const authorizeParams: fhirclient.AuthorizeParams = {
			iss: "https://launch.smarthealthit.org/v/r4/sim/<your id here>/fhir",
			clientId: "my-client-id",
			scope: "encounter/*.read patient/*.read user/*.read openid fhirUser offline_access",
			redirectUri,
		};

		const sessionObj: any = {};
		await smart(req, res, new StorageWrapper(sessionObj)).authorize({ ...authorizeParams, redirectUri });

		console.log("we never get here");

		res.status(200);
	} catch (error) {
		res.status(500).json(error);
	}
}

buttercoding avatar Jul 30 '24 15:07 buttercoding

Tested essentially the same code in Express and it works fine. Confirmed it is something related to NextJs settings. What would those be?

buttercoding avatar Jul 30 '24 17:07 buttercoding

I've tracked this down to NextJs having a value for the header x-forwarded-host, while Express does not. The getUrl function in NodeAdapter.js of this project...

    let host = req.headers.host;
    if (req.headers["x-forwarded-host"]) {
      host = req.headers["x-forwarded-host"];
      if (req.headers["x-forwarded-port"]) {
        host += ":" + req.headers["x-forwarded-port"];
      }
    }

...is causing the problem. NextJs has x-forwarded-host header value of localhost:3000 and x-forwarded-port header value 3000, so the above code results in a Url of localhost:3000:3000.

Express does not have the x-forwarded-host header, so it uses the value from req.headers.host which is localhost:3000.

buttercoding avatar Aug 01 '24 15:08 buttercoding

I am also seeing this same issue and think this is a good solution.

aoxenrider avatar Aug 13 '24 21:08 aoxenrider

This is now included in [email protected]. Thank you!

vlad-ignatov avatar Aug 27 '24 17:08 vlad-ignatov