Is it possible to get the name of the method executed in resolver at runtime AppSync? - aws-appsync

I have an AppSync PIPELINE composed of an auth-service + business-service.
I have implemented RBAC in auth-service, so based on the operation and the role that the user has, it allows or dennies the execution of the bussiness-service.
I need to map the GraphQL Mutation or Query field (method called from the client) to the operation (for example if the user try to do the Mutation: addUser, this is the operation).
Is it possible to get the method executed by the client in the resolver at run time? (for example addUser, deletePost). In order to not have to implement a different auth-service for each of the Queries and Mutations?

Similar scenario, here's what I'm doing:
Before Mapping - Save identity/claims from Cognito etc. to the stash.
Function Request - Check stash, if unauthorized $util.error, else
store the operation name and operand details in the stash before
continuing.
Function Response - Perform any other filtering or ownership checks
on the response, $util.error/early return if unauthorized.
After Mapping - Final transformation of the response or passthrough.
Basically I felt that exposing deep knowledge about an Entity to a generic pipeline auth function was a bad idea, I was more comfortable with an entity's resolver function being aware of what is allowed/disallowed.

Related

RESTFUL API: Using path parameters vs Query parameters

First, I do know path parameters need to be used when you are pointing at a resource and query parameters are meant to be used when you define something that can add a "property" (or change in time).
However, let's assume i need to get data belong to a user.
In this case, I am a fan of writing the REST API URL like this.
https://mylink/user/getbyid
AND not
https://mylink/user/get
In the way I write the REST API, i will call the URL like /user/getbyid?id=1. In the way I DO NOT write the API, you will call it /user/get/1.
Since I write my API calls like /user/getbyid, /user/getbyname, /user/getbyuid I rarely use Path parameters. 99% of the time i am using Query parameters.
Considering the way I write my api calls, am I going against the best practices? Or what I do is right or ignorable?
I do know path parameters need to be used when you are pointing at a resource and query parameters are meant to be used when you define something that can add a "property" (or change in time).
That's not actually right - you are welcome to encode information into either the path or the query as you prefer; the machines don't care, as long as your identifiers are consistent with the production rules defined in RFC 3986.
The "resource identifier" includes both the path and the query_part.
Since I write my API calls like /user/getbyid, /user/getbyname, /user/getbyuid I rarely use Path parameters. 99% of the time i am using Query parameters.
Yup, that's fine.
Considering the way I write my api calls, am I going against the best practices? Or what I do is right or ignorable?
Ignorable, I'd say. Resource identifiers are a lot like variable names; people can spend hours arguing about variable names, and the machines don't care. The same is true of resource identifiers.
Could these identifiers be improved? I think so; the key idea being that we're identifying a resource, rather than identifying the implementation details of how the resource is implemented. The identifier is, in a sense, the "name of the document".
Removing the getby... path segment would also be fine.
/users?id=1
/users?name=bob
/users?uuid=469149ae-ecc6-4652-b094-17c211ff58ef
... but, depending on your routing implementation, disambiguating those three resources might be clumsy. Adding additional path segments to make the routing easier is fine.
The best practices to design a REST API to perform the basic CRUD (Create, Read, Update, Delete) operations, use a combination of HTTP methods GET POST PUT PATCH DELETE, URL and/or parameter(s).
Assuming you want to design a REST API to perform CRUD operation for User
1. Create
To perform create, design an endpoint /users with POST http method.
# http method URL parameters
POST https://<yourdomain>/users, { first_name: "Peak", last_name: "Gen"}
2. Read
To perform Read, design an endpoint /users/<id> with GET http method.
# http method URL parameters
GET https://<yourdomain>/users/1
2. Update
To perform Update, design an endpoint /users/<id> with PUT or PATCH http method.
# http method URL parameters
PUT https://<yourdomain>/users/1, { first_name: "Nitin", last_name: "Sri"}
2. DELETE
To perform Delete, design an endpoint /users/<id> with DELETE http method.
# http method URL parameters
DELETE https://<yourdomain>/users/1
If you notice, the same URL is being used in Read, Update and Delete while their HTTP methods are different. Means the same URL routes to different actions based on their HTTP methods.
Read more about REST API

How to use additional save feature along with search feature HTTP API call

I have implemented an /GET HTTP endpoint to provide search feature. The user sends search terms in query parameters and receives JSON response containing all search results.
Now I have to add a new feature i.e. save search. It means the user sends same search parameters and can also send a boolean parameter say save=true. I have to save the search term in database in this case for future uses. However this parameter is not mandatory.
I am confused over the following points:
Modify same GET HTTP endpoint allowing additional save parameter in query parameters.
Modify same GET HTTP endpoint but passing save parameter in request body instead of query parameters as its backend state changing parameter.
Use separate endpoint for save the parameters using POST method.
What is the standard/acceptable way of doing this?
As far as I understood your question you try to store a search request and by storing it also retrieve the response in one go?
Usually GET is used to retrieve a resources' state though as this method is defined as safe it shouldn't be used if certain state is created for the invoked resource as persisting the search query would be. RFC 7231 further states that:
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
I therefore would refrain from option #1 or #2 as this might break interoperability by certain clients.
POST on the otherhand is defined in RFC 7231 as
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
It therefore should be used in every situation the other HTTP operations don't fit. The HTTP spec further defines that creating a new resource a 201 Created HTTP status code should be returned including a HTTP response header named Location containing the URI of the created resource. This URI can later be used to retrieve it's state (i.e. the performed search result).
From a client's perspective you are basically storing some query definition on the server and don't care where or how the server is actually persisting it. All you care is to retrieve a handle you can later on invoke. This doesn't prevent the server from returning the current search result within the response payload. And this is what I'd do exactly.
Proposed steps:
Send search request via POST
Store query definition
Generate the URI for the stored query
Perform the search according to the query
Return a response with a 201 Created status code and Location header pointing to the URI of the stored query and add the query result within the response payload
A client can later on use the returned URI to retrieve the current state of the resource, which the server can interpret as: execute the query stored for that URI and return the search result.
How the URI has to look like is not defined by the REST architecture. You might generate UUIDs or generate a hash value based on the query generate. The latter approach has the benefit that multiple identical queries wouldn't result in additional queries created but in the reusage of such. In such cases a redirect to the existing query resource should be performed to tell the client that his query already existed which also teaches the client the actual URI of the query resource as a side effect.

REST Creating a resource at point-of-request

Say I have the need to expose a service, where I can request an analysis of a user over a specific range of time (common actions, activities, relationships, etc.).
I would immediately think of this as:
/users/{userId}/analyses - POST
/users/{userId}/analyses/{analysisId} - GET
The problem here, is where the 'analysis' resource comes into existence - it is inherently request-based as it is the service that will do this complex analysis, and also the service that has the most up-to-date state of the user data. In short, it doesn't exist prior to request.
My current thinking has me at three options for requesting an analysis for the first time (with retrieval being the same):
/users/{userId}/analyses?from=2017-01-01&to=2018-01-01 - GET
/users/{userId}/analyses - POST { "from": "2017-01-01", "to": "2018-01-01" }
/users/{userId}/analyses?from=2017-01-01&to=2018-01-01 - POST
I like the GET with query parameters, as I'm requesting a resource, and scoping the user data to be used, until I recognise that the resource could change between requests (based on data on the back end, or processing logic change), and that I would need to call a second time to POST this resource.
I like the POST with the request body, as I'm expecting a resource to be created, until I recognise that the state I've transferred, is not the state I would get back when I retrieve this later, nor is it even the same hypermedia type.
I like the POST with query parameters and no body, as I'm creating a resource and scoping that resource, but I'm still transferring a state that isn't the resource or end media type, and I've seen practically no other examples of POSTs with query parameters.
Anyone have experience with these kinds of actions in a RESTful manner?
In my opinion, using GET /users/{userId}/analyses?from=...&to=... is a good approach.
You request a resource of type analysis which means you have to use HTTP verb GET. You pass parameters to limit the scope. That the resource might change between two requests is not a problem. You request a resource in a specific state and this state might be changed right after your GET request. Compare this to a collection resource where other clients are allowed to POST something.
Using POST would imply that you want clients to create a resource of type analysis with all necessary data, which is from what I understand not true in your case. Your own counter-arguments for the second and third example are correct, in my opinion.

AWS API Gateway multiple Integration Request per Method

My resource /api has a method POST which proxies the body to Kinesis Firehose (and then to ES). At the same time I want it to trigger a Lambda function.
I tried adding an additional method ANY to trigger the Lambda function but API Gateway seems to preference the POST handler.
I am aware that I can trigger Lambda on POST and submit from the Lambda function to Firehose but I'd prefer having those two independent from each other.
API Gateway doesn't fork a request into multiple concurrent actions. An ANY method means "any method without a defined method." Since you also have POST defined, any POST will not see the ANY.
To do what you appear to be attempting -- execute a Lambda function and make a call to the Kinesis API, you will need to write an initial Lambda function that serves as a wrapper and performs both actions -- send a request to Kinesis and send a request to Lambda (to invoke the other Lambda function) -- asynchronously if the business logic permits it -- then marshal the results into a single coherent response that meets your needs.
This first Lambda function does not need to be in the same language as the second, so for example, if the existing Lambda function is in Java, the wrapper function could be written in Node, with no negative performance implications, since it executes independently on the other side of the Lambda API.

How to model a CANCEL action in a RESTful way?

We are currently in the process of wrangling smaller services from our monoliths. Our domain is very similar to a ticketing system. We have decided to start with the cancellation process of the domain.
Our cancel service has as simple endpoint "Cancel" which takes in the id of the ticket. Internally, we retrieve the id, perform some operations related to cancel on it and update the state of the entity in the store. From the store's perspective the only difference between a cancelled ticket and a live ticket are a few properties.
From what I have read, PATCH seems to be the correct verb to be used in this case, as am updating only a simple property in the resource.
PATCH /api/tickets/{id}
Payload {isCancelled: true}
But isCancelled is not an actual property in the entity. Is it fair to send properties in the payload that are not part of the entity or should I think of some other form of modeling this request? I would not want to send the entire entity as part of the payload, since it is large.
I have considered creating a new resource CancelledTickets, but in our domain we would never have the need to a GET on cancelled tickets. Hence stayed away from having to create a new resource.
Exposing the GET interface of a resource is not compulsory.
For example, use
PUT /api/tickets/{id}/actions/cancel
to submit the cancellation request. I choose PUT since there would be no more than one cancellation request in effect.
Hope it be helpful.
Take a look what exactly is RESTful way. No matter if you send PATCH request with isCancelled as payload or even DELETE if you want tickets to disappear. It's still RESTful.
Your move depends on your needs. As you said
I have considered creating a new resource CancelledTickets, but in our
domain we would never have the need to a GET on cancelled tickets.
I would just send DELETE. You don't have to remove it physically. If it's possible to un-cancel, then implement isCancelled mechanism. It's just question of taste.
REST is basically a generalization of the browser based Web. Any concepts you apply for the Web can also be applied to REST.
So, how would you design a cancel activity in a Web page? You'd probably have a table row with certain activities like edit and delete outlined with icons and mouse-over text that on clicking invoke a URI on the server and lead to a followup state. You are not that much interested how the URI of that button might look like or if a PATCH or DELETE command is invoked in the back. You are just interested that the request is processed.
The same holds true if you want to perform the same via REST. Instead of images that hint the user that an edit or cancel activity is performed on an entry, a meaningful link-relation name should be used to hint the client about the possiblities. In your case this might be something like reserve new tickets, edit reservation or cancel reservation. Each link relation name is accompanied by a URL the client can invoke if he wants to perform one of the activities. The exact characters of the URI is not of importance here to the client also. Which method to invoke might either be provided already in the response (as further accompanying field) or via the media type the response was processed for. If neither the media type nor an accompanying field gives a hint on which HTTP operation to use an OPTIONS request may be issued on the URI beforehand. The rule of thumb here is, the server should teach a client on how to achieve something in the end.
By following such a concept you decouple a client from the API and make it robust to changes. Instead of a client generating a URI to invoke the client is fed by the server with possible URIs to invoke. If the server ever changes its iternal URI structure a client using one of the provided URIs will still be able to invoke the service as it simply used one of the URIs provided by the server. Which one to use is determined by analyzing the link relation name that hints the client when to invoke such URI. As mentioned above, such link relation names need to be defined somewhere. But this is exactly what Fielding claimed back in 2008 by:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
Which HTTP operation to choose for canceling a ticket/reservation may depend on your desing. While some of the answers recommended DELETE RFC 7231 states that only the association between the URI and the resource is removed and no gurantee is given that the actual resource is also being removed here as well. If you design a system where a cancelation might be undone, then DELETE is not the right choice for you as the mapping of the URI to the resource should not exist further after handling a DELETE request. If you, however, consider a cancelation to also lead to a removal of the reservation then you MAY use DELETE.
If you model your resource in a way that maintains the state as property within the resource, PATCHing the resource might be a valid option. However, simply sending something like state=canceled is probably not enough here as PATCH is a calculation of steps done by the client in order to transform a certain resource (or multipe resources) into a desired target state. JSON Patch might give a clue on how this might be done. A further note needs to be done on the atomicy requirement PATCH has. Either all of the instructions succeed or none at all.
As also PUT was mentioned in one of the other answers. PUT has the semantics of replacing the current representation available at the given URI with the one given in the request' payload. The server is further allowed to either reject the content or transform it to a more suitable representation and also affect other resources as well, i.e. if they mimic a version history of the resource.
If neither of the above mentioned operations really satisfies your needs you should use POST as this is the all-purpose, swiss-army-knife toolkit of HTTP. While this operation is usually used to create new resources, it isn't limited to it. It should be used in any situation where the semantics of the other operations aren't applicable. According to the HTTP specification
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
This is basically the get-free-out-of-jail card. Here you can literally process anything at the server according to your own rules. If you want to cancel or pause something, just do it.
I highly discourage to use GET for creating, altering or canceling/removing something. GET is a safe operation and gurantees any invoking client that it wont alter any state for the invoked resource on the server. Note that it might have minor side-effects, i.e. logging, though the actual state should be unaffected by an invocation. This is a property Web crawler rely on. They will simply invoke any URI via GET and learn the content of the received response. And I assume you don't want Google (or any other crawler) to cancel all of your reservations, or do you?
As mentioned above, which HTTP operation you should use depends on your design. DELETE should only be used if you are also going to remove the representation, eventhough the spec does not necessarily require this, but once the URI mapping to the resource is gone, you basically have no way to invoke this resource further (unless you have created a further URI mapping first, of course). If you designed your resource to keep the state within a property I'd probably go for PATCH but in general I'd basically opt for POST here as here you have all the choices at your hands.
I would suggest having a state resource.
This keeps things RESTful. You have your HTTP method acting as the verb. The state part of the URI is a noun. Then your request body is simple and consistent with the URI.
The only thing I don't like about this is the value of state requires documentation, meaning what states are there? This could be solved via the API by providing possible states on a meta resource or part of the ticket body in meta object.
PUT /api/tickets/:id/state
{state: "canceled"}
GET /api/meta/tickets/state
// returns
[
"canceled",
...
]
GET /api/tickets/:id
{
id: ...
meta: {
states: [
"canceled",
...
]
}
}
For modelling CANCEL Action in Restful way :
Suppose we have to delete a note in DB by providing noteId(Note's ID) and Note is a pojo
1] At controller :
#DeleteMapping(value="/delete/{noteId}")
public ResponseEntity<Note> deleteNote( #PathVariable Long noteId)
{
noteServiceImpl.deleteNote(noteId);
return ResponseEntity.ok().build();
}
2]Service Layer :
#Service
public class NoteServiceImpl {
#Autowired
private NotesRepository notesDao;
public void deleteNote(Long id) {
notesDao.delete(id);
}
}
3] Repository layer :
#Repository
public interface NotesRepository extends CrudRepository<Note, Long> {
}
and in 4] postman : http://localhost:8080/delete/1
So we have deleted note Id 1 from DB by CANCEL Action