import ballerina/http;
import ballerina/log;
import ballerina/lang.runtime;

http:Client backendClientEP = check new ("http://localhost:8080", {
        // Timeout configuration.
        timeout: 10

    });

// Create an HTTP service bound to the listener endpoint.
service /timeout on new http:Listener(9090) {

    resource function get .(http:Caller caller, http:Request request) {
        var backendResponse = backendClientEP->forward("/hello", request);

        // If `backendResponse` is an `http:Response`, it is sent back to the
        // client. If `backendResponse` is an `http:ClientError`, an internal
        // server error is returned to the client.
        if (backendResponse is http:Response) {
            var responseToCaller = caller->respond(<@untainted>backendResponse);
            if (responseToCaller is error) {
                log:printError("Error sending response",
                                'error = responseToCaller);
            }
        } else {
            http:Response response = new;
            response.statusCode = http:STATUS_INTERNAL_SERVER_ERROR;
            string errorMessage = backendResponse.message();
            string expectedMessage = "Idle timeout triggered before " +
                "initiating inbound response";
            if (errorMessage == expectedMessage) {
                response.setPayload(
                    "Request timed out. Please try again in sometime."
                );
            } else {
                response.setPayload(<@untainted>errorMessage);
            }
            var responseToCaller = caller->respond(response);
            if (responseToCaller is error) {
                log:printError("Error sending response",
                                'error = responseToCaller);
            }
        }

    }
}

// This sample service is used to mock connection timeouts.
service /hello on new http:Listener(8080) {

    resource function get .(http:Caller caller, http:Request req) {
        // Delay the response by 15 seconds to mimic the network level delays.
        runtime:sleep(15);

        var result = caller->respond("Hello World!!!");
        if (result is error) {
            log:printError("Error sending response from mock service",
                            'error = result);
        }
    }
}

Timeout

The Timeout is used to gracefully handle network timeouts, which occur when using the HTTP Client.

For more information on the underlying module, see the HTTP module.

import ballerina/http;
import ballerina/log;
import ballerina/lang.runtime;
http:Client backendClientEP = check new ("http://localhost:8080", {
        timeout: 10

Timeout configuration.

    });
service /timeout on new http:Listener(9090) {

Create an HTTP service bound to the listener endpoint.

    resource function get .(http:Caller caller, http:Request request) {
        var backendResponse = backendClientEP->forward("/hello", request);
        if (backendResponse is http:Response) {
            var responseToCaller = caller->respond(<@untainted>backendResponse);
            if (responseToCaller is error) {
                log:printError("Error sending response",
                                'error = responseToCaller);
            }
        } else {
            http:Response response = new;
            response.statusCode = http:STATUS_INTERNAL_SERVER_ERROR;
            string errorMessage = backendResponse.message();
            string expectedMessage = "Idle timeout triggered before " +
                "initiating inbound response";
            if (errorMessage == expectedMessage) {
                response.setPayload(
                    "Request timed out. Please try again in sometime."
                );
            } else {
                response.setPayload(<@untainted>errorMessage);
            }
            var responseToCaller = caller->respond(response);
            if (responseToCaller is error) {
                log:printError("Error sending response",
                                'error = responseToCaller);
            }
        }

If backendResponse is an http:Response, it is sent back to the client. If backendResponse is an http:ClientError, an internal server error is returned to the client.

    }
}
service /hello on new http:Listener(8080) {

This sample service is used to mock connection timeouts.

    resource function get .(http:Caller caller, http:Request req) {
        runtime:sleep(15);

Delay the response by 15 seconds to mimic the network level delays.

        var result = caller->respond("Hello World!!!");
        if (result is error) {
            log:printError("Error sending response from mock service",
                            'error = result);
        }
    }
}
# To start the services, navigate to the directory that contains the
# `.bal` file and use the `bal run` command below.
bal run http_timeout.bal
[ballerina/http] started HTTP/WS listener 0.0.0.0:9090
[ballerina/http] started HTTP/WS listener 0.0.0.0:8080
time = 2021-01-21 18:56:14,394 level = ERROR module = "" message = "Error sending response from mock service" error = "Connection between remote client and host is closed"
curl -v http://localhost:9090/timeout
*   Trying 127.0.0.1:9090...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9090 (#0)
> GET /timeout HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< content-type: text/plain
< content-length: 48
< server: ballerina
< date: Mon, 21 Sep 2020 20:36:56 +0530
< 
* Connection #0 to host localhost left intact
Request timed out. Please try again in sometime.

Invoke the service using “cURL”.