commit 89d6c5a3328bf705dca2d2de3fc4eac82800dab9 Author: 宇天 Date: Sat Apr 9 20:26:23 2022 +0800 完成 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec781c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +.DS_Store +.AppleDouble +.LSOverride + + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes +package-lock.json + +node_modules +.vscode-test +out.js +*.vsix +*.css \ No newline at end of file diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..c0e277f --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,10 @@ +jsxBracketSameLine: true +jsxSingleQuote: true +semi: false +singleQuote: true +printWidth: 100 +useTabs: false +tabWidth: 2 +trailingComma: none +bracketSpacing: true +arrowParens: avoid \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6899e23 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +// A launch configuration that launches the extension inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ] + }, + { + "name": "Extension Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/test/suite/index" + ] + } + ] +} diff --git a/.vscodeignore b/.vscodeignore new file mode 100644 index 0000000..1bd2951 --- /dev/null +++ b/.vscodeignore @@ -0,0 +1,10 @@ +.vscode/** +.vscode-test/** +node_modules/** +test/** +package-lock.json +.travis.yml +.gitignore +index.js +test.js + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ab60297 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6142709 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# simple.http +> 🔥 简单的http服务器, 方便临时调试html。 + +[![Version](https://vsmarketplacebadge.apphb.com/version-short/yutent.simple.http.svg)](https://marketplace.visualstudio.com/items?itemName=yutent.simple.http) +[![Rating](https://vsmarketplacebadge.apphb.com/rating-short/yutent.simple.http.svg)](https://marketplace.visualstudio.com/items?itemName=yutent.simple.http) +[![Installs](https://vsmarketplacebadge.apphb.com/installs/yutent.simple.http.svg)](https://marketplace.visualstudio.com/items?itemName=yutent.simple.http) + +## 插件说明 +> 这插件只是应一个基友需求, 临时写的。如果你有其他的功能需求, 请在插件商店中`搜索其他插件`。 + + +## 插件使用 +> 在项目根目录中放置 `.httpserver`文件, 并配置好之后, 重启或重新加载窗口, 以启动服务。 + + + +## .httpserver 文件 +> 使用`.httpserver`来配置web服务器信息, 该文件应为一个json格式的。 + +```json +{ + "port": 23333, // 默认使用 23333 端口, 如果被使用了, 会向上查找可用端口 + "enabled": true // 这里配置为 true 才会启动web服务 +} +``` diff --git a/index.js b/index.js new file mode 100644 index 0000000..9cc77f5 --- /dev/null +++ b/index.js @@ -0,0 +1,146 @@ +/** + * + * @author yutent + * @date 2022/04/09 18:26:35 + */ + +const vsc = require('vscode') +const { join } = require('path') +const { parse } = require('url') +const http = require('http') +const fs = require('iofs') + +const std = vsc.window.createOutputChannel('http.server') +const decode = decodeURIComponent + +const MIME_TYPES = { + html: 'text/html;charset=utf-8', + txt: 'text/plain;charset=utf-8', + css: 'text/css;charset=utf-8', + xml: 'text/xml;charset=utf-8', + gif: 'image/gif', + jpg: 'image/jpeg', + webp: 'image/webp', + tiff: 'image/tiff', + png: 'image/png', + svg: 'image/svg+xml', + ico: 'image/x-icon', + bmp: 'image/x-ms-bmp', + js: 'application/javascript;charset=utf-8', + json: 'application/json;charset=utf-8', + mp3: 'audio/mpeg', + ogg: 'audio/ogg', + m4a: 'audio/x-m4a', + mp4: 'video/mp4', + webm: 'video/webm', + ttf: 'font/font-ttf', + woff: 'font/font-woff', + woff2: 'font/font-woff2', + other: 'application/octet-stream' +} + +MIME_TYPES.htm = MIME_TYPES.html +MIME_TYPES.jpeg = MIME_TYPES.jpg +MIME_TYPES.tif = MIME_TYPES.tiff + +let root +let enabled = false +let port = 23333 +let baseUrl = 'http://127.0.0.1:' + port + +std.out = function (...args) { + std.appendLine('[simple.http]: ' + args.join(' ')) +} + +function createServer() { + if (port > 65535) { + std.out('端口超出有效范围0-65535, 当前为: ' + port) + enabled = false + return + } + std.out(`尝试使用${port}端口...`) + http + .createServer(function (req, res) { + let pathname = parse(req.url) + .pathname.slice(1) + .replace(/[\/]+$/, '') + + pathname = decode(pathname) || 'index.html' + + let file = join(root, pathname) + let stat = fs.stat(file) + let ext = pathname.split('.').pop() + + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Allow-Headers', '*') + res.setHeader('Cache-Control', 'no-store') + res.setHeader('X-Powered-By', 'VS Code simple.http') + + if (stat.isFile()) { + res.setHeader('Accept-Ranges', 'bytes') + res.setHeader('Content-Type', MIME_TYPES[ext] || MIME_TYPES.other) + res.setHeader('Content-Length', stat.size) + res.writeHead(200, 'OK') + fs.origin.createReadStream(file).pipe(res) + } else { + res.setHeader('Content-Type', MIME_TYPES.html) + res.setHeader('Content-Length', 0) + res.writeHead(404, 'Not Found') + res.end('') + } + }) + .listen(port) + .on('error', err => { + std.out(`${port}端口被占用~~~`) + port++ + createServer() + }) + .on('listening', _ => { + baseUrl = 'http://127.0.0.1:' + port + std.out('启动成功, 请访问', baseUrl) + }) +} + +function __init__() { + let folders = vsc.workspace.workspaceFolders + + if (folders && folders.length) { + root = folders[0].uri.fsPath + } + if (root) { + let file = join(root, '.httpserver') + // + if (fs.isfile(file)) { + let conf = JSON.parse(fs.cat(file).toString()) + if (conf.enabled) { + enabled = true + port = conf.port || 23333 + + createServer() + } else { + std.out('发现配置文件, 但服务为 关闭状态') + } + } + } +} + +function deactivate() {} + +exports.activate = function (ctx) { + __init__() + + let cmd = vsc.commands.registerCommand('HttpServer.open', _ => { + if (enabled) { + let editor = vsc.window.activeTextEditor + if (editor) { + console.log(editor) + + let pathname = editor.document.uri.fsPath.slice(root.length) + + vsc.commands.executeCommand('vscode.open', baseUrl + pathname) + } + } + }) + ctx.subscriptions.push(cmd) +} +exports.deactivate = deactivate diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..c953a62 Binary files /dev/null and b/logo.png differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..1b0d9c1 --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "simple.http", + "displayName": "simple.http", + "description": "🔥 简单的http服务器, 方便临时调试html", + "version": "1.0.0", + "publisher": "yutent", + "author": "Yutent [@yutent]", + "icon": "logo.png", + "engines": { + "vscode": "^1.28.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "*" + ], + "main": "out.js", + "contributes": { + "commands": [ + { + "command": "HttpServer.open", + "title": "在浏览器中打开" + } + ], + "menus": { + "editor/context": [ + { + "when": "!inOutput", + "command": "HttpServer.open", + "title": "在浏览器中打开" + } + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/yutent/http.server.git" + }, + "keywords": [ + "http.server", + "http server", + "simple http", + "yutent" + ], + "scripts": { + "start": "esbuild index.js --bundle --outfile=out.js --external:vscode --format=cjs --platform=node", + "pack": "npm start -- --minify" + }, + "license": "MIT", + "dependencies": { + "iofs": "^1.5.0" + }, + "devDependencies": { + "esbuild": "^0.12.14" + } +}