brendanhay / amazonka

A comprehensive Amazon Web Services SDK for Haskell.
https://amazonka.brendanhay.nz
Other
605 stars 227 forks source link

How to change endpoint of a service? Especially the APIGatewayManagementAPI service #786

Closed stevemao closed 1 year ago

stevemao commented 2 years ago

I'm reading the document:

The Amazon API Gateway Management API allows you to directly manage runtime aspects of your deployed APIs. To use it, you must explicitly set the SDK's endpoint to point to the endpoint of your deployed API. The endpoint will be of the form https://{api-id}.execute-api.{region}.amazonaws.com/{stage}, or will be the endpoint corresponding to your API's custom domain and base path, if applicable.

But it doesn't say how we can change the endpoint.

The closet I can find is serviceEndpoint

let url = "https://{api-id}.execute-api.{region}.amazonaws.com/{stage}"
let env' = override (over serviceEndpoint (endpointHost .~ encodeUtf8 url)) env

But this only changes the domain. The stage part needs to be a part of the path. The connectionId is also on the path so stage needs to be prefixed. Is there a way to achieve this?

endgame commented 1 year ago

That docstring will have been pulled from botocore, so don't expect it to necessarily say anything sensible (though it's often pretty handy).

I see a couple of options here:

  1. Add stage parameters to every relevant request in the AWS API Gateway Management API:
    • You'll need to edit config/annexes/apigatewaymanagementapi.json, which gets merged with the service definition from botocore.
    • Add a path parameter to each request shape, and update the requestUri field on each endpoint definition to reference the new parameter.
    • In a nix-shell, run scripts/generate --commit apigatewaymanagementapi to regenerate and commit the service binding. (For config changes which regenerate all service bindings, I like to do them in a second PR to keep the diff clean, but when it's only one service I think it's fine to do them on the same branch.) This will give you a change similar to your PR #865 but will require manual intervention whenever AWS updates their management API.
  2. Update the way we handle Endpoints so that we can store more than a DNS name in the host :: ByteString field.
  3. Add a basePath field to the Endpoint record in amazonka/lib/amazonka-core/src/Amazonka/Types.hs and default it to some sort of empty value. Not sure whether this should be a ByteString, [ByteString], or something else.

I like options 2 and 3 best, because they're less maintenance and might also allow people to mount non-S3 object stores at a path under a domain, which could be nice. I'm more inclined to go for option 3, because then we don't have to worry about base paths leaking into a host: header.

endgame commented 1 year ago

What are your thoughts?

stevemao commented 1 year ago

I like option 3 for the same reason.