How to Import request-promise module in Hosted Target

Hi @Dino-at-Google this is follow up question related to below.

https://community.apigee.com/questions/78487/how-to-import-js-request-module-in-hosted-target.html

I created a JS using request-promise and it gave the response when I tried online tool - https://repl.it/repls/RichTomatoModel

But when I execute through the CLI, it gives the below error. It is similar error that I have received for request module too earlier.

Error: Cannot find module 'request-promise' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)

- Assuming this could be problem with my NodeJS installation?

- Also attached the Hosted Target bundle, please could you let me know if I am missing anything here?

Thanks much!!nodejstest-rev2-2020-01-16.zip

Solved Solved
0 10 1,979
1 ACCEPTED SOLUTION


Thanks for attaching the proxy bundle.

Not sure exactly what the problem is. but I See a couple problems,.

First, this is the proxy bundle I see

 apiproxy/proxies/default.xml
 apiproxy/resources/hosted/package.json
 apiproxy/resources/hosted/app.yaml
 apiproxy/resources/hosted/index.js
 apiproxy/resources/node/request.zip
 apiproxy/nodejstest.xml
 apiproxy/targets/default.xml
 apiproxy/manifests/manifest.xml
 apiproxy/manifests/hosted-target-manifest.xml

It seems like you have your app logic (index.js) in the resources/hosted directory, and then.. the request.zip thing (a resource I suppose) is in the resources/node directory. That's not right. You don't want that. In fact request.zip should not be there, and the resources/node directory should not be there.

Next, this is what I see in package.json :

{
  "name": "nodejstest",
  "main": "index.js",
  "scripts": {
   "start": "node index.js"
  },
  "dependencies": {
      "http": "",
      "request-promise": ""
  }
}


I am not an npm expert, but I think it may be a problem that you don't have a version numbmer in that package.json file for either of the dependencies. Also , http is a builtin, so you don't need to reference it in the package.json file. From that I conclude that you are building this dependency file manually. That's probably the wrong thing to do.

If you try running that nodejs code from a terminal window, does it work? It does not work for me. This is what I see:

$ npm run start


> nodejstest@ start /Users/dchiesa/dev/node/tmp/apiproxy/resources/hosted
> node index.js

###
### The "request" library is not installed automatically anymore.
### But is a dependency of "request-promise".
### Please install it with:
### npm install request --save
###


/Users/dchiesa/dev/node/tmp/apiproxy/resources/hosted/node_modules/request-promise/lib/rp.js:23
    throw err;
    ^


Error: Cannot find module 'request'


Node is telling me that there's a missing dependency. (I have previously run "npm install").

So your package.json file is incorrect, and this code won't run from the terminal. It also won't run when you try to deploy an aPI Proxy with that code.

To fix those problems, fix the package.json file. First, use a text editor to remove the existing dependencies from that package.json file.

Then, use the npm commands to install dependencies, which automatically updates the package.json file correctly. After these commands:

$ npm install request --save
$ npm install request-promise --save

... I get a package.json file that looks like this :

{
  "name": "nodejstest",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "request": "^2.88.0",
    "request-promise": "^4.2.5"
  }
}

And then running the code from the terminal works.

The next step is to bundle the apiproxy and deploy it. To do that you can use a tool like importAndDeploy.js. This will package up the proxy into a zip, and will correctly exclude the node_modules file. Another option is to use the apigee_tool.

good luck.

View solution in original post

10 REPLIES 10


Thanks for attaching the proxy bundle.

Not sure exactly what the problem is. but I See a couple problems,.

First, this is the proxy bundle I see

 apiproxy/proxies/default.xml
 apiproxy/resources/hosted/package.json
 apiproxy/resources/hosted/app.yaml
 apiproxy/resources/hosted/index.js
 apiproxy/resources/node/request.zip
 apiproxy/nodejstest.xml
 apiproxy/targets/default.xml
 apiproxy/manifests/manifest.xml
 apiproxy/manifests/hosted-target-manifest.xml

It seems like you have your app logic (index.js) in the resources/hosted directory, and then.. the request.zip thing (a resource I suppose) is in the resources/node directory. That's not right. You don't want that. In fact request.zip should not be there, and the resources/node directory should not be there.

Next, this is what I see in package.json :

{
  "name": "nodejstest",
  "main": "index.js",
  "scripts": {
   "start": "node index.js"
  },
  "dependencies": {
      "http": "",
      "request-promise": ""
  }
}


I am not an npm expert, but I think it may be a problem that you don't have a version numbmer in that package.json file for either of the dependencies. Also , http is a builtin, so you don't need to reference it in the package.json file. From that I conclude that you are building this dependency file manually. That's probably the wrong thing to do.

If you try running that nodejs code from a terminal window, does it work? It does not work for me. This is what I see:

$ npm run start


> nodejstest@ start /Users/dchiesa/dev/node/tmp/apiproxy/resources/hosted
> node index.js

###
### The "request" library is not installed automatically anymore.
### But is a dependency of "request-promise".
### Please install it with:
### npm install request --save
###


/Users/dchiesa/dev/node/tmp/apiproxy/resources/hosted/node_modules/request-promise/lib/rp.js:23
    throw err;
    ^


Error: Cannot find module 'request'


Node is telling me that there's a missing dependency. (I have previously run "npm install").

So your package.json file is incorrect, and this code won't run from the terminal. It also won't run when you try to deploy an aPI Proxy with that code.

To fix those problems, fix the package.json file. First, use a text editor to remove the existing dependencies from that package.json file.

Then, use the npm commands to install dependencies, which automatically updates the package.json file correctly. After these commands:

$ npm install request --save
$ npm install request-promise --save

... I get a package.json file that looks like this :

{
  "name": "nodejstest",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "request": "^2.88.0",
    "request-promise": "^4.2.5"
  }
}

And then running the code from the terminal works.

The next step is to bundle the apiproxy and deploy it. To do that you can use a tool like importAndDeploy.js. This will package up the proxy into a zip, and will correctly exclude the node_modules file. Another option is to use the apigee_tool.

good luck.

@Dino-at-Google Thanks, it helped. But couldn't achieve 100%. I did the below:

- Executed the same commands that you suggested, and works fine in terminal now. Able to get the output as expected.

- I took the same package.json from local and deployed the api proxy which is everytime returning 500 error when I test it. Please note the below.

1. The package.json in the proxy has same dependency as you referred, but I removed the ^ as the package-lock.json that loaded the dependencies version doesn't contain it.

2. I have deployed proxy directly using my Edge account, and not through importAndDeploy.js and apigee_tool. Also please remember I am using trial account, don't think that matters in this case though.

Hi Ravi

try the attached as an example. Import it with the wizard. Then deploy it. Maybe you can start from this.

apiproxy-hosted-target-1.zip

Hi Dino,

I imported it and able to receive 200 status when I tested your proxy.

I tried to do changes on top of it with the same code I earlier had, but receiving 504 error.

Guess, this gateway error could be with proxy trying to load the dependencies for request-promise module or something else. Not sure.

I'm sorry you're still having trouble. That sounds like a problem in your code. The good news is that you can sort it out, outside of an Apigee environment. Just run the node server locally. Much simpler during development.

Good luck!

no problem, yes the initial issue due to 504 was I didn't add the listener. So I added it now as below, but ended up with 404 (cannot GET error).

I have followed point 3 in the below link for this, think I am missing something very small.

https://docs.apigee.com/api-platform/hosted-targets/hosted-targets-tutorials

var express = require('express');

var app = express();

/* actual code that works fine*/

var server = app.listen(process.env.PORT || 3000, function() { console.log("Example app listening at http://%s:%s", server.address().port); });

You should be able to test and debug that kind of thing outside of the Apigee environment. If your nodejs code works when you run it on your own workstation, then another possibility is that the thing that is upstream, the endpoint that the nodejs server is connecting to, can be reached from your workstation, but cannot be reached from a nodejs running as a hosted target.

This would be the case if, for example, your workstation was running on a corporate intranet and the upstream system was also somewhere on the corporate network. And the upstream endpoint is not exposed to the public internet.

The degenerate case of this is a server on your localhost. For example you could run a nodejs server on localhost, listening at port 3000, and then in the (actual code that works fine) you might connect to a different endpoint on the same localhost, maybe port 3002. This will work fine obviously when both endpoints run on your local workstation. But if you change it so that the nodejs server runs on the hosted target, and the other endpoint remains running on your local workstation, listening on port 3002, then the HT nodejs server will not be able to reach the upstream.

The HT nodejs runtime will access endpoints over the internet. Any DNS names must be resolvable, and the IP addresses must be reachable.

Got it finally working.

It express module syntax issue, where I had to fit that in my current script with request-promise.

The online tutorials are very static though, but got it right after reading documentation and doing some trial and error.

Thanks for your support on this, now I am happy that I understand the HT and npm to some extent.

Not applicable

Since version 0.3.0 Request-Promise is not a wrapper around Request anymore. It now adds a .then(...) method to the Request prototype and exports the original Request object. This means you can now use all features of Request.

Hi @elizabeth becky Thanks for your response.

I am using request-promise, and bluebird. I am able to work my sample script through terminal but doesn't work in the hosted target/proxy when deployment, receiving 504 during the test.

I have used the same package.json and package-lock.json files.