mime-typesmimeballerinaballerina-swan-lakeballerina-http

How can I return a stream value in a http resource function in Ballerina?


I am reading set values in a csv file as a stream of records. Instead of converting them to an array of records I want to send the stream as it is in a http response. How can I achieve this?


Solution

  • Ballerina only supports returning sub types of anydata type in http resources. But you can use the http:Caller object to add the stream as a mime:Entity body part in the response.

    Lets say you have csv file like this in the resource folder,

    name,department
    Jo,IT
    Jane,IT
    Jim,Sales
    Kim,Marketing
    

    And you can define the http resource in the service as below,

    import ballerina/http;
    import ballerina/io;
    import ballerina/mime;
    
    string[] arr = [];
    
    type Employee record {|
        string name;
        string department;
    |};
    
    service /api on new http:Listener(8080) {
    
        resource function get employeesAsMime(http:Caller caller) returns error? {
            stream<Employee, io:Error?> employees = check getEmployees();
            stream<byte[], io:Error?> payload = stream from var employee in employees
                select employee.toString().toBytes();
            mime:Entity entity = new;
            entity.setContentId("employee-stream");
            entity.setBody(payload);
            http:Response response = new;
            response.setBodyParts([entity]);
            check caller->respond(response);
        }
    }
    
    function getEmployees() returns stream<Employee, io:Error?>|io:Error {
        return io:fileReadCsvAsStream("./resources/employees.csv");
    }
    

    And using the http:Client you can consume this stream as below,

    import ballerina/io;
    import ballerina/http;
    import ballerina/mime;
    
    public function main() returns error? {
        http:Client cl = check new ("http://localhost:8080");
    
        http:Response mimeResponse = check cl->/api/employeesAsMime();
        mime:Entity[] bodyParts = check mimeResponse.getBodyParts();
        foreach mime:Entity bodyPart in bodyParts {
            if bodyPart.getContentId() == "employee-stream" {
                stream<byte[], io:Error?> byteArrayStream = check bodyPart.getByteStream();
                check from var byteArray in byteArrayStream
                do {
                    io:println(string:fromBytes(byteArray));
                };
            }
        }
    }