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

Embedded Sandbox default connection endpoint of http://0.0.0.0:4000/ results in query errors #1785

Closed
prasek opened this issue Sep 15, 2022 · 5 comments · Fixed by #1796
Closed
Assignees

Comments

@prasek
Copy link
Contributor

prasek commented Sep 15, 2022

Describe the bug
Embedded Sandbox at http://locahost:4000 defaults to connection endpoint of http://0.0.0.0:4000/ resulting in query errors

To Reproduce
Steps to reproduce the behavior:

  1. Console window 1:
git clone https://github.com/apollographql/supergraph-demo-fed2.git
cd supergraph-demo-fed2
make run-router-main

Note this runs with acme_router --dev -c router.yaml (using router as a lib)

cors:
  allow_any_origin: true
supergraph:
  listen: 0.0.0.0:4000
  introspection: true
sandbox: # temporary workaround until RC1 is released
  listen: 0.0.0.0:4000
include_subgraph_errors:
  all: true # Propagate errors from all subraphs
telemetry:
  apollo:
    # The percentage of requests will include HTTP request and response headers in traces sent to Apollo Studio.
    # This is expensive and should be left at a low value.
    # This cannot be higher than tracing->trace_config->sampler
    field_level_instrumentation_sampler: 1 # (default)
  tracing:
    trace_config:
      sampler: 1 # The percentage of requests that will generate traces (a rate or `always_on` or `always_off`)
include_subgraph_errors:
  all: true # Propagate errors from all subraphs
  1. Verify router has started

3: Console window 2:

make smoke
  1. verify smoke tests pass

  2. open http://localhost:4000 to load the Embedded Sandbox using Chrome

  3. see the Sandbox connection endpoint is set to http://0.0.0.0:4000/

  4. Run the following query in Sandbox

fragment MyFragment on Product {
    variation { name }
  }
}
query Dimensions {
  allProducts {
    ...MyFragment @defer
    sku
    id
  }
}
  1. See the following error
{
  "error": {
    "message": "Failed to fetch",
    "stack": "TypeError: Failed to fetch\n    at <anonymous>:1:876\n    at handleRequest.s.includeCookies (https://embeddable-sandbox.cdn.apollographql.com/_latest/embeddable-sandbox.umd.production.min.js:1:52074)\n    at https://embeddable-sandbox.cdn.apollographql.com/_latest/embeddable-sandbox.umd.production.min.js:1:54762\n    at l (https://embeddable-sandbox.cdn.apollographql.com/_latest/embeddable-sandbox.umd.production.min.js:1:60081)"
  }
}
  1. Adjust the Sandbox connection endpoint to: http://localhost:4000/

  2. See the query execute successfully

Expected behavior
Embedded Sandbox connection endpoint should default to a host/IP where the router can be queried.

Where possible Sandbox should default to the browser window URL, but regardless when accessing Sandbox at http://localhost:4000 the queries should just work without having to adjust the Sandbox connection endpoint.

Output
See above

Desktop (please complete the following information):
Apollo Router v1.0.0-rc.0
OS: Mac OS 12.5.1 [64-bit]
Shell: /bin/zsh

Additional context
Add any other context about the problem here.

@abernix
Copy link
Member

abernix commented Sep 15, 2022

this is a great set of reproduction steps. thanks much!

@abernix abernix added this to the v1.0.0-rc.1 milestone Sep 15, 2022
@abernix abernix added bug and removed triage labels Sep 15, 2022
@o0Ignition0o
Copy link
Contributor

The problem:

The sandbox used to rely on window.location.href to load the correct router url to point to.

However since we're now allowing users to bind Sandbox to a custom listenAddress (ip and port) and path, using window.location.href would yield an incorrect result. For example, the sandbox being available on /sandbox would make it wrongly assume the supergraph endpoint is located at localhost:4000/sandbox.

This is the reason why sandbox now used the supergraph.listen and supergraph.path values to generate the url.

In a scenario where the supergraph endpoint is served on 127.0.0.1:5000/graphql and sandbox is served on 0.0.0.0:10000/sandbox, the loaded sandbox will point to 127.0.0.1:5000/graphql.

The constraints:

  • We cannot rely on window.location.href to serve sandbox on the browser, since both endpoints can be served on a different URL
  • A server's bind address is only correct on the client side if it uses 127.0.0.1
  • Customizing endpoints was one of our goals, and since we're at 1.0 we want to make additive changes only as much as we can.
  • The backend doesn't have enough context at startup to confidently know what public supergraph url will allow clients to make graphql requests (localhost is only correct if the supergraph is running on a local machine, container environments can change any of this ad any point, and dns will come in play as well)

Possible solutions and outcomes:

1: add a supergraph.public_endpoint_url field in the configuration, to give awareness of the url:

Pros:

  • the user specifies the actual url router clients will use to make GraphQL requests to the supergraph.
  • if we fallback to localhost:<supergraph_port><supergraph_path>, adding this is not a breaking change.
  • the fallback will work for the currently common scenario, which is local dev.
  • This would work for sandbox AND homepage (if homepage provides us with a way to interpolate the url).

Cons:

  • One more field in the config

2: use the host header from a graphql request as hostname, and derive the supergraph endpoint url by replacing the port and path:

Pros:

  • No need to change the configuration
  • This will work in most cases
  • This would work for sandbox AND homepage (if homepage provides us with a way to interpolate the url).

Cons:

  • In container scenarios, This won't work if the publicly exposed port doesn't match the private one.

3: don't allow sandbox to bind to an other listen address (path is fine)

Pros:

  • much less hassle trying to figure out the right url, we strip the path, put the supergraph endpoint's

Cons:

  • Endpoints won't be customizable anymore
  • It's a breaking change

I'm in favor of 1, and against 3.

@o0Ignition0o
Copy link
Contributor

Here's what we discussed during huddle:

Most of our products assume Sandbox and Homepage are exposed on the same endpoint as the one serving GraphQL requests. Allowing sandbox to bind to an other path / url will require deeper validation across the whole platform.

Homepage and Sandbox are mutually exclusive: if both are enabled: print an error message and fail at startup
Sandbox cannot work if introspection is disabled: print an error message and fail at startup.

We have decided the safer approach is 3: Sandbox will be an enabled boolean, and it will bind to the Supergraph endpoint.

I'll work on a PR today, which will supersede #1781 that won't be needed anymore, and fix #1783

@abernix
Copy link
Member

abernix commented Sep 15, 2022

The above sounds good to me. I think we can re-consider the flexibility we (very temporarily) offered in a future version. Thanks!

o0Ignition0o added a commit that referenced this issue Sep 15, 2022
Fixes #1783, #1785

We have rolled back an addition that we released in yesteday’s
`v1.0.0-rc.0` which allowed Sandbox to be on a custom listener address.
In retrospect, we believe it was premature to make this change without
considering the broader impact of this change which touches on CORS and
some developer experiences bits.
We would like more time to make sure we provide you with the best
experience before we attempt to make the change again.

Sandbox will continue to be on the same listener address as the GraphQL
listener.

If you have updated your configuration for `v1.0.0-rc.0` and enabled the
sandbox here is a diff of what has changed:

```diff
sandbox:
-  listen: 127.0.0.1:4000
-  path: /
  enabled: true
# do not forget to enable introspection,
# otherwise the sandbox won't work!
supergraph:
  introspection: true
```

Note this means you can either enable the Landing page, or the sandbox.
@abernix abernix linked a pull request Sep 15, 2022 that will close this issue
@o0Ignition0o
Copy link
Contributor

fixed by #1796

o0Ignition0o pushed a commit that referenced this issue Sep 16, 2022
> **Note**
> We're almost to 1.0! We've got a couple relatively small breaking
changes to the configuration for this release (none to the API) that
should be relatively easy to adapt to and a number of bug fixes and
usability improvements.

## ❗ BREAKING ❗

### Change `headers` propagation configuration ([PR
#1795](#1795))

While it wasn't necessary today, we want to avoid a necessary breaking
change in the future by proactively making room for up-and-coming work.
We've therefore introduced another level into the `headers`
configuration with a `request` object, to allow for a `response` (see
[Issue #1284](#1284)) to
be an _additive_ feature after 1.0.

A rough look at this should just be a matter of adding in `request` and
indenting everything that was inside it:

```patch
headers:
    all:
+     request:
          - remove:
              named: "test"
```

The good news is that we'll have `response` in the future! For a full
set of examples, please see the [header propagation
documentation](https://www.apollographql.com/docs/router/configuration/header-propagation/).

By @bnjjj in #1795

### Bind the Sandbox on the same endpoint as the Supergraph, again
([Issue #1785](#1785))

We have rolled back an addition that we released in this week's
`v1.0.0-rc.0` which allowed Sandbox (an HTML page that makes requests to
the `supergraph` endpoint) to be on a custom socket. In retrospect, we
believe it was premature to make this change without considering the
broader impact of this change which ultimately touches on CORS and some
developer experiences bits. Practically speaking, we may not want to
introduce this because it complicates the model in a number of ways.

For the foreseeable future, Sandbox will continue to be on the same
listener address as the `supergraph` listener.

It's unlikely anyone has really leaned into this much already, but if
you've already re-configured `sandbox` or `homepage` to be on a custom
`listen`-er and/or `path` in `1.0.0-rc.0`, here is a diff of what you
should remove:

```diff
sandbox:
-  listen: 127.0.0.1:4000
-  path: /
  enabled: false
homepage:
-  listen: 127.0.0.1:4000
-  path: /
  enabled: true
```

Note this means you can either enable the `homepage`, or the `sandbox`,
but not both.

By @o0Ignition0o in #1796

## 🚀 Features

### Automatically check "Return Query Plans from Router" checkbox in
Sandbox ([Issue
#1803](#1803))

When loading Sandbox, we now automatically configure it to toggle the
"Request query plans from Router" checkbox to the enabled position which
requests query plans from the Apollo Router when executing operations.
These query plans are displayed in the Sandbox interface and can be seen
by selecting "Query Plan Preview" from the drop-down above the panel on
the right side of the interface.

By @abernix in #1804

## 🐛 Fixes

### Fix `--dev` mode when no configuration file is specified ([Issue
#1801](#1801)) ([Issue
#1802](#1802))

We've reconciled an issue where the `--dev` mode flag was being ignored
when running the router without a configuration file. (While many use
cases do require a configuration file, the Router actually doesn't
_need_ a confguration in many cases!)

By @bnjjj in #1808

### Respect `supergraph`'s `path` for Kubernetes deployment probes
([Issue #1787](#1787))

If you've configured the `supergraph`'s `path` property using the Helm
chart, the liveness
and readiness probes now utilize these correctly. This fixes a bug where
they continued to use the _default_ path of `/` and resulted in a
startup failure.

By @damienpontifex in #1788

### Get variable default values from the query for query plan condition
nodes ([PR #1640](#1640))

The query plan condition nodes, generated by the `if` argument of the
`@defer` directive, were
not using the default value of the variable passed in as an argument.

This _also_ fixes _default value_ validations for non-`@defer`'d
queries.

By @Geal in #1640

### Correctly hot-reload when changing the `supergraph`'s `listen`
socket ([Issue
#1814](#1814))

If you change the `supergraph`'s `listen` socket while in `--hot-reload`
mode, the Router will now correctly pickup the change and bind to the
new socket.

By @o0Ignition0o in #1815

## 🛠 Maintenance

### Improve error message when querying non existent field [Issue
#1816](#1816)

When querying a non-existent field you will get a better error message:

```patch
{
  "errors": [
    {
-       "message": "invalid type error, expected another type than 'Named type Computer'"
+       "message": "Cannot query field \"xxx\" on type \"Computer\""
    }
  ]
}
```

By @bnjjj in #1817

### Update `apollo-router-scaffold` to use the published `apollo-router`
crate [PR #1782](#1782)

Now that `apollo-router` is released on
[crates.io](https://crates.io/crates/apollo-router), we have updated the
project scaffold to rely on the published crate instead of Git tags.

By @o0Ignition0o in #1782

### Refactor `Configuration` validation [Issue
#1791](#1791)

Instantiating `Configuration`s is now fallible, because it will run
consistency checks on top of the already run structure checks.

By @o0Ignition0o in #1794

### Refactor response-formatting tests
[#1798](#1798)

Rewrite the response-formatting tests to use a builder pattern instead
of macros and move the tests to a separate file.

By @Geal in #1798

## 📚 Documentation

### Add `rustdoc` documentation to various modules ([Issue
#799](#799))

Adds documentation for:

- `apollo-router/src/layers/instrument.rs`
- `apollo-router/src/layers/map_first_graphql_response.rs`
- `apollo-router/src/layers/map_future_with_request_data.rs`
- `apollo-router/src/layers/sync_checkpoint.rs`
- `apollo-router/src/plugin/serde.rs`
- `apollo-router/src/tracer.rs`

By @garypen in #1792

### Fixed `docs.rs` publishing error from our last release

During our last release we discovered for the first time that our
documentation wasn't able to compile on the [docs.rs](https://docs.rs)
website, leaving our documentation in a [failed
state](https://docs.rs/crate/apollo-router/1.0.0-rc.0/builds/629200).

While we've reconciled _that particular problem_, we're now being
affected by
[this](https://docs.rs/crate/router-bridge/0.1.7/builds/629895) internal
compiler errors (ICE) that [is
affecting](rust-lang/rust#101844) anyone using
`1.65.0-nightly` builds circa today. Since docs.rs uses `nightly` for
all builds, this means it'll be a few more days before we're published
there.

With thanks to @SimonSapin in
apollographql/federation-rs#185

Co-authored-by: Coenen Benjamin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants