Using apollo-upload-client with rest link
DamiToma opened this issue · 6 comments
Hi! I'm working on an app which is using Apollo Client on the frontend and need to upload files to my backend. So I set up my mutation as follows:
import { gql } from "@apollo/client";
import * as Apollo from "@apollo/client";
export type UploadFileInput = {
taskId: number;
input: { file: any };
};
export type UploadFileMutation = {
create: { success: boolean };
};
export const UploadFileDocument = gql`
mutation UploadFile($taskId: ID!, $file: Upload!) {
create(taskId: $taskId, file: $file, input: {})
@rest(type: "File" path: "/task/{args.taskId}/upload-file" method: "POST") {
success
}
}
`;
export function useUploadFileMutation(
baseOptions?: Apollo.MutationHookOptions<UploadFileMutation, UploadFileInput>
) {
return Apollo.useMutation<UploadFileMutation, UploadFileInput>(
UploadFileDocument,
{ ...baseOptions }
);
}
Then I have a form with an input type file that submits the call as follows:
uploadFile({
variables: {
taskId: taskIds[i],
file: task.document[0],
},
});
The problem is when I check the request sent to the backend, the payload is always empty (its value is {}
). I think it might be related to the fact I added input: {}
in the mutation definition, but I must do that as a body cannot be empty in a POST request (Apollo would throw an error otherwise).
I'm 100% sure that task.document[0]
holds the right file information, printing it out to the console shows it's a File
object. So I wonder whether the fact that I'm using a REST link might be causing any issues. I gave it several tries, but could not get it to work. Any help on this would be much appreciated, thanks!
Usually when a File
value in a payload is incorrectly {}
, that means that the upload terminating link isn't setup correctly in Apollo Client, because that's how the regular HTTP link from Apollo serialises a File
. Double check that the installation instructions have been followed correctly:
https://github.com/jaydenseric/apollo-upload-client/tree/v17.0.0#installation
I'm not using HttpLink
, but RestLink
from apollo-link-rest
. The client has a chain of links
const client = new ApolloClient({
cache: RootCache,
link: from([
authLink,
createUploadLink({
uri: URI
}),
]),
});
Where authLink
is defined concatenating the authentication link with the httpLink
const httpLink = new RestLink({
uri: URI,
});
const withToken = setContext((_, { headers }) => {
...
});
const authLink = withToken.concat(httpLink);
Might this be causing issues, even if I'm not using the HTTP link from @apollo/client
?
You can only have one "terminating" link that ends the chain and makes the request. As per the installation instructions:
Apollo Client can only have 1 terminating Apollo Link that sends the GraphQL requests; if one such as
HttpLink
is already setup, remove it.
I'm not experienced with the REST link, but it looks like a terminating link that sends requests.
I'm sorry for the additional question, but I'm not very experienced with Apollo Client. By removing the terminating link, do you mean I should get rid of .concat(httpLink)
? I've looked the link you shared up and seems like it can be the only terminating link. The thing is if I remove it how is the client going to send the request then?
The link created by createUploadLink
is a terminating link that sends the final request. If there are no files to upload, it sends a GraphQL POST request, if there are files to upload, it sends a GraphQL multipart request. If you are working with a REST API instead of a GraphQL API, then the REST API isn't going to know what to do with a GraphQL multipart request. This apollo-upload-client
package is for making requests to a GraphQL API, not a REST API so I think it might not be appropriate for your project.
Bummer, was hoping to have the two work together. Thanks a lot for the help!