gaxios or axios library to handle outgoing requests securely. You configure the function's HTTP trigger to accept calls, then implement logic within the Node.js runtime to construct and send the POST or GET request to the target VM endpoint.
Prerequisites and Network Configuration
Before writing any code, your infrastructure must be correctly configured to allow traffic between the serverless environment and your compute instance. By default, Cloud Functions cannot reach private resources unless they are in the same VPC network and properly routed. For this tutorial, we assume the VM has a static external IP address for simplicity, though internal IPs require Serverless VPC Access configuration.
Ensure your Compute Engine instance is running and listening on a specific port, typically 80 for HTTP or 443 for HTTPS. If you are using a custom port, verify that the firewall rules associated with your VM’s network tag allow inbound traffic from all sources (0.0.0.0/0) or specifically from the Cloud Functions range. A common pitfall is leaving the firewall closed, which results in timeout errors during testing.
If you encounter resolution issues later, such as Troubleshooting ERR_NAME_NOT_RESOLVED Error on Google Cloud Platform, it is often due to misconfigured DNS or incorrect hostnames being passed in the request URL. Always use the full URL including the protocol (http:// or https://) when constructing your request object.
Setting Up the Cloud Function Environment
Navigate to the Cloud Functions section in the Google Cloud Console. Click on "Create Function" and select the second-generation runtime. Choose Node.js 18 or a later supported version as your runtime environment. This ensures compatibility with modern asynchronous libraries like gaxios.
In the "Function name" field, provide a descriptive identifier such as vm-http-trigger. Under the "Trigger" section, select "HTTP". This creates a publicly accessible URL that can be called via standard HTTP methods. You may restrict access by setting "Authentication" to "Allow uninvoked invocations" if you plan to call it from other services without strict IAM checks, but for development, allowing unauthenticated access simplifies the initial setup.
Scroll down to the "Code" editor area. You will see a default skeleton for an HTTP function. Replace the existing code with the implementation detailed below. Before deploying, you must add dependencies. In the "Dependencies" section, click "Add Dependency" and enter gaxios. Alternatively, you can define these in your package.json file if you are uploading a zip archive instead of editing directly in the console.
Implementing the Node.js Logic
The core logic involves importing the HTTP client library and defining the main export function. The function receives an req (request) and res (response) object. We will extract parameters from the query string or body to make the request dynamic.
const gaxios = require('gaxios');
exports.triggerVmRequest = async (req, res) => {
// Define the target VM URL
const vmUrl = 'http://YOUR_VM_EXTERNAL_IP:8080/api/data';
try {
// Construct the payload
const payload = {
message: req.query.message || 'Hello from Cloud Function',
timestamp: new Date().toISOString()
};
// Make the HTTP request
const response = await gaxios.request({
url: vmUrl,
method: 'POST',
data: payload,
headers: {
'Content-Type': 'application/json'
}
});
// Respond back to the caller
res.status(200).send({
status: 'Success',
vmResponse: response.data
});
} catch (error) {
console.error('Error communicating with VM:', error);
res.status(500).send({
status: 'Error',
message: 'Failed to reach VM instance'
});
}
};
In this snippet, we replace YOUR_VM_EXTERNAL_IP with the actual static IP address of your Compute Engine instance. The gaxios library handles the underlying HTTP transport. It automatically manages retries and timeouts, which is crucial for serverless environments where cold starts might introduce latency. The function waits for the VM to respond before sending a final JSON response back to the original caller.
Deploying and Testing
Click the "Deploy" button in the top right corner of the Cloud Functions page. Wait for the deployment status to turn green. Once deployed, copy the "Function URL" provided in the console details. Open a terminal or a tool like Postman and send a GET request to this URL.
You can pass additional parameters via query strings, for example: https://us-central1-your-project.cloudfunctions.net/vm-http-trigger?message=TestData. Check the logs in the Cloud Logging dashboard to see the execution flow. If the VM is reachable, you should see a 200 OK response. If you receive a timeout, double-check your firewall rules and ensure the VM is actually listening on the specified port.
Frequently Asked Questions
Why does my Cloud Function timeout when calling the VM?
Timeouts usually occur because the VM is not responding quickly enough or the firewall is blocking the connection. Ensure the VM service is active and the firewall allows inbound traffic on the specific port. Also, check that the Cloud Function and VM are in compatible networks or that the VM has a valid external IP.
Can I use internal IP addresses instead of external ones?
Yes, but you must configure Serverless VPC Access. Without this connector, Cloud Functions cannot route traffic to private subnets. If you use an internal IP without VPC Access, the request will fail with a connection refused or timeout error.
How do I handle authentication for the HTTP request?
If your VM requires authentication, include the necessary headers in the gaxios request config. For example, add an Authorization header with a Bearer token or Basic auth credentials. Never hardcode sensitive credentials in the function code; use Secret Manager instead.
What happens if the VM is offline during the request?
The gaxios library will throw an error caught by the catch block. Your function should handle this gracefully by returning a 500 Internal Server Error or a specific failure message to the caller, rather than crashing unexpectedly.
Is it secure to expose Cloud Functions publicly?
Exposing functions publicly increases the attack surface. To secure them, enable "Authentication" in the trigger settings so only authorized users or service accounts can invoke the function. Additionally, use HTTPS URLs exclusively to encrypt data in transit.