Open dominik-myszkowski opened 1 year ago
I'm having the same issue, I can't figure out why the headers set in willSendRequest
are ignored. Any clue?
Actually, this was fixed by https://github.com/profusion/apollo-federation-file-upload/commit/962583d88afa8843a0e0d4cce71696417d8aec50 but not released yet ?
Same problem here. I can see that the gateway sets the headers based on the context via the willSendRequest method but the headers don't propagate to the corresponding service with subgraph. Any solutions pls? Right now I can't authenticate user accessing upload resolver implemeted by the microservice :/
@superlevure please have you somehow managed to get it to set the headers? If so could you please provide a workaround?
For anyone having this issue, my workaround for now is simply constructing the headers object based on context value received via GraphQLDataSourceProcessOptions args. Somehow the request?.http?.headers returns undefined so I relied on the context, where my authenticated user is set. So basically I tweaked the processFiles method like this
private async processFiles(
args: GraphQLDataSourceProcessOptions,
fileVariables: FileVariablesTuple[]
): ProcessResult {
const { context, request } = args;
const form = new FormData();
const variables = cloneDeep(request.variables || {});
fileVariables.forEach(([variableName]: FileVariablesTuple): void => {
set(variables, variableName, null);
});
const operations = JSON.stringify({
query: request.query,
variables,
});
form.append("operations", operations);
const fileMap: { [key: string]: string[] } = {};
const resolvedFiles: FileUpload[] = await Promise.all(
fileVariables.map(
async (
[variableName, file]: FileVariablesTuple,
i: number
): Promise<FileUpload> => {
const fileUpload: FileUpload = await file;
fileMap[i] = [`variables.${variableName}`];
return fileUpload;
}
)
);
// This must come before the file contents append bellow
form.append("map", JSON.stringify(fileMap));
await this.addDataHandler(form, resolvedFiles);
// This must happen before constructing the request headers
// otherwise any custom headers set in willSendRequest are ignored
if (this.willSendRequest) {
await this.willSendRequest(args);
}
console.log(context.user, context.locale);
const headers = {
// ...Object.fromEntries(request?.http?.headers || []),
...Object.fromEntries([["user", JSON.stringify(context[user])]]),
...form.getHeaders(),
};
console.log(headers);
Object.assign(headers, form.getHeaders() || {});
const httpRequest = {
headers,
method: "POST",
url: this.url,
};
const options = {
...httpRequest,
body: form,
};
// NOTE: there is currently a type mismatch related to Headers in @apollo/gateway and apollo-server-env:
//
// >> you should ensure that you pass "plain" objects rather than Headers or Request objects,
// >> as the newer version has slightly different logic about how to recognize Headers and
// >> Request objects.
//
// see:
// - https://github.com/apollographql/federation/pull/1906
// - https://github.com/profusion/apollo-federation-file-upload/issues/52#issuecomment-1148946002
request.http = httpRequest as Exclude<typeof request.http, undefined>;
let httpResponse: Response | undefined;
try {
httpResponse = await this.fetcher(this.url, options);
const body = await this.parseBody(httpResponse);
if (!isObject(body)) {
throw new Error(`Expected JSON response body, but received: ${body}`);
}
const response = {
...body,
http: httpResponse,
};
if (typeof this.didReceiveResponse === "function") {
return this.didReceiveResponse({ context, request, response });
}
return response;
} catch (error) {
this.didEncounterError(error, options, httpResponse);
throw error;
}
}`
Ran into this problem too; it seems like the code here is the culprit as it never passes the headers down to the Request constructor. This will cause lots of issues with subgraphs that need access to e.g. Authorization or apollo-require-preflight headers to function correctly.
As mentioned above there seems to be a commit that fixes this - can this be released soon?
request.http = {
headers,
method: 'POST',
url: this.url,
};
if (this.willSendRequest) {
yield this.willSendRequest(args);
}
const options = Object.assign(Object.assign({}, request.http), {
// Apollo types are not up-to-date, make TS happy
body: form });
const httpRequest = new apollo_server_env_1.Request(request.http.url, options);
will this be released soon? 💯
Any idea, I got stucked on this. Upload works fine, yet headers are not overwritten.
🚀 Feature Request
Description
Implementation details
Potential caveats
Acceptance criteria
Additional context and visual reference
*