Skip to content
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

apollo-server-azure-functions #684

Closed
druidsgarden opened this issue Dec 6, 2017 · 5 comments
Closed

apollo-server-azure-functions #684

druidsgarden opened this issue Dec 6, 2017 · 5 comments

Comments

@druidsgarden
Copy link

Doesn't seem to be working correctly.

The documentation is misleading, it's missing the schema being passed into the server, which does allow it to work in a limited way

Graphiql does not work at all. The introspection information is not being returned at all.

Even when you point the standalone Electron version of GrahphiQL at the graphql server endpoint it's not returning the introspection information correctly to build the documentation.

`const server = require("apollo-server-azure-functions");
const graphqlTools = require("graphql-tools");

const typeDefs = `
type Random {
id: Int!
rand: String
}

type Query {
rands: [Random]
rand(id: Int!): Random
}
`;

const rands = [{ id: 1, rand: "random" }, { id: 2, rand: "modnar" }];

const resolvers = {
Query: {
rands: () => rands,
rand: (_, { id }) => rands.find(rand => rand.id === id)
}
};

const jsSchema = graphqlTools.makeExecutableSchema({
typeDefs,
resolvers,
});

module.exports = function run(context, request) {
//if (request.method === "POST") {

const graphQLOptions = {
  schema: jsSchema,  
  debug: true  
}; 
server.graphqlAzureFunctions(graphQLOptions)(context, request);

/* } else if (request.method === "GET") {
return server.graphiqlAzureFunctions({
endpointURL: '/api/graphql'
})(context, request);
}*/
};`

This will work if you pass the query on the command line or via standalone GraphiQL but you have to know what to call first.

This however is what you get when you point the standalone GraphiQL at the localhost endpoint

graphiql

@druidsgarden
Copy link
Author

druidsgarden commented Dec 11, 2017

So we have an update on this, my colleague found that there appears to be an obscure bug in the Node JS Support in Azure Functions V2 where the headers are getting overwritten which results in the bug we are seeing.

To fix azureFunctionsApollo.js needs to look like this:

`"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var apollo_server_core_1 = require("apollo-server-core");
var GraphiQL = require("apollo-server-module-graphiql");
function graphqlAzureFunctions(options) {
if (!options) {
throw new Error('Apollo Server requires options.');
}
if (arguments.length > 1) {
throw new Error("Apollo Server expects exactly one argument, got " + arguments.length);
}
return function (httpContext, request) {
var queryRequest = {
method: request.method,
options: options,
query: request.method === 'POST' ? request.body : request.query,
};
if (queryRequest.query && typeof queryRequest.query === 'string') {
queryRequest.query = JSON.parse(queryRequest.query);
}
return apollo_server_core_1.runHttpQuery([httpContext, request], queryRequest)
.then(function (gqlResponse) {
/* var result = {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: gqlResponse,
};
httpContext.res = result;
httpContext.done(null, result);*/
httpContext.res.setHeader('Content-Type', 'application/json' );
httpContext.res.raw(gqlResponse);

    })
        .catch(function (error) {
        var result = {
            status: error.statusCode,
            headers: error.headers,
            body: error.message,
        };
        httpContext.res = result;
        httpContext.done(null, result);
    });
};

}
exports.graphqlAzureFunctions = graphqlAzureFunctions;
function graphiqlAzureFunctions(options) {
return function (httpContext, request) {
var query = request.query;
GraphiQL.resolveGraphiQLString(query, options, httpContext, request).then(function (graphiqlString) {
/* httpContext.res = {
status: 200,
headers: {
'Content-Type': 'text/html',
},
body: graphiqlString,
};
httpContext.done(null, httpContext.res);*/
httpContext.res.setHeader('Content-Type', 'application/html', 'charset-utf-8');
httpContext.res.raw(graphiqlString);
}, function (error) {
httpContext.res = {
status: 500,
body: error.message,
};
httpContext.done(null, httpContext.res);
});
};
}
exports.graphiqlAzureFunctions = graphiqlAzureFunctions;
//# sourceMappingURL=azureFunctionsApollo.js.map`

@michael-golfi
Copy link
Contributor

michael-golfi commented Jan 7, 2018

I'm running into an issue with the Azure function sample, the GraphiQL page doesn't display at all. I tried the solution proposed by @druidsgarden to change the Content-Type to 'application/html', 'charset-utf-8' but when I tried that it downloads the html as a file in Chrome on Windows 10.

Instead, I set Content-Type to 'text/html; charset-utf-8' and it displays the page but the docs pane is empty and instead the result of the schema query is displayed in the results window, same as seen above.

Object.defineProperty(exports, "__esModule", { value: true });
var apollo_server_core_1 = require("apollo-server-core");
var GraphiQL = require("apollo-server-module-graphiql");

...

function graphiqlAzureFunctions(options) {
    return function (httpContext, request) {
        var query = request.query;
        GraphiQL.resolveGraphiQLString(query, options, httpContext, request).then(function (graphiqlString) {
            // httpContext.res = {
            //     status: 200,
            //     headers: {
            //         'Content-Type': 'text/html',
            //     },
            //     body: graphiqlString,
            // };
            // httpContext.done(null, httpContext.res);
            httpContext.res.setHeader('Content-Type', 'text/html; charset-utf-8');
            httpContext.res.raw(graphiqlString);
        }, function (error) {
            httpContext.res = {
                status: 500,
                body: error.message,
            };
            httpContext.done(null, httpContext.res);
        });
    };
}
exports.graphiqlAzureFunctions = graphiqlAzureFunctions;
//# sourceMappingURL=azureFunctionsApollo.js.map

@michael-golfi
Copy link
Contributor

michael-golfi commented Jan 7, 2018

I managed to fix this with three changes. I had to change the response Content-Type and populate the query field for GraphiQL.

First, I made the changes that @druidsgarden suggested above. I also tried separating the GraphiQL handling from the GraphQL API endpoint.

First of all, here is my apolloFunctionsAzure.js:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var apollo_server_core_1 = require("apollo-server-core");
var GraphiQL = require("apollo-server-module-graphiql");
function graphqlAzureFunctions(options) {
    if (!options) {
        throw new Error('Apollo Server requires options.');
    }
    if (arguments.length > 1) {
        throw new Error("Apollo Server expects exactly one argument, got " + arguments.length);
    }
    return function (httpContext, request) {
        var queryRequest = {
            method: request.method,
            options: options,
            query: request.method === 'POST' ? request.body : request.query,
        };
        if (queryRequest.query && typeof queryRequest.query === 'string') {
            queryRequest.query = JSON.parse(queryRequest.query);
        }
        return apollo_server_core_1.runHttpQuery([httpContext, request], queryRequest)
            .then(function (gqlResponse) {
                // var result = {
                //     status: 200,
                //     headers: { 'Content-Type': 'application/json' },
                //     body: gqlResponse,
                // };
                // httpContext.res = result;
                // httpContext.done(null, result);
                httpContext.res.setHeader('Content-Type', 'application/json');
                httpContext.res.raw(gqlResponse);
                httpContext.done(null, httpContext.res);
            })
            .catch(function (error) {
                var result = {
                    status: error.statusCode,
                    headers: error.headers,
                    body: error.message,
                };
                httpContext.res = result;
                httpContext.done(null, result);
            });
    };
}
exports.graphqlAzureFunctions = graphqlAzureFunctions;
function graphiqlAzureFunctions(options) {
    return function (httpContext, request) {
        var query = request.query;
        GraphiQL.resolveGraphiQLString(query, options, httpContext, request).then(function (graphiqlString) {
            // httpContext.res = {
            //     status: 200,
            //     headers: {
            //         'Content-Type': 'text/html; charset-utf-8',
            //     },
            //     body: graphiqlString,
            // };
            // httpContext.done(null, httpContext.res);
            httpContext.res.setHeader('Content-Type', 'text/html; charset-utf-8');
            httpContext.res.raw(graphiqlString);
            httpContext.done(null, httpContext.res);
        }, function (error) {
            httpContext.res = {
                status: 500,
                body: error.message,
            };
            httpContext.done(null, httpContext.res);
        });
    };
}
exports.graphiqlAzureFunctions = graphiqlAzureFunctions;
//# sourceMappingURL=azureFunctionsApollo.js.map

This is my index.ts for my graphiql function:

import { graphiqlAzureFunctions } from 'apollo-server-azure-functions';
import { HttpContext, IFunctionRequest } from 'azure-functions-typescript';

export function run(context: HttpContext, request: IFunctionRequest) {
    graphiqlAzureFunctions({ endpointURL: '/api/graphql', query: '{ me { email } }' })(context, request);
};

I learned that if you only make the changes to apolloAzureFunctions.js then you will end up with a GraphiQL client that dumps the schema in the results menu and doesn't update the docs schema pane properly. For some reason the query field has to be populated to avoid that particular problem. But if you set the query and don't patch the apolloAzureFunctions.js then your GraphiQL may not display properly and also the JSON responses will be strings and not well formed JSON.

@thoughtspeed7
Copy link

Do we have to deploy Apollo GraphQL Server and GraphiQL separately as two different Azure Functions?

@abernix
Copy link
Member

abernix commented Jun 21, 2018

@thoughtspeed7 You shouldn't have to! Typically, it's possible to have them listen on different endpoints.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants