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

Multiple Rest Clients #1102

Closed
tim-field opened this issue Nov 21, 2018 · 8 comments · Fixed by feathersjs-ecosystem/docs#1419
Closed

Multiple Rest Clients #1102

tim-field opened this issue Nov 21, 2018 · 8 comments · Fixed by feathersjs-ecosystem/docs#1419
Labels

Comments

@tim-field
Copy link

Hi I'm trying to have my service A use remote services B and C should this be possible? It works perfectly if I just have service B, but fails with Only one default client provider can be configured once I add service C.

I've tried various invocations of use and configure without any luck

const B = rest("http://localhost:3030")
const C = rest("http://localhost:3080")

const requestClient = request.defaults({})

const app = express(feathers())
  .use(express.json())
  .use(express.urlencoded({ extended: true }))
  .use(cors())
  .configure(B.request(requestClient))
  .configure(C.request(requestClient))
  .configure(express.rest())
  .configure(A)
  .use("/", (req, res) => {
    res.json({ service: "period-report", status: "running" })
  })

Thanks

@subodhpareek18
Copy link

subodhpareek18 commented Nov 21, 2018

Here's a util I've written, which might be a little different from your use case.

import feathers from '@feathersjs/client';
import errors from '@feathersjs/errors';
import ax from 'axios';

export default class FeathersClient {
  constructor(opts) {
    const { url, token } = opts;

    const client = feathers();
    const restClient = feathers.rest(url);
    const axios = ax.create({ headers: { 'X-Access-Token': token } });
    client.configure(restClient.axios(axios));

    this.client = client;
  }

  async create(rawData) {
    const { service, method, args: { id, data, params } = {} } = rawData;
    const proxy = this.client.service(service);

    const methodMap = {
      find: () => proxy.find(params),
      get: () => proxy.get(id, params),
      create: () => proxy.create(data, params),
      update: () => proxy.update(id, data, params),
      patch: () => proxy.patch(id, data, params),
      remove: () => proxy.remove(id, params)
    };

    try {
      const res = await methodMap[method]();
      return res;
    } catch (error) {
      throw new (errors[error.name] || errors.BadRequest)(error.message);
    }
  }
}
import { FeathersClient } from 'app/utils';

app.use('/serviceA', new FeathersClient(optsA)); // both are remote feathers servers
app.use('/serviceB', new FeathersClient(optsB)); 
// using one in the other
export default class ServiceB {
  setup(app) {
    this.serviceA = app.service('/serviceA');
  }

  async find(params) {
    return this.serviceA
      .create({
        service: '/subServiceA.1',
        method: 'find',
        args: {
          params: {
            ...
          }
        }
      })
  }
}

@tim-field
Copy link
Author

Is there no way to do this natively ?

@subodhpareek18
Copy link

subodhpareek18 commented Nov 21, 2018

The simplest way to do it would look like so. Not sure what you mean by native. There is no official plugin to handle remote services.

app.use('/local/service/alias', feathersClient.service('/remote/service'))

You can also have a look here https://github.com/kalisio/feathers-distributed

@daffl
Copy link
Member

daffl commented Nov 21, 2018

The REST clients are just normal services themselves and can be registered directly. They require a connection (reference to the transport library), name and base:

const superagent = require('superagent');
const SuperAgentClient = require('@feathersjs/rest-client/lib/superagent');

app.use('/users', new SuperAgentClient({
  connection: superagent,
  name: 'users',
  base: 'http://myotherFeathersServer.com'
});

@tim-field
Copy link
Author

Thanks @daffl that worked. This is quite different from the example here https://docs.feathersjs.com/api/client/rest.html#restbaseurl

So it seems one should only use @feathersjs/rest-client when a single rest service will be used?

@daffl
Copy link
Member

daffl commented Nov 22, 2018

Going to reopen because I did want to make it a little easier to instantiate separate clients. Right now, only the main single client usage is documented. Not sure how the API would look like yet though.

const server1 = rest('http://feathers-api1.com')
const server2 = rest('http://feathers-api2.com')

app.use('/users', server1.superagent('/users', superagent));
app.use('/messages', server2.superagent('/messages', superagent));

@daffl daffl reopened this Nov 22, 2018
@daffl daffl added the Feature label Nov 22, 2018
@tim-field
Copy link
Author

tim-field commented Nov 26, 2018

@daffl is the above an example of something that should work now, or a design goal?

What I would like to know is if I can call a sub service of one of these registered services.

.use(
    "/foo",
    new requestClient({
      connection: request,
      name: "foo",
      base: "foo-ap1.com"
    })
  )

Lets say my foo api ( which is now a service used in this feathers app ) internally has a number of services. I'd like to call these service of foo from my client.

I was hoping that in my app I could `

const fooService = app.use('foo')
const fooUsersService = fooService.service('users')   // users is a sub service of foo

Or am I way off track? Would I instead need to register each sub service in my client ?

.use(
    "/foo-users",
    new requestClient({
      connection: request,
      name: "users",
      base: "http://ap1.com" // note same api URI here
    })
  )
.use(
    "/foo-products",
    new requestClient({
      connection: request,
      name: "products",
      base: "http://ap1.com" // note same api URI here
    })
  )

@daffl
Copy link
Member

daffl commented Jan 18, 2020

I just realized that this has been possible for years already. Now documented at https://docs.feathersjs.com/api/client/rest.html#connecting-to-multiple-servers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants