2.3 "Motoko Advanced" Http_Response related issues

2.3 "Motoko Advanced" Http_Response related issues

Introduction to Http_Response

Our traditional method of accessing canister is through agent proxy, which needs to run normally in an environment that supports JavaScript. But in fact, canister also supports Http Request access, and only needs a URL to return the corresponding data.

Since there is a cycleLimit for a single request between the edge node and the canister , small data can be returned directly through the http_response method without callback, while large data needs to be fragmented and returned serially through the http_response method with callback.

For example, we can send /fileA request information to canister through the URL https://${canisterId}.raw.ic0.app/fileA, and canister can return customized data according to business logic.

Core code (Types + http_request function)

type HeaderField = (Text, Text);
type StreamingCallbackHttpResponse = {
    
    
    body: Blob;
    token: ?Token;
};
type Token = {
    
    }; // 对象类型,可根据需要添加参数
type StreamingStrategy = {
    
    
    #Callback: {
    
    
        callback: shared (Token) -> async (StreamingCallbackHttpResponse);
        token: Token;
    }
};
type HttpRequest =  {
    
    
    method: Text;
    url: Text;
    headers: [HeaderField];        
    body: Blob;
};
type HttpResponse = {
    
    
    status_code: Nat16;
    headers: [HeaderField];
    body: Blob;
    streaming_strategy: ?StreamingStrategy;
};

public query func http_request(request: HttpRequest): async HttpResponse{
    
    
    ...
};

Example - no callback ( Callback ) function type

import Text "mo:base/Text";

// 仅解析url,无callback版本
actor http {
    
    
    type HeaderField = (Text, Text);
    type StreamingCallbackHttpResponse = {
    
    
        body: Blob;
        token: ?Token;
    };
    type Token = {
    
    };
    type StreamingStrategy = {
    
    
        #Callback: {
    
    
            callback: shared (Token) -> async (StreamingCallbackHttpResponse);
            token: Token;
        }
    };
    type HttpRequest =  {
    
    
        method: Text;
        url: Text; // 为ic0.app后的路径
        headers: [HeaderField];        
        body: Blob;
    };
    type HttpResponse = {
    
    
        status_code: Nat16;
        headers: [HeaderField];
        body: Blob;
        streaming_strategy: ?StreamingStrategy;
    };

    public query func http_request(request: HttpRequest): async HttpResponse {
    
    
        if(request.url == "/fileA") {
    
    
            {
    
    
                status_code = 200;
                headers = [];
                body = Text.encodeUtf8("I'm file A.");
                streaming_strategy = null;
            }
        } else {
    
    
            {
    
    
                status_code = 404;
                headers = [];
                body = Text.encodeUtf8("worng url");
                streaming_strategy = null;
            }
        }
    };
};

Example - callback ( Callback ) function type

import Text "mo:base/Text";
import Blob "mo:base/Blob";

// callback版本
actor http {
    
    
    let ans: [Text] = ["A","B","C","D","E"];
    type HeaderField = (Text, Text);
    type StreamingCallbackHttpResponse = {
    
    
        body: Blob;
        token: ?CallbackToken;
    };
    type CallbackToken = {
    
    
        index: Nat;
    };
    type StreamingStrategy = {
    
    
        #Callback: {
    
    
            callback: query (CallbackToken) -> async (StreamingCallbackHttpResponse);
            token: CallbackToken;
        }
    };
    type HttpRequest =  {
    
    
        method: Text;
        url: Text;
        headers: [HeaderField];        
        body: Blob;
    };
    type HttpResponse = {
    
    
        status_code: Nat16;
        headers: [HeaderField];
        body: Blob;
        streaming_strategy: ?StreamingStrategy;
    };

    public query func streamingCallback(tk: CallbackToken): async StreamingCallbackHttpResponse{
    
    
        let (payload, token) = _workContent(tk.index, 3);
        {
    
    
            body = payload;
            token = token;
        }
    };

    private func _workContent(index: Nat,size: Nat): (Blob, ?CallbackToken) {
    
    
        let payload = Text.encodeUtf8(ans[index]);
        if(index == size) return (payload, null);
        (payload, ?{
    
    index = index + 1;})
    };

    public query func http_request(request: HttpRequest): async HttpResponse {
    
    
        if(request.url == "/text") {
    
    
            let (payload, token) = _workContent(1,3);
            {
    
    
                status_code = 200;
                headers = [("Content-Type", "txt")];
                body = payload;
                streaming_strategy = switch(token) {
    
    
                    case(null) {
    
    null;};
                    case(?tk) {
    
    
                        ?#Callback({
    
    
                            callback = streamingCallback;
                            token = tk;
                        })
                    }
                }
            }
        } else {
    
    
            {
    
    
                status_code = 404;
                headers = [];
                body = Text.encodeUtf8("worng url");
                streaming_strategy = null;
            }
        }
    };
};

——The sample code is from xiaoyuanxun , with deletions and modifications.

— Motoko —

Guess you like

Origin blog.csdn.net/qq_29810031/article/details/123248471