博主信息
Sky
博文
291
粉丝
0
评论
0
访问量
7461
积分:0
P豆:617

rust+wasm写前端真香之请求数据.md

2021年10月18日 20:56:13阅读数:15博客 / Sky

[sealer]是阿里巴巴开源的基于kuberentes的集群镜像开源技术,可以把整个集群整体打包。

Sealer Cloud可以在线化帮助用户进行集群打包分享和运行,Sealer cloud前后端也使用了非常先进的
rust+wasm技术实现。

sealer cloud会与docker registry交互,未来你甚至可以把sealer cloud当作docker hub使用。

定义数据结构

可以看到registry返回的数据:

curl http://localhost:5000/v2/_catalog
{"repositories":["centos","golang"]}

所以对应返回的数据我们定义个数据结构:

#[derive(Deserialize, Debug, Clone)]
pub struct RegistryCatalog {
   pub repositories: Vec<String>,
}

这个结构体用来接收后台返回的数据,我们还需要Model的结构体:

pub struct Images {
   // props: Props,
   pub repos: Option<Vec<String>>,
   pub error: Option<String>,
   pub link: ComponentLink<Self>,
   pub task: Option<FetchTask>
}

消息枚举,通过不同的消息在页面更新时判断应该做什么样的动作:

#[derive(Debug)]
pub enum Msg {
   GetRegistryCatelog(Result<RegistryCatalog, anyhow::Error>),
}

页面首次初始化

首次初始化的时候向后台请求数据:

fn rendered(&mut self, first_render: bool) {
   if first_render {
       ConsoleService::info("view app");
       let request = Request::get("http://localhost:8001/v2/_catalog")
           .body(Nothing)
           .expect("could not build request.");
       let callback = self.link.callback(
           |response: Response<Json<Result<RegistryCatalog, anyhow::Error>>>| {
               let Json(data) = response.into_body();
               Msg::GetRegistryCatelog(data)
           },
       );
       let task = FetchService::fetch(request, callback).expect("failed to start request");
       self.task = Some(task);
   }
}
first_render用于判断是不是第一次渲染,不写在这里面可能会导致页面渲染死循环。ConsoleService::info 可以帮助我们往控制台打印调试信息定义一个request和一个请求成功后的回调函数callbackcallback内部接收到数据后返回对应的消息类型即可触发update函数(后面介绍)fetch函数触发http请求调用,传入request与callback重中之重,一定要把task存到self.task里面,不然task立马被回收会触发一个[The user aborted a request]的错误

页面更新接口

在first render的时候我们向后台请求了数据,callback函数会触发update的调用。
把消息带过去交给update函数处理。

fn update(&mut self, msg: Self::Message) -> ShouldRender {
   use Msg::*;
   match msg {
       GetRegistryCatelog(response) => match response {
           Ok(repos) => {
               ConsoleService::info(&format!("info {:?}", repos));
               self.repos = Some(repos.repositories);
           }
           Err(error) => {
               ConsoleService::info(&format!("info {:?}", error.to_string()));
           },
       },
   }
   true
}

msg可以有多种消息类型,此处就写一个

#[derive(Debug)]
pub enum Msg {
   GetRegistryCatelog(Result<RegistryCatalog, anyhow::Error>),
}

response就是Result<RegistryCatalog, anyhow::Error>类型,Ok时把它放到结构体中保存就好。

最后渲染到页面上:

fn view(&self) -> Html {
   html! {
       <div class="container column is-10">
       { self.image_list() }
       </div>
   }
}

fn image_list(&self) -> Html {
   match &self.repos {
       Some(images) => {
           html! {
            <div class="columns is-multiline">
              {
                  for images.iter().map(|image|{
                      self.image_info(image)
                  })
              }
            </div>
           }
       }
       None => {
           html! {
             <p> {"image not found"} </p>
           }
       }
   }
}

如此就完成了整个数据请求的绑定渲染。

实际运行

因为请求docker registry会有跨域问题,手机靓号所以整个nginx代理:

docker run -p 5000:5000 -d --name registry registry:2.7.1

nginx.conf:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
   worker_connections  1024;
}


http {
   include       /etc/nginx/mime.types;
   default_type  application/octet-stream;

   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';

   access_log  /var/log/nginx/access.log  main;

   sendfile        on;
   #tcp_nopush     on;

   keepalive_timeout  65;

   server {
       listen       8000;  #监听8000端口,可以改成其他端口
       server_name  localhost; # 当前服务的域名

       location / {
         if ($request_method = 'OPTIONS') {
           add_header 'Access-Control-Allow-Origin' '*' always;
           add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
           add_header 'Access-Control-Allow-Headers' '*' always;
           add_header 'Access-Control-Max-Age' 1728000 always;
           add_header 'Content-Length' 0;
           add_header 'Content-Type' 'text/plain; charset=utf-8';
           return 204;
         }

         if ($request_method ~* '(GET|POST|DELETE|PUT)') {
           add_header 'Access-Control-Allow-Origin' '*' always;
         }
         proxy_pass http://172.17.0.3:5000; # the registry IP or domain name
         proxy_http_version 1.1;
       }
   }

   #gzip  on;

   include /etc/nginx/conf.d/*.conf;
}
docker run -d --name registry-proxy -p 8001:8000 \
 -v /Users/fanghaitao/nginx/nginx.conf:/etc/nginx/nginx.conf nginx:1.19.0

测试registry api是否能通:

curl http://localhost:8001/v2/_catalog
{"repositories":["centos","golang"]}

然后代码里面访问nginx代理的这个地址即可


版权申明:本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论