如何使用 Rust 在 UNIX 套接字上正确代理 Docker HTTP 引擎 API

问题描述

我正在尝试使用 Rust 代理跨 UNIX 域套接字的 Docker 引擎 API 请求。我有以下代码创建并侦听 /tmp/docker-proxy.sock 处的套接字。

use std::io::{BufRead,BufReader};
use std::io::BufWriter;
use std::os::unix::net::{UnixStream,UnixListener};
use std::thread;
use std::io::Write;
use std::io;
use std::fmt::format;

pub static DOCKER_SOCKET_PATH: &'static str = "/run/docker.sock";

fn handle_client(mut proxy_stream: UnixStream) {
    let mut docker_stream = UnixStream::connect(DOCKER_SOCKET_PATH).unwrap();

    let proxy_reader = BufReader::new(&proxy_stream);
    let mut proxy_writer = BufWriter::new(&proxy_stream);
    let mut docker_reader = BufReader::new(&docker_stream);
    let mut docker_writer = BufWriter::new(&docker_stream);

    for line in proxy_reader.lines() {
        let x = line.unwrap();
        println!("{}",x);
        docker_writer.write(format!("{}\n",x).as_bytes());
        if x == "" {
            break;
        }
    }
    docker_writer.write("\n".as_bytes());
    docker_writer.flush();


    for line in docker_reader.lines() {
        let y = line.unwrap();
        println!("{}",y);
        proxy_writer.write(format!("{}\n",y).as_bytes());
    }
    proxy_writer.write("\n".as_bytes());
    proxy_writer.flush();
}

fn main() {
    let listener = UnixListener::bind("/tmp/docker-proxy.sock").unwrap();

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                thread::spawn(|| handle_client(stream));
            }
            Err(err) => {
                println!("Error: {}",err);
                break;
            }
        }
    }
}

如果我尝试使用 docker -H unix:///tmp/docker-proxy.sock ps 使用此代理,我会收到以下响应:

docker -H unix:///tmp/docker-proxy.sock ps
2021/04/04 21:27:02 Unsolicited response received on idle HTTP channel starting with "HTTP/1.1 400 Bad Request\nContent-Type: text/plain; charset=utf-8\nConnection: close\n\n400 Bad Request\n\n"; err=<nil>
2021/04/04 21:27:02 Unsolicited response received on idle HTTP channel starting with "HTTP/1.1 400 Bad Request\nContent-Type: text/plain; charset=utf-8\nConnection: close\n\n400 Bad Request\n\n"; err=<nil>
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
970cd603429f        testcodaa           "/bin/sh"           9 days ago          Up 9 days           3000/tcp            crazy_khorana

我觉得我正在做的事情真的很原始:从传入请求的缓冲区中读取行并打破双新行(特定于 HTTP 协议),然后切换到另一个套接字进行写入和读取。不知何故,我也从服务器收到了 400 无效的回复。我尝试删除 \ndocker_writer 写入,但是如果我删除它或刷新,整个过程就会挂起。

最终,我的目标是创建一个代理,如果第一行包含我想限制的 API 端点,它将继续代理请求或返回 401。在 Rust 中做这样的事情的最佳实践是什么?我一直在查看 API/示例,我怀疑我可能应该扩展一个类,我可以将其用作两个流之间的读/写链,以便将它们短路,但我是 Rust 的新手,不确定这样做的最佳方式。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...