-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Provide a way to customize the URL structure #1909
Comments
Absolutely, I had customizing of the URLs for endpoints in mind with that, too. |
@steve-chavez so this would be a separate module that somehow plugs in before the |
Hm no, there isn't. This is mostly a high-level idea at this stage, extensibility is pretty new.
Sounds about right, though TBH I haven't looked yet at the implementation details. |
At a higher level, my idea was roughly along the following lines:
Does that make sense? |
Hmm, let me try to echo back what you are saying. There would be a new data type called
The |
Hm. Using the names you suggested, I think data Router = Router {
-- some kind of representation of appconfig and dbstructure and routing rules
}
makeRouter :: AppConfig -> DbStructure -> Router
applyRouting :: Router -> Request -> RequestBody -> Either ApiRequestError ApiRequest |
@wolfgangwalther yes this makes sense. However, if I try to write a function in haskell whose job is to
So going with postgrest's motto of doing one thing well, I suggest we somehow provide this So, something like, if you provide an executable in the configuration file, postgrest will start that executable on a separate process. And we provide a default executable (router) with postgrest which may implement what we have discussed above. For example:
Now when you start postgrest, and it finds a This way, we can still allow people to configure routes on postgrest out of the box. And we give them a path to either go with some kind of cloud native architecture like AWS Apigateway or their own kubernetes setup with nginx gradually. We also give them the ability to configure much more than just the routes. Because this program can just rewrite the entire request, swapping out the request method, body and headers in arbitrary ways that the users can imagine. (This is possible inside the postgrest function we discussed above as well, however, the configuration dsl will become evil at that point). |
True, it's looking complex. And the DSL I put above only considers the URL part, ideally we'd also be able to extend PostgREST to be compatible with IDL-based standards such as graphql — for this we'd need to parse the request body + map it to PostgREST query params. That is one of the reasons I mentioned the embedded scripting language idea in #1698 (comment). There might be another option. I've just read about List-based parser combinators, which is a way to do parser combinators dinamically. With this we could(in theory) allow to modify PostgREST parser combinators through the configuration file(or with a nicer interface through postgrest-contrib). We'd need a library for the List-based parser combinators, because there's only an example for Haskell. Then we could use that lib for parsing the body + the URL part(maybe). |
Proper strong haskell typing should avoid that.
I don't think this is going to be a very complex thing. I'm pretty sure it should be straight-forward to add a parser that reads in a JSON config for the router, maps that to a haskell data type and throws decent parsing errors.
I think this is just going to complicate things a lot more. For everything that goes beyond the simple set of features that we want to support directly at the PostgREST level, nginx as a reverse-proxy is still the best solution. We don't need to reinvent the wheel here.
The whole scripting language idea sounds promising - as a second step after the routing refactor. In that second step, we would basically rewrite the request parser in that scripting language, to make it possible to swap it out by a replacement. Does that make sense? |
Hmm yes. The embedded scripting language part gets me more excited than this refactor 😛. And the idea of extending postgrest to be compatible with graphql is very exciting. I would love to see some specs about how to do these things. But for a starter I can refactor the router out as @wolfgangwalther suggested above. Can @steve-chavez or @wolfgangwalther throw some more light on how it can be evolved to support graphql or start another issue/rfc for that? |
@gautam1168 I don't have anything specific but really that part should be left for another repo. My main motivation here is to provide a generic interface for extensibility. Also, seems that dhall might have issues with graphql because it doesn't have recursiveness? |
hmm ok. Let me open a PR for this refactor first. |
Regarding embedded scripting languages, there's also Embedded SQL - PostgreSQL has ECPG for example. For Haskell, I found hesql(does a subset of Postgres' SQL), it doesn't seem maintained but the idea of embedded SQL in PostgREST seems really cool 😮 🤯 💥 |
I've seen that Dhall supports toml, that doesn't seem that different from supporting graphql. So maybe not all things can be done in pure dhall, but dhall can be extended with Haskell. So we'd need to upgrade our Dhall dependency in some cases, but that's not too bad, we'd still support extensibility off the core repo.
That might be shooting for the stars for now, Dhall is looking like the most feasible alternative. |
There was a request in gitter about making PostgREST read-only. Of course a read replica or having a read-only role would work but maybe we can allow to restrict our http methods so only GETs are possible and POSTs or other methods don't even touch the db. Or for a more "db as source of truth" approach, we could reject http methods without hitting the db based on the role's privileges. This requires more smartness from the schema cache though. Edit: we shouldn't do this because those are different things: "not allowed to" vs "not capable to" . |
This discussion derailed a bit of its original purpose. There's a more plausible alternative now on #1086 (comment) Basically by defining the custom URL as a view or function name: CREATE VIEW "./projects/:id" AS
SELECT *
FROM projects
WHERE id = current_setting('request.path.id`, false); Let's follow up there. |
Problem
We recommend customizing the URL structure through Nginx, however doing so is complicated and requires additional tools. This can be seen on ppKrauss/PostgREST-writeAPI, which uses mustache templating plus a nodejs script to generate the Nginx rewrite config.
Additionally, changing the URL in the proxy will not be reflected in our OpenAPI spec - which would need rewriting on the proxy as well, which is also more work.
Relying solely on the proxy for this hurts our extensibility, ideally PostgREST should be able to adapt to other standards, like more classical REST with nested routes or maybe more complex ones like Odata; and do so outside of PostgREST core.
Note that we do have a way forward to customize the response body(see this discussion regarding JSON-LD), but not the URL structure.
Proposal
Provide a way to customize the URL through the config file or through postgrest-contrib. It could be like so:
Related
@wolfgangwalther I think you had an idea about a "routing refactor", this may be related.
The text was updated successfully, but these errors were encountered: