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

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”.