-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only works with top-level variables #5
Comments
Maybe we could introduce a top-level variable
Edit: I now realize that we need to deeply parse the variables anyway, because we have to append the |
Fully working example fixing a lot of issues (a mix of your script and the script from here): import { printAST } from 'apollo-client';
import { HTTPFetchNetworkInterface } from 'apollo-client/transport/networkInterface';
import RecursiveIterator from 'recursive-iterator';
import objectPath from 'object-path';
export default function createNetworkInterface(opts) {
const { uri } = opts;
return new UploadHTTPFetchNetworkInterface(uri, opts);
};
class UploadHTTPFetchNetworkInterface extends HTTPFetchNetworkInterface {
constructor(...args) {
super(...args);
const normalQuery = this.fetchFromRemoteEndpoint.bind(this);
this.fetchFromRemoteEndpoint = ({request, options}) => {
const formData = new FormData();
// search for File objects on the request and set it as formData
let hasFile = false;
for (let { node, path } of new RecursiveIterator(request.variables)) {
if (node instanceof File) {
hasFile = true;
const id = Math.random().toString(36);
formData.append(id, node);
objectPath.set(request.variables, path.join('.'), id);
}
}
if (hasFile) {
return this.uploadQuery({request, options}, formData);
} else {
return normalQuery({request, options});
}
};
}
uploadQuery({request, options}, formData) {
formData.append('operationName', request.operationName);
formData.append('query', printAST(request.query));
formData.append('variables', JSON.stringify(request.variables || {}));
return fetch(this._opts.uri, {
...options,
body: formData,
method: 'POST',
headers: {
Accept: '*/*',
...options.headers
}
});
}
};
|
@jessedvrs your comment was really helpful, this feature is supported in apollo-upload-server. I referenced you in the readme 🙂 See here in the src. I created a generic |
@jaydenseric happy to help! |
I've been thinking about this a lot. I think the simplest way to implement this is to recursively traverse the variables object and look for file types such as files, file lists, etc. If we find files, we should push them into an array leave a token in place of the file object that can be programmatically parsed to determine where in the array the file was placed. If a file list is an encountered, we loop across it and push each file into the array, leaving an array of tokens rather than a single token. Then, we convert to form data and preserve the order of the files. On the server, we can then re-constitute the exact positions of the files using the tokens before we pass the variables into the resolvers. The trick here is that we only want to worry about this if we are using HTTP. For users using WebSockets as their primary transport, a different solution would need to exist. For this reason, I think it's best for this to live in the |
We should probably support FileLists nested in variables. It's common to pass an input type rather than scalars for mutation and query params. It seems like a simple bit of recursion could make this work.
The text was updated successfully, but these errors were encountered: