apollo-server icon indicating copy to clipboard operation
apollo-server copied to clipboard

Call for maintainers: apollo-server-hapi

Open glasser opened this issue 3 years ago • 5 comments

As described in the roadmap, Apollo Server 4 will shift from the model of "9 web framework integrations maintained by a team who only uses one of them and nope, you can't create your own" to "a stable web framework integration API that anyone can use for their favorite web framework".

As part of this, the Apollo Server core team is no longer planning to maintain apollo-server-hapi. We think users of Hapi are best served if their framework integration is maintained by a team of people who use Hapi every day.

This is where you come in! Do you love Hapi? Do you use it with Apollo Server? Would you like to be part of a team of community members who maintain apollo-server-hapi?

If so, chime in below! We'd love to find a group of people who will maintain the Apollo Server 4 version of apollo-server-hapi, and to help us maintain the section of the Apollo Server docs that shows how to use Apollo Server with Hapi.

We expect that maintaining this package will be more straightforward than maintaining an Apollo Server integration today, because its only responsibility will be translating Hapi's HTTP request and response objects to the formats used by Apollo Server's new API.

At the time that this issue is opened, we are actively looking for interested collaborators; however, the API you'll be implementing isn't yet ready. We can use this issue to get a team together who can get started at some point between an initial alpha release of the new @apollo/server package and the final v4.0.0 release.

glasser avatar Jan 25 '22 21:01 glasser

@glasser I could potentially help on the hapijs integration when things are ready

arimus avatar Jul 26 '22 07:07 arimus

Hey @arimus, that'd be great!

We've written a step-by-step guide and built out a couple of working examples.

Let me know if you have any issues or if there's anything I can do to help. If you'd like to keep me updated on any progress that'd be super helpful for me. Thanks in advance!

-- Trevor

trevor-scheer avatar Jul 28 '22 23:07 trevor-scheer

@trevor-scheer great, I'll take a look!

arimus avatar Jul 30 '22 17:07 arimus

Just an FYI that I'm looking to begin working on this soon. I've been unable to tackle it as of yet, but just wanted to keep folks in the loop. Still here :)

arimus avatar Aug 31 '22 19:08 arimus

@arimus thanks for the update! We're going to have AS4 ready fairly soon and would love to have integrations ready to go leading up to that. If there's anything I can do to help fast track the process just let me know.

trevor-scheer avatar Aug 31 '22 22:08 trevor-scheer

One new note — we've set up a new GH org (https://github.com/apollo-server-integrations/) and @as-integrations npm namespace for these integrations. Hopefully we can get a Hapi one set up there soon!

glasser avatar Oct 03 '22 21:10 glasser

Heh. I was about to give an update on this last night and sorry for the delay. I just started poking into the docs and getting set up last night to get going on the integration. I saw that the preview was released (great work and congrats!) and I need to get my butt in gear!

On Mon, Oct 3, 2022 at 3:28 PM David Glasser @.***> wrote:

One new note — we've set up a new GH org ( https://github.com/apollo-server-integrations/) and @as-integrations npm namespace for these integrations. Hopefully we can get a Hapi one set up there soon!

— Reply to this email directly, view it on GitHub https://github.com/apollographql/apollo-server/issues/6028#issuecomment-1266073360, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABXYKUJSHJPIIZEQJ2AZHLWBNFZHANCNFSM5MZKUXTA . You are receiving this because you were mentioned.Message ID: @.***>

arimus avatar Oct 03 '22 22:10 arimus

Apollo Server v4.0.0 will be published to latest soon!

We now have a community GH org where people can create an integration repo as well as an NPM scope for publishing integration packages. If you'd like to be involved over there, feel free to get in touch with me. This is not a requirement for building and publishing an integration, but we wanted to offer a sensible place for these community-maintained packages to live.

https://github.com/apollo-server-integrations https://www.npmjs.com/search?q=%40as-integrations

trevor-scheer avatar Oct 10 '22 17:10 trevor-scheer

Trevor, I've started leveraging some of the scaffolding for some of the other plugins and created a project in my github, but yeah it may make sense to move it over and utilize the CI over there. I'm still working through getting some tests to succeed :)

David

On Mon, Oct 10, 2022 at 11:43 AM Trevor Scheer @.***> wrote:

Apollo Server v4.0.0 will be published to latest soon!

We now have a community GH org where people can create an integration repo as well as an NPM scope for publishing integration packages. If you'd like to be involved over there, feel free to get in touch with me. This is not a requirement for building and publishing an integration, but we wanted to offer a sensible place for these community-maintained packages to live.

https://github.com/apollo-server-integrations https://www.npmjs.com/search?q=%40as-integrations

— Reply to this email directly, view it on GitHub https://github.com/apollographql/apollo-server/issues/6028#issuecomment-1273636728, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABXYKWWGZUWHRSQXYFFTQTWCRIVXANCNFSM5MZKUXTA . You are receiving this because you were mentioned.Message ID: @.***>

arimus avatar Oct 11 '22 18:10 arimus

Sounds great David. I just sent you an invite to the org and created a Hapi team. You should be able to transfer the repo over there at your convenience. If I can help with anything, just let me know 😄

trevor-scheer avatar Oct 11 '22 19:10 trevor-scheer

@trevor-scheer I could use a pointer here, as there are a lot of things going on under the hood for the integration tests. Here's the current state and half of the tests succeed. There's an error wrapping item I need to play with some more, but it appears that the rest of the tests fail with "ECONNREFUSED 127.0.0.1:80"

I'm not sure why the integration tests would be trying to connect to localhost port 80. The URL returned for the integration test to successfully hit the hapi server is working, but I don't see where or why it would be trying to connect to something different. It's probably something silly I'm missing, any hints?

  integration tests
    apolloServerTests.ts
      constructor
        validation rules
          ✓ accepts additional rules (186 ms)
          ✓ allows introspection by default (21 ms)
          ✓ prevents introspection by default during production (15 ms)
          ✓ allows introspection to be enabled explicitly (11 ms)
        appropriate error for bad user input
          ✓ variable coercion errors (21 ms)
          ✓ catches required type variable error and returns UserInputError (16 ms)
          ✓ catches required List type variable error and returns UserInputError (13 ms)
          ✓ catches non-null type variable error and returns UserInputError (19 ms)
          ✓ catches non-null List type variable error and returns UserInputError (16 ms)
          ✓ catches List of non-null type variable error and returns UserInputError (12 ms)
        schema creation
          ✓ accepts typeDefs and resolvers (20 ms)
          ✓ accepts a gateway's schema and calls its executor (14 ms)
          ✓ rejected load promise is thrown by server.start (3 ms)
      Plugins
        ✓ returns correct status code for a normal operation (17 ms)
        ✓ allows setting a custom status code for an error (13 ms)
        ✓ preserves user-added "extensions" in the response when parsing errors occur (11 ms)
        ✓ preserves user-added "extensions" in the response when validation errors occur (17 ms)
      formatError
        ✕ wraps thrown error from validation rules (12 ms)
      lifecycle
        ✓ errors thrown in plugins call formatError and are wrapped (15 ms)
        ✓ propagates error codes in production (25 ms)
        ✓ propagates error codes with null response in production (13 ms)
        ✓ propagates error codes in dev mode (20 ms)
        ✓ shows error extensions in extensions (only!) (20 ms)
        for Apollo usage reporting
          traces
            ✓ cachePolicy (46 ms)
            ✓ does not expose stack (33 ms)
            ✓ sets the trace key to operationName when it is defined (17 ms)
            ✓ sets the trace key to unknown operation for missing operation (14 ms)
            ✓ sets the trace key to parse failure when non-parsable gql (18 ms)
            ✓ sets the trace key to validation failure when invalid operation (18 ms)
            ✓ sets the trace key to "-" when operationName is undefined (16 ms)
            ✓ doesn't resort to query body signature on `didResolveOperation` error (16 ms)
            ✓ doesn't internal server error on an APQ (16 ms)
            ○ skipped includes all fields with defer
            error munging
              ✓ undefined error (21 ms)
              ✓ unmodified (17 ms)
              ✓ masked (23 ms)
              sendErrors
                ✓ new error (16 ms)
                ✓ modified error (21 ms)
                ✓ nulled error (15 ms)
        context field
          ✓ defers context eval with thunk until after options creation (21 ms)
          context cloning
            ✓ clones the context for request pipeline requests (14 ms)
            ✓ for every request with executeOperation (9 ms)
          as a function
            ✓ can accept nothing and return an empty object (5 ms)
            ✓ can be an async function (19 ms)
            context errors
              ✓ GraphQLErrors are formatted, defaulting to status 500 (12 ms)
              ✓ GraphQLErrors are formatted, defaulting to INTERNAL_SERVER_ERROR (9 ms)
              ✓ GraphQLErrors are formatted, obeying http extension (12 ms)
              ✓ non-GraphQLErrors are formatted (12 ms)
          as an object
            ✓ can be an empty object (12 ms)
            ✓ can contain arbitrary values (15 ms)
      Persisted Queries
        ✓ returns PersistedQueryNotFound on the first try (12 ms)
        ✓ returns result on the second try (30 ms)
        ✓ returns result on the persisted query (14 ms)
        ✓ returns error when hash does not match (7 ms)
        ✓ returns correct result for persisted query link (20 ms)
        ✓ returns correct result for persisted query link using get request (27 ms)
      usage reporting
        graphql server functions even when Apollo servers are down
          ✓ with retryable error (409 ms)
          ✓ with network error (457 ms)
          ✓ with non-retryable error (19 ms)
      Federated tracing
        ✓ doesn't include federated trace without the special header (24 ms)
        ✓ doesn't include federated trace without _Service in the schema (23 ms)
        ✓ reports a total duration that is longer than the duration of its resolvers (22 ms)
        ✓ includes errors in federated trace (18 ms)
      Gateway
        ✓ receives schema updates from the gateway (with document store: true) (20 ms)
        ✓ receives schema updates from the gateway (with document store: false) (27 ms)
        ✓ passes apollo data to the gateway (11 ms)
        ✓ unsubscribes from schema update on close (4 ms)
        ✓ waits until gateway has resolved a schema to respond to queries (10 ms)
        ✓ can serve multiple active schemas simultaneously during a schema rollover (27 ms)
      renderLandingPage
        ✕ defaults to LocalDefault (9 ms)
        ✕ can specify version for LocalDefault (9 ms)
        ✕ can install playground with specific version (10 ms)
        ✕ can be disabled (13 ms)
        basic functionality
          ✕ basic GET works (6 ms)
          ✕ basic GET works with more complex header (11 ms)
          ✕ no landing page with application/json (8 ms)
          ✕ no landing page with */* (10 ms)
          ✕ needs the header (6 ms)
        startup errors
          ✓ only one plugin can implement renderLandingPage (5 ms)
      CSRF prevention
        ✕ default (7 ms)
        ✕ csrfPrevention: {requestHeaders} (11 ms)
        ✕ csrfPrevention: false (5 ms)
    httpServerTests.ts
      graphqlHTTP
        ✕ rejects the request if the method is not POST or GET (12 ms)
        ✕ throws an error if POST body is empty (7 ms)
        ✕ throws an error if POST body is missing even with content-type (5 ms)
        ✕ throws an error if invalid content-type (5 ms)
        ✕ throws an error if POST operation is missing (5 ms)
        ✕ throws an error if POST operation is empty (6 ms)
        ✕ throws an error if POST JSON is malformed (6 ms)
        ✕ returns an error on parse failure (5 ms)
        ✕ returns an error on validation failure (18 ms)
        ✕ unknown operation name returns 400 and OPERATION_RESOLUTION_FAILURE (5 ms)
        ✕ multiple operations with no `operationName` specified returns 400 and OPERATION_RESOLUTION_FAILURE (5 ms)
        ✕ throws an error if GET query is missing (4 ms)
        ✕ can handle a basic GET request (6 ms)
        ✕ can handle a basic implicit GET request (6 ms)
        ✕ throws error if trying to use mutation using GET request (5 ms)
        ✕ throws error if trying to use mutation with fragment using GET request (7 ms)
        ✕ does not accept multiple query search parameters (6 ms)
        ✕ can handle a GET request with variables (6 ms)
        ✕ can handle a basic request (10 ms)
        ✕ can handle a basic request accepting application/json (4 ms)
        ✕ can handle a basic request accepting application/json; charset=utf-8 (5 ms)
        ✕ can handle a basic request accepting application/graphql-response+json (17 ms)
        ✕ can handle a basic request accepting application/graphql-response+json; charset=utf-8 (4 ms)
        ✕ can handle a basic request accepting application/graphql-response+json, application/json (4 ms)
        ✕ can handle a basic request accepting application/json, application/graphql-response+json (4 ms)
        ✕ can handle a basic request accepting application/json; q=0.5, application/graphql-response+json (4 ms)
        ✕ responses have content-length headers (4 ms)
        ✕ cache-control not set without any hints (10 ms)
        ✕ cache-control set with dynamic hint (6 ms)
        ✕ cache-control set with defaultMaxAge (4 ms)
        ✕ returns PersistedQueryNotSupported to a GET request if PQs disabled (6 ms)
        ✕ returns PersistedQueryNotSupported to a POST request if PQs disabled (7 ms)
        ✕ returns PersistedQueryNotFound to a GET request (8 ms)
        ✕ returns PersistedQueryNotFound to a POST request (5 ms)
        ✕ can handle a request with variables (5 ms)
        ✕ POST does not handle a request with variables as string (13 ms)
        ✕ POST does not handle a request with extensions as string (5 ms)
        ✕ can handle a request with operationName (6 ms)
        ✕ can handle introspection request (4 ms)
        ✕ does not accept a query AST (5 ms)
        ✕ can handle batch requests (4 ms)
        ✕ can handle non-batch requests when allowBatchedHttpRequests is true (4 ms)
        ✕ can handle batch requests with one element (5 ms)
        ✕ returns an error on batch requests with no elements (6 ms)
        ✕ can handle batch requests in parallel (5 ms)
        ✕ disables batch requests by default (4 ms)
        ✕ clones batch context (5 ms)
        ✕ executes batch context if it is a function (8 ms)
        ✕ can handle a request with a mutation (4 ms)
        ✕ willSendResponse can be equivalent to the old formatResponse function (4 ms)
        ✕ passes the context to the resolver (7 ms)
        ✕ passes the rootValue to the resolver (4 ms)
        ✕ passes the rootValue function result to the resolver (4 ms)
        ✕ returns errors (14 ms)
        ✕ applies formatError if provided (4 ms)
        ✕ formatError receives error that can be unwrapped to pass instanceof checks (5 ms)
        ✕ formatError receives error that passes instanceof checks when GraphQLError (4 ms)
        ✕ GraphQLError HTTP extensions are respected and stripped (5 ms)
        ✕ formatError receives correct error for parse failure (4 ms)
        ✕ allows for custom error formatting to sanitize (6 ms)
        ✕ allows for custom error formatting to elaborate (5 ms)
        ✕ sends internal server error when formatError fails (4 ms)
        ✕ applies additional validationRules (7 ms)
        cache-control
          ✕ applies cacheControl Headers (8 ms)
          ✕ contains no cacheControl Headers when uncacheable (7 ms)
          ✕ contains private cacheControl Headers when scoped (5 ms)
          ✕ runs when cache-control is disabled (6 ms)
      status code
        ✕ allows setting a custom status code (6 ms)
      incremental delivery
        mocked execution
          ○ skipped basic @defer working
          ○ skipped first payload sent while deferred field is blocking
        tests that require graphql@17
          ○ skipped errors when @defer is used with accept: undefined
          ○ skipped errors when @defer is used with accept: application/json
          ○ skipped errors when @defer is used with accept: multipart/mixed
          ○ skipped errors when @defer is used with accept: multipart/mixed; deferSpec=12345
          ○ skipped basic @defer working with accept: multipart/mixed; deferSpec=20220824
          ○ skipped basic @defer working with accept: multipart/mixed; deferSpec=20220824, application/json
          ○ skipped basic @defer working with accept: application/json, multipart/mixed; deferSpec=20220824
          ○ skipped first payload sent while deferred field is blocking
      Persisted Queries
        ✕ when ttlSeconds is set, passes ttl to the apq cache set call (11 ms)
        ✕ when ttlSeconds is unset, ttl is not passed to apq cache (5 ms)
        ✕ errors when version is not specified (4 ms)
        ✕ errors when version is unsupported (17 ms)
        ✕ errors when hash is mismatched (4 ms)
        ✕ returns PersistedQueryNotFound on the first try (5 ms)
        ✕ returns result on the second try (4 ms)
        ✕ returns with batched persisted queries (14 ms)
        ✕ returns result on the persisted query (5 ms)
        ✕ returns error when hash does not match (6 ms)
        ✕ returns correct result using get request (8 ms)

  ● integration tests › apolloServerTests.ts › formatError › wraps thrown error from validation rules

    connect ECONNREFUSED 127.0.0.1:80

arimus avatar Oct 20 '22 16:10 arimus

@arimus Do you have a link to your code? I'm guessing this means that you're not including a port in the url returned from your createServer function?

glasser avatar Oct 20 '22 16:10 glasser

@glasser I'll get my code pushed up, but for now I'm pasting from integration.test.ts. So apollo server created, hapi server created on random port, plugin wired up to tie them together, returned URL with host + port + /graphql where mapped. All the first half of tests works, which is why it doesn't seem to make sense that there is still something trying to hit localhost:80.

defineIntegrationTestSuite(
  async function (
    serverOptions: ApolloServerOptions<BaseContext>,
    testOptions?: CreateServerForIntegrationTestsOptions,
  ) {
    const apolloServer = new ApolloServer({
      ...serverOptions,
      plugins: [...(serverOptions.plugins ?? [])],
    });
    await apolloServer.start();

    const hapi = new Server({
      debug: {
        log: ['*'],
        request: ['*']
      },
      host: 'localhost',
      port: 0
    });

    const context = testOptions?.context;

    await hapi.register({
      plugin: require('..'),
      options: {
        context,
        apolloServer
      }
    });

    await hapi.start();

    const url = path.join(hapi.info.uri, 'graphql');
    return { server: apolloServer, url };
}

arimus avatar Oct 24 '22 17:10 arimus

@arimus did you push it somewhere? Did you verify that hapi.info.uri really does return what you expect?

glasser avatar Oct 24 '22 23:10 glasser

and what do you mean by "the first half"?

glasser avatar Oct 24 '22 23:10 glasser

Pushed the initial here: https://github.com/arimus/apollo-server-integration-hapijs

The base template that @trevor-scheer pointed me to looks like it's broken into two parts: apolloServerTests.ts which are all passing except one and httpServerTests.ts which are all failing with this error. You can see it in the test pass / fail above, although it's harder to pick out without color.

Also, yes I'm sure that it's returning what is expected. When that was incorrect, the apolloServerTests.ts were all failing.

arimus avatar Oct 25 '22 02:10 arimus

path.join in your test setup code is treating the URL as a path, which includes normalizing double slashes to a single slash, so your URL starts with http:/localhost:55314. For whatever reason, the HTTP client used by most tests in one file treats this similarly to the doubled slash, and the HTTP client used by most tests in the other file doesn't.

You don't actually need to add /graphql at all; the Express integration tests don't.

glasser avatar Oct 25 '22 04:10 glasser

@glasser thanks for pointing out what was right in front of my face re: single / when using path.join. I fixed that, which did indeed help. I also mapped everything to /, because that's an expectation of the tests, however I still need to make this path configurable via options. Tests are looking better, but still have some adjustments to make:

Test Suites: 2 failed, 2 total Tests: 33 failed, 11 skipped, 136 passed, 180 total Snapshots: 23 passed, 23 total Time: 7.402 s Ran all test suites.

arimus avatar Oct 25 '22 05:10 arimus

Heh, I mean I had to clone it and add lots of debug logs to figure it out :)

glasser avatar Oct 25 '22 17:10 glasser

Almost there:

 PASS  src/__tests__/hapi.test.ts
  ✓ check basic query (150 ms)

 FAIL  src/__tests__/integration.test.ts (6.356 s)
  integration tests
    apolloServerTests.ts
      constructor
        validation rules
          ✓ accepts additional rules (122 ms)
          ✓ allows introspection by default (17 ms)
          ✓ prevents introspection by default during production (19 ms)
          ✓ allows introspection to be enabled explicitly (13 ms)
        appropriate error for bad user input
          ✓ variable coercion errors (19 ms)
          ✓ catches required type variable error and returns UserInputError (11 ms)
          ✓ catches required List type variable error and returns UserInputError (17 ms)
          ✓ catches non-null type variable error and returns UserInputError (11 ms)
          ✓ catches non-null List type variable error and returns UserInputError (12 ms)
          ✓ catches List of non-null type variable error and returns UserInputError (14 ms)
        schema creation
          ✓ accepts typeDefs and resolvers (11 ms)
          ✓ accepts a gateway's schema and calls its executor (15 ms)
          ✓ rejected load promise is thrown by server.start (2 ms)
      Plugins
        ✓ returns correct status code for a normal operation (14 ms)
        ✓ allows setting a custom status code for an error (13 ms)
        ✓ preserves user-added "extensions" in the response when parsing errors occur (29 ms)
        ✓ preserves user-added "extensions" in the response when validation errors occur (18 ms)
      formatError
        ✓ wraps thrown error from validation rules (28 ms)
      lifecycle
        ✓ errors thrown in plugins call formatError and are wrapped (15 ms)
        ✓ propagates error codes in production (14 ms)
        ✓ propagates error codes with null response in production (12 ms)
        ✓ propagates error codes in dev mode (17 ms)
        ✓ shows error extensions in extensions (only!) (11 ms)
        for Apollo usage reporting
          traces
            ✓ cachePolicy (42 ms)
            ✓ does not expose stack (30 ms)
            ✓ sets the trace key to operationName when it is defined (19 ms)
            ✓ sets the trace key to unknown operation for missing operation (14 ms)
            ✓ sets the trace key to parse failure when non-parsable gql (18 ms)
            ✓ sets the trace key to validation failure when invalid operation (18 ms)
            ✓ sets the trace key to "-" when operationName is undefined (17 ms)
            ✓ doesn't resort to query body signature on `didResolveOperation` error (16 ms)
            ✓ doesn't internal server error on an APQ (13 ms)
            ○ skipped includes all fields with defer
            error munging
              ✓ undefined error (21 ms)
              ✓ unmodified (21 ms)
              ✓ masked (20 ms)
              sendErrors
                ✓ new error (15 ms)
                ✓ modified error (20 ms)
                ✓ nulled error (14 ms)
        context field
          ✓ defers context eval with thunk until after options creation (18 ms)
          context cloning
            ✓ clones the context for request pipeline requests (14 ms)
            ✓ for every request with executeOperation (11 ms)
          as a function
            ✓ can accept nothing and return an empty object (9 ms)
            ✓ can be an async function (14 ms)
            context errors
              ✓ GraphQLErrors are formatted, defaulting to status 500 (12 ms)
              ✓ GraphQLErrors are formatted, defaulting to INTERNAL_SERVER_ERROR (9 ms)
              ✓ GraphQLErrors are formatted, obeying http extension (14 ms)
              ✓ non-GraphQLErrors are formatted (11 ms)
          as an object
            ✓ can be an empty object (7 ms)
            ✓ can contain arbitrary values (6 ms)
      Persisted Queries
        ✓ returns PersistedQueryNotFound on the first try (12 ms)
        ✓ returns result on the second try (10 ms)
        ✓ returns result on the persisted query (15 ms)
        ✓ returns error when hash does not match (11 ms)
        ✓ returns correct result for persisted query link (20 ms)
        ✓ returns correct result for persisted query link using get request (17 ms)
      usage reporting
        graphql server functions even when Apollo servers are down
          ✓ with retryable error (547 ms)
          ✓ with network error (415 ms)
          ✓ with non-retryable error (24 ms)
      Federated tracing
        ✓ doesn't include federated trace without the special header (28 ms)
        ✓ doesn't include federated trace without _Service in the schema (24 ms)
        ✓ reports a total duration that is longer than the duration of its resolvers (24 ms)
        ✓ includes errors in federated trace (23 ms)
      Gateway
        ✓ receives schema updates from the gateway (with document store: true) (17 ms)
        ✓ receives schema updates from the gateway (with document store: false) (15 ms)
        ✓ passes apollo data to the gateway (7 ms)
        ✓ unsubscribes from schema update on close (6 ms)
        ✓ waits until gateway has resolved a schema to respond to queries (8 ms)
        ✓ can serve multiple active schemas simultaneously during a schema rollover (16 ms)
      renderLandingPage
        ✓ defaults to LocalDefault (13 ms)
        ✓ can specify version for LocalDefault (13 ms)
        ✓ can install playground with specific version (15 ms)
        ✓ can be disabled (10 ms)
        basic functionality
          ✓ basic GET works (9 ms)
          ✓ basic GET works with more complex header (13 ms)
          ✓ no landing page with application/json (11 ms)
          ✓ no landing page with */* (10 ms)
          ✓ needs the header (9 ms)
        startup errors
          ✓ only one plugin can implement renderLandingPage (3 ms)
      CSRF prevention
        ✓ default (28 ms)
        ✓ csrfPrevention: {requestHeaders} (27 ms)
        ✓ csrfPrevention: false (12 ms)
    httpServerTests.ts
      graphqlHTTP
        ✓ rejects the request if the method is not POST or GET (14 ms)
        ✓ throws an error if POST body is empty (8 ms)
        ✓ throws an error if POST body is missing even with content-type (7 ms)
        ✓ throws an error if invalid content-type (8 ms)
        ✓ throws an error if POST operation is missing (7 ms)
        ✓ throws an error if POST operation is empty (8 ms)
        ✓ throws an error if POST JSON is malformed (8 ms)
        ✓ returns an error on parse failure (8 ms)
        ✓ returns an error on validation failure (10 ms)
        ✓ unknown operation name returns 400 and OPERATION_RESOLUTION_FAILURE (10 ms)
        ✓ unknown operation name returns 400 and OPERATION_RESOLUTION_FAILURE for GET requests (11 ms)
        ✓ throwing in didResolveOperation results in error with default HTTP status code (10 ms)
        ✓ throwing in didResolveOperation results in error with specified HTTP status code (8 ms)
        ✓ multiple operations with no `operationName` specified returns 400 and OPERATION_RESOLUTION_FAILURE (9 ms)
        ✓ throws an error if GET query is missing (8 ms)
        ✓ can handle a basic GET request (7 ms)
        ✓ GET request with array body is not interpreted as batch (10 ms)
        ✓ can handle a basic implicit GET request (8 ms)
        ✓ throws error if trying to use mutation using GET request (8 ms)
        ✓ throws error if trying to use mutation with fragment using GET request (8 ms)
        ✓ does not accept multiple query search parameters (9 ms)
        ✓ can handle a GET request with variables (8 ms)
        ✓ can handle a basic request (7 ms)
        ✓ can handle a basic request accepting application/json (8 ms)
        ✓ can handle a basic request accepting application/json; charset=utf-8 (8 ms)
        ✓ can handle a basic request accepting application/graphql-response+json (9 ms)
        ✓ can handle a basic request accepting application/graphql-response+json; charset=utf-8 (13 ms)
        ✓ can handle a basic request accepting application/graphql-response+json, application/json (8 ms)
        ✓ can handle a basic request accepting application/json, application/graphql-response+json (8 ms)
        ✓ can handle a basic request accepting application/json; q=0.5, application/graphql-response+json (8 ms)
        ✓ responses have content-length headers (7 ms)
        ✕ cache-control not set without any hints with if-cacheable (10 ms)
        ✓ cache-control set to no-store without any hints (9 ms)
        ✓ cache-control set with dynamic hint (8 ms)
        ✓ cache-control set with defaultMaxAge (10 ms)
        ✓ returns PersistedQueryNotSupported to a GET request if PQs disabled (8 ms)
        ✓ returns PersistedQueryNotSupported to a POST request if PQs disabled (8 ms)
        ✓ returns PersistedQueryNotFound to a GET request (10 ms)
        ✓ returns PersistedQueryNotFound to a POST request (8 ms)
        ✓ can handle a request with variables (9 ms)
        ✓ POST does not handle a request with variables as string (7 ms)
        ✓ POST does not handle a request with extensions as string (8 ms)
        ✓ can handle a request with operationName (8 ms)
        ✓ can handle introspection request (16 ms)
        ✓ does not accept a query AST (9 ms)
        ✓ can handle batch requests (9 ms)
        ✓ can handle non-batch requests when allowBatchedHttpRequests is true (9 ms)
        ✓ can handle batch requests with one element (8 ms)
        ✓ returns an error on batch requests with no elements (10 ms)
        ✓ can handle batch requests in parallel (92 ms)
        ✓ disables batch requests by default (11 ms)
        ✓ clones batch context (10 ms)
        ✓ executes batch context if it is a function (7 ms)
        ✓ can handle a request with a mutation (10 ms)
        ✓ willSendResponse can be equivalent to the old formatResponse function (7 ms)
        ✓ passes the context to the resolver (8 ms)
        ✓ passes the rootValue to the resolver (10 ms)
        ✓ passes the rootValue function result to the resolver (10 ms)
        ✓ returns errors (9 ms)
        ✓ applies formatError if provided (8 ms)
        ✓ formatError receives error that can be unwrapped to pass instanceof checks (9 ms)
        ✓ formatError receives error that passes instanceof checks when GraphQLError (10 ms)
        ✓ GraphQLError HTTP extensions are respected and stripped (10 ms)
        ✓ formatError receives correct error for parse failure (9 ms)
        ✓ allows for custom error formatting to sanitize (9 ms)
        ✓ allows for custom error formatting to elaborate (12 ms)
        ✓ sends internal server error when formatError fails (12 ms)
        ✓ applies additional validationRules (10 ms)
        cache-control
          ✓ applies cacheControl Headers (11 ms)
          ✓ applies cacheControl Headers with if-cacheable (10 ms)
          ✓ contains no cacheControl Headers when uncacheable (10 ms)
          ✓ contains private cacheControl Headers when scoped (10 ms)
          ✕ runs when cache-control is disabled (11 ms)
      status code
        ✓ allows setting a custom status code (11 ms)
      incremental delivery
        mocked execution
          ○ skipped basic @defer working
          ○ skipped first payload sent while deferred field is blocking
        tests that require graphql@17
          ○ skipped errors when @defer is used with accept: undefined
          ○ skipped errors when @defer is used with accept: application/json
          ○ skipped errors when @defer is used with accept: multipart/mixed
          ○ skipped errors when @defer is used with accept: multipart/mixed; deferSpec=12345
          ○ skipped basic @defer working with accept: multipart/mixed; deferSpec=20220824
          ○ skipped basic @defer working with accept: multipart/mixed; deferSpec=20220824, application/json
          ○ skipped basic @defer working with accept: application/json, multipart/mixed; deferSpec=20220824
          ○ skipped first payload sent while deferred field is blocking
      Persisted Queries
        ✓ when ttlSeconds is set, passes ttl to the apq cache set call (9 ms)
        ✓ when ttlSeconds is unset, ttl is not passed to apq cache (11 ms)
        ✓ errors when version is not specified (9 ms)
        ✓ errors when version is unsupported (18 ms)
        ✓ errors when hash is mismatched (17 ms)
        ✓ returns PersistedQueryNotFound on the first try (9 ms)
        ✓ returns result on the second try (11 ms)
        ✓ returns with batched persisted queries (11 ms)
        ✓ returns result on the persisted query (11 ms)
        ✓ returns error when hash does not match (8 ms)
        ✓ returns correct result using get request (11 ms)
      gateway execution
        ✓ executor can read and write response HTTP headers and status (8 ms)

  ● integration tests › httpServerTests.ts › graphqlHTTP › cache-control › runs when cache-control is disabled

    expect(received).toBeUndefined()

    Received: "no-cache"

      at Object.<anonymous> (node_modules/@apollo/server-integration-testsuite/src/httpServerTests.ts:984:48)
          at runMicrotasks (<anonymous>)

  ● integration tests › httpServerTests.ts › graphqlHTTP › cache-control not set without any hints with if-cacheable

    expect(received).toBeUndefined()

    Received: "no-cache"

      at node_modules/@apollo/server-integration-testsuite/src/httpServerTests.ts:1006:48
          at runMicrotasks (<anonymous>)

arimus avatar Oct 29 '22 20:10 arimus

All tests passing, but still need to clean things up, add a bit of configuration, etc.

arimus avatar Oct 29 '22 21:10 arimus

@trevor-scheer the invite for the integrations org expired. Can you please re-send when you get a chance?

arimus avatar Oct 29 '22 21:10 arimus

@arimus resent the invitation 👍

trevor-scheer avatar Oct 31 '22 03:10 trevor-scheer

The integration can now be found here: https://github.com/apollo-server-integrations/apollo-server-integration-hapi/

It's still a work in progress. Tests are passing, but there is some needed configuration support necessary.

arimus avatar Nov 05 '22 18:11 arimus

@arimus Awesome! Is it ready for us to add it to https://www.apollographql.com/docs/apollo-server/integrations/integration-index ?

glasser avatar Nov 07 '22 19:11 glasser

@glasser I need to add a way to at least configure the path, but it seems that some other integrations aren't set up to do that yet either. Your call. I guess if we publish it for visibility, the worst case is that someone will report a bug that I fix / feature that I add :)

arimus avatar Nov 08 '22 18:11 arimus

Up to you — though looks like it still needs to be published to npm first (and maybe a few things tweaked like the description in the package.json).

glasser avatar Nov 09 '22 00:11 glasser

Okay. I'll get the path configurable and review the description and get things deployed to NPM. Will try to get that taken care of in the next few days

arimus avatar Nov 09 '22 20:11 arimus

Going to close this out since it's in active development and nearly ready to publish! Anyone interested in the project can follow along and participate over here: https://github.com/apollo-server-integrations/apollo-server-integration-hapi

trevor-scheer avatar Nov 10 '22 00:11 trevor-scheer

Package has been published (https://www.npmjs.com/package/@as-integrations/hapi). I had already done the work to do path configuration, but hadn't added a test for it yet (until now). Everything looks good, deps upgrades and 1.0.0 published to npmjs.

arimus avatar Nov 10 '22 09:11 arimus