import ballerina/http;
import ballerina/log;
import ballerina/runtime;http:Client backendClientEP = new ("http://localhost:8080", {
    timeoutInMillis: 10000});
@http:ServiceConfig {
    basePath: "/timeout"
}
service timeoutService on new http:Listener(9090) {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    resource function invokeEndpoint(http:Caller caller, http:Request request) {
        var backendResponse = backendClientEP->forward("/hello", request);
        if (backendResponse is http:Response) {
            var responseToCaller = caller->respond(backendResponse);
            if (responseToCaller is error) {
                log:printError("Error sending response", responseToCaller);
            }
        } else {
            http:Response response = new;
            response.statusCode = http:STATUS_INTERNAL_SERVER_ERROR;
            string errorMessage = <string>backendResponse.detail()?.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(errorMessage);
            }
            var responseToCaller = caller->respond(response);
            if (responseToCaller is error) {
                log:printError("Error sending response", responseToCaller);
            }
        }
    }
}
@http:ServiceConfig {
    basePath: "/hello"
}
service helloWorld on new http:Listener(8080) {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    resource function sayHello(http:Caller caller, http:Request req) {
        runtime:sleep(15000);        var result = caller->respond("Hello World!!!");
        if (result is error) {
            log:printError("Error sending response from mock service", result);
        }
    }
}# To start the services, navigate to the directory that contains the
# `.bal` file and use the `ballerina run` command.
ballerina run http_timeout.bal
[ballerina/http] started HTTP/WS listener 0.0.0.0:8080
[ballerina/http] started HTTP/WS listener 0.0.0.0:9090
2019-09-04 16:21:39,541 ERROR [] - Error sending response from mock service : error {ballerina/http}GenericListenerError message=Connection between remote client and host is closed
curl -v http://localhost:9090/timeout
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /timeout HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< content-type: text/plain
< content-length: 48
< server: ballerina/1.0.0-beta
< date: Wed, 4 Sep 2019 16:21:34 +0530
<
* Connection #0 to host localhost left intact
Request timed out. Please try again in sometime.

Timeout

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

import ballerina/http;
import ballerina/log;
import ballerina/runtime;
http:Client backendClientEP = new ("http://localhost:8080", {
    timeoutInMillis: 10000

Timeout configuration.

});
@http:ServiceConfig {
    basePath: "/timeout"
}
service timeoutService on new http:Listener(9090) {

Create an HTTP service bound to the listener endpoint.

    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }

Create a REST resource within the API.

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

The parameters include a reference to the caller endpoint and an object of the request data.

        if (backendResponse is http:Response) {
            var responseToCaller = caller->respond(backendResponse);
            if (responseToCaller is error) {
                log:printError("Error sending response", responseToCaller);
            }
        } else {
            http:Response response = new;
            response.statusCode = http:STATUS_INTERNAL_SERVER_ERROR;
            string errorMessage = <string>backendResponse.detail()?.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(errorMessage);
            }
            var responseToCaller = caller->respond(response);
            if (responseToCaller is error) {
                log:printError("Error sending response", 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.

@http:ServiceConfig {
    basePath: "/hello"
}
service helloWorld on new http:Listener(8080) {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    resource function sayHello(http:Caller caller, http:Request req) {

This sample service is used to mock connection timeouts.

        runtime:sleep(15000);

Delay the response by 15000 milliseconds to mimic the network level delays.

        var result = caller->respond("Hello World!!!");
        if (result is error) {
            log:printError("Error sending response from mock service", result);
        }
    }
}
# To start the services, navigate to the directory that contains the
# `.bal` file and use the `ballerina run` command.
ballerina run http_timeout.bal
[ballerina/http] started HTTP/WS listener 0.0.0.0:8080
[ballerina/http] started HTTP/WS listener 0.0.0.0:9090
2019-09-04 16:21:39,541 ERROR [] - Error sending response from mock service : error {ballerina/http}GenericListenerError message=Connection between remote client and host is closed
curl -v http://localhost:9090/timeout
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /timeout HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< content-type: text/plain
< content-length: 48
< server: ballerina/1.0.0-beta
< date: Wed, 4 Sep 2019 16:21:34 +0530
<
* Connection #0 to host localhost left intact
Request timed out. Please try again in sometime.

Invoke the service using “curl”.