AWS AppSync Subscription Arguments - amazon-web-services

What can the arguments on an AppSync GraphQL subscription be used for? According to the real-time data page on the docs:
An important part of using GraphQL subscriptions is understanding when and how to use arguments, as subtle changes will allow you to modify how and when clients are notified of mutations that have occured.
(...)
In the default sample, clients can subscribe to Comments when a specific eventId argument is passed through
I can't find any way to access the subscription arguments, though. I have different 'channels' of comments that I'd like users to be able to subscribe to individually, optionally with a password. The subscription I've set up responds to comments in all channels instead.
Is there any way to 'filter' the data coming through the subscription with a mapping template or similar? If not, what's the intended use of the subscription arguments? Must the filtering be done client side?

The name of the argument is expected to be the same as the name of the field in the mutation response that triggered the event. If your mutation returns a value of type "Post" that contains a field "title" then passing an argument named "title" to the subscription that is subscribed to that mutation will only get pushed values where the "title" passed to the subscription equals the value of field named "title" returned by the mutation.

The arguments control what data clients will get subscription notifications from. For example if you put in an argument via the schema which is required by using the bang (!) symbol then clients can only subscribe to data on a specific mutation for that parameter.
GraphQL arguments, including those passed in a subscription, should be available via $ctx.args in your resolver (this is shorthand for $context.arguments). For example if you have a query of getThing(name:"XYZ") then you can access in your resolver with $ctx.args.name.
For your use case I would suggest using arguments along with a resolver on the subscription so that users can only subscribe to a channel by that argument, if they match some authorization criteria, such as the password or looking at the logged in user. You can find an example of this here: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html#real-time-data

Related

Appsync: Subscribe to element in array

With respect to AWS AppSync Is there a way of subscribing to an element in an array , eg:
onSendMessage(recipientIds:[myID,otherPotentiallyRandomAndUnknownIds]) {
}
I have tried simply adding the element I'm looking for, however it doesn't trigger a subscription if I'm missing the other elements (and in order too)
Unfortunately this is something that can't be done trivially. Also the as you noted the order matters because in GraphQL it should viewed as a List (which is ordered). So the subscription triggers expecting the order you provided on the schema. It also expects the exact arguments you provide in the list because a GraphQL Schema is essentially viewed as a contract by clients so if the contract dictates that the subscription is on a List with these elements in this order - then it will initiate the subscription based on that.
Now what you could do is set up a dynamo stream (assuming DynamoDB as your data source) that feeds any changes on the table into a lambda from where you can make a mutation on AppSync (depending on if a change to was made to an element in the array) to trigger a subscription (set up simple mutation/subscriptions for this use case only). This is sort of a hack-y workaround, and there may be other novel solutions you can explore.

Is it possible to retrieve topic name inside a Lambda function called by an Iot rule

I've got a lambda function called by an IoT rule and I would like to know the topic name from inside this lambda function.
So far i'm only able to retrieve the message data from the event parameter. Nothing in the context parameter neither.
I haven't found anything in the documentation...
Is it even possible ?
You need to use topic() function in AWS IoT SQL query. Like this:
SELECT * as data, topic() as topic FROM 'desired/+/topic'
In this case, your event will include the original message in 'data' field and the used topic in 'topic' field. You can also use integer number as a parameter inside topic() function, to return only sub-group.
More data in oficial documentation: http://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-functions.html#iot-function-topic

How to modify a query parameter in AWS API Gateway in the integration request for an HTTP Proxy

I have a client facing API that takes a query parameter Time. The format is 14:00:00. Originally it would pass through this query parameter to the back end endpoint. However the back end endpoint (that I do not control) is now expecting time in the format 0001-01-01T14:00:00.
Is it possible to to modify the value of the query param before passing it on in AWS API Gateway?
I know you can modify the request body with a mapping template, and in the template you can access the queryParameters, but can you change them so that it modifies the actual request made to the back end?
I saw this:
https://forums.aws.amazon.com/thread.jspa?messageID=696524&#696524
but the user said he gave up trying to modify
Potential workaround I can think of right now are pass the parameters to a lambda and have the lambda build and make the request with modified values, with the response as the return value for the lambda
For now one can overrides query string in Mapping Templates using velocity templates e.g:
$context.requestOverride.querystring.time="_your_transformed_data_"
There is docs
I think you basically answered your own question :)
There is no way to transform query or header request parameters. All transformations need to happen in the body mapping template.
Best workaround would be to forward request on to a Lambda function to massage the parameters into the expected shape

Consuming RSS feed with AWS Lambda and API Gateway

I'm a newbie rails programmer, and I have even less experience with all the AWS products. I'm trying to use lambda to subscribe to and consume an rss feed from youtube. I am able to send the subscription request just fine with HTTParty from my locally hosted rails app:
query = {'hub.mode':'subscribe', 'hub.verify':'sync', 'hub.topic': 'https://www.youtube.com/feeds/videos.xml?channel_id=CHANNELID', 'hub.callback':'API Endpoint for Lambda'}
subscribe = 'HTTParty.post(https://pubsubhubbub.appspot.com/subscribe, :query=>query)
and it will ping the lambda function with a get request. I know that I need to echo back a hub.challenge string, but I don't know how. The lambda event is empty, I didn't see anything useful in the context. I tried formatting the response in the API gateway but that didn't work either. So right now when I try to subscribe I get back a 'Challenge Mismatch' error.
I know this: https://pubsubhubbub.googlecode.come/git/pubsubhubbub-core-0.3.html#subscribing explains what I'm trying to do better than what I just did, and section 6.2.1 is where the breakdown is. How do I set up either the AWS Lambda function and/or the API Gateway to reflect back the 'hub.challenge' verification token string?
You need to use the parameter mapping functionality of API Gateway to map the parameters from the incoming query string to a parameter passed to your Lambda function. From the documentation link you provided, it looks like you'll at least need to map the hub.challenge query string parameter, but you may also need the other parameters (hub.mode, hub.topic, and hub.verify_token) depending on what validation logic (if any) that you're implementing.
The first step is to declare your query string parameters in the method request page. Once you have declared the parameters open the integration request page (where you specify which Lambda function API Gateway should call) and use the "+" icon to add a new template. In the template you will have to specify a content type (application/json), and then the body you want to send to Lambda. You can read both query string and header parameters using the params() function. In that input mapping field you are creating the event body that is posted to AWS Lambda. For example: { "challenge": "$input.params('hub.challenge')" }
Documentation for mapping query string parameters

Is it possible to generate custom event on s3?

I tried to enable notifications in S3 bucket, but i get JSON format long data to my registered email , i want to filter on notifications's attribute such as "object deleted" , "date-time" only, so is it possible ?
If you want to either limit the fields returned, or filter the events that get generated, you are going to have to do that yourself.
Easiest way would probably be to have the s3 event notifications sent to a custom lambda function (that you write) that can filter and/or reformat the raw s3eventnotification and then have lambda send it on to your downstream consumer, i.e. via email if you want - but there is nothing built-in to aws to do the filtering/reformatting for you.