Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distinguish API routes and console routes #430

Closed
david-crespo opened this issue Nov 24, 2021 · 11 comments
Closed

Distinguish API routes and console routes #430

david-crespo opened this issue Nov 24, 2021 · 11 comments

Comments

@david-crespo
Copy link
Contributor

david-crespo commented Nov 24, 2021

Followup to #356 and #384

If we are going to serve console pages and the external API from the same server (Nexus), we need a way of distinguishing between the two sets of routes. More specifically, we need to be able to designate a catch-all route that matches all console URLs without matching any API routes.

In #384, we are able to cheat because all currently existing console routes start with /orgs, so we just use /orgs/* as the catchall route for console pages. This only works because a) there aren't any other console routes, and b) the API routes for orgs start with the full word /organizations. If we were to add console pages that don't start with /orgs OR shorten the API ones to /orgs (which we've discussed), we'd need another way of doing this.

A common approach is to put an /api prefix on all the API routes. This is the solution @zephraph and I lean toward, though to make it really clean we would want /* to match console routes, which would require Dropshot to allow overlapping route definitions (see oxidecomputer/dropshot#199).

On the other hand, we can avoid this problem entirely by serving console and nexus from different origins, but in order to do that we would have to solve #410.

@ahl
Copy link
Contributor

ahl commented Jan 18, 2022

An approach I've considered in the past (along with the different origins) was to have a very short prefix for the UI, something like https://myoxide.crespo.nft/c/... along side the api prefix. We could have GET of / redirect to /c

@david-crespo
Copy link
Contributor Author

david-crespo commented Sep 29, 2022

Just realized the hack we've been relying on for /orgs/* and /settings/* does not work for /system/* routes because, unlike the other two, /system/* routes exist in both the API and the console. This increases the urgency of solving this problem in a more robust way.

// Dropshot does not have route match ranking and does not allow overlapping
// route definitions, so we cannot have a catchall `/*` route for console pages
// and then also define, e.g., `/api/blah/blah` and give the latter priority
// because it's a more specific match. So for now we simply give the console
// catchall route a prefix to avoid overlap. Long-term, if a route prefix is
// part of the solution, we would probably prefer it to be on the API endpoints,
// not on the console pages. Conveniently, all the console page routes start
// with /orgs already.
#[endpoint {
method = GET,
path = "/orgs/{path:.*}",
unpublished = true,
}]
pub async fn console_page(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
_path_params: Path<RestPathParam>,
) -> Result<Response<Body>, HttpError> {
console_index_or_login_redirect(rqctx).await
}
#[endpoint {
method = GET,
path = "/settings/{path:.*}",
unpublished = true,
}]
pub async fn console_settings_page(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
_path_params: Path<RestPathParam>,
) -> Result<Response<Body>, HttpError> {
console_index_or_login_redirect(rqctx).await
}

@david-crespo
Copy link
Contributor Author

david-crespo commented Sep 29, 2022

A temporary workaround would be to define handlers for all these directly instead of using /system/* EXCEPT I can't do that because /system/silos is itself an API route. So this is probably a real problem.

/system/silos
/system/silos-new
/system/issues
/system/utilization
/system/inventory
/system/health
/system/update
/system/networking
/system/settings

As a very temporary workaround, I will change the console routes to use /sys/* just so they work. But I don't want to keep that in there.

@david-crespo
Copy link
Contributor Author

Ok. I chatted with @smklein about this and we figured out some useful things. I will bring this up at Control Plane huddle since it affects everyone, but I want to collect my thoughts here. If we get to the point of proposing a particular course of action, this will probably become a short RFD.

We don't need Dropshot support for overlapping routes to go with the /api prefix option

I had assumed we'd want to serve console from /* and routes from /api/*, which would mean Dropshot would have to know that a call to /api/system/silos matches the silos list handler more strongly than it matches the /* handler even though technically it matches both. Some other web server frameworks handle route collisions through ranking (e.g., Rocket), so it's at the very least not a bizarre thing to do. However, if instead of /* we use a few top-level handlers like /orgs/*, /system/*, /settings/* for the console routes (which is what we're doing now), there is no conflict with /api/* routes, we don't need route ranking, and we preserve the possibility of other top-level routes that are neither API routes nor console routes.

@davepacheco
Copy link
Collaborator

Is it worth prioritizing the work to figure out how API and console DNS names play into this and having Nexus figure out which one you're hitting by the server name?

@david-crespo
Copy link
Contributor Author

Yes. And I suppose another option would be to serve the console from a different Dropshot server.

@zephraph
Copy link
Contributor

Is it worth prioritizing the work to figure out how API and console DNS names play into this and having Nexus figure out which one you're hitting by the server name?

It's not clear to me why we would want different DNS names for each. I would expect that hitting the root of the silo URI gives you an auth screen that takes you to the console. It seems like standard practice that /api/ would access the API. I believe that's preferable to api.my-silo.customer.com.

@david-crespo
Copy link
Contributor Author

At the very least the DNS version feels a lot more complicated for little, if any, benefit.

@ahl
Copy link
Contributor

ahl commented Sep 30, 2022

This may just be FUD, but in a past product we used a different subdomain for API calls and I recall it running afoul of Safari's anti-cross-site scripting heuristics. This was several years ago so the state of the art and the understand of that system may have evolved significantly.

@davepacheco
Copy link
Collaborator

Yeah, let's forget the separate domains question then. I think it's still worth looking into for future-proofing, but we can always do it later.

@david-crespo
Copy link
Contributor Author

This is solved. All API routes will be behind /v1/*, and console routes will be whatever they need to be. If we ever do oxidecomputer/dropshot#199, we can use /* for console, but we don't have to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants