Skip to content

Conversation

@Aniruddh25
Copy link
Collaborator

@Aniruddh25 Aniruddh25 commented Nov 17, 2021

Summary

Alongwith graphql, DataGateway Service should support REST api requests too. This change introduces the necessary classes that help add REST support and implements the GET verb for the FindById operation for MsSql only.

How

  • Adds a RestController to accept routes matching https://localhost:5001/users/id/1?_f=id,username
    where users is the entityName, id is the primary key field name, 1 is the value for the primary key
    _f in the query string is the keyword used for the selected field names.
  • For composite primary keys, the route would be https://localhost:5001/users/id/1/partition_key/200?_f=id,username where id and partition_key together form the primary key.
  • Adds a RestService to handle the request by invoking the RequestParser to parse the request and populate the FindQueryStructure class which holds the major components of the query to be generated
  • MsSqlQueryBuilder PostgresQueryBuilder use the FindQueryStructure class to build the required query for the FindById operation.

image

Testing

  • Tested using PostMan that the route for FindById returns expected Json document when given no fields and also with specific fields.
  • Added MsSqlRestApiTests to test the same. Moved some common test code to MsSqlTestBase.

Motivation and future thoughts

  • This change uses some of the request parsing logic from existing work done here SqlRestApi. In future, for addition of filter clause etc, we can similarly reuse that parsing logic.
  • It is also inspired by the draft PR(Initial version of query generation for Postgres and MS SQL #55) for query generation for GraphQL.
    The FindQueryStructure is similar to the SqlQueryStructure class from that PR(Initial version of query generation for Postgres and MS SQL #55).
    FindQueryStructure could be useful for CosmosDb query generation so the class SqlQueryStructure should be derived from FindQueryStructure. Once this and the draft PR are merged in, queries for SQL like databases will be autogenerated for both REST and GraphQL.
  • When support for CosmosDb query generation Cosmos DB: Query with automatic resolver #71 is added to the mix, its possible to further redesign the query generation class structure.
  • For other REST verbs like POST, PUT, DELETE, we would need similar classes like FindQueryStructure, at which point again more abstraction would be needed.
  • Routing

Issues to be addressed in future

}

services.AddSingleton<GraphQLService, GraphQLService>();
services.AddSingleton<RestService, RestService>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

services.AddSingleton<RestService, RestService>();

We'll probably have to add logic to pick GraphQL vs REST service to avoid 1) having both active simultaneously and 2) avoid route collision i.e. localhost:5001/entityName vs. localhost:5001/graphql

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats a good point to discuss - we need to have both GraphQL and REST active at the same time.
I tested localhost:5001/graphql alongwith the REST GET and this continues to the graphql route..

That said, it might collide for other REST verbs. We need to make sure the routes don't collide.
One option would be to modify the route to be localhost:5001/databasename/entityName

Copy link
Collaborator Author

@Aniruddh25 Aniruddh25 Nov 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested localhost:5001/graphql after creating a table named graphql but the GET would return 404 not found proving the GraphQL controller route took precedence. I think we shouldn't be allowing tables with 'graphql' as their names.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm as opposed to adding rules to what devs have in their own databases, localhost:5001/api/databasename/entityName would also mitigate us looking into ASP.NET route restrictions , as we still want to expose localhost:5001/graphql no matter what for GraphQL requests. another reason to be open to adding /api would be for Runtime endpoint versioning. i.e. localhost:5001/api/v1.0/entity can bring this up in future Hawaii PM sync

Copy link
Contributor

@JelteF JelteF Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm definitely in favour of prefixing all REST requests with some well known path. I think /api/v1.0/ would indeed be a good choice because it allows for versioning. Another way to do versioning would be to use a version=v1.0 query parameter.

@Aniruddh25 Aniruddh25 linked an issue Nov 18, 2021 that may be closed by this pull request
Copy link
Member

@mbhaskar mbhaskar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the changes.

For cosmos, the primary key is combination of id + partition key. Without partition key, findById could return various documents that match the id but differ in partitionkey.
@moderakh We should probably document about partition key header x-ms-documentdb-partitionkey

Copy link
Contributor

@seantleonard seantleonard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for getting this in and addressing PR comments. Very helpful and looking forward to using this to progress further on more REST cases!

@Aniruddh25 Aniruddh25 merged commit 4ff9aae into main Nov 23, 2021
@Aniruddh25 Aniruddh25 deleted the dev/anmunde/findByIdRestSql branch November 23, 2021 05:28

for (int primaryKeyIndex = 0; primaryKeyIndex < primaryKeyValues.Length; primaryKeyIndex += 2)
{
queryStructure.Conditions.Add($"{primaryKeyValues[primaryKeyIndex]} = @{primaryKeyValues[primaryKeyIndex]}");
Copy link
Contributor

@JelteF JelteF Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows for SQL injection if the URL is provided is something like localhost:5000/users/id; DROP TABLE users/2

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

Successfully merging this pull request may close these issues.

MsSql: FindById REST GET

5 participants