From bc8687deb5f0f9273fc771e79b070f3b49e39fed Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Tue, 30 Dec 2014 21:51:07 +1300 Subject: Basic conversion: browserified web app now works. --- web/gulpfile.js | 320 +++++++++------ web/gulpfile.old.js | 179 +++++++++ web/package.json | 27 +- web/src/fonts/fontawesome-webfont.eot | Bin 0 -> 56006 bytes web/src/fonts/fontawesome-webfont.svg | 520 +++++++++++++++++++++++++ web/src/fonts/fontawesome-webfont.ttf | Bin 0 -> 112160 bytes web/src/fonts/fontawesome-webfont.woff | Bin 0 -> 65452 bytes web/src/index.html | 11 +- web/src/js/actions.js | 6 + web/src/js/app.js | 10 +- web/src/js/components/flowdetail.jsx.js | 4 +- web/src/js/components/flowtable-columns.jsx.js | 14 +- web/src/js/components/flowtable.jsx.js | 11 +- web/src/js/components/footer.jsx.js | 4 + web/src/js/components/header.jsx.js | 16 +- web/src/js/components/mainview.jsx.js | 16 +- web/src/js/components/proxyapp.jsx.js | 28 +- web/src/js/components/utils.jsx.js | 14 +- web/src/js/components/virtualscroll.jsx.js | 6 +- web/src/js/connection.js | 14 +- web/src/js/dispatcher.js | 4 + web/src/js/filt/filt.js | 10 +- web/src/js/flow/utils.js | 9 +- web/src/js/store/store.js | 38 +- web/src/js/store/view.js | 14 +- web/src/js/utils.js | 14 +- 26 files changed, 1118 insertions(+), 171 deletions(-) create mode 100644 web/gulpfile.old.js create mode 100644 web/src/fonts/fontawesome-webfont.eot create mode 100644 web/src/fonts/fontawesome-webfont.svg create mode 100644 web/src/fonts/fontawesome-webfont.ttf create mode 100644 web/src/fonts/fontawesome-webfont.woff (limited to 'web') diff --git a/web/gulpfile.js b/web/gulpfile.js index 5a0b93af..60f0f1b7 100644 --- a/web/gulpfile.js +++ b/web/gulpfile.js @@ -1,179 +1,275 @@ var gulp = require("gulp"); -var merge = require('merge-stream'); +var path = require('path'); +var _ = require('lodash'); +var browserify = require('browserify'); var concat = require('gulp-concat'); +var connect = require('gulp-connect'); +var buffer = require('vinyl-buffer'); var jshint = require("gulp-jshint"); var less = require("gulp-less"); var livereload = require("gulp-livereload"); +var map = require("map-stream"); var minifyCSS = require('gulp-minify-css'); var notify = require("gulp-notify"); -var peg = require("gulp-peg"); var plumber = require("gulp-plumber"); -var qunit = require("gulp-qunit"); +var rev = require("gulp-rev"); var react = require("gulp-react"); +var reactify = require('reactify'); var rename = require("gulp-rename"); +var replace = require('gulp-replace'); +var source = require('vinyl-source-stream'); var sourcemaps = require('gulp-sourcemaps'); +var transform = require('vinyl-transform'); var uglify = require('gulp-uglify'); +var packagejs = require('./package.json'); -var dont_break_on_errors = function () { - return plumber(function (error) { - notify.onError("<%= error.message %>").apply(this, arguments); - this.emit('end'); - }); + +// FIXME: react-with-addons.min.js for prod use issue + +var manifest = { + "vendor.css": "vendor.css", + "app.css": "app.css", + "vendor.js": "vendor.js", + "app.js": "app.js", }; -var path = { - dist: "../libmproxy/web/", +var CONF = { + dist: "../libmproxy/web", + static: "../libmproxy/web/static", js: { - vendor: [ - 'vendor/jquery/jquery.js', - 'vendor/lodash/lodash.js', - 'vendor/react/react-with-addons.js', - 'vendor/react-router/react-router.js', + // Don't package these in the vendor distribution + vendor_excludes: [ + "bootstrap" ], - app: [ - 'js/utils.js', - 'js/dispatcher.js', - 'js/actions.js', - 'js/filt/filt.js', - 'js/flow/utils.js', - 'js/store/store.js', - 'js/store/view.js', - 'js/connection.js', - 'js/components/utils.jsx.js', - 'js/components/virtualscroll.jsx.js', - 'js/components/header.jsx.js', - 'js/components/flowtable-columns.jsx.js', - 'js/components/flowtable.jsx.js', - 'js/components/flowdetail.jsx.js', - 'js/components/mainview.jsx.js', - 'js/components/eventlog.jsx.js', - 'js/components/footer.jsx.js', - 'js/components/proxyapp.jsx.js', - 'js/app.js', + // Package these as well as the dependencies + vendor_includes: [ + "react/addons" ], + app: 'src/js/app.js' }, - peg: "js/filt/filt.pegjs", css: { - vendor: ["css/vendor.less"], - app: ["css/app.less"], - all: ["css/**"] + vendor: ["src/css/vendor.less"], + app: ["src/css/app.less"] }, - vendor: ["vendor/**"], - fonts: ["src/vendor/fontawesome/fontawesome-webfont.*"], - html: ["*.html", "!benchmark.html", "!test.html"], - images: ["images/**"], - test: ["test.html"], - opts: {base: "src", cwd: "src"} + copy: [ + "src/examples/**", + "src/fonts/**", + ], + templates: [ + "src/templates/*" + ], + fonts: ["src/fontawesome/fontawesome-webfont.*"], + port: 8082 +}; + +var vendor_packages = _.difference( + _.union( + _.keys(packagejs.dependencies), + CONF.js.vendor_includes + ), + CONF.js.vendor_excludes + ); + + +// Custom linting reporter used for error notify +var jsHintErrorReporter = function(){ + return map(function (file, cb) { + if (file.jshint && !file.jshint.success) { + file.jshint.results.forEach(function (err) { + if (err) { + var msg = [ + path.basename(file.path), + 'Line: ' + err.error.line, + 'Reason: ' + err.error.reason + ]; + notify.onError( + "Error: <%= error.message %>" + )(new Error(msg.join("\n"))); + } + }); + } + cb(null, file); + }) +}; + +var save_rev = function(){ + return map(function(file, callback){ + if (file.revOrigBase){ + manifest[path.basename(file.revOrigPath)] = path.basename(file.path); + } + callback(null, file); + }) +} + +var dont_break_on_errors = function(){ + return plumber( + function(error){ + notify.onError("Error: <%= error.message %>").apply(this, arguments); + this.emit('end'); + } + ); }; gulp.task("fonts", function () { - return gulp.src(path.fonts) - .pipe(gulp.dest(path.dist + "static/fonts")); + return gulp.src(CONF.fonts) + .pipe(gulp.dest(CONF.dist + "fonts")); }); function styles_dev(files) { - return (gulp.src(files, path.opts) + return (gulp.src(files) .pipe(dont_break_on_errors()) .pipe(sourcemaps.init()) .pipe(less()) .pipe(sourcemaps.write(".", {sourceRoot: "/static"})) - .pipe(gulp.dest(path.dist + "static")) - .pipe(livereload({auto: false}))); + .pipe(gulp.dest(CONF.static)) + .pipe(livereload({ auto: false }))); } -gulp.task("styles-app-dev", styles_dev.bind(undefined, path.css.app)); -gulp.task("styles-vendor-dev", styles_dev.bind(undefined, path.css.vendor)); -gulp.task("styles-dev", ["styles-app-dev", "styles-vendor-dev"]); +gulp.task("styles-app-dev", function(){ + styles_dev(CONF.css.app); +}); +gulp.task("styles-vendor-dev", function(){ + styles_dev(CONF.css.vendor); +}); function styles_prod(files) { - return (gulp.src(files, path.opts) + return (gulp.src(files) .pipe(less()) // No sourcemaps support yet :-/ // https://github.com/jonathanepollack/gulp-minify-css/issues/34 .pipe(minifyCSS()) - .pipe(gulp.dest(path.dist + "static")) - .pipe(livereload({auto: false}))); + .pipe(rev()) + .pipe(save_rev()) + .pipe(gulp.dest(CONF.static)) + .pipe(livereload({ auto: false }))); } -gulp.task("styles-app-prod", styles_prod.bind(undefined, path.css.app)); -gulp.task("styles-vendor-prod", styles_prod.bind(undefined, path.css.vendor)); -gulp.task("styles-prod", ["styles-app-prod", "styles-vendor-prod"]); +gulp.task("styles-app-prod", function(){ + styles_prod(CONF.css.app); +}); +gulp.task("styles-vendor-prod", function(){ + styles_prod(CONF.css.vendor); +}); -function scripts_dev(files, filename) { - return gulp.src(files, path.opts) - .pipe(dont_break_on_errors()) - .pipe(sourcemaps.init()) - .pipe(react()) - .pipe(concat(filename)) - .pipe(sourcemaps.write(".", {sourceRoot: "/static"})) - .pipe(gulp.dest(path.dist + "static/js")) - .pipe(livereload({auto: false})); +function vendor_stream(debug){ + var vendor = browserify(vendor_packages, {debug: debug}); + _.each(vendor_packages, function(v){ + vendor.require(v); + }); + return vendor.bundle() + .pipe(source("dummy.js")) + .pipe(rename("vendor.js")); } -gulp.task("scripts-app-dev", scripts_dev.bind(undefined, path.js.app, "app.js")); -gulp.task("scripts-vendor-dev", scripts_dev.bind(undefined, path.js.vendor, "vendor.js")); -gulp.task("scripts-dev", ["scripts-app-dev", "scripts-vendor-dev"]); +gulp.task("scripts-vendor-dev", function (){ + return vendor_stream(true) + .pipe(gulp.dest(CONF.static)); +}); +gulp.task("scripts-vendor-prod", function(){ + return vendor_stream(false) + .pipe(buffer()) + .pipe(uglify()) + .pipe(rev()) + .pipe(save_rev()) + .pipe(gulp.dest(CONF.static)); +}); -function scripts_prod(files, filename) { - return gulp.src(files, path.opts) - .pipe(react()) - .pipe(concat(filename)) +function app_stream(debug) { + var browserified = transform(function(filename) { + var b = browserify(filename, {debug: debug}) + _.each(vendor_packages, function(v){ + b.external(v); + }); + b.transform(reactify); + return b.bundle(); + }); + return gulp.src([CONF.js.app]) + .pipe(dont_break_on_errors()) + .pipe(browserified) + .pipe(rename("app.js")); +}; +gulp.task('scripts-app-dev', function () { + return app_stream(true) + .pipe(gulp.dest(CONF.static)) + .pipe(livereload({ auto: false })); +}); +gulp.task('scripts-app-prod', function () { + return app_stream(true) + .pipe(buffer()) .pipe(uglify()) - .pipe(gulp.dest(path.dist + "static/js")) - .pipe(livereload({auto: false})); -} -gulp.task("scripts-app-prod", scripts_prod.bind(undefined, path.js.app, "app.js")); -gulp.task("scripts-vendor-prod", scripts_prod.bind(undefined, path.js.vendor, "vendor.js")); -gulp.task("scripts-prod", ["scripts-app-prod", "scripts-vendor-prod"]); + .pipe(rev()) + .pipe(save_rev()) + .pipe(gulp.dest(CONF.static)); +}); gulp.task("jshint", function () { - return gulp.src(path.js.app.concat(["!"+path.peg.replace("pegjs","js")]), path.opts) + return gulp.src(["src/js/**.js"]) .pipe(dont_break_on_errors()) .pipe(react()) + .pipe(plumber()) .pipe(jshint()) - .pipe(jshint.reporter("jshint-stylish")); -}); - -gulp.task("peg", function () { - return gulp.src(path.peg, path.opts) - .pipe(dont_break_on_errors()) - .pipe(peg({exportVar:"Filt"})) - .pipe(gulp.dest(".", path.opts)); + .pipe(jshint.reporter("jshint-stylish")) + .pipe(jsHintErrorReporter()); }); -gulp.task("images", function () { - //(spriting code in commit 4ca720b55680e40b3a4361141a2ad39f9de81111) - return gulp.src(path.images, path.opts) - .pipe(gulp.dest(path.dist + "static")); +gulp.task("copy", function(){ + return gulp.src(CONF.copy, {base:"src/"}) + .pipe(gulp.dest(CONF.dist)); }); -gulp.task("html", function () { - return gulp.src(path.html, path.opts) - .pipe(gulp.dest(path.dist + "templates")) - .pipe(livereload({auto: false})); -}); +function templates(){ + return gulp.src(CONF.templates, {base:"src/"}) + .pipe(replace(/\{\{\{(\S*)\}\}\}/g, function(match, p1) { + return manifest[p1]; + })) + .pipe(gulp.dest(CONF.dist)); +}; +gulp.task('templates', templates); -gulp.task('test', function () { - return gulp.src(path.test, path.opts) - .pipe(qunit({verbose: true})); +gulp.task('connect', function() { + connect.server({ + port: CONF.port + }); }); +common = ["fonts", "copy"]; +gulp.task( + "dev", + [ + "fonts", + "copy", + "styles-vendor-dev", + "styles-app-dev", + "scripts-vendor-dev", + "scripts-app-dev", + ], + templates +); +gulp.task( + "prod", + [ + "fonts", + "copy", + "styles-vendor-prod", + "styles-app-prod", + "scripts-vendor-prod", + "scripts-app-prod", + "connect" + ], + templates +); -common = ["fonts", "html", "jshint", "peg", "images"]; -gulp.task("dev", common.concat(["styles-dev", "scripts-dev"])); -gulp.task("prod", common.concat(["styles-prod", "scripts-prod"])); - -gulp.task("default", ["dev"], function () { +gulp.task("default", ["dev", "connect"], function () { livereload.listen({auto: true}); - gulp.watch(path.vendor, path.opts, ["scripts-vendor-dev", "styles-vendor-dev"]); - gulp.watch(path.js.app, path.opts, ["scripts-app-dev", "jshint"]); - gulp.watch(path.peg, path.opts, ["peg"]); - gulp.watch(path.css.all, path.opts, ["styles-app-dev"]); - gulp.watch(path.html, path.opts, ["html"]); + gulp.watch(["src/css/vendor*"], ["styles-vendor-dev"]); + gulp.watch(["src/js/**"], ["scripts-app-dev", "jshint"]); + gulp.watch(["src/css/**"], ["styles-app-dev"]); + gulp.watch(CONF.templates, ["templates"]); + gulp.watch(CONF.copy, ["copy"]); }); diff --git a/web/gulpfile.old.js b/web/gulpfile.old.js new file mode 100644 index 00000000..5a0b93af --- /dev/null +++ b/web/gulpfile.old.js @@ -0,0 +1,179 @@ +var gulp = require("gulp"); +var merge = require('merge-stream'); + +var concat = require('gulp-concat'); +var jshint = require("gulp-jshint"); +var less = require("gulp-less"); +var livereload = require("gulp-livereload"); +var minifyCSS = require('gulp-minify-css'); +var notify = require("gulp-notify"); +var peg = require("gulp-peg"); +var plumber = require("gulp-plumber"); +var qunit = require("gulp-qunit"); +var react = require("gulp-react"); +var rename = require("gulp-rename"); +var sourcemaps = require('gulp-sourcemaps'); +var uglify = require('gulp-uglify'); + + +var dont_break_on_errors = function () { + return plumber(function (error) { + notify.onError("<%= error.message %>").apply(this, arguments); + this.emit('end'); + }); +}; + +var path = { + dist: "../libmproxy/web/", + js: { + vendor: [ + 'vendor/jquery/jquery.js', + 'vendor/lodash/lodash.js', + 'vendor/react/react-with-addons.js', + 'vendor/react-router/react-router.js', + ], + app: [ + 'js/utils.js', + 'js/dispatcher.js', + 'js/actions.js', + 'js/filt/filt.js', + 'js/flow/utils.js', + 'js/store/store.js', + 'js/store/view.js', + 'js/connection.js', + 'js/components/utils.jsx.js', + 'js/components/virtualscroll.jsx.js', + 'js/components/header.jsx.js', + 'js/components/flowtable-columns.jsx.js', + 'js/components/flowtable.jsx.js', + 'js/components/flowdetail.jsx.js', + 'js/components/mainview.jsx.js', + 'js/components/eventlog.jsx.js', + 'js/components/footer.jsx.js', + 'js/components/proxyapp.jsx.js', + 'js/app.js', + ], + }, + peg: "js/filt/filt.pegjs", + css: { + vendor: ["css/vendor.less"], + app: ["css/app.less"], + all: ["css/**"] + }, + vendor: ["vendor/**"], + fonts: ["src/vendor/fontawesome/fontawesome-webfont.*"], + html: ["*.html", "!benchmark.html", "!test.html"], + images: ["images/**"], + test: ["test.html"], + opts: {base: "src", cwd: "src"} +}; + + +gulp.task("fonts", function () { + return gulp.src(path.fonts) + .pipe(gulp.dest(path.dist + "static/fonts")); +}); + + +function styles_dev(files) { + return (gulp.src(files, path.opts) + .pipe(dont_break_on_errors()) + .pipe(sourcemaps.init()) + .pipe(less()) + .pipe(sourcemaps.write(".", {sourceRoot: "/static"})) + .pipe(gulp.dest(path.dist + "static")) + .pipe(livereload({auto: false}))); +} +gulp.task("styles-app-dev", styles_dev.bind(undefined, path.css.app)); +gulp.task("styles-vendor-dev", styles_dev.bind(undefined, path.css.vendor)); +gulp.task("styles-dev", ["styles-app-dev", "styles-vendor-dev"]); + + +function styles_prod(files) { + return (gulp.src(files, path.opts) + .pipe(less()) + // No sourcemaps support yet :-/ + // https://github.com/jonathanepollack/gulp-minify-css/issues/34 + .pipe(minifyCSS()) + .pipe(gulp.dest(path.dist + "static")) + .pipe(livereload({auto: false}))); +} +gulp.task("styles-app-prod", styles_prod.bind(undefined, path.css.app)); +gulp.task("styles-vendor-prod", styles_prod.bind(undefined, path.css.vendor)); +gulp.task("styles-prod", ["styles-app-prod", "styles-vendor-prod"]); + + +function scripts_dev(files, filename) { + return gulp.src(files, path.opts) + .pipe(dont_break_on_errors()) + .pipe(sourcemaps.init()) + .pipe(react()) + .pipe(concat(filename)) + .pipe(sourcemaps.write(".", {sourceRoot: "/static"})) + .pipe(gulp.dest(path.dist + "static/js")) + .pipe(livereload({auto: false})); +} +gulp.task("scripts-app-dev", scripts_dev.bind(undefined, path.js.app, "app.js")); +gulp.task("scripts-vendor-dev", scripts_dev.bind(undefined, path.js.vendor, "vendor.js")); +gulp.task("scripts-dev", ["scripts-app-dev", "scripts-vendor-dev"]); + + +function scripts_prod(files, filename) { + return gulp.src(files, path.opts) + .pipe(react()) + .pipe(concat(filename)) + .pipe(uglify()) + .pipe(gulp.dest(path.dist + "static/js")) + .pipe(livereload({auto: false})); +} +gulp.task("scripts-app-prod", scripts_prod.bind(undefined, path.js.app, "app.js")); +gulp.task("scripts-vendor-prod", scripts_prod.bind(undefined, path.js.vendor, "vendor.js")); +gulp.task("scripts-prod", ["scripts-app-prod", "scripts-vendor-prod"]); + + +gulp.task("jshint", function () { + return gulp.src(path.js.app.concat(["!"+path.peg.replace("pegjs","js")]), path.opts) + .pipe(dont_break_on_errors()) + .pipe(react()) + .pipe(jshint()) + .pipe(jshint.reporter("jshint-stylish")); +}); + +gulp.task("peg", function () { + return gulp.src(path.peg, path.opts) + .pipe(dont_break_on_errors()) + .pipe(peg({exportVar:"Filt"})) + .pipe(gulp.dest(".", path.opts)); +}); + +gulp.task("images", function () { + //(spriting code in commit 4ca720b55680e40b3a4361141a2ad39f9de81111) + return gulp.src(path.images, path.opts) + .pipe(gulp.dest(path.dist + "static")); +}); + +gulp.task("html", function () { + return gulp.src(path.html, path.opts) + .pipe(gulp.dest(path.dist + "templates")) + .pipe(livereload({auto: false})); +}); + + +gulp.task('test', function () { + return gulp.src(path.test, path.opts) + .pipe(qunit({verbose: true})); +}); + + +common = ["fonts", "html", "jshint", "peg", "images"]; +gulp.task("dev", common.concat(["styles-dev", "scripts-dev"])); +gulp.task("prod", common.concat(["styles-prod", "scripts-prod"])); + +gulp.task("default", ["dev"], function () { + livereload.listen({auto: true}); + gulp.watch(path.vendor, path.opts, ["scripts-vendor-dev", "styles-vendor-dev"]); + gulp.watch(path.js.app, path.opts, ["scripts-app-dev", "jshint"]); + gulp.watch(path.peg, path.opts, ["peg"]); + gulp.watch(path.css.all, path.opts, ["styles-app-dev"]); + gulp.watch(path.html, path.opts, ["html"]); +}); diff --git a/web/package.json b/web/package.json index 8e33396a..944dbdb1 100644 --- a/web/package.json +++ b/web/package.json @@ -1,28 +1,43 @@ { "name": "mitmproxy", "private": true, + "dependencies": { + "jquery": "", + "lodash": "", + "react": "", + "react-router": "", + "bootstrap": "" + }, "devDependencies": { "bower": "", - "bower-installer": "", - "clean-css": "", + "browserify": "^6.3.4", "gulp": "", "gulp-concat": "", + "gulp-connect": "", "gulp-jshint": "", "gulp-less": "", "gulp-livereload": "", "gulp-minify-css": "", "gulp-notify": "", - "gulp-peg": "", "gulp-plumber": "", - "gulp-qunit": "", "gulp-react": "", "gulp-rename": "", + "gulp-replace": "", + "gulp-rev": "", "gulp-sourcemaps": "", "gulp-uglify": "", "gulp-util": "", + "jest-cli": "^0.1.18", "jshint-stylish": "", - "merge-stream": "", + "lodash": "", + "map-stream": "", "react": "", - "react-tools": "" + "react-tools": "", + "reactify": "", + "vinyl-buffer": "", + "vinyl-source-stream": "", + "vinyl-transform": "", + + "gulp-peg": "" } } diff --git a/web/src/fonts/fontawesome-webfont.eot b/web/src/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..84677bc0 Binary files /dev/null and b/web/src/fonts/fontawesome-webfont.eot differ diff --git a/web/src/fonts/fontawesome-webfont.svg b/web/src/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..d907b25a --- /dev/null +++ b/web/src/fonts/fontawesome-webfont.svg @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/fonts/fontawesome-webfont.ttf b/web/src/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..96a3639c Binary files /dev/null and b/web/src/fonts/fontawesome-webfont.ttf differ diff --git a/web/src/fonts/fontawesome-webfont.woff b/web/src/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..628b6a52 Binary files /dev/null and b/web/src/fonts/fontawesome-webfont.woff differ diff --git a/web/src/index.html b/web/src/index.html index 571845b9..c40936e0 100644 --- a/web/src/index.html +++ b/web/src/index.html @@ -4,11 +4,10 @@ mitmproxy - - - - + + + + - - + \ No newline at end of file diff --git a/web/src/js/actions.js b/web/src/js/actions.js index 7f4fd0b0..6dc11825 100644 --- a/web/src/js/actions.js +++ b/web/src/js/actions.js @@ -108,4 +108,10 @@ Query = { FILTER: "f", HIGHLIGHT: "h", SHOW_EVENTLOG: "e" +}; + +module.exports = { + ActionTypes: ActionTypes, + ConnectionActions: ConnectionActions + }; \ No newline at end of file diff --git a/web/src/js/app.js b/web/src/js/app.js index 5146cb46..f2ddc2ae 100644 --- a/web/src/js/app.js +++ b/web/src/js/app.js @@ -1,7 +1,15 @@ + +var React = require("react"); +var ReactRouter = require("react-router"); +var $ = require("jquery"); + +var Connection = require("./connection"); +var proxyapp = require("./components/proxyapp.jsx.js"); + $(function () { window.ws = new Connection("/updates"); - ReactRouter.run(routes, function (Handler) { + ReactRouter.run(proxyapp.routes, function (Handler) { React.render(, document.body); }); }); \ No newline at end of file diff --git a/web/src/js/components/flowdetail.jsx.js b/web/src/js/components/flowdetail.jsx.js index 594d1a0e..0f91bde1 100644 --- a/web/src/js/components/flowdetail.jsx.js +++ b/web/src/js/components/flowdetail.jsx.js @@ -34,11 +34,11 @@ var FlowDetailNav = React.createClass({ var acceptButton = null; if(flow.intercepted){ - acceptButton = + acceptButton = ; } var revertButton = null; if(flow.modified){ - revertButton = + revertButton = ; } return ( diff --git a/web/src/js/components/flowtable-columns.jsx.js b/web/src/js/components/flowtable-columns.jsx.js index 9162e077..39c4bd8d 100644 --- a/web/src/js/components/flowtable-columns.jsx.js +++ b/web/src/js/components/flowtable-columns.jsx.js @@ -1,3 +1,7 @@ +var React = require("react"); +var flowutils = require("../flow/utils.js"); +var utils = require("../utils.js"); + var TLSColumn = React.createClass({ statics: { renderTitle: function () { @@ -29,7 +33,7 @@ var IconColumn = React.createClass({ var icon; if (flow.response) { - var contentType = ResponseUtils.getContentType(flow.response); + var contentType = flowutils.ResponseUtils.getContentType(flow.response); //TODO: We should assign a type to the flow somewhere else. if (flow.response.code == 304) { @@ -120,7 +124,7 @@ var SizeColumn = React.createClass({ if (flow.response) { total += flow.response.contentLength || 0; } - var size = formatSize(total); + var size = utils.formatSize(total); return {size}; } }); @@ -136,7 +140,7 @@ var TimeColumn = React.createClass({ var flow = this.props.flow; var time; if (flow.response) { - time = formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start)); + time = utils.formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start)); } else { time = "..."; } @@ -154,3 +158,7 @@ var all_columns = [ SizeColumn, TimeColumn]; + +module.exports = all_columns; + + diff --git a/web/src/js/components/flowtable.jsx.js b/web/src/js/components/flowtable.jsx.js index a3a37c40..90eebbc1 100644 --- a/web/src/js/components/flowtable.jsx.js +++ b/web/src/js/components/flowtable.jsx.js @@ -1,3 +1,8 @@ +var React = require("react"); +var utils = require("./utils.jsx.js"); +var VirtualScrollMixin = require("./virtualscroll.jsx.js"); +var flowtable_columns = require("./flowtable-columns.jsx.js"); + var FlowRow = React.createClass({ render: function () { var flow = this.props.flow; @@ -52,10 +57,10 @@ var FlowTableHead = React.createClass({ var ROW_HEIGHT = 32; var FlowTable = React.createClass({ - mixins: [StickyHeadMixin, AutoScrollMixin, VirtualScrollMixin], + mixins: [utils.StickyHeadMixin, utils.AutoScrollMixin, VirtualScrollMixin], getInitialState: function () { return { - columns: all_columns + columns: flowtable_columns }; }, componentWillMount: function () { @@ -127,3 +132,5 @@ var FlowTable = React.createClass({ ); } }); + +module.exports = FlowTable; diff --git a/web/src/js/components/footer.jsx.js b/web/src/js/components/footer.jsx.js index 52d52e0f..d04fb615 100644 --- a/web/src/js/components/footer.jsx.js +++ b/web/src/js/components/footer.jsx.js @@ -1,3 +1,5 @@ +var React = require("react"); + var Footer = React.createClass({ render: function () { var mode = this.props.settings.mode; @@ -11,3 +13,5 @@ var Footer = React.createClass({ ); } }); + +module.exports = Footer; \ No newline at end of file diff --git a/web/src/js/components/header.jsx.js b/web/src/js/components/header.jsx.js index 6470aec5..d9fd9ab0 100644 --- a/web/src/js/components/header.jsx.js +++ b/web/src/js/components/header.jsx.js @@ -1,3 +1,8 @@ +var React = require("react"); +var $ = require("jquery"); + +var utils = require("./utils.jsx.js"); + var FilterDocs = React.createClass({ statics: { xhr: false, @@ -148,7 +153,7 @@ var FilterInput = React.createClass({ }); var MainMenu = React.createClass({ - mixins: [Navigation, State], + mixins: [utils.Navigation, utils.State], statics: { title: "Start", route: "flows" @@ -205,7 +210,7 @@ var ViewMenu = React.createClass({ title: "View", route: "flows" }, - mixins: [Navigation, State], + mixins: [utils.Navigation, utils.State], toggleEventLog: function () { var d = {}; @@ -334,7 +339,7 @@ var header_entries = [MainMenu, ViewMenu /*, ReportsMenu */]; var Header = React.createClass({ - mixins: [Navigation], + mixins: [utils.Navigation], getInitialState: function () { return { active: header_entries[0] @@ -377,3 +382,8 @@ var Header = React.createClass({ ); } }); + + +module.exports = { + Header: Header +} \ No newline at end of file diff --git a/web/src/js/components/mainview.jsx.js b/web/src/js/components/mainview.jsx.js index af65ca1e..85ca36bb 100644 --- a/web/src/js/components/mainview.jsx.js +++ b/web/src/js/components/mainview.jsx.js @@ -1,5 +1,13 @@ +var React = require("react"); + +var utils = require("./utils.jsx.js"); +var views = require("../store/view.js"); +var Filt = require("../filt/filt.js"); +FlowTable = require("./flowtable.jsx.js"); + + var MainView = React.createClass({ - mixins: [Navigation, State], + mixins: [utils.Navigation, utils.State], getInitialState: function () { this.onQueryChange(Query.FILTER, function () { this.state.view.recalculate(this.getViewFilt(), this.getViewSort()); @@ -37,7 +45,7 @@ var MainView = React.createClass({ } }, openView: function (store) { - var view = new StoreView(store, this.getViewFilt(), this.getViewSort()); + var view = new views.StoreView(store, this.getViewFilt(), this.getViewSort()); this.setState({ view: view }); @@ -217,4 +225,6 @@ var MainView = React.createClass({ ); } -}); \ No newline at end of file +}); + +module.exports = MainView; diff --git a/web/src/js/components/proxyapp.jsx.js b/web/src/js/components/proxyapp.jsx.js index 92fc0e49..2431ad46 100644 --- a/web/src/js/components/proxyapp.jsx.js +++ b/web/src/js/components/proxyapp.jsx.js @@ -1,3 +1,14 @@ +var React = require("react"); +var ReactRouter = require("react-router"); +var _ = require("lodash"); + +var utils = require("./utils.jsx.js"); +var MainView = require("./mainview.jsx.js"); +var Footer = require("./footer.jsx.js"); +var header = require("./header.jsx.js"); +var store = require("../store/store.js"); + + //TODO: Move out of here, just a stub. var Reports = React.createClass({ render: function () { @@ -7,11 +18,11 @@ var Reports = React.createClass({ var ProxyAppMain = React.createClass({ - mixins: [State], + mixins: [utils.State], getInitialState: function () { - var eventStore = new EventLogStore(); - var flowStore = new FlowStore(); - var settings = new SettingsStore(); + var eventStore = new store.EventLogStore(); + var flowStore = new store.FlowStore(); + var settings = new store.SettingsStore(); // Default Settings before fetch _.extend(settings.dict,{ @@ -48,7 +59,7 @@ var ProxyAppMain = React.createClass({ return (
-
+ {eventlog}
); } -}); \ No newline at end of file +}); + +module.exports = { + State: State, + Navigation: Navigation, + StickyHeadMixin: StickyHeadMixin, + AutoScrollMixin: AutoScrollMixin, + Splitter: Splitter +} \ No newline at end of file diff --git a/web/src/js/components/virtualscroll.jsx.js b/web/src/js/components/virtualscroll.jsx.js index 4f946cb4..956e1a0b 100644 --- a/web/src/js/components/virtualscroll.jsx.js +++ b/web/src/js/components/virtualscroll.jsx.js @@ -1,3 +1,5 @@ +var React = require("react"); + var VirtualScrollMixin = { getInitialState: function () { return { @@ -78,4 +80,6 @@ var VirtualScrollMixin = { viewport.scrollTop = row_bottom - viewport.offsetHeight; } }, -}; \ No newline at end of file +}; + +module.exports = VirtualScrollMixin; \ No newline at end of file diff --git a/web/src/js/connection.js b/web/src/js/connection.js index 6ca353b3..85514c3c 100644 --- a/web/src/js/connection.js +++ b/web/src/js/connection.js @@ -1,24 +1,28 @@ -function Connection(url) { +var actions = require("./actions.js"); + +function Connection(url) { if (url[0] === "/") { url = location.origin.replace("http", "ws") + url; } var ws = new WebSocket(url); ws.onopen = function () { - ConnectionActions.open(); + actions.ConnectionActions.open(); }; ws.onmessage = function (message) { var m = JSON.parse(message.data); AppDispatcher.dispatchServerAction(m); }; ws.onerror = function () { - ConnectionActions.error(); + actions.ConnectionActions.error(); EventLogActions.add_event("WebSocket connection error."); }; ws.onclose = function () { - ConnectionActions.close(); + actions.ConnectionActions.close(); EventLogActions.add_event("WebSocket connection closed."); }; return ws; -} \ No newline at end of file +} + +module.exports = Connection; \ No newline at end of file diff --git a/web/src/js/dispatcher.js b/web/src/js/dispatcher.js index 860ade9f..9a5dd3dd 100644 --- a/web/src/js/dispatcher.js +++ b/web/src/js/dispatcher.js @@ -33,3 +33,7 @@ AppDispatcher.dispatchServerAction = function (action) { action.source = PayloadSources.SERVER; this.dispatch(action); }; + +module.exports = { + AppDispatcher: AppDispatcher +}; \ No newline at end of file diff --git a/web/src/js/filt/filt.js b/web/src/js/filt/filt.js index 0d93b767..095081ac 100644 --- a/web/src/js/filt/filt.js +++ b/web/src/js/filt/filt.js @@ -1,3 +1,4 @@ +/* jshint ignore:start */ Filt = (function() { /* * Generated by PEG.js 0.8.0. @@ -278,11 +279,11 @@ Filt = (function() { expectedDescs[i] = expected[i].description; } - expectedDesc = (expected.length > 1 + expectedDesc = expected.length > 1 ? expectedDescs.slice(0, -1).join(", ") + " or " + expectedDescs[expected.length - 1] - : expectedDescs[0]); + : expectedDescs[0]; foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; @@ -1769,4 +1770,7 @@ Filt = (function() { SyntaxError: SyntaxError, parse: parse }; -})(); \ No newline at end of file +})(); +/* jshint ignore:end */ + +module.exports = Filt; diff --git a/web/src/js/flow/utils.js b/web/src/js/flow/utils.js index 113f0b1a..50305482 100644 --- a/web/src/js/flow/utils.js +++ b/web/src/js/flow/utils.js @@ -1,3 +1,5 @@ +var _ = require("lodash"); + var _MessageUtils = { getContentType: function (message) { return this.get_first_header(message, /^Content-Type$/i); @@ -54,4 +56,9 @@ var RequestUtils = _.extend(_MessageUtils, { } }); -var ResponseUtils = _.extend(_MessageUtils, {}); \ No newline at end of file +var ResponseUtils = _.extend(_MessageUtils, {}); + + +module.exports = { + ResponseUtils: ResponseUtils +} \ No newline at end of file diff --git a/web/src/js/store/store.js b/web/src/js/store/store.js index ce5c0338..60913ca6 100644 --- a/web/src/js/store/store.js +++ b/web/src/js/store/store.js @@ -1,8 +1,17 @@ + +var _ = require("lodash"); +var $ = require("jquery"); + +var utils = require("../utils.js"); +var actions = require("../actions.js"); +var dispatcher = require("../dispatcher.js"); + + function ListStore() { - EventEmitter.call(this); + utils.EventEmitter.call(this); this.reset(); } -_.extend(ListStore.prototype, EventEmitter.prototype, { +_.extend(ListStore.prototype, utils.EventEmitter.prototype, { add: function (elem) { if (elem.id in this._pos_map) { return; @@ -48,10 +57,10 @@ _.extend(ListStore.prototype, EventEmitter.prototype, { function DictStore() { - EventEmitter.call(this); + utils.EventEmitter.call(this); this.reset(); } -_.extend(DictStore.prototype, EventEmitter.prototype, { +_.extend(DictStore.prototype, utils.EventEmitter.prototype, { update: function (dict) { _.merge(this.dict, dict); this.emit("recalculate"); @@ -69,7 +78,7 @@ function LiveStoreMixin(type) { this._fetchxhr = false; this.handle = this.handle.bind(this); - AppDispatcher.register(this.handle); + dispatcher.AppDispatcher.register(this.handle); // Avoid double-fetch on startup. if (!(window.ws && window.ws.readyState === WebSocket.CONNECTING)) { @@ -78,7 +87,7 @@ function LiveStoreMixin(type) { } _.extend(LiveStoreMixin.prototype, { handle: function (event) { - if (event.type === ActionTypes.CONNECTION_OPEN) { + if (event.type === actions.ActionTypes.CONNECTION_OPEN) { return this.fetch(); } if (event.type === this.type) { @@ -93,7 +102,7 @@ _.extend(LiveStoreMixin.prototype, { } }, close: function () { - AppDispatcher.unregister(this.handle); + dispatcher.AppDispatcher.unregister(this.handle); }, fetch: function (data) { console.log("fetch " + this.type); @@ -139,15 +148,15 @@ _.extend(LiveDictStore.prototype, DictStore.prototype, LiveStoreMixin.prototype) function FlowStore() { - return new LiveListStore(ActionTypes.FLOW_STORE); + return new LiveListStore(actions.ActionTypes.FLOW_STORE); } function SettingsStore() { - return new LiveDictStore(ActionTypes.SETTINGS_STORE); + return new LiveDictStore(actions.ActionTypes.SETTINGS_STORE); } function EventLogStore() { - LiveListStore.call(this, ActionTypes.EVENT_STORE); + LiveListStore.call(this, actions.ActionTypes.EVENT_STORE); } _.extend(EventLogStore.prototype, LiveListStore.prototype, { fetch: function(){ @@ -161,4 +170,11 @@ _.extend(EventLogStore.prototype, LiveListStore.prototype, { }.bind(this)); } } -}); \ No newline at end of file +}); + + +module.exports = { + EventLogStore: EventLogStore, + SettingsStore: SettingsStore, + FlowStore: FlowStore +}; \ No newline at end of file diff --git a/web/src/js/store/view.js b/web/src/js/store/view.js index 9619f994..e96d1bcc 100644 --- a/web/src/js/store/view.js +++ b/web/src/js/store/view.js @@ -1,3 +1,7 @@ +var _ = require("lodash"); + +var utils = require("../utils.js"); + function SortByStoreOrder(elem) { return this.store.index(elem.id); } @@ -8,7 +12,7 @@ var default_filt = function(elem){ }; function StoreView(store, filt, sortfun) { - EventEmitter.call(this); + utils.EventEmitter.call(this); filt = filt || default_filt; sortfun = sortfun || default_sort; @@ -26,7 +30,7 @@ function StoreView(store, filt, sortfun) { this.recalculate(filt, sortfun); } -_.extend(StoreView.prototype, EventEmitter.prototype, { +_.extend(StoreView.prototype, utils.EventEmitter.prototype, { close: function () { this.store.removeListener("add", this.add); this.store.removeListener("update", this.update); @@ -96,4 +100,8 @@ _.extend(StoreView.prototype, EventEmitter.prototype, { } } } -}); \ No newline at end of file +}); + +module.exports = { + StoreView: StoreView +}; \ No newline at end of file diff --git a/web/src/js/utils.js b/web/src/js/utils.js index a8565243..0371810c 100644 --- a/web/src/js/utils.js +++ b/web/src/js/utils.js @@ -1,3 +1,6 @@ +var $ = require("jquery"); + + var Key = { UP: 38, DOWN: 40, @@ -88,7 +91,7 @@ function getCookie(name) { var xsrf = $.param({_xsrf: getCookie("_xsrf")}); //Tornado XSRF Protection. -jQuery.ajaxPrefilter(function (options) { +$.ajaxPrefilter(function (options) { if (["post", "put", "delete"].indexOf(options.type.toLowerCase()) >= 0 && options.url[0] === "/") { if (options.data) { options.data += ("&" + xsrf); @@ -103,4 +106,11 @@ $(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { console.error(message, arguments); EventLogActions.add_event(thrownError + ": " + message); window.alert(message); -}); \ No newline at end of file +}); + +module.exports = { + EventEmitter: EventEmitter, + formatSize: formatSize, + formatTimeDelta: formatTimeDelta, + formatTimeStamp: formatTimeStamp +}; \ No newline at end of file -- cgit v1.2.3