From fc19d336ef2d78d1a7c436a51b038bbe227a7371 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Sat, 4 Apr 2020 18:21:28 +0530 Subject: [PATCH 1/9] Initial port to rust --- .eslintrc | 26 --- .gitignore | 64 +----- Cargo.toml | 9 + build.js | 26 --- gulpfile.js | 149 -------------- package.json | 30 --- src/main.rs | 3 + src/main.ts | 108 ----------- src/package-lock.json | 442 ------------------------------------------ src/package.json | 15 -- src/test.ts | 31 --- tsconfig.json | 11 -- tslint.json | 116 ----------- 13 files changed, 13 insertions(+), 1017 deletions(-) delete mode 100755 .eslintrc mode change 100755 => 100644 .gitignore create mode 100644 Cargo.toml delete mode 100755 build.js delete mode 100755 gulpfile.js delete mode 100755 package.json create mode 100644 src/main.rs delete mode 100755 src/main.ts delete mode 100755 src/package-lock.json delete mode 100755 src/package.json delete mode 100755 src/test.ts delete mode 100755 tsconfig.json delete mode 100755 tslint.json diff --git a/.eslintrc b/.eslintrc deleted file mode 100755 index 1bf5428..0000000 --- a/.eslintrc +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": "eslint:recommended", - "env": { - "browser": true, - "commonjs": true, - "es6": true, - "node": true - }, - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 2017, - "sourceType": "module" - }, - "rules": { - "no-const-assign": "warn", - "no-this-before-super": "warn", - "no-undef": "warn", - "no-unreachable": "warn", - "no-unused-vars": "warn", - "constructor-super": "warn", - "valid-typeof": "warn", - "no-console": "off" - } -} \ No newline at end of file diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 index 256fdb0..ea8c4bf --- a/.gitignore +++ b/.gitignore @@ -1,63 +1 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# next.js build output -.next - -bin \ No newline at end of file +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ed07e88 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "http" +version = "0.1.0" +authors = ["Rakshith Ravi "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/build.js b/build.js deleted file mode 100755 index ec23e4d..0000000 --- a/build.js +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env node -var childProcess = require('child_process'); -var fs = require('fs'); - -console.log('Building application...'); -var env = process.env; -env.NODE_ENV = 'production'; -childProcess.execSync('gulp', { - env: env, - stdio: [0, 1, 2] -}); - -console.log('Correcting package.json...'); -var pkg = JSON.parse(fs.readFileSync('./src/package.json').toString()); -if(pkg.scripts && pkg.scripts.start) - pkg.scripts.start = `NODE_ENV=production ${pkg.scripts.start.replace('ts-node', 'node').replace('.ts', '.js')}`; -if(pkg.devDependencies) - delete pkg.devDependencies; -fs.writeFileSync('./bin/package.json', JSON.stringify(pkg, null, '\t')); - -console.log('Installing production dependencies...'); -childProcess.execSync('npm install --only=production', { - cwd: './bin', - env: env, - stdio: [0, 1, 2] -}); diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100755 index a34ae88..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,149 +0,0 @@ -let gulp = require('gulp'); -let htmlmin = require('gulp-htmlmin'); -let scss = require('gulp-sass'); -let minifyCSS = require('gulp-csso'); -let uglify = require('gulp-uglify-es').default; -let minify = require('gulp-minify'); -let preprocess = require('gulp-preprocess'); -let prettyData = require('gulp-pretty-data'); -let clean = require('gulp-clean'); -let newer = require('gulp-newer'); -let ts = require('gulp-typescript'); - -let tsProject = ts.createProject("tsconfig.json"); - -let configuredExtensions = []; - -gulp.task('html', () => { - configuredExtensions.push('html'); - return gulp.src([ - 'src/**/*.html', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(htmlmin({ - collapseWhitespace: true, - minifyCSS: true, - minifyJS: true - })) - .pipe(gulp.dest('bin')); -}); - -gulp.task('scss', () => { - configuredExtensions.push('sass'); - configuredExtensions.push('scss'); - return gulp.src([ - 'src/**/*.{scss,sass}', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(scss()) - .pipe(minifyCSS()) - .pipe(gulp.dest('bin')); -}); - -gulp.task('css', () => { - configuredExtensions.push('css'); - return gulp.src([ - 'src/**/*.css', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(minifyCSS()) - .pipe(gulp.dest('bin')); -}); - -gulp.task('js', () => { - configuredExtensions.push('js'); - return gulp.src([ - 'src/**/*.js', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(preprocess()) - .pipe(uglify()) - .pipe(minify({ - ext: { - min: '.js' - }, - noSource: true - })) - .pipe(gulp.dest('bin')); -}); - -gulp.task('ts', () => { - configuredExtensions.push('ts'); - return gulp.src([ - 'src/**/*.ts', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(preprocess()) - .pipe(tsProject()) - .pipe(uglify()) - .pipe(minify({ - ext: { - min: '.js' - }, - noSource: true - })) - .pipe(gulp.dest('bin')); -}); - -gulp.task('images', () => { - configuredExtensions.push('png'); - configuredExtensions.push('jpg'); - configuredExtensions.push('jpeg'); - configuredExtensions.push('gif'); - configuredExtensions.push('tif'); - return gulp.src([ - 'src/**/*.{png,jpg,jpeg,gif,tif}', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(gulp.dest('bin')); -}); - -gulp.task('pretty-data', () => { - configuredExtensions.push('xml'); - configuredExtensions.push('json'); - configuredExtensions.push('xlf'); - configuredExtensions.push('svg'); - return gulp.src([ - 'src/**/*.{xml,json,xlf,svg}', - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(prettyData({ - type: "minify", - preserveComments: false - })) - .pipe(gulp.dest('bin')); -}); - -gulp.task('copy', () => { - return gulp.src([ - 'src/**/*', - `!src/**/*.{${configuredExtensions.join(',')}}`, - '!src/**/node_modules/', - '!src/**/node_modules/**/*' - ]) - .pipe(newer('bin')) - .pipe(gulp.dest('bin')); -}); - -gulp.task('clean', () => { - return gulp.src('bin') - .pipe(clean()); -}); - -gulp.task('default', gulp.parallel('html', 'scss', 'css', 'js', 'ts', 'images', 'pretty-data', 'copy')); -gulp.task('build', gulp.series('default')); -gulp.task('rebuild', gulp.series('clean', 'default')); \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100755 index 30b2ad7..0000000 --- a/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "http-project", - "version": "1.0.0", - "description": "Holder project for http", - "private": true, - "scripts": { - "build": "node build.js", - "clean": "gulp clean", - "rebuild": "gulp clean && npm run build", - "postinstall": "cd src && npm install", - "start": "cd src && npm start" - }, - "license": "ISC", - "devDependencies": { - "gulp": "^4.0.0", - "gulp-clean": "latest", - "gulp-csso": "latest", - "gulp-htmlmin": "latest", - "gulp-minify": "latest", - "gulp-newer": "latest", - "gulp-preprocess": "latest", - "gulp-pretty-data": "latest", - "gulp-pug": "latest", - "gulp-sass": "latest", - "gulp-typescript": "latest", - "gulp-uglify-es": "latest", - "ts-node": "latest", - "typescript": "latest" - } -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/main.ts b/src/main.ts deleted file mode 100755 index 4e0f59a..0000000 --- a/src/main.ts +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env node -import GothamModule from '../../gotham-nodejs/src/gotham-node'; -import * as express from 'express'; -import * as http from 'http'; -const metaData = require('./package.json'); - -const app = express(); -app.use(express.json()); -app.use(express.urlencoded()); - -async function main() { - const gotham = GothamModule.default('../gotham.sock'); - - await gotham.initialize(metaData.name, metaData.version); - - await gotham.declareFunction('use', (args: any) => { - app.use(args.path, async (req, res, next) => { - const response: any = await gotham.callFunction(args.function, getReqObject(req)); - if (response.next === true) { - next(response.data); - } else { - if (response.contentType) { - res.contentType(response.contentType); - } - if (response.headers) { - for (const header in response.headers) { - if (response.headers.hasOwnProperty(header)) { - res.setHeader(header, response.headers[header]); - } - } - } - if (typeof(response.body) !== typeof('') || typeof(response.body) !== typeof(0)) { - res.send(JSON.stringify(response.body)); - } else { - res.send(response.body); - } - } - }); - }); - - await gotham.declareFunction('get', async (args: any) => { - app.get(args.path, async (req, res, next) => { - const response: any = await gotham.callFunction(args.function, getReqObject(req)); - if (response.next === true) { - next(response.data); - } else { - if (response.contentType) { - res.contentType(response.contentType); - } - if (response.headers) { - for (const header in response.headers) { - if (response.headers.hasOwnProperty(header)) { - res.setHeader(header, response.headers[header]); - } - } - } - if (typeof(response.body) !== typeof('') || typeof(response.body) !== typeof(0)) { - res.send(JSON.stringify(response.body)); - } else { - res.send(response.body); - } - } - }); - }); - - await gotham.declareFunction('post', (args: any) => { - app.post(args.path, async (req, res, next) => { - const response: any = await gotham.callFunction(args.function, getReqObject(req)); - if (response.next === true) { - next(response.data); - } else { - if (response.contentType) { - res.contentType(response.contentType); - } - if (response.headers) { - for (const header in response.headers) { - if (response.headers.hasOwnProperty(header)) { - res.setHeader(header, response.headers[header]); - } - } - } - if (typeof(response.body) !== typeof('') || typeof(response.body) !== typeof(0)) { - res.send(JSON.stringify(response.body)); - } else { - res.send(response.body); - } - } - }); - }); - - await gotham.declareFunction('patch', (args: any) => { - app.patch(args.path, async (req, res, next) => { - const response: any = await gotham.callFunction(args.function, getReqObject(req)); - if (response.next === true) { - next(response.data); - } else { - if (response.contentType) { - res.contentType(response.contentType); - } - if (response.headers) { - for (const header in response.headers) { - if (response.headers.hasOwnProperty(header)) { - res.setHeader(header, response.headers[header]); - } - } - } - if (typeof(response.body) !== typeof('') || typeof(response.body) !== typeof(0)) { - res.send(JSON.st \ No newline at end of file diff --git a/src/package-lock.json b/src/package-lock.json deleted file mode 100755 index 0bb88a1..0000000 --- a/src/package-lock.json +++ /dev/null @@ -1,442 +0,0 @@ -{ - "name": "http", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/body-parser": { - "version": "1.17.1", - "resolved": "https://npm.vicara.co/@types%2fbody-parser/-/body-parser-1.17.1.tgz", - "integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.33", - "resolved": "https://npm.vicara.co/@types%2fconnect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/express": { - "version": "4.17.2", - "resolved": "https://npm.vicara.co/@types%2fexpress/-/express-4.17.2.tgz", - "integrity": "sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.1", - "resolved": "https://npm.vicara.co/@types%2fexpress-serve-static-core/-/express-serve-static-core-4.17.1.tgz", - "integrity": "sha512-9e7jj549ZI+RxY21Cl0t8uBnWyb22HzILupyHZjYEVK//5TT/1bZodU+yUbLnPdoYViBBnNWbxp4zYjGV0zUGw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/range-parser": "*" - } - }, - "@types/mime": { - "version": "2.0.1", - "resolved": "https://npm.vicara.co/@types%2fmime/-/mime-2.0.1.tgz", - "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", - "dev": true - }, - "@types/node": { - "version": "13.1.7", - "resolved": "https://npm.vicara.co/@types%2fnode/-/node-13.1.7.tgz", - "integrity": "sha512-HU0q9GXazqiKwviVxg9SI/+t/nAsGkvLDkIdxz+ObejG2nX6Si00TeLqHMoS+a/1tjH7a8YpKVQwtgHuMQsldg==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://npm.vicara.co/@types%2frange-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", - "dev": true - }, - "@types/serve-static": { - "version": "1.13.3", - "resolved": "https://npm.vicara.co/@types%2fserve-static/-/serve-static-1.13.3.tgz", - "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://npm.vicara.co/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://npm.vicara.co/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://npm.vicara.co/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://npm.vicara.co/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://npm.vicara.co/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://npm.vicara.co/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://npm.vicara.co/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://npm.vicara.co/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://npm.vicara.co/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://npm.vicara.co/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://npm.vicara.co/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://npm.vicara.co/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://npm.vicara.co/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://npm.vicara.co/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://npm.vicara.co/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://npm.vicara.co/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://npm.vicara.co/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://npm.vicara.co/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://npm.vicara.co/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://npm.vicara.co/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://npm.vicara.co/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://npm.vicara.co/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://npm.vicara.co/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://npm.vicara.co/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://npm.vicara.co/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://npm.vicara.co/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://npm.vicara.co/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.43.0", - "resolved": "https://npm.vicara.co/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" - }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://npm.vicara.co/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", - "requires": { - "mime-db": "1.43.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://npm.vicara.co/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://npm.vicara.co/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://npm.vicara.co/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://npm.vicara.co/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://npm.vicara.co/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://npm.vicara.co/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://npm.vicara.co/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://npm.vicara.co/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://npm.vicara.co/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://npm.vicara.co/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://npm.vicara.co/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://npm.vicara.co/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://npm.vicara.co/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://npm.vicara.co/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://npm.vicara.co/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://npm.vicara.co/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://npm.vicara.co/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://npm.vicara.co/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://npm.vicara.co/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://npm.vicara.co/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://npm.vicara.co/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - } - } -} diff --git a/src/package.json b/src/package.json deleted file mode 100755 index 25ef193..0000000 --- a/src/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "http", - "version": "1.0.0", - "private": true, - "scripts": { - "start": "ts-node main.ts" - }, - "dependencies": { - "express": "^4.17.1" - }, - "devDependencies": { - "@types/express": "^4.17.2", - "@types/node": "^13.1.7" - } -} diff --git a/src/test.ts b/src/test.ts deleted file mode 100755 index bb1dcc3..0000000 --- a/src/test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import GothamModule from '../../gotham-nodejs/src/gotham-node'; - -async function main() { - const gotham = GothamModule.default('../../gotham.sock'); - - await gotham.initialize('test', '1.0.0', { - 'http2': '1.0.0' - }); - - await gotham.declareFunction('onRequest', async (args: any) => { - return { - contentType: 'json', - body: JSON.stringify({ - success: true, - applicationId: 'kai-sdk', - version: '1.0.0' - }) - }; - }); - - await gotham.callFunction('http2.get', { - path: '/', - function: 'test.onRequest' - }); - - await gotham.callFunction('http2.listen', { - port: 8080 - }); -} - -main(); diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100755 index d974bda..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "removeComments": false, - "noImplicitAny": true, - "lib": [ - "dom", - "es2018", - "es5" - ] - } -} \ No newline at end of file diff --git a/tslint.json b/tslint.json deleted file mode 100755 index a36c458..0000000 --- a/tslint.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "rules": { - "arrow-return-shorthand": true, - "callable-types": true, - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "curly": true, - "deprecation": { - "severity": "warn" - }, - "eofline": true, - "forin": true, - "import-blacklist": [ - true, - "rxjs/Rx" - ], - "import-spacing": true, - "indent": [ - true, - "tabs" - ], - "interface-over-type-literal": true, - "label-position": true, - "max-line-length": [ - true, - 300 - ], - "member-access": false, - "member-ordering": [ - true, - { - "order": [ - "static-field", - "instance-field", - "static-method", - "instance-method" - ] - } - ], - "no-arg": true, - "no-bitwise": true, - "no-console": [ - true, - "debug", - "time", - "timeEnd", - "trace" - ], - "no-construct": true, - "no-debugger": true, - "no-duplicate-super": true, - "no-empty": false, - "no-empty-interface": true, - "no-eval": true, - "no-inferrable-types": [ - true, - "ignore-params" - ], - "no-misused-new": true, - "no-non-null-assertion": true, - "no-shadowed-variable": true, - "no-string-literal": false, - "no-string-throw": true, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": true, - "no-unnecessary-initializer": true, - "no-unused-expression": true, - "no-use-before-declare": true, - "no-var-keyword": true, - "object-literal-sort-keys": false, - "one-line": [ - true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" - ], - "prefer-const": true, - "quotemark": [ - true, - "single" - ], - "radix": true, - "semicolon": [ - true, - "always" - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "unified-signatures": true, - "variable-name": false, - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ] - } -} From 61b390a72284c79b619bc02015d0c258581bab3d Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 9 Apr 2020 17:43:01 +0530 Subject: [PATCH 2/9] Test implementation --- Cargo.lock | 916 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 + src/http_config.rs | 26 ++ src/main.rs | 172 ++++++++- 4 files changed, 1121 insertions(+), 2 deletions(-) create mode 100644 Cargo.lock create mode 100644 src/http_config.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2ba98d8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,916 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "async-std" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267" +dependencies = [ + "async-task", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "futures-core", + "futures-io", + "futures-timer", + "kv-log-macro", + "log 0.4.8", + "memchr", + "mio", + "mio-uds", + "num_cpus", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "async-task" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ac2c016b079e771204030951c366db398864f5026f84a44dafb0ff20f02085d" +dependencies = [ + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "async-trait" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab5c215748dc1ad11a145359b1067107ae0f8ca5e99844fa64067ed5bf198e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "bytes" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +dependencies = [ + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" + +[[package]] +name = "futures-executor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" + +[[package]] +name = "futures-macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" + +[[package]] +name = "futures-timer" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "gotham" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "futures", + "futures-util", + "serde_json", +] + +[[package]] +name = "groupable" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57" + +[[package]] +name = "hermit-abi" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.1.0" +dependencies = [ + "clap", + "futures", + "gotham", + "lazy_static", + "nickel", + "tokio", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64", + "httparse", + "language-tags", + "log 0.3.9", + "mime", + "num_cpus", + "time", + "traitobject", + "typeable", + "unicase", + "url", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" +dependencies = [ + "log 0.4.8", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.8", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "memoffset" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + +[[package]] +name = "mio" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +dependencies = [ + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log 0.4.8", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +dependencies = [ + "iovec", + "libc", + "mio", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "modifier" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" + +[[package]] +name = "mustache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51956ef1c5d20a1384524d91e616fb44dfc7d8f249bf696d49c97dd3289ecab5" +dependencies = [ + "log 0.3.9", + "serde", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +dependencies = [ + "cfg-if", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "nickel" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5061a832728db2dacb61cefe0ce303b58f85764ec680e71d9138229640a46d9" +dependencies = [ + "groupable", + "hyper", + "lazy_static", + "log 0.3.9", + "modifier", + "mustache", + "plugin", + "regex", + "serde", + "serde_json", + "time", + "typemap", + "url", +] + +[[package]] +name = "num_cpus" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "pin-project-lite" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" + +[[package]] +name = "plugin" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" +dependencies = [ + "typemap", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" + +[[package]] +name = "proc-macro-nested" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" + +[[package]] +name = "proc-macro2" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "regex" +version = "1.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" + +[[package]] +name = "ryu" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" + +[[package]] +name = "serde_json" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "smallvec" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +dependencies = [ + "libc", + "redox_syscall", + "winapi 0.3.8", +] + +[[package]] +name = "tokio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13fb0a0dab58ae3db3832810b2aabb98dd42be27c04e7f7f1ae3a6ac78f858d1" +dependencies = [ + "bytes", + "fnv", + "pin-project-lite", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + +[[package]] +name = "typemap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" +dependencies = [ + "unsafe-any", +] + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +dependencies = [ + "smallvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "unsafe-any" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" +dependencies = [ + "traitobject", +] + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/Cargo.toml b/Cargo.toml index ed07e88..59560c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,12 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +gotham = { path = "../gotham-rust/" } +lazy_static = "1.4.0" +clap = "2.33.0" +futures = "0.3.4" +nickel = "0.11.0" + +[dependencies.tokio] +version = "0.2.5" +features = ["macros", "rt-core", "sync"] diff --git a/src/http_config.rs b/src/http_config.rs new file mode 100644 index 0000000..1cfff4c --- /dev/null +++ b/src/http_config.rs @@ -0,0 +1,26 @@ +use nickel::Middleware; +use gotham::models::Value; + +pub struct HttpConfig { + pub config_type: MiddlewareType, + pub func_name: String, + pub path: String +} + +pub enum MiddlewareType { + USE, + DELETE, + GET, + OPTIONS, + POST, + PUT, + UPDATE, +} + +pub struct MiddlewareContext { + pub data: Value +} + +impl Middleware for HttpConfig { + // TODO implement the trait +} diff --git a/src/main.rs b/src/main.rs index e7a11a9..128047c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,171 @@ -fn main() { - println!("Hello, world!"); +#[macro_use] +extern crate lazy_static; +extern crate clap; +extern crate futures; +extern crate gotham; +extern crate nickel; +extern crate tokio; + +mod http_config; + +use http_config::HttpConfig; +use http_config::MiddlewareType; + +use clap::{crate_authors, crate_name, crate_version, App, Arg}; +use gotham::{models::Value, GothamModule}; +use nickel::Nickel; +use std::collections::HashMap; +use std::sync::Mutex; + +lazy_static! { + static ref HTTP_CONFIG: Mutex> = Mutex::new(Vec::new()); +} + +#[tokio::main] +async fn main() { + let mut module = from_cli_args(); + module + .initialize(crate_name!(), crate_version!(), HashMap::new()) + .await + .unwrap(); + + module + .declare_function("clearConfig", clear_config) + .await + .unwrap(); + + module.declare_function("use", app_use).await.unwrap(); +} + +fn app_use(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::USE, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +fn listen(args: HashMap) -> Value { + let mut server = Nickel::new(); + // Populate `server` from HTTP_CONFIG + // Setup routers and middlwares accordingly + if args.get("socket").is_none() { + // Need a binding address to bind to + return Value::Null; + } + + let listener = server + .listen(args.get("socket").unwrap().as_string().unwrap()) + .unwrap(); + // Add `listener` to a global mutex like HTTP_CONFIG + // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one + + Value::Null +} + +fn clear_config(_args: HashMap) -> Value { + Value::Null +} + +#[allow(clippy::collapsible_if)] +pub fn from_cli_args() -> GothamModule { + let args = App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!()) + .about("Http module") + .arg( + Arg::with_name("socket-location") + .conflicts_with("port") + .conflicts_with("host") + .short("s") + .long("socket-location") + .takes_value(true) + .value_name("FILE") + .help("Sets the location of the socket to connect"), + ) + .arg( + Arg::with_name("port") + .conflicts_with("socket-location") + .short("p") + .long("port") + .takes_value(true) + .value_name("PORT") + .help("Sets the port for the socket to connect to"), + ) + .arg( + Arg::with_name("host") + .conflicts_with("socket-location") + .short("h") + .long("host") + .takes_value(true) + .value_name("HOST-IP") + .help("Sets the host address for the socket to connect"), + ) + .arg( + Arg::with_name("V") + .short("V") + .multiple(true) + .help("Sets the level of verbosity (max 3)"), + ) + .arg( + Arg::with_name("version") + .short("v") + .long("version") + .help("Prints version information"), + ) + .get_matches(); + + if args.is_present("version") { + println!("{}", crate_version!()); + panic!(); + } + + let mut default_socket_location = std::env::current_dir().unwrap(); + default_socket_location.push(args.value_of("socket-location").unwrap_or("../gotham.sock")); + let default_socket_location = default_socket_location.as_os_str().to_str().unwrap(); + + if cfg!(target_family = "windows") { + if args.value_of("socket-location").is_some() { + panic!("Listening on unix sockets are not supported on windows"); + } else { + GothamModule::from_inet_socket( + args.value_of("host").unwrap_or("127.0.0.1"), + args.value_of("port") + .unwrap_or("2203") + .parse::() + .unwrap(), + ) + } + } else { + if args.value_of("port").is_some() { + GothamModule::from_inet_socket( + args.value_of("host").unwrap_or("127.0.0.1"), + args.value_of("port") + .unwrap_or("2203") + .parse::() + .unwrap(), + ) + } else { + GothamModule::from_unix_socket( + args.value_of("socket-location") + .unwrap_or(default_socket_location), + ) + } + } } From da7eab2102aaa8967ccb95b79de70eb906269ae8 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 9 Apr 2020 18:03:39 +0530 Subject: [PATCH 3/9] Added all required routers. Need to implement the listen function is all --- src/cli_parser.rs | 89 ++++++++++++++++++++ src/http_config.rs | 32 +++++--- src/main.rs | 180 ++++++++++------------------------------- src/server.rs | 198 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 347 insertions(+), 152 deletions(-) create mode 100644 src/cli_parser.rs create mode 100644 src/server.rs diff --git a/src/cli_parser.rs b/src/cli_parser.rs new file mode 100644 index 0000000..0a67947 --- /dev/null +++ b/src/cli_parser.rs @@ -0,0 +1,89 @@ +use clap::{crate_authors, crate_name, crate_version, App, Arg}; +use gotham::GothamModule; + +#[allow(clippy::collapsible_if)] +pub fn from_cli_args() -> GothamModule { + let args = App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!()) + .about("Http module") + .arg( + Arg::with_name("socket-location") + .conflicts_with("port") + .conflicts_with("host") + .short("s") + .long("socket-location") + .takes_value(true) + .value_name("FILE") + .help("Sets the location of the socket to connect"), + ) + .arg( + Arg::with_name("port") + .conflicts_with("socket-location") + .short("p") + .long("port") + .takes_value(true) + .value_name("PORT") + .help("Sets the port for the socket to connect to"), + ) + .arg( + Arg::with_name("host") + .conflicts_with("socket-location") + .short("h") + .long("host") + .takes_value(true) + .value_name("HOST-IP") + .help("Sets the host address for the socket to connect"), + ) + .arg( + Arg::with_name("V") + .short("V") + .multiple(true) + .help("Sets the level of verbosity (max 3)"), + ) + .arg( + Arg::with_name("version") + .short("v") + .long("version") + .help("Prints version information"), + ) + .get_matches(); + + if args.is_present("version") { + println!("{}", crate_version!()); + panic!(); + } + + let mut default_socket_location = std::env::current_dir().unwrap(); + default_socket_location.push(args.value_of("socket-location").unwrap_or("../gotham.sock")); + let default_socket_location = default_socket_location.as_os_str().to_str().unwrap(); + + if cfg!(target_family = "windows") { + if args.value_of("socket-location").is_some() { + panic!("Listening on unix sockets are not supported on windows"); + } else { + GothamModule::from_inet_socket( + args.value_of("host").unwrap_or("127.0.0.1"), + args.value_of("port") + .unwrap_or("2203") + .parse::() + .unwrap(), + ) + } + } else { + if args.value_of("port").is_some() { + GothamModule::from_inet_socket( + args.value_of("host").unwrap_or("127.0.0.1"), + args.value_of("port") + .unwrap_or("2203") + .parse::() + .unwrap(), + ) + } else { + GothamModule::from_unix_socket( + args.value_of("socket-location") + .unwrap_or(default_socket_location), + ) + } + } +} \ No newline at end of file diff --git a/src/http_config.rs b/src/http_config.rs index 1cfff4c..6d28e61 100644 --- a/src/http_config.rs +++ b/src/http_config.rs @@ -1,26 +1,32 @@ -use nickel::Middleware; use gotham::models::Value; +use nickel::{hyper::net::Fresh, Middleware, MiddlewareResult, Request, Response}; pub struct HttpConfig { - pub config_type: MiddlewareType, - pub func_name: String, - pub path: String + pub config_type: MiddlewareType, + pub func_name: String, + pub path: String, } pub enum MiddlewareType { - USE, - DELETE, - GET, - OPTIONS, - POST, - PUT, - UPDATE, + DELETE, + GET, + OPTIONS, + POST, + PUT, + UPDATE, + USE, } pub struct MiddlewareContext { - pub data: Value + pub data: Value, } impl Middleware for HttpConfig { - // TODO implement the trait + fn invoke<'mw, 'conn>( + &'mw self, + _req: &mut Request<'mw, 'conn, MiddlewareContext>, + res: Response<'mw, MiddlewareContext, Fresh>, + ) -> MiddlewareResult<'mw, MiddlewareContext> { + res.next_middleware() + } } diff --git a/src/main.rs b/src/main.rs index 128047c..128768f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,166 +6,68 @@ extern crate gotham; extern crate nickel; extern crate tokio; +mod cli_parser; mod http_config; +mod server; use http_config::HttpConfig; -use http_config::MiddlewareType; -use clap::{crate_authors, crate_name, crate_version, App, Arg}; -use gotham::{models::Value, GothamModule}; -use nickel::Nickel; use std::collections::HashMap; use std::sync::Mutex; +use nickel::ListeningServer; + +use clap::{crate_name, crate_version}; + lazy_static! { - static ref HTTP_CONFIG: Mutex> = Mutex::new(Vec::new()); + pub static ref HTTP_CONFIG: Mutex> = Mutex::new(Vec::new()); + pub static ref LISTENER: Mutex< } #[tokio::main] async fn main() { - let mut module = from_cli_args(); + let mut module = cli_parser::from_cli_args(); module .initialize(crate_name!(), crate_version!(), HashMap::new()) .await .unwrap(); module - .declare_function("clearConfig", clear_config) + .declare_function("delete", server::app_delete) .await .unwrap(); - - module.declare_function("use", app_use).await.unwrap(); -} - -fn app_use(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::USE, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -fn listen(args: HashMap) -> Value { - let mut server = Nickel::new(); - // Populate `server` from HTTP_CONFIG - // Setup routers and middlwares accordingly - if args.get("socket").is_none() { - // Need a binding address to bind to - return Value::Null; - } - - let listener = server - .listen(args.get("socket").unwrap().as_string().unwrap()) + module + .declare_function("get", server::app_get) + .await + .unwrap(); + module + .declare_function("options", server::app_options) + .await + .unwrap(); + module + .declare_function("post", server::app_post) + .await + .unwrap(); + module + .declare_function("put", server::app_put) + .await + .unwrap(); + module + .declare_function("update", server::app_update) + .await + .unwrap(); + module + .declare_function("use", server::app_use) + .await .unwrap(); - // Add `listener` to a global mutex like HTTP_CONFIG - // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one - - Value::Null -} - -fn clear_config(_args: HashMap) -> Value { - Value::Null -} - -#[allow(clippy::collapsible_if)] -pub fn from_cli_args() -> GothamModule { - let args = App::new(crate_name!()) - .version(crate_version!()) - .author(crate_authors!()) - .about("Http module") - .arg( - Arg::with_name("socket-location") - .conflicts_with("port") - .conflicts_with("host") - .short("s") - .long("socket-location") - .takes_value(true) - .value_name("FILE") - .help("Sets the location of the socket to connect"), - ) - .arg( - Arg::with_name("port") - .conflicts_with("socket-location") - .short("p") - .long("port") - .takes_value(true) - .value_name("PORT") - .help("Sets the port for the socket to connect to"), - ) - .arg( - Arg::with_name("host") - .conflicts_with("socket-location") - .short("h") - .long("host") - .takes_value(true) - .value_name("HOST-IP") - .help("Sets the host address for the socket to connect"), - ) - .arg( - Arg::with_name("V") - .short("V") - .multiple(true) - .help("Sets the level of verbosity (max 3)"), - ) - .arg( - Arg::with_name("version") - .short("v") - .long("version") - .help("Prints version information"), - ) - .get_matches(); - - if args.is_present("version") { - println!("{}", crate_version!()); - panic!(); - } - let mut default_socket_location = std::env::current_dir().unwrap(); - default_socket_location.push(args.value_of("socket-location").unwrap_or("../gotham.sock")); - let default_socket_location = default_socket_location.as_os_str().to_str().unwrap(); + module + .declare_function("listen", server::listen) + .await + .unwrap(); - if cfg!(target_family = "windows") { - if args.value_of("socket-location").is_some() { - panic!("Listening on unix sockets are not supported on windows"); - } else { - GothamModule::from_inet_socket( - args.value_of("host").unwrap_or("127.0.0.1"), - args.value_of("port") - .unwrap_or("2203") - .parse::() - .unwrap(), - ) - } - } else { - if args.value_of("port").is_some() { - GothamModule::from_inet_socket( - args.value_of("host").unwrap_or("127.0.0.1"), - args.value_of("port") - .unwrap_or("2203") - .parse::() - .unwrap(), - ) - } else { - GothamModule::from_unix_socket( - args.value_of("socket-location") - .unwrap_or(default_socket_location), - ) - } - } + module + .declare_function("clearConfig", server::clear_config) + .await + .unwrap(); } diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..661e71d --- /dev/null +++ b/src/server.rs @@ -0,0 +1,198 @@ +use crate::http_config::MiddlewareType; +use crate::http_config::HttpConfig; + +use std::collections::HashMap; + +use gotham::models::Value; +use nickel::Nickel; + +pub fn app_delete(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::DELETE, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn app_get(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::GET, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn app_options(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::OPTIONS, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn app_post(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::POST, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn app_put(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::PUT, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn app_update(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::UPDATE, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn app_use(args: HashMap) -> Value { + let value = Value::String(String::from("/")); + let string = String::from("/"); + let path = args + .get("path") + .unwrap_or(&value) + .as_string() + .unwrap_or(&string); + + let function = args.get("function").unwrap_or(&Value::Null).as_string(); + if function.is_none() { + return Value::Null; + } + let function = function.unwrap(); + + crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { + config_type: MiddlewareType::USE, + func_name: function.clone(), + path: path.clone(), + }); + + Value::Null +} + +pub fn listen(args: HashMap) -> Value { + let mut server = Nickel::new(); + // Populate `server` from HTTP_CONFIG + // Setup routers and middlwares accordingly + if args.get("socket").is_none() { + // Need a binding address to bind to + return Value::Null; + } + + let listener = server + .listen(args.get("socket").unwrap().as_string().unwrap()) + .unwrap(); + // Add `listener` to a global mutex like HTTP_CONFIG + // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one + + Value::Null +} + +pub fn clear_config(_args: HashMap) -> Value { + crate::HTTP_CONFIG.lock().unwrap().clear(); + Value::Null +} \ No newline at end of file From 5b16cc9d6a2e452ee6a41b305a0e92b1a5baf128 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 9 Apr 2020 18:08:32 +0530 Subject: [PATCH 4/9] Added module.json to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea8c4bf..f4d7f0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +module.json From c1dc062e67d78e5b234e6bcadcdb47d28669e924 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 9 Apr 2020 18:47:22 +0530 Subject: [PATCH 5/9] Added appropriate functions. No way to kill a nickel server. That's my only problem as of now. --- src/http_config.rs | 16 ++++++----- src/main.rs | 8 +++--- src/server.rs | 68 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/http_config.rs b/src/http_config.rs index 6d28e61..674df4f 100644 --- a/src/http_config.rs +++ b/src/http_config.rs @@ -1,20 +1,22 @@ use gotham::models::Value; use nickel::{hyper::net::Fresh, Middleware, MiddlewareResult, Request, Response}; +#[derive(Clone)] pub struct HttpConfig { pub config_type: MiddlewareType, pub func_name: String, pub path: String, } +#[derive(Clone)] pub enum MiddlewareType { - DELETE, - GET, - OPTIONS, - POST, - PUT, - UPDATE, - USE, + Delete, + Get, + Options, + Patch, + Post, + Put, + Use } pub struct MiddlewareContext { diff --git a/src/main.rs b/src/main.rs index 128768f..d9e7f52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use clap::{crate_name, crate_version}; lazy_static! { pub static ref HTTP_CONFIG: Mutex> = Mutex::new(Vec::new()); - pub static ref LISTENER: Mutex< + pub static ref LISTENER: Mutex> = Mutex::new(None); } #[tokio::main] @@ -45,15 +45,15 @@ async fn main() { .await .unwrap(); module - .declare_function("post", server::app_post) + .declare_function("patch", server::app_patch) .await .unwrap(); module - .declare_function("put", server::app_put) + .declare_function("post", server::app_post) .await .unwrap(); module - .declare_function("update", server::app_update) + .declare_function("put", server::app_put) .await .unwrap(); module diff --git a/src/server.rs b/src/server.rs index 661e71d..817bf39 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,10 +1,11 @@ use crate::http_config::MiddlewareType; use crate::http_config::HttpConfig; +use crate::http_config::MiddlewareContext; use std::collections::HashMap; use gotham::models::Value; -use nickel::Nickel; +use nickel::{Nickel, HttpRouter}; pub fn app_delete(args: HashMap) -> Value { let value = Value::String(String::from("/")); @@ -22,7 +23,7 @@ pub fn app_delete(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::DELETE, + config_type: MiddlewareType::Delete, func_name: function.clone(), path: path.clone(), }); @@ -46,7 +47,7 @@ pub fn app_get(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::GET, + config_type: MiddlewareType::Get, func_name: function.clone(), path: path.clone(), }); @@ -70,7 +71,7 @@ pub fn app_options(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::OPTIONS, + config_type: MiddlewareType::Options, func_name: function.clone(), path: path.clone(), }); @@ -78,7 +79,7 @@ pub fn app_options(args: HashMap) -> Value { Value::Null } -pub fn app_post(args: HashMap) -> Value { +pub fn app_patch(args: HashMap) -> Value { let value = Value::String(String::from("/")); let string = String::from("/"); let path = args @@ -94,7 +95,7 @@ pub fn app_post(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::POST, + config_type: MiddlewareType::Patch, func_name: function.clone(), path: path.clone(), }); @@ -102,7 +103,7 @@ pub fn app_post(args: HashMap) -> Value { Value::Null } -pub fn app_put(args: HashMap) -> Value { +pub fn app_post(args: HashMap) -> Value { let value = Value::String(String::from("/")); let string = String::from("/"); let path = args @@ -118,7 +119,7 @@ pub fn app_put(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::PUT, + config_type: MiddlewareType::Post, func_name: function.clone(), path: path.clone(), }); @@ -126,8 +127,8 @@ pub fn app_put(args: HashMap) -> Value { Value::Null } -pub fn app_update(args: HashMap) -> Value { - let value = Value::String(String::from("/")); +pub fn app_put(args: HashMap) -> Value { + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -142,7 +143,7 @@ pub fn app_update(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::UPDATE, + config_type: MiddlewareType::Put, func_name: function.clone(), path: path.clone(), }); @@ -166,7 +167,7 @@ pub fn app_use(args: HashMap) -> Value { let function = function.unwrap(); crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::USE, + config_type: MiddlewareType::Use, func_name: function.clone(), path: path.clone(), }); @@ -175,7 +176,45 @@ pub fn app_use(args: HashMap) -> Value { } pub fn listen(args: HashMap) -> Value { - let mut server = Nickel::new(); + let mut http_listener = crate::LISTENER.lock().unwrap(); + let http_config = crate::HTTP_CONFIG.lock().unwrap(); + + if http_listener.is_some() { + // Kill the server. + // So far, no way to do that. Nickel doesn't support it yet + panic!("Excuse me wtf?"); + } + + let mut server = Nickel::with_data(MiddlewareContext { + data: Value::Null + }); + + for config in http_config.iter() { + match &config.config_type { + MiddlewareType::Delete => { + server.delete::(config.path.clone(), config.clone()); + }, + MiddlewareType::Get => { + server.get::(config.path.clone(), config.clone()); + }, + MiddlewareType::Options => { + server.options::(config.path.clone(), config.clone()); + }, + MiddlewareType::Patch => { + server.patch::(config.path.clone(), config.clone()); + }, + MiddlewareType::Post => { + server.post::(config.path.clone(), config.clone()); + }, + MiddlewareType::Put => { + server.put::(config.path.clone(), config.clone()); + }, + MiddlewareType::Use => { + server.utilize::(config.clone()); + }, + } + } + // Populate `server` from HTTP_CONFIG // Setup routers and middlwares accordingly if args.get("socket").is_none() { @@ -187,7 +226,8 @@ pub fn listen(args: HashMap) -> Value { .listen(args.get("socket").unwrap().as_string().unwrap()) .unwrap(); // Add `listener` to a global mutex like HTTP_CONFIG - // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one + // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one + *http_listener = Some(listener); Value::Null } From 6890d525e9229b482f24b19f7e3d3feea3a4c00a Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 9 Apr 2020 20:29:07 +0530 Subject: [PATCH 6/9] Renamed gotham to juno --- Cargo.lock | 25 ++++++------- Cargo.toml | 4 +-- src/cli_parser.rs | 12 +++---- src/http_config.rs | 10 +++--- src/main.rs | 7 +++- src/server.rs | 90 +++++++++++++++++++++++----------------------- 6 files changed, 77 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ba98d8..1bef1bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,17 +296,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gotham" -version = "0.1.0" -dependencies = [ - "async-std", - "async-trait", - "futures", - "futures-util", - "serde_json", -] - [[package]] name = "groupable" version = "0.2.0" @@ -328,7 +317,7 @@ version = "0.1.0" dependencies = [ "clap", "futures", - "gotham", + "juno", "lazy_static", "nickel", "tokio", @@ -385,6 +374,17 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +[[package]] +name = "juno" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "futures", + "futures-util", + "serde_json", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -765,6 +765,7 @@ dependencies = [ "bytes", "fnv", "pin-project-lite", + "slab", "tokio-macros", ] diff --git a/Cargo.toml b/Cargo.toml index 59560c8..e33330e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -gotham = { path = "../gotham-rust/" } +juno = { path = "../juno-rust/" } lazy_static = "1.4.0" clap = "2.33.0" futures = "0.3.4" @@ -15,4 +15,4 @@ nickel = "0.11.0" [dependencies.tokio] version = "0.2.5" -features = ["macros", "rt-core", "sync"] +features = ["macros", "rt-core", "sync", "time"] diff --git a/src/cli_parser.rs b/src/cli_parser.rs index 0a67947..5954ff4 100644 --- a/src/cli_parser.rs +++ b/src/cli_parser.rs @@ -1,8 +1,8 @@ use clap::{crate_authors, crate_name, crate_version, App, Arg}; -use gotham::GothamModule; +use juno::JunoModule; #[allow(clippy::collapsible_if)] -pub fn from_cli_args() -> GothamModule { +pub fn from_cli_args() -> JunoModule { let args = App::new(crate_name!()) .version(crate_version!()) .author(crate_authors!()) @@ -55,14 +55,14 @@ pub fn from_cli_args() -> GothamModule { } let mut default_socket_location = std::env::current_dir().unwrap(); - default_socket_location.push(args.value_of("socket-location").unwrap_or("../gotham.sock")); + default_socket_location.push(args.value_of("socket-location").unwrap_or("../juno.sock")); let default_socket_location = default_socket_location.as_os_str().to_str().unwrap(); if cfg!(target_family = "windows") { if args.value_of("socket-location").is_some() { panic!("Listening on unix sockets are not supported on windows"); } else { - GothamModule::from_inet_socket( + JunoModule::from_inet_socket( args.value_of("host").unwrap_or("127.0.0.1"), args.value_of("port") .unwrap_or("2203") @@ -72,7 +72,7 @@ pub fn from_cli_args() -> GothamModule { } } else { if args.value_of("port").is_some() { - GothamModule::from_inet_socket( + JunoModule::from_inet_socket( args.value_of("host").unwrap_or("127.0.0.1"), args.value_of("port") .unwrap_or("2203") @@ -80,7 +80,7 @@ pub fn from_cli_args() -> GothamModule { .unwrap(), ) } else { - GothamModule::from_unix_socket( + JunoModule::from_unix_socket( args.value_of("socket-location") .unwrap_or(default_socket_location), ) diff --git a/src/http_config.rs b/src/http_config.rs index 674df4f..ba11f9f 100644 --- a/src/http_config.rs +++ b/src/http_config.rs @@ -1,4 +1,4 @@ -use gotham::models::Value; +use juno::models::Value; use nickel::{hyper::net::Fresh, Middleware, MiddlewareResult, Request, Response}; #[derive(Clone)] @@ -10,12 +10,12 @@ pub struct HttpConfig { #[derive(Clone)] pub enum MiddlewareType { - Delete, - Get, + Delete, + Get, Options, Patch, - Post, - Put, + Post, + Put, Use } diff --git a/src/main.rs b/src/main.rs index d9e7f52..899cbb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ extern crate lazy_static; extern crate clap; extern crate futures; -extern crate gotham; +extern crate juno; extern crate nickel; extern crate tokio; @@ -14,6 +14,7 @@ use http_config::HttpConfig; use std::collections::HashMap; use std::sync::Mutex; +use std::time::Duration; use nickel::ListeningServer; @@ -70,4 +71,8 @@ async fn main() { .declare_function("clearConfig", server::clear_config) .await .unwrap(); + + loop { + tokio::time::delay_for(Duration::from_millis(1000)).await; + } } diff --git a/src/server.rs b/src/server.rs index 817bf39..e3f5c60 100644 --- a/src/server.rs +++ b/src/server.rs @@ -4,11 +4,11 @@ use crate::http_config::MiddlewareContext; use std::collections::HashMap; -use gotham::models::Value; +use juno::models::Value; use nickel::{Nickel, HttpRouter}; pub fn app_delete(args: HashMap) -> Value { - let value = Value::String(String::from("/")); + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -32,7 +32,7 @@ pub fn app_delete(args: HashMap) -> Value { } pub fn app_get(args: HashMap) -> Value { - let value = Value::String(String::from("/")); + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -56,7 +56,7 @@ pub fn app_get(args: HashMap) -> Value { } pub fn app_options(args: HashMap) -> Value { - let value = Value::String(String::from("/")); + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -80,7 +80,7 @@ pub fn app_options(args: HashMap) -> Value { } pub fn app_patch(args: HashMap) -> Value { - let value = Value::String(String::from("/")); + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -104,7 +104,7 @@ pub fn app_patch(args: HashMap) -> Value { } pub fn app_post(args: HashMap) -> Value { - let value = Value::String(String::from("/")); + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -128,7 +128,7 @@ pub fn app_post(args: HashMap) -> Value { } pub fn app_put(args: HashMap) -> Value { - let value = Value::String(String::from("/")); + let value = Value::String(String::from("/")); let string = String::from("/"); let path = args .get("path") @@ -176,44 +176,44 @@ pub fn app_use(args: HashMap) -> Value { } pub fn listen(args: HashMap) -> Value { - let mut http_listener = crate::LISTENER.lock().unwrap(); - let http_config = crate::HTTP_CONFIG.lock().unwrap(); + let mut http_listener = crate::LISTENER.lock().unwrap(); + let http_config = crate::HTTP_CONFIG.lock().unwrap(); - if http_listener.is_some() { - // Kill the server. - // So far, no way to do that. Nickel doesn't support it yet - panic!("Excuse me wtf?"); - } + if http_listener.is_some() { + // Kill the server. + // So far, no way to do that. Nickel doesn't support it yet + panic!("Excuse me wtf?"); + } let mut server = Nickel::with_data(MiddlewareContext { - data: Value::Null - }); - - for config in http_config.iter() { - match &config.config_type { - MiddlewareType::Delete => { - server.delete::(config.path.clone(), config.clone()); - }, - MiddlewareType::Get => { - server.get::(config.path.clone(), config.clone()); - }, - MiddlewareType::Options => { - server.options::(config.path.clone(), config.clone()); - }, - MiddlewareType::Patch => { - server.patch::(config.path.clone(), config.clone()); - }, - MiddlewareType::Post => { - server.post::(config.path.clone(), config.clone()); - }, - MiddlewareType::Put => { - server.put::(config.path.clone(), config.clone()); - }, - MiddlewareType::Use => { - server.utilize::(config.clone()); - }, - } - } + data: Value::Null + }); + + for config in http_config.iter() { + match &config.config_type { + MiddlewareType::Delete => { + server.delete::(config.path.clone(), config.clone()); + }, + MiddlewareType::Get => { + server.get::(config.path.clone(), config.clone()); + }, + MiddlewareType::Options => { + server.options::(config.path.clone(), config.clone()); + }, + MiddlewareType::Patch => { + server.patch::(config.path.clone(), config.clone()); + }, + MiddlewareType::Post => { + server.post::(config.path.clone(), config.clone()); + }, + MiddlewareType::Put => { + server.put::(config.path.clone(), config.clone()); + }, + MiddlewareType::Use => { + server.utilize::(config.clone()); + }, + } + } // Populate `server` from HTTP_CONFIG // Setup routers and middlwares accordingly @@ -226,13 +226,13 @@ pub fn listen(args: HashMap) -> Value { .listen(args.get("socket").unwrap().as_string().unwrap()) .unwrap(); // Add `listener` to a global mutex like HTTP_CONFIG - // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one - *http_listener = Some(listener); + // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one + *http_listener = Some(listener); Value::Null } pub fn clear_config(_args: HashMap) -> Value { - crate::HTTP_CONFIG.lock().unwrap().clear(); + crate::HTTP_CONFIG.lock().unwrap().clear(); Value::Null } \ No newline at end of file From af8e343a0bf563f5a4f4b5767c3f01ccf28597b1 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Sat, 25 Apr 2020 20:35:19 +0530 Subject: [PATCH 7/9] Base structure done. Being ported to rust --- .rustfmt.toml | 8 + Cargo.lock | 631 ++++++++++++++++++++++++++------------------ Cargo.toml | 5 +- src/cli_parser.rs | 2 +- src/http_config.rs | 27 +- src/http_context.rs | 169 ++++++++++++ src/main.rs | 33 ++- src/server.rs | 125 +++++++-- 8 files changed, 688 insertions(+), 312 deletions(-) create mode 100644 .rustfmt.toml create mode 100644 src/http_context.rs diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..10a8f4b --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,8 @@ +binop_separator = "Back" +combine_control_expr = false +condense_wildcard_suffixes = true +format_code_in_doc_comments = true +hard_tabs = true +imports_layout = "HorizontalVertical" +merge_imports = true +use_field_init_shorthand = true \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 1bef1bd..34f3f66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,14 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "aho-corasick" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" -dependencies = [ - "memchr", -] - [[package]] name = "ansi_term" version = "0.11.0" @@ -18,6 +9,12 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "arc-swap" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" + [[package]] name = "async-std" version = "1.5.0" @@ -32,7 +29,7 @@ dependencies = [ "futures-io", "futures-timer", "kv-log-macro", - "log 0.4.8", + "log", "memchr", "mio", "mio-uds", @@ -55,13 +52,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab5c215748dc1ad11a145359b1067107ae0f8ca5e99844fa64067ed5bf198e3" +checksum = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.18", ] [[package]] @@ -77,19 +74,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.0" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] -name = "base64" -version = "0.9.3" +name = "autocfg" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "bitflags" @@ -103,6 +96,16 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "0.5.4" @@ -130,6 +133,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "crossbeam-channel" version = "0.4.2" @@ -157,7 +169,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg", + "autocfg 1.0.0", "cfg-if", "crossbeam-utils", "lazy_static", @@ -172,7 +184,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg", + "autocfg 1.0.0", "cfg-if", "lazy_static", ] @@ -183,6 +195,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -199,6 +217,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "futures" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" + [[package]] name = "futures" version = "0.3.4" @@ -254,9 +278,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" dependencies = [ "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.18", ] [[package]] @@ -296,17 +320,11 @@ dependencies = [ "slab", ] -[[package]] -name = "groupable" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57" - [[package]] name = "hermit-abi" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" dependencies = [ "libc", ] @@ -315,49 +333,42 @@ dependencies = [ name = "http" version = "0.1.0" dependencies = [ + "bytes 0.5.4", "clap", - "futures", + "futures 0.3.4", "juno", "lazy_static", - "nickel", + "thruster", "tokio", ] [[package]] -name = "httparse" -version = "1.3.4" +name = "http" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +dependencies = [ + "bytes 0.4.12", + "fnv", + "itoa", +] [[package]] -name = "hyper" -version = "0.10.16" +name = "http" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ - "base64", - "httparse", - "language-tags", - "log 0.3.9", - "mime", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase", - "url", + "bytes 0.5.4", + "fnv", + "itoa", ] [[package]] -name = "idna" -version = "0.1.5" +name = "httparse" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "iovec" @@ -376,11 +387,13 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "juno" -version = "0.1.0" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30daf3321be539ae2c45992f6309ae78d98844f40f34b448bbabb2ae554415be" dependencies = [ "async-std", "async-trait", - "futures", + "futures 0.3.4", "futures-util", "serde_json", ] @@ -401,15 +414,9 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" dependencies = [ - "log 0.4.8", + "log", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.4.0" @@ -418,18 +425,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.8", -] +checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" [[package]] name = "log" @@ -440,12 +438,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - [[package]] name = "maybe-uninit" version = "2.0.0" @@ -464,16 +456,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", + "autocfg 1.0.0", ] [[package]] @@ -488,13 +471,25 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.8", - "miow", + "log", + "miow 0.2.1", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio-named-pipes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" +dependencies = [ + "log", + "mio", + "miow 0.3.3", + "winapi 0.3.8", +] + [[package]] name = "mio-uds" version = "0.6.7" @@ -519,19 +514,13 @@ dependencies = [ ] [[package]] -name = "modifier" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" - -[[package]] -name = "mustache" -version = "0.9.0" +name = "miow" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51956ef1c5d20a1384524d91e616fb44dfc7d8f249bf696d49c97dd3289ecab5" +checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" dependencies = [ - "log 0.3.9", - "serde", + "socket2", + "winapi 0.3.8", ] [[package]] @@ -545,32 +534,11 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "nickel" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5061a832728db2dacb61cefe0ce303b58f85764ec680e71d9138229640a46d9" -dependencies = [ - "groupable", - "hyper", - "lazy_static", - "log 0.3.9", - "modifier", - "mustache", - "plugin", - "regex", - "serde", - "serde_json", - "time", - "typemap", - "url", -] - [[package]] name = "num_cpus" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", "libc", @@ -582,12 +550,6 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "pin-project-lite" version = "0.1.4" @@ -596,18 +558,9 @@ checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" [[package]] name = "pin-utils" -version = "0.1.0-alpha.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" - -[[package]] -name = "plugin" -version = "0.2.6" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" -dependencies = [ - "typemap", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro-hack" @@ -621,13 +574,31 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.0", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", ] [[package]] @@ -636,44 +607,135 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.10", ] [[package]] -name = "redox_syscall" -version = "0.1.56" +name = "rand" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.7", + "libc", + "rand_chacha", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.8", +] [[package]] -name = "regex" -version = "1.3.6" +name = "rand_chacha" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", + "autocfg 0.1.7", + "rand_core 0.3.1", ] [[package]] -name = "regex-syntax" -version = "0.6.17" +name = "rand_core" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] [[package]] -name = "ryu" -version = "1.0.3" +name = "rand_core" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] -name = "safemem" -version = "0.3.3" +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi 0.3.8", +] + +[[package]] +name = "rand_os" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.8", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "ryu" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "scopeguard" @@ -687,17 +749,38 @@ version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" +[[package]] +name = "serde_derive" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.18", +] + [[package]] name = "serde_json" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" +checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "signal-hook-registry" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +dependencies = [ + "arc-swap", + "libc", +] + [[package]] name = "slab" version = "0.4.2" @@ -706,9 +789,24 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.3.0" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +dependencies = [ + "maybe-uninit", +] + +[[package]] +name = "socket2" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] [[package]] name = "strsim" @@ -718,13 +816,33 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "1.0.17" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" +dependencies = [ + "proc-macro2 1.0.10", + "quote 1.0.3", + "unicode-xid 0.2.0", +] + +[[package]] +name = "templatify" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a528032d6917c9a80cf894d9feeffe34056e8d62d3492bbfc15abfdcfa8a8fe1" +dependencies = [ + "bytes 0.4.12", ] [[package]] @@ -737,36 +855,78 @@ dependencies = [ ] [[package]] -name = "thread_local" -version = "1.0.1" +name = "thruster" +version = "0.9.0-alpha.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe496baf41937762dacdd775eb4845b8ad4feaab4ec84bc3b1904cb676812b1d" +dependencies = [ + "async-trait", + "bytes 0.5.4", + "futures 0.1.29", + "futures 0.3.4", + "http 0.1.21", + "http 0.2.1", + "httparse", + "lazy_static", + "log", + "net2", + "num_cpus", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "templatify", + "thruster-proc", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "thruster-proc" +version = "0.9.0-alpha.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +checksum = "e3c64b3abf028f665e872d305c74016c109f8b0ef9d471914db1e44e9117e729" dependencies = [ "lazy_static", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", + "uuid", ] [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall", "winapi 0.3.8", ] [[package]] name = "tokio" -version = "0.2.5" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fb0a0dab58ae3db3832810b2aabb98dd42be27c04e7f7f1ae3a6ac78f858d1" +checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713" dependencies = [ - "bytes", + "bytes 0.5.4", "fnv", + "futures-core", + "iovec", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-named-pipes", + "mio-uds", + "num_cpus", "pin-project-lite", + "signal-hook-registry", "slab", "tokio-macros", + "winapi 0.3.8", ] [[package]] @@ -775,57 +935,23 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - -[[package]] -name = "typemap" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" -dependencies = [ - "unsafe-any", -] - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", + "proc-macro2 1.0.10", + "quote 1.0.3", + "syn 1.0.18", ] [[package]] -name = "unicode-normalization" -version = "0.1.12" +name = "tokio-util" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" dependencies = [ - "smallvec", + "bytes 0.5.4", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", ] [[package]] @@ -836,28 +962,23 @@ checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] -name = "unsafe-any" -version = "0.4.2" +name = "unicode-xid" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" -dependencies = [ - "traitobject", -] +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] -name = "url" -version = "1.7.2" +name = "uuid" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" dependencies = [ - "idna", - "matches", - "percent-encoding", + "rand", ] [[package]] @@ -866,12 +987,6 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index e33330e..0c2dba9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,11 +7,12 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -juno = { path = "../juno-rust/" } +juno = "0.1" lazy_static = "1.4.0" clap = "2.33.0" futures = "0.3.4" -nickel = "0.11.0" +thruster = "0.9.0-alpha.8" +bytes = "0.5.4" [dependencies.tokio] version = "0.2.5" diff --git a/src/cli_parser.rs b/src/cli_parser.rs index 5954ff4..678a9b4 100644 --- a/src/cli_parser.rs +++ b/src/cli_parser.rs @@ -86,4 +86,4 @@ pub fn from_cli_args() -> JunoModule { ) } } -} \ No newline at end of file +} diff --git a/src/http_config.rs b/src/http_config.rs index ba11f9f..02e0c62 100644 --- a/src/http_config.rs +++ b/src/http_config.rs @@ -1,6 +1,3 @@ -use juno::models::Value; -use nickel::{hyper::net::Fresh, Middleware, MiddlewareResult, Request, Response}; - #[derive(Clone)] pub struct HttpConfig { pub config_type: MiddlewareType, @@ -16,19 +13,19 @@ pub enum MiddlewareType { Patch, Post, Put, - Use -} - -pub struct MiddlewareContext { - pub data: Value, + Use, } -impl Middleware for HttpConfig { - fn invoke<'mw, 'conn>( - &'mw self, - _req: &mut Request<'mw, 'conn, MiddlewareContext>, - res: Response<'mw, MiddlewareContext, Fresh>, - ) -> MiddlewareResult<'mw, MiddlewareContext> { - res.next_middleware() +impl MiddlewareType { + pub fn to_capitalized_string(&self) -> &str { + match self { + MiddlewareType::Delete => "DELETE", + MiddlewareType::Get => "GET", + MiddlewareType::Options => "OPTIONS", + MiddlewareType::Patch => "PATCH", + MiddlewareType::Post => "POST", + MiddlewareType::Put => "PUT", + MiddlewareType::Use => "USE", + } } } diff --git a/src/http_context.rs b/src/http_context.rs new file mode 100644 index 0000000..23613bb --- /dev/null +++ b/src/http_context.rs @@ -0,0 +1,169 @@ +use crate::HttpConfig; + +use bytes::Bytes; +use juno::models::Value; +use std::{collections::HashMap, str}; +use thruster::{ + middleware::{ + cookies::{Cookie, CookieOptions, HasCookies, SameSite}, + query_params::HasQueryParams, + }, + Context, + Request, + Response, +}; + +pub struct HttpContext { + response: Response, + cookies: Vec, + params: HashMap, + query_params: HashMap, + request: Request, + status: u32, + headers: HashMap, + matched_route: String, + pub data: Value, + pub route_configs: Vec, +} + +impl HttpContext { + pub fn new(request: Request, matched_route: String, route_configs: Vec) -> Self { + let body = request.body().to_string(); + let mut context = HttpContext { + response: Response::new(), + cookies: Vec::new(), + params: request.params().clone(), + query_params: HashMap::new(), + headers: request.headers().clone(), + request, + status: 200, + matched_route, + data: Value::Null, + route_configs, + }; + context.body(&body); + context.set("Server", "Thruster"); + + context + } + + pub fn matched_route(&self) -> &String { + &self.matched_route + } + + pub fn body(&mut self, body_string: &str) { + self.response + .body_bytes_from_vec(body_string.as_bytes().to_vec()); + } + pub fn get_body(&self) -> String { + str::from_utf8(&self.response.response) + .unwrap_or("") + .to_owned() + } + + pub fn status(&mut self, code: u32) { + self.status = code; + } + + pub fn set_content_type(&mut self, c_type: &str) { + self.set("Content-Type", c_type); + } + + pub fn redirect(&mut self, destination: &str) { + self.status(302); + + self.set("Location", destination); + } + + pub fn method(&self) -> &str { + &self.request.method() + } + + pub fn set_cookie(&mut self, name: &str, value: &str, options: &CookieOptions) { + let cookie_value = match self.headers.get("Set-Cookie") { + Some(val) => format!("{}, {}", val, self.cookify_options(name, value, &options)), + None => self.cookify_options(name, value, &options), + }; + + self.set("Set-Cookie", &cookie_value); + } + + fn cookify_options(&self, name: &str, value: &str, options: &CookieOptions) -> String { + let mut pieces = vec![format!("Path={}", options.path)]; + + if options.expires > 0 { + pieces.push(format!("Expires={}", options.expires)); + } + + if options.max_age > 0 { + pieces.push(format!("Max-Age={}", options.max_age)); + } + + if !options.domain.is_empty() { + pieces.push(format!("Domain={}", options.domain)); + } + + if options.secure { + pieces.push("Secure".to_owned()); + } + + if options.http_only { + pieces.push("HttpOnly".to_owned()); + } + + if let Some(ref same_site) = options.same_site { + match same_site { + SameSite::Strict => pieces.push("SameSite=Strict".to_owned()), + SameSite::Lax => pieces.push("SameSite=Lax".to_owned()), + }; + } + + format!("{}={}; {}", name, value, pieces.join(", ")) + } +} + +impl Context for HttpContext { + type Response = Response; + + fn get_response(mut self) -> Self::Response { + self.response.status_code(self.status, ""); + + self.response + } + + fn set_body(&mut self, body: Vec) { + self.response.body_bytes_from_vec(body); + } + + fn set_body_bytes(&mut self, body_bytes: Bytes) { + self.response.body_bytes(&body_bytes); + } + + fn route(&self) -> &str { + self.request.path() + } + + fn set(&mut self, key: &str, value: &str) { + self.headers.insert(key.to_owned(), value.to_owned()); + } + + fn remove(&mut self, key: &str) { + self.headers.remove(key); + } +} + +impl HasQueryParams for HttpContext { + fn set_query_params(&mut self, query_params: HashMap) { + self.query_params = query_params; + } +} + +impl HasCookies for HttpContext { + fn set_cookies(&mut self, cookies: Vec) { + self.cookies = cookies; + } + + fn headers(&self) -> HashMap { + self.request.headers() + } +} diff --git a/src/main.rs b/src/main.rs index 899cbb9..da4c2cc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,32 +1,36 @@ #[macro_use] extern crate lazy_static; +extern crate bytes; extern crate clap; extern crate futures; extern crate juno; -extern crate nickel; +extern crate thruster; extern crate tokio; mod cli_parser; mod http_config; +mod http_context; mod server; use http_config::HttpConfig; -use std::collections::HashMap; -use std::sync::Mutex; -use std::time::Duration; +use std::{collections::HashMap, sync::Mutex, time::Duration}; -use nickel::ListeningServer; +use thruster::Server; use clap::{crate_name, crate_version}; lazy_static! { pub static ref HTTP_CONFIG: Mutex> = Mutex::new(Vec::new()); - pub static ref LISTENER: Mutex> = Mutex::new(None); + pub static ref LISTENER: Mutex>> = + Mutex::new(None); } -#[tokio::main] -async fn main() { +//#[tokio::main] +fn main() { + server::listen(HashMap::new()); + + /* let mut module = cli_parser::from_cli_args(); module .initialize(crate_name!(), crate_version!(), HashMap::new()) @@ -72,7 +76,20 @@ async fn main() { .await .unwrap(); + module + .call_function("logger.verbose", { + let mut map = HashMap::new(); + map.insert( + "data".to_owned(), + juno::models::Value::String("Some data here".to_owned()), + ); + map + }) + .await + .unwrap(); + loop { tokio::time::delay_for(Duration::from_millis(1000)).await; } + */ } diff --git a/src/server.rs b/src/server.rs index e3f5c60..2d7d090 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,11 +1,16 @@ -use crate::http_config::MiddlewareType; -use crate::http_config::HttpConfig; -use crate::http_config::MiddlewareContext; +use crate::{ + http_config::{HttpConfig, MiddlewareType}, + http_context::HttpContext, +}; use std::collections::HashMap; +use juno::models::Number; use juno::models::Value; -use nickel::{Nickel, HttpRouter}; +use thruster::{ + async_middleware, middleware_fn, App, Context, MiddlewareNext, MiddlewareResult, Request, + Server, ThrusterServer, +}; pub fn app_delete(args: HashMap) -> Value { let value = Value::String(String::from("/")); @@ -176,7 +181,7 @@ pub fn app_use(args: HashMap) -> Value { } pub fn listen(args: HashMap) -> Value { - let mut http_listener = crate::LISTENER.lock().unwrap(); + let http_listener = crate::LISTENER.lock().unwrap(); let http_config = crate::HTTP_CONFIG.lock().unwrap(); if http_listener.is_some() { @@ -185,35 +190,38 @@ pub fn listen(args: HashMap) -> Value { panic!("Excuse me wtf?"); } - let mut server = Nickel::with_data(MiddlewareContext { - data: Value::Null - }); + let mut app = + App::>::create(generate_context, http_config.clone()); + app.use_middleware("/", async_middleware!(HttpContext, [handle_middleware])); for config in http_config.iter() { + let path = config.path.clone(); + let path = Box::leak(path.into_boxed_str()); match &config.config_type { MiddlewareType::Delete => { - server.delete::(config.path.clone(), config.clone()); - }, + app.delete(path, async_middleware!(HttpContext, [handle_data])); + } MiddlewareType::Get => { - server.get::(config.path.clone(), config.clone()); - }, + app.get(path, async_middleware!(HttpContext, [handle_data])); + } MiddlewareType::Options => { - server.options::(config.path.clone(), config.clone()); - }, + app.options(path, async_middleware!(HttpContext, [handle_data])); + } MiddlewareType::Patch => { - server.patch::(config.path.clone(), config.clone()); - }, + app.update(path, async_middleware!(HttpContext, [handle_data])); + } MiddlewareType::Post => { - server.post::(config.path.clone(), config.clone()); - }, + app.post(path, async_middleware!(HttpContext, [handle_data])); + } MiddlewareType::Put => { - server.put::(config.path.clone(), config.clone()); - }, - MiddlewareType::Use => { - server.utilize::(config.clone()); - }, + app.put(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Use => {} } } + app.set404(async_middleware!(HttpContext, [handle_404])); + + let server = Server::new(app); // Populate `server` from HTTP_CONFIG // Setup routers and middlwares accordingly @@ -222,12 +230,25 @@ pub fn listen(args: HashMap) -> Value { return Value::Null; } - let listener = server - .listen(args.get("socket").unwrap().as_string().unwrap()) - .unwrap(); + tokio::spawn(async move { + server + .build( + args.get("socket") + .unwrap_or(&Value::String("127.0.0.1".to_string())) + .as_string() + .unwrap_or(&String::from("127.0.0.1")), + args.get("port") + .unwrap_or(&Value::Number(Number::PosInt(3000))) + .as_number() + .unwrap_or(&Number::PosInt(3000)) + .as_u64() + .unwrap_or(3000) as u16, + ) + .await; + }); // Add `listener` to a global mutex like HTTP_CONFIG // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one - *http_listener = Some(listener); + //*http_listener = Some(server); Value::Null } @@ -235,4 +256,52 @@ pub fn listen(args: HashMap) -> Value { pub fn clear_config(_args: HashMap) -> Value { crate::HTTP_CONFIG.lock().unwrap().clear(); Value::Null -} \ No newline at end of file +} + +fn generate_context(request: Request, state: &Vec, path: &str) -> HttpContext { + let start = request.method().len() + 4; + let matched_route = String::from(&path[start..]); + + HttpContext::new(request, matched_route, state.clone()) +} + +#[middleware_fn] +async fn handle_data( + mut context: HttpContext, + next: MiddlewareNext, +) -> MiddlewareResult { + let fn_name = context + .route_configs + .iter() + .filter(|config| { + context.method() == config.config_type.to_capitalized_string() + && context.matched_route() == &config.path + }) + .next(); + if fn_name.is_none() { + return next(context).await; + } + let fn_name = fn_name.unwrap(); + // TODO get an instance to juno module from here and call the function + + Ok(context) +} + +#[middleware_fn] +async fn handle_middleware( + context: HttpContext, + next: MiddlewareNext, +) -> MiddlewareResult { + println!("Got middleware on {}", context.matched_route()); + next(context).await +} + +#[middleware_fn] +async fn handle_404( + mut context: HttpContext, + _next: MiddlewareNext, +) -> MiddlewareResult { + context.status(404); + context.body(&format!("Cannot {} {}", context.method(), context.route())); + Ok(context) +} From 7b759e19ce016abfd47ec1c86804782e3ed70123 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Wed, 29 Apr 2020 02:18:43 +0530 Subject: [PATCH 8/9] Added basic working version. TODO more, especially in the middleware section --- Cargo.lock | 19 +- Cargo.toml | 5 +- src/cli_parser.rs | 89 --------- src/http_context.rs | 126 ++++++++++++- src/http_server.rs | 193 ++++++++++++++++++++ src/juno_module.rs | 263 +++++++++++++++++++++++++++ src/main.rs | 91 ++-------- src/{http_config.rs => misc.rs} | 15 ++ src/server.rs | 307 -------------------------------- 9 files changed, 614 insertions(+), 494 deletions(-) delete mode 100644 src/cli_parser.rs create mode 100644 src/http_server.rs create mode 100644 src/juno_module.rs rename src/{http_config.rs => misc.rs} (62%) delete mode 100644 src/server.rs diff --git a/Cargo.lock b/Cargo.lock index 34f3f66..8fb07eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,9 +322,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" +checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" dependencies = [ "libc", ] @@ -338,6 +338,7 @@ dependencies = [ "futures 0.3.4", "juno", "lazy_static", + "serde_json", "thruster", "tokio", ] @@ -388,8 +389,6 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "juno" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30daf3321be539ae2c45992f6309ae78d98844f40f34b448bbabb2ae554415be" dependencies = [ "async-std", "async-trait", @@ -762,9 +761,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" +checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" dependencies = [ "itoa", "ryu", @@ -856,9 +855,9 @@ dependencies = [ [[package]] name = "thruster" -version = "0.9.0-alpha.8" +version = "0.9.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe496baf41937762dacdd775eb4845b8ad4feaab4ec84bc3b1904cb676812b1d" +checksum = "de8331fef1fd6a44c4fe3e1bd93f905a237594c3fb7f733b28d8af08b133f011" dependencies = [ "async-trait", "bytes 0.5.4", @@ -907,9 +906,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713" +checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c" dependencies = [ "bytes 0.5.4", "fnv", diff --git a/Cargo.toml b/Cargo.toml index 0c2dba9..fa61811 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,12 +7,13 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -juno = "0.1" -lazy_static = "1.4.0" +juno = { path = "../juno-rust" } clap = "2.33.0" futures = "0.3.4" thruster = "0.9.0-alpha.8" bytes = "0.5.4" +lazy_static = "1.4.0" +serde_json = "1.0.52" [dependencies.tokio] version = "0.2.5" diff --git a/src/cli_parser.rs b/src/cli_parser.rs deleted file mode 100644 index 678a9b4..0000000 --- a/src/cli_parser.rs +++ /dev/null @@ -1,89 +0,0 @@ -use clap::{crate_authors, crate_name, crate_version, App, Arg}; -use juno::JunoModule; - -#[allow(clippy::collapsible_if)] -pub fn from_cli_args() -> JunoModule { - let args = App::new(crate_name!()) - .version(crate_version!()) - .author(crate_authors!()) - .about("Http module") - .arg( - Arg::with_name("socket-location") - .conflicts_with("port") - .conflicts_with("host") - .short("s") - .long("socket-location") - .takes_value(true) - .value_name("FILE") - .help("Sets the location of the socket to connect"), - ) - .arg( - Arg::with_name("port") - .conflicts_with("socket-location") - .short("p") - .long("port") - .takes_value(true) - .value_name("PORT") - .help("Sets the port for the socket to connect to"), - ) - .arg( - Arg::with_name("host") - .conflicts_with("socket-location") - .short("h") - .long("host") - .takes_value(true) - .value_name("HOST-IP") - .help("Sets the host address for the socket to connect"), - ) - .arg( - Arg::with_name("V") - .short("V") - .multiple(true) - .help("Sets the level of verbosity (max 3)"), - ) - .arg( - Arg::with_name("version") - .short("v") - .long("version") - .help("Prints version information"), - ) - .get_matches(); - - if args.is_present("version") { - println!("{}", crate_version!()); - panic!(); - } - - let mut default_socket_location = std::env::current_dir().unwrap(); - default_socket_location.push(args.value_of("socket-location").unwrap_or("../juno.sock")); - let default_socket_location = default_socket_location.as_os_str().to_str().unwrap(); - - if cfg!(target_family = "windows") { - if args.value_of("socket-location").is_some() { - panic!("Listening on unix sockets are not supported on windows"); - } else { - JunoModule::from_inet_socket( - args.value_of("host").unwrap_or("127.0.0.1"), - args.value_of("port") - .unwrap_or("2203") - .parse::() - .unwrap(), - ) - } - } else { - if args.value_of("port").is_some() { - JunoModule::from_inet_socket( - args.value_of("host").unwrap_or("127.0.0.1"), - args.value_of("port") - .unwrap_or("2203") - .parse::() - .unwrap(), - ) - } else { - JunoModule::from_unix_socket( - args.value_of("socket-location") - .unwrap_or(default_socket_location), - ) - } - } -} diff --git a/src/http_context.rs b/src/http_context.rs index 23613bb..822289a 100644 --- a/src/http_context.rs +++ b/src/http_context.rs @@ -1,17 +1,16 @@ -use crate::HttpConfig; - +use crate::{misc::JunoCommands, HttpConfig}; use bytes::Bytes; use juno::models::Value; +use serde_json::from_str; use std::{collections::HashMap, str}; use thruster::{ middleware::{ cookies::{Cookie, CookieOptions, HasCookies, SameSite}, query_params::HasQueryParams, }, - Context, - Request, - Response, + Context, Request, Response, }; +use tokio::sync::mpsc::UnboundedSender; pub struct HttpContext { response: Response, @@ -22,27 +21,40 @@ pub struct HttpContext { status: u32, headers: HashMap, matched_route: String, + http_version: u8, + juno_representation: HashMap, + pub http_configs: Vec, + pub juno_sender: UnboundedSender, pub data: Value, - pub route_configs: Vec, } impl HttpContext { - pub fn new(request: Request, matched_route: String, route_configs: Vec) -> Self { + pub fn new( + request: Request, + matched_route: String, + http_configs: Vec, + juno_sender: UnboundedSender, + ) -> Self { let body = request.body().to_string(); + let http_version = request.version(); let mut context = HttpContext { response: Response::new(), cookies: Vec::new(), params: request.params().clone(), query_params: HashMap::new(), - headers: request.headers().clone(), + headers: request.headers(), request, status: 200, matched_route, + http_version, + juno_representation: HashMap::new(), + http_configs, + juno_sender, data: Value::Null, - route_configs, }; context.body(&body); context.set("Server", "Thruster"); + context.generate_juno_representation(); context } @@ -67,6 +79,16 @@ impl HttpContext { pub fn set_content_type(&mut self, c_type: &str) { self.set("Content-Type", c_type); + + if c_type == "application/json" { + let body: serde_json::Value = + from_str(&self.get_body()).unwrap_or(serde_json::Value::Null); + self.juno_representation + .insert(String::from("body"), From::from(body)); + } else { + self.juno_representation + .insert(String::from("body"), Value::String(self.get_body())); + } } pub fn redirect(&mut self, destination: &str) { @@ -79,6 +101,89 @@ impl HttpContext { &self.request.method() } + pub fn http_version(&self) -> u8 { + self.http_version + } + + pub fn juno_representation(&self) -> &HashMap { + &self.juno_representation + } + + pub fn generate_juno_representation(&mut self) { + let mut map = HashMap::new(); + + map.insert( + String::from("httpVersion"), + Value::String(format!("{}", self.http_version())), + ); + + map.insert( + String::from("headers"), + Value::Object( + self.headers + .iter() + .map(|item| (item.0.clone(), Value::String(item.1.clone()))) + .collect(), + ), + ); + + let mut raw_headers: Vec = vec![]; + let _ = self.headers.iter().map(|item| { + raw_headers.push(Value::String(item.0.clone())); + raw_headers.push(Value::String(item.1.clone())); + }); + map.insert(String::from("rawHeaders"), Value::Array(raw_headers)); + + map.insert(String::from("url"), Value::String(self.route().to_string())); + map.insert( + String::from("method"), + Value::String(self.method().to_string()), + ); + + map.insert( + String::from("params"), + Value::Object( + self.params + .iter() + .map(|item| (item.0.clone(), Value::String(item.1.clone()))) + .collect(), + ), + ); + + map.insert( + String::from("query"), + Value::Object( + self.query_params + .iter() + .map(|item| (item.0.clone(), Value::String(item.1.clone()))) + .collect(), + ), + ); + + map.insert( + String::from("cookies"), + Value::Object( + self.cookies + .iter() + .map(|item| (item.key.clone(), Value::String(item.value.clone()))) + .collect(), + ), + ); + + match self.headers.get("Content-Type") { + Some(value) if value == "application/json" => { + let body: serde_json::Value = + from_str(&self.get_body()).unwrap_or(serde_json::Value::Null); + map.insert(String::from("body"), From::from(body)); + } + _ => { + map.insert(String::from("body"), Value::String(self.get_body())); + } + }; + + self.juno_representation = map; + } + pub fn set_cookie(&mut self, name: &str, value: &str, options: &CookieOptions) { let cookie_value = match self.headers.get("Set-Cookie") { Some(val) => format!("{}, {}", val, self.cookify_options(name, value, &options)), @@ -145,6 +250,9 @@ impl Context for HttpContext { fn set(&mut self, key: &str, value: &str) { self.headers.insert(key.to_owned(), value.to_owned()); + if let Value::Object(map) = self.juno_representation.get_mut("headers").unwrap() { + map.insert(key.to_string(), Value::String(value.to_string())); + } } fn remove(&mut self, key: &str) { diff --git a/src/http_server.rs b/src/http_server.rs new file mode 100644 index 0000000..f720a0c --- /dev/null +++ b/src/http_server.rs @@ -0,0 +1,193 @@ +use crate::{ + http_context::HttpContext, + misc::{HttpConfig, HttpServerCommands, JunoCommands, MiddlewareType}, +}; +use futures::StreamExt; +use juno::{ + models::{Number, Value}, + Result, +}; +use std::net::SocketAddr; +use thruster::{ + async_middleware, middleware_fn, App, Context, MiddlewareNext, MiddlewareResult, Request, + Server, ThrusterServer, +}; +use tokio::sync::{ + mpsc::{UnboundedReceiver, UnboundedSender}, + oneshot::channel, +}; + +pub async fn http_loop( + mut http_receiver: UnboundedReceiver, + juno_sender: UnboundedSender, +) { + let mut http_config: Vec = vec![]; + while let Some(command) = http_receiver.next().await { + match command { + HttpServerCommands::AddConfig(config) => { + http_config.push(config); + } + HttpServerCommands::ClearConfig => { + http_config.clear(); + } + HttpServerCommands::Listen(socket_addr) => { + create_http_server(socket_addr, http_config.clone(), juno_sender.clone()) + } + } + } +} + +fn create_http_server( + socket_addr: SocketAddr, + http_config: Vec, + juno_sender: UnboundedSender, +) { + let mut app = + App::, UnboundedSender)>::create( + generate_context, + (http_config.clone(), juno_sender), + ); + app.use_middleware("/", async_middleware!(HttpContext, [handle_middleware])); + + for config in http_config.iter() { + let path = &config.path; + match &config.config_type { + MiddlewareType::Delete => { + app.delete(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Get => { + app.get(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Options => { + app.options(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Patch => { + app.patch(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Post => { + app.post(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Put => { + app.put(path, async_middleware!(HttpContext, [handle_data])); + } + MiddlewareType::Use => {} + } + } + + let server = Server::new(app); + server.start(&format!("{}", socket_addr.ip()), socket_addr.port()); +} + +fn generate_context( + request: Request, + state: &(Vec, UnboundedSender), + path: &str, +) -> HttpContext { + let start = request.method().len() + 4; + let matched_route = String::from(&path[start..]); + + HttpContext::new(request, matched_route, state.0.clone(), state.1.clone()) +} + +#[middleware_fn] +async fn handle_data( + mut context: HttpContext, + next: MiddlewareNext, +) -> MiddlewareResult { + let fn_name = context.http_configs.iter().find(|config| { + context.method() == config.config_type.to_capitalized_string() + && context.matched_route() == &config.path + }); + if fn_name.is_none() { + return next(context).await; + } + let fn_name = &fn_name.unwrap().func_name; + + let (sender, receiver) = channel::>(); + + let result = context.juno_sender.send(JunoCommands::CallFunction( + fn_name.clone(), + context.juno_representation().clone(), + sender, + )); + if result.is_err() { + println!( + "Error sending command across channels: {}", + result.unwrap_err() + ); + return next(context).await; + } + + let response = receiver.await; + if response.is_err() { + println!( + "Error receiving command across channels: {}", + response.unwrap_err() + ); + return next(context).await; + } + let response = response.unwrap(); + if response.is_err() { + println!("Error calling function on juno: {}", response.unwrap_err()); + return next(context).await; + } + let response = response.unwrap(); + + if response.as_object().is_none() { + println!("Didn't get back object from function response"); + return next(context).await; + } + let response = response.as_object().unwrap(); + + if response.get("next") == Some(&Value::Bool(true)) { + if response.get("data").is_some() { + context.data = response.get("data").unwrap().clone(); + } + next(context).await + } else { + if let Some(content_type) = response.get("contentType") { + context.set_content_type( + content_type + .as_string() + .unwrap_or(&String::from("text/html")), + ); + } + + if let Some(Value::Object(headers)) = response.get("headers") { + let _ = headers.iter().map(|item| { + if item.1.is_string() { + context.set(item.0, item.1.as_string().unwrap()); + } + }); + } + + if let Some(Value::Number(Number::PosInt(num))) = response.get("status") { + context.status(*num as u32); + } + + if let Some(json) = response.get("json") { + context.set_content_type("application/json"); + let json: serde_json::Value = json.clone().into(); + context.body(&json.to_string()); + } else { + context.body( + response + .get("body") + .unwrap_or(&Value::Null) + .as_string() + .unwrap_or(&String::from("")), + ); + } + + Ok(context) + } +} + +#[middleware_fn] +async fn handle_middleware( + context: HttpContext, + next: MiddlewareNext, +) -> MiddlewareResult { + println!("Got middleware on {}", context.matched_route()); + next(context).await +} diff --git a/src/juno_module.rs b/src/juno_module.rs new file mode 100644 index 0000000..60983ee --- /dev/null +++ b/src/juno_module.rs @@ -0,0 +1,263 @@ +use crate::misc::{HttpConfig, HttpServerCommands, JunoCommands, MiddlewareType}; +use clap::{crate_authors, crate_name, crate_version, App, Arg}; +use futures::StreamExt; +use juno::{ + models::{Number, Value}, + JunoModule, +}; +use std::{ + collections::HashMap, + net::{IpAddr, Ipv4Addr, SocketAddr}, +}; +use tokio::{ + runtime::Runtime, + sync::{ + mpsc::{UnboundedReceiver, UnboundedSender}, + Mutex, + }, +}; + +lazy_static! { + static ref HTTP_SENDER: Mutex>> = Mutex::new(None); +} + +#[allow(clippy::collapsible_if)] +fn from_cli_args() -> JunoModule { + let args = App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!()) + .about("Http module") + .arg( + Arg::with_name("socket-location") + .conflicts_with("port") + .conflicts_with("host") + .short("s") + .long("socket-location") + .takes_value(true) + .value_name("FILE") + .help("Sets the location of the socket to connect"), + ) + .arg( + Arg::with_name("port") + .conflicts_with("socket-location") + .short("p") + .long("port") + .takes_value(true) + .value_name("PORT") + .help("Sets the port for the socket to connect to"), + ) + .arg( + Arg::with_name("host") + .conflicts_with("socket-location") + .short("h") + .long("host") + .takes_value(true) + .value_name("HOST-IP") + .help("Sets the host address for the socket to connect"), + ) + .arg( + Arg::with_name("V") + .short("V") + .multiple(true) + .help("Sets the level of verbosity (max 3)"), + ) + .arg( + Arg::with_name("version") + .short("v") + .long("version") + .help("Prints version information"), + ) + .get_matches(); + + if args.is_present("version") { + println!("{}", crate_version!()); + panic!(); + } + + let mut default_socket_location = std::env::current_dir().unwrap(); + default_socket_location.push(args.value_of("socket-location").unwrap_or("../juno.sock")); + let default_socket_location = default_socket_location.as_os_str().to_str().unwrap(); + + if cfg!(target_family = "windows") { + if args.value_of("socket-location").is_some() { + panic!("Listening on unix sockets are not supported on windows"); + } else { + JunoModule::from_inet_socket( + args.value_of("host").unwrap_or("127.0.0.1"), + args.value_of("port") + .unwrap_or("2203") + .parse::() + .unwrap(), + ) + } + } else { + if args.value_of("port").is_some() { + JunoModule::from_inet_socket( + args.value_of("host").unwrap_or("127.0.0.1"), + args.value_of("port") + .unwrap_or("2203") + .parse::() + .unwrap(), + ) + } else { + JunoModule::from_unix_socket( + args.value_of("socket-location") + .unwrap_or(default_socket_location), + ) + } + } +} + +pub async fn juno_loop( + mut juno_receiver: UnboundedReceiver, + http_sender: UnboundedSender, +) { + HTTP_SENDER.lock().await.replace(http_sender); + + let mut module = from_cli_args(); + module + .initialize(crate_name!(), crate_version!(), HashMap::new()) + .await + .unwrap(); + + module + .declare_function("delete", |args| { + add_app_command(MiddlewareType::Delete, args) + }) + .await + .unwrap(); + module + .declare_function("get", |args| add_app_command(MiddlewareType::Get, args)) + .await + .unwrap(); + module + .declare_function("options", |args| { + add_app_command(MiddlewareType::Options, args) + }) + .await + .unwrap(); + module + .declare_function("patch", |args| add_app_command(MiddlewareType::Patch, args)) + .await + .unwrap(); + module + .declare_function("post", |args| add_app_command(MiddlewareType::Post, args)) + .await + .unwrap(); + module + .declare_function("put", |args| add_app_command(MiddlewareType::Put, args)) + .await + .unwrap(); + module + .declare_function("use", |args| add_app_command(MiddlewareType::Use, args)) + .await + .unwrap(); + + module + .declare_function("listen", listen_command) + .await + .unwrap(); + + module + .declare_function("clearConfig", clear_app_config) + .await + .unwrap(); + while let Some(data) = juno_receiver.next().await { + match data { + JunoCommands::CallFunction(function_name, args, response_sender) => { + let result = response_sender.send(module.call_function(&function_name, args).await); + if result.is_err() { + println!( + "Error sending function_call response: {:#?}", + result.unwrap_err() + ); + } + } + JunoCommands::TriggerHook(hook_name) => { + let result = module.trigger_hook(&hook_name).await; + if result.is_err() { + println!("Error triggering hook: {}", result.unwrap_err()); + } + } + } + } +} + +fn add_app_command(middleware_type: MiddlewareType, args: HashMap) -> Value { + Runtime::new().unwrap().block_on(async { + let sender = HTTP_SENDER.lock().await; + let sender = sender.as_ref().unwrap(); + + let string = Value::String("/".to_string()); + let path = String::from("/"); + let path = args + .get("path") + .unwrap_or(&string) + .as_string() + .unwrap_or(&path); + + let func_name = args.get("function").unwrap_or(&Value::Null).as_string(); + if func_name.is_none() { + return; + } + + let result = sender.send(HttpServerCommands::AddConfig(HttpConfig { + config_type: middleware_type, + func_name: func_name.unwrap().clone(), + path: path.clone(), + })); + if result.is_err() { + println!("Error sending add-config command: {}", result.unwrap_err()); + } + }); + Value::Null +} + +fn listen_command(args: HashMap) -> Value { + Runtime::new().unwrap().block_on(async { + let sender = HTTP_SENDER.lock().await; + let sender = sender.as_ref().unwrap(); + + let string = Value::String("127.0.0.1".to_string()); + let socket = String::from("127.0.0.1"); + let socket = args + .get("socket") + .unwrap_or(&string) + .as_string() + .unwrap_or(&socket); + + let port = args + .get("port") + .unwrap_or(&Value::Number(Number::PosInt(3000))) + .as_number() + .unwrap_or(&Number::PosInt(3000)) + .as_u64() + .unwrap_or(3000) as u16; + + let result = sender.send(HttpServerCommands::Listen(SocketAddr::new( + socket.parse().unwrap_or(IpAddr::V4(Ipv4Addr::LOCALHOST)), + port, + ))); + if result.is_err() { + println!("Error sending listen command: {}", result.unwrap_err()); + } + }); + Value::Null +} + +fn clear_app_config(_: HashMap) -> Value { + let result = Runtime::new() + .unwrap() + .block_on(HTTP_SENDER.lock()) + .as_ref() + .unwrap() + .send(HttpServerCommands::ClearConfig); + + if result.is_err() { + println!( + "Error sending clear-config command: {}", + result.unwrap_err() + ); + } + Value::Null +} diff --git a/src/main.rs b/src/main.rs index da4c2cc..845690d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,92 +4,29 @@ extern crate bytes; extern crate clap; extern crate futures; extern crate juno; +extern crate serde_json; extern crate thruster; extern crate tokio; -mod cli_parser; -mod http_config; mod http_context; -mod server; +mod http_server; +mod juno_module; +mod misc; -use http_config::HttpConfig; +use misc::{HttpConfig, HttpServerCommands, JunoCommands}; -use std::{collections::HashMap, sync::Mutex, time::Duration}; +use std::time::Duration; +use tokio::{sync::mpsc, time}; -use thruster::Server; +#[tokio::main] +async fn main() { + let (juno_sender, juno_receiver) = mpsc::unbounded_channel::(); + let (http_sender, http_receiver) = mpsc::unbounded_channel::(); -use clap::{crate_name, crate_version}; - -lazy_static! { - pub static ref HTTP_CONFIG: Mutex> = Mutex::new(Vec::new()); - pub static ref LISTENER: Mutex>> = - Mutex::new(None); -} - -//#[tokio::main] -fn main() { - server::listen(HashMap::new()); - - /* - let mut module = cli_parser::from_cli_args(); - module - .initialize(crate_name!(), crate_version!(), HashMap::new()) - .await - .unwrap(); - - module - .declare_function("delete", server::app_delete) - .await - .unwrap(); - module - .declare_function("get", server::app_get) - .await - .unwrap(); - module - .declare_function("options", server::app_options) - .await - .unwrap(); - module - .declare_function("patch", server::app_patch) - .await - .unwrap(); - module - .declare_function("post", server::app_post) - .await - .unwrap(); - module - .declare_function("put", server::app_put) - .await - .unwrap(); - module - .declare_function("use", server::app_use) - .await - .unwrap(); - - module - .declare_function("listen", server::listen) - .await - .unwrap(); - - module - .declare_function("clearConfig", server::clear_config) - .await - .unwrap(); - - module - .call_function("logger.verbose", { - let mut map = HashMap::new(); - map.insert( - "data".to_owned(), - juno::models::Value::String("Some data here".to_owned()), - ); - map - }) - .await - .unwrap(); + tokio::spawn(juno_module::juno_loop(juno_receiver, http_sender)); + tokio::spawn(http_server::http_loop(http_receiver, juno_sender)); loop { - tokio::time::delay_for(Duration::from_millis(1000)).await; + time::delay_for(Duration::from_millis(1000)).await; } - */ } diff --git a/src/http_config.rs b/src/misc.rs similarity index 62% rename from src/http_config.rs rename to src/misc.rs index 02e0c62..f13c457 100644 --- a/src/http_config.rs +++ b/src/misc.rs @@ -1,3 +1,18 @@ +use juno::{models::Value, Result}; +use std::{collections::HashMap, net::SocketAddr}; +use tokio::sync::oneshot::Sender; + +pub enum HttpServerCommands { + AddConfig(HttpConfig), + ClearConfig, + Listen(SocketAddr), +} + +pub enum JunoCommands { + CallFunction(String, HashMap, Sender>), + TriggerHook(String), +} + #[derive(Clone)] pub struct HttpConfig { pub config_type: MiddlewareType, diff --git a/src/server.rs b/src/server.rs deleted file mode 100644 index 2d7d090..0000000 --- a/src/server.rs +++ /dev/null @@ -1,307 +0,0 @@ -use crate::{ - http_config::{HttpConfig, MiddlewareType}, - http_context::HttpContext, -}; - -use std::collections::HashMap; - -use juno::models::Number; -use juno::models::Value; -use thruster::{ - async_middleware, middleware_fn, App, Context, MiddlewareNext, MiddlewareResult, Request, - Server, ThrusterServer, -}; - -pub fn app_delete(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Delete, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn app_get(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Get, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn app_options(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Options, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn app_patch(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Patch, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn app_post(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Post, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn app_put(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Put, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn app_use(args: HashMap) -> Value { - let value = Value::String(String::from("/")); - let string = String::from("/"); - let path = args - .get("path") - .unwrap_or(&value) - .as_string() - .unwrap_or(&string); - - let function = args.get("function").unwrap_or(&Value::Null).as_string(); - if function.is_none() { - return Value::Null; - } - let function = function.unwrap(); - - crate::HTTP_CONFIG.lock().unwrap().push(HttpConfig { - config_type: MiddlewareType::Use, - func_name: function.clone(), - path: path.clone(), - }); - - Value::Null -} - -pub fn listen(args: HashMap) -> Value { - let http_listener = crate::LISTENER.lock().unwrap(); - let http_config = crate::HTTP_CONFIG.lock().unwrap(); - - if http_listener.is_some() { - // Kill the server. - // So far, no way to do that. Nickel doesn't support it yet - panic!("Excuse me wtf?"); - } - - let mut app = - App::>::create(generate_context, http_config.clone()); - app.use_middleware("/", async_middleware!(HttpContext, [handle_middleware])); - - for config in http_config.iter() { - let path = config.path.clone(); - let path = Box::leak(path.into_boxed_str()); - match &config.config_type { - MiddlewareType::Delete => { - app.delete(path, async_middleware!(HttpContext, [handle_data])); - } - MiddlewareType::Get => { - app.get(path, async_middleware!(HttpContext, [handle_data])); - } - MiddlewareType::Options => { - app.options(path, async_middleware!(HttpContext, [handle_data])); - } - MiddlewareType::Patch => { - app.update(path, async_middleware!(HttpContext, [handle_data])); - } - MiddlewareType::Post => { - app.post(path, async_middleware!(HttpContext, [handle_data])); - } - MiddlewareType::Put => { - app.put(path, async_middleware!(HttpContext, [handle_data])); - } - MiddlewareType::Use => {} - } - } - app.set404(async_middleware!(HttpContext, [handle_404])); - - let server = Server::new(app); - - // Populate `server` from HTTP_CONFIG - // Setup routers and middlwares accordingly - if args.get("socket").is_none() { - // Need a binding address to bind to - return Value::Null; - } - - tokio::spawn(async move { - server - .build( - args.get("socket") - .unwrap_or(&Value::String("127.0.0.1".to_string())) - .as_string() - .unwrap_or(&String::from("127.0.0.1")), - args.get("port") - .unwrap_or(&Value::Number(Number::PosInt(3000))) - .as_number() - .unwrap_or(&Number::PosInt(3000)) - .as_u64() - .unwrap_or(3000) as u16, - ) - .await; - }); - // Add `listener` to a global mutex like HTTP_CONFIG - // Then, on clearConfig, if the global mutex is not null, force quit the server and start a new one - //*http_listener = Some(server); - - Value::Null -} - -pub fn clear_config(_args: HashMap) -> Value { - crate::HTTP_CONFIG.lock().unwrap().clear(); - Value::Null -} - -fn generate_context(request: Request, state: &Vec, path: &str) -> HttpContext { - let start = request.method().len() + 4; - let matched_route = String::from(&path[start..]); - - HttpContext::new(request, matched_route, state.clone()) -} - -#[middleware_fn] -async fn handle_data( - mut context: HttpContext, - next: MiddlewareNext, -) -> MiddlewareResult { - let fn_name = context - .route_configs - .iter() - .filter(|config| { - context.method() == config.config_type.to_capitalized_string() - && context.matched_route() == &config.path - }) - .next(); - if fn_name.is_none() { - return next(context).await; - } - let fn_name = fn_name.unwrap(); - // TODO get an instance to juno module from here and call the function - - Ok(context) -} - -#[middleware_fn] -async fn handle_middleware( - context: HttpContext, - next: MiddlewareNext, -) -> MiddlewareResult { - println!("Got middleware on {}", context.matched_route()); - next(context).await -} - -#[middleware_fn] -async fn handle_404( - mut context: HttpContext, - _next: MiddlewareNext, -) -> MiddlewareResult { - context.status(404); - context.body(&format!("Cannot {} {}", context.method(), context.route())); - Ok(context) -} From 671c7ad27fb930fd733a35abfcf4cd57ba89482e Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Sun, 24 May 2020 20:05:19 +0530 Subject: [PATCH 9/9] Added matching routes --- Cargo.lock | 2 +- src/http_context.rs | 2 +- src/http_server.rs | 105 ++++++++++++++++++++++++++++++++++++++++++-- src/juno_module.rs | 2 +- src/misc.rs | 3 +- 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8fb07eb..0f11541 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -388,7 +388,7 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "juno" -version = "0.1.1" +version = "0.1.3-4" dependencies = [ "async-std", "async-trait", diff --git a/src/http_context.rs b/src/http_context.rs index 822289a..afc266b 100644 --- a/src/http_context.rs +++ b/src/http_context.rs @@ -128,7 +128,7 @@ impl HttpContext { ); let mut raw_headers: Vec = vec![]; - let _ = self.headers.iter().map(|item| { + self.headers.iter().for_each(|item| { raw_headers.push(Value::String(item.0.clone())); raw_headers.push(Value::String(item.1.clone())); }); diff --git a/src/http_server.rs b/src/http_server.rs index f720a0c..ed92774 100644 --- a/src/http_server.rs +++ b/src/http_server.rs @@ -145,6 +145,11 @@ async fn handle_data( } next(context).await } else { + if let Some(Value::String(url)) = response.get("redirect") { + context.redirect(url); + return Ok(context); + } + if let Some(content_type) = response.get("contentType") { context.set_content_type( content_type @@ -185,9 +190,103 @@ async fn handle_data( #[middleware_fn] async fn handle_middleware( - context: HttpContext, + mut context: HttpContext, next: MiddlewareNext, ) -> MiddlewareResult { - println!("Got middleware on {}", context.matched_route()); - next(context).await + let fn_name: Vec<&HttpConfig> = context + .http_configs + .iter() + .filter(|config| { + config.config_type == MiddlewareType::Use + && context.matched_route().starts_with(&config.path) + }) + .collect(); + if fn_name.get(0).is_none() { + return next(context).await; + } + let fn_name = &fn_name.get(0).unwrap().func_name; + + let (sender, receiver) = channel::>(); + + let result = context.juno_sender.send(JunoCommands::CallFunction( + fn_name.clone(), + context.juno_representation().clone(), + sender, + )); + if result.is_err() { + println!( + "Error sending command across channels: {}", + result.unwrap_err() + ); + return next(context).await; + } + + let response = receiver.await; + if response.is_err() { + println!( + "Error receiving command across channels: {}", + response.unwrap_err() + ); + return next(context).await; + } + let response = response.unwrap(); + if response.is_err() { + println!("Error calling function on juno: {}", response.unwrap_err()); + return next(context).await; + } + let response = response.unwrap(); + + if response.as_object().is_none() { + println!("Didn't get back object from function response"); + return next(context).await; + } + let response = response.as_object().unwrap(); + + if response.get("next") == Some(&Value::Bool(true)) { + if response.get("data").is_some() { + context.data = response.get("data").unwrap().clone(); + } + next(context).await + } else { + if let Some(Value::String(url)) = response.get("redirect") { + context.redirect(url); + return Ok(context); + } + + if let Some(content_type) = response.get("contentType") { + context.set_content_type( + content_type + .as_string() + .unwrap_or(&String::from("text/html")), + ); + } + + if let Some(Value::Object(headers)) = response.get("headers") { + let _ = headers.iter().map(|item| { + if item.1.is_string() { + context.set(item.0, item.1.as_string().unwrap()); + } + }); + } + + if let Some(Value::Number(Number::PosInt(num))) = response.get("status") { + context.status(*num as u32); + } + + if let Some(json) = response.get("json") { + context.set_content_type("application/json"); + let json: serde_json::Value = json.clone().into(); + context.body(&json.to_string()); + } else { + context.body( + response + .get("body") + .unwrap_or(&Value::Null) + .as_string() + .unwrap_or(&String::from("")), + ); + } + + Ok(context) + } } diff --git a/src/juno_module.rs b/src/juno_module.rs index 60983ee..bdd5c5b 100644 --- a/src/juno_module.rs +++ b/src/juno_module.rs @@ -174,7 +174,7 @@ pub async fn juno_loop( } } JunoCommands::TriggerHook(hook_name) => { - let result = module.trigger_hook(&hook_name).await; + let result = module.trigger_hook(&hook_name, Value::Null).await; if result.is_err() { println!("Error triggering hook: {}", result.unwrap_err()); } diff --git a/src/misc.rs b/src/misc.rs index f13c457..545531b 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -8,6 +8,7 @@ pub enum HttpServerCommands { Listen(SocketAddr), } +#[allow(dead_code)] pub enum JunoCommands { CallFunction(String, HashMap, Sender>), TriggerHook(String), @@ -20,7 +21,7 @@ pub struct HttpConfig { pub path: String, } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum MiddlewareType { Delete, Get,