aws-sdk-ios
aws-sdk-ios copied to clipboard
Generated API.swift sends mimeType and localUri from S3ObjectTypeInput with mutation.
Describe the bug I've added storage to my amplify project, and wired it into my GraphQL API as described in the docs, by adding an S3Object type to my schema.
type S3Object {
bucket: String!
region: String!
key: String!
}
As expected, this adds the S3Object type to the schema in AppSync, along with it's associated S3ObjectInput.
input S3ObjectInput {
bucket: String!
region: String!
key: String!
}
The generated API.swift file correctly generates the S3ObjectInput struct, including mimeType
and localUri
which are needed for AppSync to perform an upload in in conjunction with a mutation on an item containing an S3Object.
public struct S3ObjectInput: GraphQLMapConvertible {
public var graphQLMap: GraphQLMap
public init(bucket: String, region: String, key: String, localUri: String, mimeType: String) {
graphQLMap = ["bucket": bucket, "region": region, "key": key, "localUri": localUri, "mimeType": mimeType]
}
public var bucket: String {
get {
return graphQLMap["bucket"] as! String
}
set {
graphQLMap.updateValue(newValue, forKey: "bucket")
}
}
So far, so good.
However, when a migration is run on an item containing an s3Object using s3ObjectInput, the mimeType
and localUri
are also sent to AppSync with the mutation. The file upload completes successfully, but the mutation fails with an error since AppSync isn't expecting mimeType or localUri (as expected).
Error saving the item on server: [The variables input contains a field name 'mimeType' that is not defined for input object type 'S3ObjectInput' ]
It looks like this might not have been an issue so much in the past, as most of the older attempts at getting this to work included manually defining the S3Object and S3ObjectInput, and including the mimeType
and localUri
in S3ObjectInput. This would be combined with logic in the resolver to not include these values when writing to the DB, or simply storing everything (https://github.com/awslabs/aws-mobile-appsync-sdk-ios/issues/279#issuecomment-515533619).
Due to another bug (https://github.com/aws-amplify/amplify-cli/issues/1903) this can't be used as a solution, even if it's not the best solution anyway.
To Reproduce
Create an Amplify iOS project with API and Storage, add an S3Object to your schema, push + codegen, upload a file in the iOS app.
Expected behavior
The generated API.swift should include mimeType
and localUri
in S3ObjectInput to handle the file upload, but not pass those values on to the GraphQL mutation.
- Amplify-CLI version 1.9.0
- OS: OSX
- iOS: 12.3
@cjmartin We've fixed the CLI related issue (#1903) and it's part of the latest CLI release. Transferring this issue to the amplify iOS team to take a look at your query.
@kaustavghosh06 thanks!
@yuth Let me know if you need more clarification on this. It's a bit complicated since most people who are currently using this have probably gone ahead and added the mimeType
and localUri
fields to the S3ObjectInput
type in their graphql schema and are ignoring the values on The AppSync side in their resolvers (this is what I'm currently doing).
It would be really nice if the iOS Codegen + generated swift code could detect if the mimeType
and or localUri
were specifically included in the schema and send them if so, otherwise use them for the upload but don't send them as part of the graphQL request. If this worked I would remove the localUri
from my schema at the very least.
Thanks!
Not sure what I did to unassign @yuth there ☝️ 🤷♂
@palpatim is there some thing that SDK can do to remove mimeType
and localUri
If the fields are code-generated, they'll be included in the request automatically, but the SDK doesn't do any field-level filtering. I wouldn't really want us to be in that business in any case--once we start inspecting fields at the SDK level, we run into all kinds of problems with potentially inconsistent behaviors across app versions, platforms, etc, not to mention the cognitive burden of remembering where the magic is actually happening.
I think the right behavior here is to edit the schema to remove localUri
and mimeType
from the declared S3ObjectType
, and rerun amplify codegen
to generate new Swift types for the complex object mutations.
@yuth does that match your understanding?
Opened https://github.com/aws-amplify/docs/pull/866 to clarify the expected behavior
Currently it isn't necessary to add localUri
and mimeType
to the declared S3ObjectType
, they are added automatically in the swift code by Codegen. The issue is that since they're being sent with the GraphQL request, the request will fail unless they are added to the S3ObjectInput
in the schema.
It would be great if they were added in swift, but not sent with the GraphQL request unless they are actually specified in the schema.
Does that make sense?
I should clarify that when I say "schema" I'm referring to the amplify file, not the codegen'd file.
@cjmartin Thanks for the clarification. The issue we're wrestling with is that the AppSync programming model is very much geared toward using the code-generated objects all up and down the chain. Adding special case logic to the serializer for just that object type makes me uncomfortable.
And wouldn't really be the right solution in 100% of the cases; it's conceivable that some app may actually want the localUri
to be stored in their store, and therefore actually define it in the schema. We'd have no way of knowing that since all we get on the client is the code generated schema.
At this point, I'm of the opinion that the right solution for this is going to involve the amplify CLI generating resolvers that understand how to ignore those fields by default and not throw validation errors if the incoming objects contain them. I'm discussing this with @yuth and will update this issue when we have more info.
I'm faced with this issue also. Presume I have to add S3ObjectInput to my API schema like so for now?
input S3ObjectInput {
bucket: String!
key: String!
region: String!
localUri: String!
mimeType: String!
}
Thanks for opening this feature request. We recommend using the API (GraphQL) category in Amplify Swift for this -- for more information, please visit https://docs.amplify.aws/swift/build-a-backend/graphqlapi/
Specifically, the Working with files section is relevant for your request.
Thanks!