deno学习四 docker 运行官方的一个http file server
github 上已经有人搞了一个deno 的docker 镜像,是基于源码编译的,挺好的
所以结合官方的http server demo 使用docker 运行
环境准备
- docker-compose 文件
version: "3"
services:
app:
image: maxmcd/deno:slim
volumes:
- "./app:/opt"
command: deno /opt/app.ts
file-server:
image: maxmcd/deno:slim
ports:
- "4500:4500"
volumes:
- "./server:/opt/server"
command: deno /opt/server/app.ts --allow-net
- http server 内容
http 模块的我修改为了使用http,就不用管下载的问题了
// This program serves files in the current directory over HTTP.
// TODO Stream responses instead of reading them into memory.
// TODO Add tests like these:
// https://github.com/indexzero/http-server/blob/master/test/http-server-test.js
import {
listenAndServe,
ServerRequest,
setContentLength,
Response
} from "https://deno.land/x/net/http.ts";
import { cwd, DenoError, ErrorKind, args, stat, readDir, open } from "deno";
const dirViewerTemplate = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Deno File Server</title>
<style>
td {
padding: 0 1rem;
}
td.mode {
font-family: Courier;
}
</style>
</head>
<body>
<h1>Index of <%DIRNAME%></h1>
<table>
<tr><th>Mode</th><th>Size</th><th>Name</th></tr>
<%CONTENTS%>
</table>
</body>
</html>
`;
const serverArgs = args.slice();
let CORSEnabled = false;
// TODO: switch to flags if we later want to add more options
for (let i = 0; i < serverArgs.length; i++) {
if (serverArgs[i] === "--cors") {
CORSEnabled = true;
serverArgs.splice(i, 1);
break;
}
}
let currentDir = cwd();
const target = serverArgs[1];
if (target) {
currentDir = `${currentDir}/${target}`;
}
const addr = `0.0.0.0:${serverArgs[2] || 4500}`;
const encoder = new TextEncoder();
function modeToString(isDir: boolean, maybeMode: number | null) {
const modeMap = ["---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"];
if (maybeMode === null) {
return "(unknown mode)";
}
const mode = maybeMode!.toString(8);
if (mode.length < 3) {
return "(unknown mode)";
}
let output = "";
mode
.split("")
.reverse()
.slice(0, 3)
.forEach(v => {
output = modeMap[+v] + output;
});
output = `(${isDir ? "d" : "-"}${output})`;
return output;
}
function fileLenToString(len: number) {
const multipler = 1024;
let base = 1;
const suffix = ["B", "K", "M", "G", "T"];
let suffixIndex = 0;
while (base * multipler < len) {
if (suffixIndex >= suffix.length - 1) {
break;
}
base *= multipler;
suffixIndex++;
}
return `${(len / base).toFixed(2)}${suffix[suffixIndex]}`;
}
function createDirEntryDisplay(
name: string,
path: string,
size: number | null,
mode: number | null,
isDir: boolean
) {
const sizeStr = size === null ? "" : "" + fileLenToString(size!);
return `
<tr><td class="mode">${modeToString(
isDir,
mode
)}</td><td>${sizeStr}</td><td><a href="${path}">${name}${
isDir ? "/" : ""
}</a></td>
</tr>
`;
}
// TODO: simplify this after deno.stat and deno.readDir are fixed
async function serveDir(req: ServerRequest, dirPath: string, dirName: string) {
// dirname has no prefix
const listEntry: string[] = [];
const fileInfos = await readDir(dirPath);
for (const info of fileInfos) {
if (info.name === "index.html" && info.isFile()) {
// in case index.html as dir...
return await serveFile(req, info.path);
}
// Yuck!
let mode = null;
try {
mode = (await stat(info.path)).mode;
} catch (e) {}
listEntry.push(
createDirEntryDisplay(
info.name,
dirName + "/" + info.name,
info.isFile() ? info.len : null,
mode,
info.isDirectory()
)
);
}
const page = new TextEncoder().encode(
dirViewerTemplate
.replace("<%DIRNAME%>", dirName + "/")
.replace("<%CONTENTS%>", listEntry.join(""))
);
const headers = new Headers();
headers.set("content-type", "text/html");
const res = {
status: 200,
body: page,
headers
};
setContentLength(res);
return res;
}
async function serveFile(req: ServerRequest, filename: string) {
const file = await open(filename);
const fileInfo = await stat(filename);
const headers = new Headers();
headers.set("content-length", fileInfo.len.toString());
const res = {
status: 200,
body: file,
headers
};
return res;
}
async function serveFallback(req: ServerRequest, e: Error) {
if (
e instanceof DenoError &&
(e as DenoError<any>).kind === ErrorKind.NotFound
) {
return {
status: 404,
body: encoder.encode("Not found")
};
} else {
return {
status: 500,
body: encoder.encode("Internal server error")
};
}
}
function serverLog(req: ServerRequest, res: Response) {
const d = new Date().toISOString();
const dateFmt = `[${d.slice(0, 10)} ${d.slice(11, 19)}]`;
const s = `${dateFmt} "${req.method} ${req.url} ${req.proto}" ${res.status}`;
console.log(s);
}
function setCORS(res: Response) {
if (!res.headers) {
res.headers = new Headers();
}
res.headers!.append("access-control-allow-origin", "*");
res.headers!.append(
"access-control-allow-headers",
"Origin, X-Requested-With, Content-Type, Accept, Range"
);
}
listenAndServe(addr, async req => {
const fileName = req.url.replace(/\/$/, "");
const filePath = currentDir + fileName;
let response: Response;
try {
const fileInfo = await stat(filePath);
if (fileInfo.isDirectory()) {
// Bug with deno.stat: name and path not populated
// Yuck!
response = await serveDir(req, filePath, fileName);
} else {
response = await serveFile(req, filePath);
}
} catch (e) {
response = await serveFallback(req, e);
} finally {
if (CORSEnabled) {
setCORS(response);
}
serverLog(req, response);
req.respond(response);
}
});
console.log(`HTTP server listening on http://${addr}/`);
运行&&效果
- 运行
docker-compose up -d
- 效果
说明
deno 的安全控制上做的挺不错,因为使用了net ,所以需要在运行的时候指定 --allow-net
参考资料
https://github.com/rongfengliang/deno-docker-compose
https://deno.land/
deno学习四 docker 运行官方的一个http file server的更多相关文章
- docker 运行jenkins及vue项目与springboot项目(四.docker运行nginx)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- Singer 学习五 docker 运行说明
介绍过一个工具knots ,方便Singer 可视化开发的工具,但是默认这个工具包含的tap 以及target 比较少(可以自己扩展) 同时这个工具就是基于docker 运行的 docker 运行的几 ...
- ICE学习笔记一----运行官方的java版demo程序
建议新手和我一样,从官网下载英文文档,开个有道词典,慢慢啃. 官方文档下载: http://download.csdn.net/detail/xiong_mao_1/6300631 程序代码就不说了, ...
- OpenGL学习——搭建OpenGL运行环境——生成一个空白视口——基于GLFW&GLEW
最近学习OpenGL,读OpenGL宝典一头蒙,各种gl函数不知所云.逐决定先搭OpenGL运行环境,详细如下. 1.首先OpenGL是什么?是一个标准规范,是一个巨大的状态机,并无具体实现,大多数实 ...
- docker学习(四) - docker构建redis主从结构
此文章假设你已经安装了docker,如果没有安装请查询本博客docker安装章节 容器网络 docker network ls 查看默认的网络 Docker安装后,默认会创建下面三种网络类型 在启动 ...
- JBPM学习(四):运行流程实例
概念: ProcessInstance,流程实例:代表流程定义的一次执行.如:张三昨天按请假流程请了一次假.一个流程实例包含了全部执行阶段,当中最典型的属性就是跟踪当前节点的指针,例如以下图. Exe ...
- docker 运行jenkins及vue项目与springboot项目(三.jenkins的使用及自动打包vue项目)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- benchmarkdotnet docker 运行
使用docker 运行基准测试是一个不错的选择,可以减少我们环境搭建的时间,同时也可以加速ci/cd 环境准备 docker-compose 文件 version: "3" ser ...
- docker 运行jenkins及vue项目与springboot项目(一.安装docker)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
随机推荐
- 网页的MVC模式简介
#! /usr/bin/env python3 # -*- coding:utf-8 -*- #MVC:Model-View-Controller 模型-视图-控制器 #Python处理URL的函数就 ...
- Linux3.10.0块IO子系统流程(1)-- 上层提交请求
Linux通用块层提供给上层的接口函数是submit_bio.上层在构造好bio之后,调用submit_bio提交给通用块层处理. submit_bio函数如下: void submit_bi ...
- error: illegal character '\ufeff' 的解决方案
今天使用scalac 命令编译scala文件的时候,出错了,出现如下错误提示:
- :状态模式:GumballMachine
#ifndef __STATE_H__ #define __STATE_H__ #include <iostream> #include<stdlib.h> using nam ...
- centos7安装kvm
一. 安装kvm前的准备工作 1. 清除iptables规则 service iptables save service iptables stop 2. 关闭selinux sed -i 's/SE ...
- MySQL:数据类型介绍
数据类型介绍 一.整数类型(可以添加自增约束条件) 数据类型 存储需要 有符号 无符号 tinyint 1个字节 -2^7~2^7-1 0~2^8 smallint 2个字节 -2^15~2^15-1 ...
- 5-log4j2.xml配置文件各个节点详解
具体配置参考官网:http://logging.apache.org/log4j/2.x/manual/configuration.html 一.log.xml文件的大致结构 <?xml ver ...
- json pickle xml shelve configparser
json:# 是一种跨平台的数据格式 也属于序列化的一种方式pickle和shevle 序列化后得到的数据 只有python才可以解析通常企业开发不可能做一个单机程序 都需要联网进行计算机间的交互 J ...
- es6 常用总结
1.变量 let 声明的变量只在它所在的代码块有效,不允许重复声明 const 声明是一个只读的常量.一旦声明,常量的值就不能改变. const与let的作用域相同,只在声明所在的块级作用域内有效. ...
- 对于src路径问题,深层理解的实践。且对于输出流write()两个方法的源码阅读。
根据昨天的总结,可深层理解图片中src的路径.所以今天实现了一个想法.就是路径写入的是Controller,然后自动去本地找. 其实就是将电脑的本地图片 显示出来.通过输出流的方式. 代码如下: @R ...